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"
42 #define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f
48 class IWritableTextureSource;
49 class IWritableShaderSource;
52 //class IWritableCraftDefManager;
53 class ClientMediaDownloader;
54 struct MapDrawControl;
60 struct MinimapMapblock;
67 enum LocalClientState {
80 PacketCounter() = default;
84 auto n = m_packets.find(command);
85 if (n == m_packets.end())
86 m_packets[command] = 1;
97 void print(std::ostream &o) const;
101 std::map<u16, u32> m_packets;
104 class ClientScripting;
107 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
111 NOTE: Nothing is thread-safe here.
115 const char *playername,
116 const std::string &password,
117 const std::string &address_name,
118 MapDrawControl &control,
119 IWritableTextureSource *tsrc,
120 IWritableShaderSource *shsrc,
121 IWritableItemDefManager *itemdef,
122 NodeDefManager *nodedef,
123 ISoundManager *sound,
124 MtEventManager *event,
130 DISABLE_CLASS_COPY(Client);
132 // Load local mods into memory
133 void scanModSubfolder(const std::string &mod_name, const std::string &mod_path,
134 std::string mod_subpath);
135 inline void scanModIntoMemory(const std::string &mod_name, const std::string &mod_path)
137 scanModSubfolder(mod_name, mod_path, "");
141 request all threads managed by client to be stopped
149 The name of the local player should already be set when
150 calling this, as it is sent in the initialization.
152 void connect(Address address, bool is_local_server);
155 Stuff that references the environment is valid only as
156 long as this is not called. (eg. Players)
157 If this throws a PeerNotFoundException, the connection has
160 void step(float dtime);
166 void handleCommand(NetworkPacket* pkt);
168 void handleCommand_Null(NetworkPacket* pkt) {};
169 void handleCommand_Deprecated(NetworkPacket* pkt);
170 void handleCommand_Hello(NetworkPacket* pkt);
171 void handleCommand_AuthAccept(NetworkPacket* pkt);
172 void handleCommand_AcceptSudoMode(NetworkPacket* pkt);
173 void handleCommand_DenySudoMode(NetworkPacket* pkt);
174 void handleCommand_AccessDenied(NetworkPacket* pkt);
175 void handleCommand_RemoveNode(NetworkPacket* pkt);
176 void handleCommand_AddNode(NetworkPacket* pkt);
177 void handleCommand_NodemetaChanged(NetworkPacket *pkt);
178 void handleCommand_BlockData(NetworkPacket* pkt);
179 void handleCommand_Inventory(NetworkPacket* pkt);
180 void handleCommand_TimeOfDay(NetworkPacket* pkt);
181 void handleCommand_ChatMessage(NetworkPacket *pkt);
182 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
183 void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
184 void handleCommand_Movement(NetworkPacket* pkt);
185 void handleCommand_Fov(NetworkPacket *pkt);
186 void handleCommand_HP(NetworkPacket* pkt);
187 void handleCommand_Breath(NetworkPacket* pkt);
188 void handleCommand_MovePlayer(NetworkPacket* pkt);
189 void handleCommand_DeathScreen(NetworkPacket* pkt);
190 void handleCommand_AnnounceMedia(NetworkPacket* pkt);
191 void handleCommand_Media(NetworkPacket* pkt);
192 void handleCommand_NodeDef(NetworkPacket* pkt);
193 void handleCommand_ItemDef(NetworkPacket* pkt);
194 void handleCommand_PlaySound(NetworkPacket* pkt);
195 void handleCommand_StopSound(NetworkPacket* pkt);
196 void handleCommand_FadeSound(NetworkPacket *pkt);
197 void handleCommand_Privileges(NetworkPacket* pkt);
198 void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
199 void handleCommand_DetachedInventory(NetworkPacket* pkt);
200 void handleCommand_ShowFormSpec(NetworkPacket* pkt);
201 void handleCommand_SpawnParticle(NetworkPacket* pkt);
202 void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
203 void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
204 void handleCommand_HudAdd(NetworkPacket* pkt);
205 void handleCommand_HudRemove(NetworkPacket* pkt);
206 void handleCommand_HudChange(NetworkPacket* pkt);
207 void handleCommand_HudSetFlags(NetworkPacket* pkt);
208 void handleCommand_HudSetParam(NetworkPacket* pkt);
209 void handleCommand_HudSetSky(NetworkPacket* pkt);
210 void handleCommand_HudSetSun(NetworkPacket* pkt);
211 void handleCommand_HudSetMoon(NetworkPacket* pkt);
212 void handleCommand_HudSetStars(NetworkPacket* pkt);
213 void handleCommand_CloudParams(NetworkPacket* pkt);
214 void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
215 void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
216 void handleCommand_EyeOffset(NetworkPacket* pkt);
217 void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
218 void handleCommand_ModChannelMsg(NetworkPacket *pkt);
219 void handleCommand_ModChannelSignal(NetworkPacket *pkt);
220 void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
221 void handleCommand_FormspecPrepend(NetworkPacket *pkt);
222 void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
223 void handleCommand_PlayerSpeed(NetworkPacket *pkt);
224 void handleCommand_MediaPush(NetworkPacket *pkt);
226 void ProcessData(NetworkPacket *pkt);
228 void Send(NetworkPacket* pkt);
230 void interact(InteractAction action, const PointedThing &pointed);
232 void sendNodemetaFields(v3s16 p, const std::string &formname,
233 const StringMap &fields);
234 void sendInventoryFields(const std::string &formname,
235 const StringMap &fields);
236 void sendInventoryAction(InventoryAction *a);
237 void sendChatMessage(const std::wstring &message);
238 void clearOutChatQueue();
239 void sendChangePassword(const std::string &oldpassword,
240 const std::string &newpassword);
241 void sendDamage(u16 damage);
245 ClientEnvironment& getEnv() { return m_env; }
246 ITextureSource *tsrc() { return getTextureSource(); }
247 ISoundManager *sound() { return getSoundManager(); }
248 static const std::string &getBuiltinLuaPath();
249 static const std::string &getClientModsLuaPath();
251 const std::vector<ModSpec> &getMods() const override;
252 const ModSpec* getModSpec(const std::string &modname) const override;
254 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
255 void removeNode(v3s16 p);
257 // helpers to enforce CSM restrictions
258 MapNode CSMGetNode(v3s16 p, bool *is_valid_position);
259 int CSMClampRadius(v3s16 pos, int radius);
260 v3s16 CSMClampPos(v3s16 pos);
262 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
264 void setPlayerControl(PlayerControl &control);
266 // Returns true if the inventory of the local player has been
267 // updated from the server. If it is true, it is set to false.
268 bool updateWieldedItem();
270 /* InventoryManager interface */
271 Inventory* getInventory(const InventoryLocation &loc) override;
272 void inventoryAction(InventoryAction *a) override;
274 // Send the item number 'item' as player item to the server
275 void setPlayerItem(u16 item);
277 const std::list<std::string> &getConnectedPlayerNames()
279 return m_env.getPlayerNames();
282 float getAnimationTime();
286 void setCrack(int level, v3s16 pos);
290 bool checkPrivilege(const std::string &priv) const
291 { return g_settings->getBool("priv_bypass") ? true : (m_privileges.count(priv) != 0); }
293 const std::unordered_set<std::string> &getPrivilegeList() const
294 { return m_privileges; }
296 bool getChatMessage(std::wstring &message);
297 void typeChatMessage(const std::wstring& message);
299 u64 getMapSeed(){ return m_map_seed; }
301 void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
302 // Including blocks at appropriate edges
303 void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
304 void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
306 void updateAllMapBlocks();
308 void updateCameraOffset(v3s16 camera_offset)
309 { m_mesh_update_thread.m_camera_offset = camera_offset; }
311 bool hasClientEvents() const { return !m_client_event_queue.empty(); }
312 // Get event from queue. If queue is empty, it triggers an assertion failure.
313 ClientEvent * getClientEvent();
315 bool accessDenied() const { return m_access_denied; }
317 bool reconnectRequested() const { return true || m_access_denied_reconnect; }
319 void setFatalError(const std::string &reason)
321 m_access_denied = true;
322 m_access_denied_reason = reason;
325 // Renaming accessDeniedReason to better name could be good as it's used to
326 // disconnect client when CSM failed.
327 const std::string &accessDeniedReason() const { return m_access_denied_reason; }
329 const bool itemdefReceived() const
330 { return m_itemdef_received; }
331 const bool nodedefReceived() const
332 { return m_nodedef_received; }
333 const bool mediaReceived() const
334 { return !m_media_downloader; }
335 const bool activeObjectsReceived() const
336 { return m_activeobjects_received; }
338 u16 getProtoVersion()
339 { return m_proto_ver; }
341 bool connectedToServer();
342 void confirmRegistration();
343 bool m_is_registration_confirmation_state = false;
344 bool m_simple_singleplayer_mode;
346 float mediaReceiveProgress();
348 void afterContentReceived();
353 Minimap* getMinimap() { return m_minimap; }
354 void setCamera(Camera* camera) { m_camera = camera; }
356 Camera* getCamera () { return m_camera; }
358 bool shouldShowMinimap() const;
360 // IGameDef interface
361 IItemDefManager* getItemDefManager() override;
362 IWritableItemDefManager* getWritableItemDefManager() override;
363 const NodeDefManager* getNodeDefManager() override;
364 NodeDefManager* getWritableNodeDefManager() override;
365 ICraftDefManager* getCraftDefManager() override;
366 ITextureSource* getTextureSource();
367 virtual IWritableShaderSource* getShaderSource();
368 u16 allocateUnknownNodeId(const std::string &name) override;
369 virtual ISoundManager* getSoundManager();
370 MtEventManager* getEventManager();
371 virtual ParticleManager* getParticleManager();
372 bool checkLocalPrivilege(const std::string &priv){ return checkPrivilege(priv); }
373 virtual scene::IAnimatedMesh* getMesh(const std::string &filename, bool cache = false);
374 const std::string* getModFile(std::string filename);
376 std::string getModStoragePath() const override;
377 bool registerModStorage(ModMetadata *meta) override;
378 void unregisterModStorage(const std::string &name) override;
380 // The following set of functions is used by ClientMediaDownloader
381 // Insert a media file appropriately into the appropriate manager
382 bool loadMedia(const std::string &data, const std::string &filename,
383 bool from_media_push = false);
384 // Send a request for conventional media transfer
385 void request_media(const std::vector<std::string> &file_requests);
387 LocalClientState getState() { return m_state; }
389 void makeScreenshot();
391 inline void pushToChatQueue(ChatMessage *cec)
393 m_chat_queue.push(cec);
396 ClientScripting *getScript() { return m_script; }
397 const bool modsLoaded() const { return m_mods_loaded; }
399 void pushToEventQueue(ClientEvent *event);
401 void showMinimap(bool show = true);
403 const Address getServerAddress();
405 const std::string &getAddressName() const
407 return m_address_name;
410 inline u64 getCSMRestrictionFlags() const
412 return m_csm_restriction_flags;
415 inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const
417 //return m_csm_restriction_flags & flag;
421 u32 getCSMNodeRangeLimit() const
423 return m_csm_restriction_noderange;
426 inline std::unordered_map<u32, u32> &getHUDTranslationMap()
428 return m_hud_server_to_client;
431 bool joinModChannel(const std::string &channel) override;
432 bool leaveModChannel(const std::string &channel) override;
433 bool sendModChannelMessage(const std::string &channel,
434 const std::string &message) override;
435 ModChannel *getModChannel(const std::string &channel) override;
437 const std::string &getFormspecPrepend() const
439 return m_env.getLocalPlayer()->formspec_prepend;
442 void sendPlayerPos(v3f pos);
443 void sendPlayerPos();
444 MeshUpdateThread m_mesh_update_thread;
448 bool checkBuiltinIntegrity();
450 // Virtual methods from con::PeerHandler
451 void peerAdded(con::Peer *peer) override;
452 void deletingPeer(con::Peer *peer, bool timeout) override;
454 void initLocalMapSaving(const Address &address,
455 const std::string &hostname,
456 bool is_local_server);
461 void deleteAuthData();
462 // helper method shared with clientpackethandler
463 static AuthMechanism choseAuthMech(const u32 mechs);
465 void sendInit(const std::string &playerName);
466 void promptConfirmRegistration(AuthMechanism chosen_auth_mechanism);
467 void startAuth(AuthMechanism chosen_auth_mechanism);
468 void sendDeletedBlocks(std::vector<v3s16> &blocks);
469 void sendGotBlocks(const std::vector<v3s16> &blocks);
470 void sendRemovedSounds(std::vector<s32> &soundList);
473 inline std::string getPlayerName()
474 { return m_env.getLocalPlayer()->getName(); }
476 bool canSendChatMessage() const;
478 float m_packetcounter_timer = 0.0f;
479 float m_connection_reinit_timer = 0.1f;
480 float m_avg_rtt_timer = 0.0f;
481 float m_playerpos_send_timer = 0.0f;
482 IntervalLimiter m_map_timer_and_unload_interval;
484 IWritableTextureSource *m_tsrc;
485 IWritableShaderSource *m_shsrc;
486 IWritableItemDefManager *m_itemdef;
487 NodeDefManager *m_nodedef;
488 ISoundManager *m_sound;
489 MtEventManager *m_event;
492 ClientEnvironment m_env;
493 ParticleManager m_particle_manager;
494 std::unique_ptr<con::Connection> m_con;
495 std::string m_address_name;
496 Camera *m_camera = nullptr;
497 Minimap *m_minimap = nullptr;
498 bool m_minimap_disabled_by_server = false;
500 // Server serialization version
503 // Used version of the protocol with server
504 // Values smaller than 25 only mean they are smaller than 25,
505 // and aren't accurate. We simply just don't know, because
506 // the server didn't send the version back then.
507 // If 0, server init hasn't been received yet.
510 bool m_update_wielded_item = false;
511 Inventory *m_inventory_from_server = nullptr;
512 float m_inventory_from_server_age = 0.0f;
513 PacketCounter m_packetcounter;
514 // Block mesh animation parameters
515 float m_animation_time = 0.0f;
516 int m_crack_level = -1;
518 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
520 //u32 m_daynight_ratio;
521 std::queue<std::wstring> m_out_chat_queue;
522 u32 m_last_chat_message_sent;
523 float m_chat_message_allowance = 5.0f;
524 std::queue<ChatMessage *> m_chat_queue;
526 // The authentication methods we can use to enter sudo mode (=change password)
527 u32 m_sudo_auth_methods;
529 // The seed returned by the server in TOCLIENT_INIT is stored here
533 std::string m_playername;
534 std::string m_password;
535 // If set, this will be sent (and cleared) upon a TOCLIENT_ACCEPT_SUDO_MODE
536 std::string m_new_password;
537 // Usable by auth mechanisms.
538 AuthMechanism m_chosen_auth_mech;
539 void *m_auth_data = nullptr;
541 bool m_access_denied = false;
542 bool m_access_denied_reconnect = false;
543 std::string m_access_denied_reason = "";
544 std::queue<ClientEvent *> m_client_event_queue;
545 bool m_itemdef_received = false;
546 bool m_nodedef_received = false;
547 bool m_activeobjects_received = false;
548 bool m_mods_loaded = false;
550 ClientMediaDownloader *m_media_downloader;
551 // Set of media filenames pushed by server at runtime
552 std::unordered_set<std::string> m_media_pushed_files;
554 // time_of_day speed approximation for old protocol
555 bool m_time_of_day_set = false;
556 float m_last_time_of_day_f = -1.0f;
557 float m_time_of_day_update_timer = 0.0f;
559 // An interval for generally sending object positions and stuff
560 float m_recommended_send_interval = 0.1f;
563 float m_removed_sounds_check_timer = 0.0f;
564 // Mapping from server sound ids to our sound ids
565 std::unordered_map<s32, int> m_sounds_server_to_client;
566 // And the other way!
567 std::unordered_map<int, s32> m_sounds_client_to_server;
568 // Relation of client id to object id
569 std::unordered_map<int, u16> m_sounds_to_objects;
571 // Map server hud ids to client hud ids
572 std::unordered_map<u32, u32> m_hud_server_to_client;
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 bool m_modding_enabled;
597 std::unordered_map<std::string, ModMetadata *> m_mod_storages;
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;