3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "clientenvironment.h"
23 #include "irrlichttypes_extrabloated.h"
28 #include <unordered_set>
29 #include "clientobject.h"
31 #include "inventorymanager.h"
32 #include "localplayer.h"
33 #include "client/hud.h"
34 #include "particles.h"
36 #include "tileanimation.h"
37 #include "mesh_generator_thread.h"
38 #include "network/address.h"
39 #include "network/peerhandler.h"
40 #include "gameparams.h"
43 #define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f
49 class RenderingEngine;
50 class IWritableTextureSource;
51 class IWritableShaderSource;
52 class IWritableItemDefManager;
55 //class IWritableCraftDefManager;
56 class ClientMediaDownloader;
57 class SingleMediaDownloader;
58 struct MapDrawControl;
64 struct MinimapMapblock;
71 enum LocalClientState {
84 PacketCounter() = default;
88 auto n = m_packets.find(command);
89 if (n == m_packets.end())
90 m_packets[command] = 1;
101 void print(std::ostream &o) const;
105 std::map<u16, u32> m_packets;
108 class ClientScripting;
111 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
115 NOTE: Nothing is thread-safe here.
119 const char *playername,
120 const std::string &password,
121 const std::string &address_name,
122 MapDrawControl &control,
123 IWritableTextureSource *tsrc,
124 IWritableShaderSource *shsrc,
125 IWritableItemDefManager *itemdef,
126 NodeDefManager *nodedef,
127 ISoundManager *sound,
128 MtEventManager *event,
129 RenderingEngine *rendering_engine,
132 ELoginRegister allow_login_or_register
136 DISABLE_CLASS_COPY(Client);
138 // Load local mods into memory
139 void scanModSubfolder(const std::string &mod_name, const std::string &mod_path,
140 std::string mod_subpath);
141 inline void scanModIntoMemory(const std::string &mod_name, const std::string &mod_path)
143 scanModSubfolder(mod_name, mod_path, "");
147 request all threads managed by client to be stopped
155 The name of the local player should already be set when
156 calling this, as it is sent in the initialization.
158 void connect(Address address, bool is_local_server);
161 Stuff that references the environment is valid only as
162 long as this is not called. (eg. Players)
163 If this throws a PeerNotFoundException, the connection has
166 void step(float dtime);
172 void handleCommand(NetworkPacket* pkt);
174 void handleCommand_Null(NetworkPacket* pkt) {};
175 void handleCommand_Deprecated(NetworkPacket* pkt);
176 void handleCommand_Hello(NetworkPacket* pkt);
177 void handleCommand_AuthAccept(NetworkPacket* pkt);
178 void handleCommand_AcceptSudoMode(NetworkPacket* pkt);
179 void handleCommand_DenySudoMode(NetworkPacket* pkt);
180 void handleCommand_AccessDenied(NetworkPacket* pkt);
181 void handleCommand_RemoveNode(NetworkPacket* pkt);
182 void handleCommand_AddNode(NetworkPacket* pkt);
183 void handleCommand_NodemetaChanged(NetworkPacket *pkt);
184 void handleCommand_BlockData(NetworkPacket* pkt);
185 void handleCommand_Inventory(NetworkPacket* pkt);
186 void handleCommand_TimeOfDay(NetworkPacket* pkt);
187 void handleCommand_ChatMessage(NetworkPacket *pkt);
188 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
189 void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
190 void handleCommand_Movement(NetworkPacket* pkt);
191 void handleCommand_Fov(NetworkPacket *pkt);
192 void handleCommand_HP(NetworkPacket* pkt);
193 void handleCommand_Breath(NetworkPacket* pkt);
194 void handleCommand_MovePlayer(NetworkPacket* pkt);
195 void handleCommand_DeathScreen(NetworkPacket* pkt);
196 void handleCommand_AnnounceMedia(NetworkPacket* pkt);
197 void handleCommand_Media(NetworkPacket* pkt);
198 void handleCommand_NodeDef(NetworkPacket* pkt);
199 void handleCommand_ItemDef(NetworkPacket* pkt);
200 void handleCommand_PlaySound(NetworkPacket* pkt);
201 void handleCommand_StopSound(NetworkPacket* pkt);
202 void handleCommand_FadeSound(NetworkPacket *pkt);
203 void handleCommand_Privileges(NetworkPacket* pkt);
204 void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
205 void handleCommand_DetachedInventory(NetworkPacket* pkt);
206 void handleCommand_ShowFormSpec(NetworkPacket* pkt);
207 void handleCommand_SpawnParticle(NetworkPacket* pkt);
208 void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
209 void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
210 void handleCommand_HudAdd(NetworkPacket* pkt);
211 void handleCommand_HudRemove(NetworkPacket* pkt);
212 void handleCommand_HudChange(NetworkPacket* pkt);
213 void handleCommand_HudSetFlags(NetworkPacket* pkt);
214 void handleCommand_HudSetParam(NetworkPacket* pkt);
215 void handleCommand_HudSetSky(NetworkPacket* pkt);
216 void handleCommand_HudSetSun(NetworkPacket* pkt);
217 void handleCommand_HudSetMoon(NetworkPacket* pkt);
218 void handleCommand_HudSetStars(NetworkPacket* pkt);
219 void handleCommand_CloudParams(NetworkPacket* pkt);
220 void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
221 void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
222 void handleCommand_EyeOffset(NetworkPacket* pkt);
223 void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
224 void handleCommand_ModChannelMsg(NetworkPacket *pkt);
225 void handleCommand_ModChannelSignal(NetworkPacket *pkt);
226 void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
227 void handleCommand_FormspecPrepend(NetworkPacket *pkt);
228 void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
229 void handleCommand_PlayerSpeed(NetworkPacket *pkt);
230 void handleCommand_MediaPush(NetworkPacket *pkt);
231 void handleCommand_MinimapModes(NetworkPacket *pkt);
232 void handleCommand_SetLighting(NetworkPacket *pkt);
234 void ProcessData(NetworkPacket *pkt);
236 void Send(NetworkPacket* pkt);
238 void interact(InteractAction action, const PointedThing &pointed);
240 void sendNodemetaFields(v3s16 p, const std::string &formname,
241 const StringMap &fields);
242 void sendInventoryFields(const std::string &formname,
243 const StringMap &fields);
244 void sendInventoryAction(InventoryAction *a);
245 void sendChatMessage(const std::wstring &message);
246 void clearOutChatQueue();
247 void sendChangePassword(const std::string &oldpassword,
248 const std::string &newpassword);
249 void sendDamage(u16 damage);
252 void sendHaveMedia(const std::vector<u32> &tokens);
254 ClientEnvironment& getEnv() { return m_env; }
255 ITextureSource *tsrc() { return getTextureSource(); }
256 ISoundManager *sound() { return getSoundManager(); }
257 static const std::string &getBuiltinLuaPath();
258 static const std::string &getClientModsLuaPath();
260 const std::vector<ModSpec> &getMods() const override;
261 const ModSpec* getModSpec(const std::string &modname) const override;
263 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
264 void removeNode(v3s16 p);
266 // helpers to enforce CSM restrictions
267 MapNode CSMGetNode(v3s16 p, bool *is_valid_position);
268 int CSMClampRadius(v3s16 pos, int radius);
269 v3s16 CSMClampPos(v3s16 pos);
271 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
273 void setPlayerControl(PlayerControl &control);
275 // Returns true if the inventory of the local player has been
276 // updated from the server. If it is true, it is set to false.
277 bool updateWieldedItem();
279 /* InventoryManager interface */
280 Inventory* getInventory(const InventoryLocation &loc) override;
281 void inventoryAction(InventoryAction *a) override;
283 // Send the item number 'item' as player item to the server
284 void setPlayerItem(u16 item);
286 const std::list<std::string> &getConnectedPlayerNames()
288 return m_env.getPlayerNames();
291 float getAnimationTime();
295 void setCrack(int level, v3s16 pos);
299 bool checkPrivilege(const std::string &priv) const
300 { return (m_privileges.count(priv) != 0); }
302 const std::unordered_set<std::string> &getPrivilegeList() const
303 { return m_privileges; }
305 bool getChatMessage(std::wstring &message);
306 void typeChatMessage(const std::wstring& message);
308 u64 getMapSeed(){ return m_map_seed; }
310 void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
311 // Including blocks at appropriate edges
312 void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
313 void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
315 void updateCameraOffset(v3s16 camera_offset)
316 { m_mesh_update_thread.m_camera_offset = camera_offset; }
318 bool hasClientEvents() const { return !m_client_event_queue.empty(); }
319 // Get event from queue. If queue is empty, it triggers an assertion failure.
320 ClientEvent * getClientEvent();
322 bool accessDenied() const { return m_access_denied; }
324 bool reconnectRequested() const { return m_access_denied_reconnect; }
326 void setFatalError(const std::string &reason)
328 m_access_denied = true;
329 m_access_denied_reason = reason;
331 inline void setFatalError(const LuaError &e)
333 setFatalError(std::string("Lua: ") + e.what());
336 // Renaming accessDeniedReason to better name could be good as it's used to
337 // disconnect client when CSM failed.
338 const std::string &accessDeniedReason() const { return m_access_denied_reason; }
340 bool itemdefReceived() const
341 { return m_itemdef_received; }
342 bool nodedefReceived() const
343 { return m_nodedef_received; }
344 bool mediaReceived() const
345 { return !m_media_downloader; }
346 bool activeObjectsReceived() const
347 { return m_activeobjects_received; }
349 u16 getProtoVersion()
350 { return m_proto_ver; }
352 ELoginRegister m_allow_login_or_register = ELoginRegister::Any;
353 bool m_simple_singleplayer_mode;
355 float mediaReceiveProgress();
357 void afterContentReceived();
358 void showUpdateProgressTexture(void *args, u32 progress, u32 max_progress);
363 Minimap* getMinimap() { return m_minimap; }
364 void setCamera(Camera* camera) { m_camera = camera; }
366 Camera* getCamera () { return m_camera; }
367 scene::ISceneManager *getSceneManager();
369 bool shouldShowMinimap() const;
371 // IGameDef interface
372 IItemDefManager* getItemDefManager() override;
373 const NodeDefManager* getNodeDefManager() override;
374 ICraftDefManager* getCraftDefManager() override;
375 ITextureSource* getTextureSource();
376 virtual IWritableShaderSource* getShaderSource();
377 u16 allocateUnknownNodeId(const std::string &name) override;
378 virtual ISoundManager* getSoundManager();
379 MtEventManager* getEventManager();
380 virtual ParticleManager* getParticleManager();
381 bool checkLocalPrivilege(const std::string &priv)
382 { return checkPrivilege(priv); }
383 virtual scene::IAnimatedMesh* getMesh(const std::string &filename, bool cache = false);
384 const std::string* getModFile(std::string filename);
385 ModMetadataDatabase *getModStorageDatabase() override { return m_mod_storage_database; }
387 bool registerModStorage(ModMetadata *meta) override;
388 void unregisterModStorage(const std::string &name) override;
390 // Migrates away old files-based mod storage if necessary
391 void migrateModStorage();
393 // The following set of functions is used by ClientMediaDownloader
394 // Insert a media file appropriately into the appropriate manager
395 bool loadMedia(const std::string &data, const std::string &filename,
396 bool from_media_push = false);
398 // Send a request for conventional media transfer
399 void request_media(const std::vector<std::string> &file_requests);
401 LocalClientState getState() { return m_state; }
403 void makeScreenshot();
405 inline void pushToChatQueue(ChatMessage *cec)
407 m_chat_queue.push(cec);
410 ClientScripting *getScript() { return m_script; }
411 bool modsLoaded() const { return m_mods_loaded; }
413 void pushToEventQueue(ClientEvent *event);
415 void showMinimap(bool show = true);
417 const Address getServerAddress();
419 const std::string &getAddressName() const
421 return m_address_name;
424 inline u64 getCSMRestrictionFlags() const
426 return m_csm_restriction_flags;
429 inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const
431 return m_csm_restriction_flags & flag;
434 bool joinModChannel(const std::string &channel) override;
435 bool leaveModChannel(const std::string &channel) override;
436 bool sendModChannelMessage(const std::string &channel,
437 const std::string &message) override;
438 ModChannel *getModChannel(const std::string &channel) override;
440 const std::string &getFormspecPrepend() const
442 return m_env.getLocalPlayer()->formspec_prepend;
447 // Virtual methods from con::PeerHandler
448 void peerAdded(con::Peer *peer) override;
449 void deletingPeer(con::Peer *peer, bool timeout) override;
451 void initLocalMapSaving(const Address &address,
452 const std::string &hostname,
453 bool is_local_server);
457 void sendPlayerPos();
459 void deleteAuthData();
460 // helper method shared with clientpackethandler
461 static AuthMechanism choseAuthMech(const u32 mechs);
463 void sendInit(const std::string &playerName);
464 void startAuth(AuthMechanism chosen_auth_mechanism);
465 void sendDeletedBlocks(std::vector<v3s16> &blocks);
466 void sendGotBlocks(const std::vector<v3s16> &blocks);
467 void sendRemovedSounds(std::vector<s32> &soundList);
470 inline std::string getPlayerName()
471 { return m_env.getLocalPlayer()->getName(); }
473 bool canSendChatMessage() const;
475 float m_packetcounter_timer = 0.0f;
476 float m_connection_reinit_timer = 0.1f;
477 float m_avg_rtt_timer = 0.0f;
478 float m_playerpos_send_timer = 0.0f;
479 IntervalLimiter m_map_timer_and_unload_interval;
481 IWritableTextureSource *m_tsrc;
482 IWritableShaderSource *m_shsrc;
483 IWritableItemDefManager *m_itemdef;
484 NodeDefManager *m_nodedef;
485 ISoundManager *m_sound;
486 MtEventManager *m_event;
487 RenderingEngine *m_rendering_engine;
490 MeshUpdateThread m_mesh_update_thread;
491 ClientEnvironment m_env;
492 ParticleManager m_particle_manager;
493 std::unique_ptr<con::Connection> m_con;
494 std::string m_address_name;
495 Camera *m_camera = nullptr;
496 Minimap *m_minimap = nullptr;
497 bool m_minimap_disabled_by_server = false;
499 // Server serialization version
502 // Used version of the protocol with server
503 // Values smaller than 25 only mean they are smaller than 25,
504 // and aren't accurate. We simply just don't know, because
505 // the server didn't send the version back then.
506 // If 0, server init hasn't been received yet.
509 bool m_update_wielded_item = false;
510 Inventory *m_inventory_from_server = nullptr;
511 float m_inventory_from_server_age = 0.0f;
512 PacketCounter m_packetcounter;
513 // Block mesh animation parameters
514 float m_animation_time = 0.0f;
515 int m_crack_level = -1;
517 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
519 //u32 m_daynight_ratio;
520 std::queue<std::wstring> m_out_chat_queue;
521 u32 m_last_chat_message_sent;
522 float m_chat_message_allowance = 5.0f;
523 std::queue<ChatMessage *> m_chat_queue;
525 // The authentication methods we can use to enter sudo mode (=change password)
526 u32 m_sudo_auth_methods;
528 // The seed returned by the server in TOCLIENT_INIT is stored here
532 std::string m_playername;
533 std::string m_password;
534 // If set, this will be sent (and cleared) upon a TOCLIENT_ACCEPT_SUDO_MODE
535 std::string m_new_password;
536 // Usable by auth mechanisms.
537 AuthMechanism m_chosen_auth_mech;
538 void *m_auth_data = nullptr;
540 bool m_access_denied = false;
541 bool m_access_denied_reconnect = false;
542 std::string m_access_denied_reason = "";
543 std::queue<ClientEvent *> m_client_event_queue;
544 bool m_itemdef_received = false;
545 bool m_nodedef_received = false;
546 bool m_activeobjects_received = false;
547 bool m_mods_loaded = false;
549 std::vector<std::string> m_remote_media_servers;
550 // Media downloader, only exists during init
551 ClientMediaDownloader *m_media_downloader;
552 // Set of media filenames pushed by server at runtime
553 std::unordered_set<std::string> m_media_pushed_files;
554 // Pending downloads of dynamic media (key: token)
555 std::vector<std::pair<u32, std::shared_ptr<SingleMediaDownloader>>> m_pending_media_downloads;
557 // time_of_day speed approximation for old protocol
558 bool m_time_of_day_set = false;
559 float m_last_time_of_day_f = -1.0f;
560 float m_time_of_day_update_timer = 0.0f;
562 // An interval for generally sending object positions and stuff
563 float m_recommended_send_interval = 0.1f;
566 float m_removed_sounds_check_timer = 0.0f;
567 // Mapping from server sound ids to our sound ids
568 std::unordered_map<s32, int> m_sounds_server_to_client;
569 // And the other way!
570 std::unordered_map<int, s32> m_sounds_client_to_server;
571 // Relation of client id to object id
572 std::unordered_map<int, u16> m_sounds_to_objects;
575 std::unordered_set<std::string> m_privileges;
577 // Detached inventories
579 std::unordered_map<std::string, Inventory*> m_detached_inventories;
581 // Storage for mesh data for creating multiple instances of the same mesh
582 StringMap m_mesh_data;
585 LocalClientState m_state;
589 // Used for saving server map to disk client-side
590 MapDatabase *m_localdb = nullptr;
591 IntervalLimiter m_localdb_save_interval;
592 u16 m_cache_save_interval;
595 ClientScripting *m_script = nullptr;
596 std::unordered_map<std::string, ModMetadata *> m_mod_storages;
597 ModMetadataDatabase *m_mod_storage_database = nullptr;
598 float m_mod_storage_save_timer = 10.0f;
599 std::vector<ModSpec> m_mods;
602 bool m_shutdown = false;
604 // CSM restrictions byteflag
605 u64 m_csm_restriction_flags = CSMRestrictionFlags::CSM_RF_NONE;
606 u32 m_csm_restriction_noderange = 8;
608 std::unique_ptr<ModChannelMgr> m_modchannel_mgr;