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;
50 class IWritableItemDefManager;
53 //class IWritableCraftDefManager;
54 class ClientMediaDownloader;
55 struct MapDrawControl;
61 struct MinimapMapblock;
68 enum LocalClientState {
81 PacketCounter() = default;
85 std::map<u16, u16>::iterator n = m_packets.find(command);
86 if(n == m_packets.end())
88 m_packets[command] = 1;
98 for (auto &m_packet : m_packets) {
103 void print(std::ostream &o)
105 for (const auto &m_packet : m_packets) {
106 o << "cmd "<< m_packet.first <<" count "<< m_packet.second << std::endl;
112 std::map<u16, u16> m_packets;
115 class ClientScripting;
118 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
122 NOTE: Nothing is thread-safe here.
126 const char *playername,
127 const std::string &password,
128 const std::string &address_name,
129 MapDrawControl &control,
130 IWritableTextureSource *tsrc,
131 IWritableShaderSource *shsrc,
132 IWritableItemDefManager *itemdef,
133 NodeDefManager *nodedef,
134 ISoundManager *sound,
135 MtEventManager *event,
141 DISABLE_CLASS_COPY(Client);
143 // Load local mods into memory
144 void scanModSubfolder(const std::string &mod_name, const std::string &mod_path,
145 std::string mod_subpath);
146 inline void scanModIntoMemory(const std::string &mod_name, const std::string &mod_path)
148 scanModSubfolder(mod_name, mod_path, "");
152 request all threads managed by client to be stopped
160 The name of the local player should already be set when
161 calling this, as it is sent in the initialization.
163 void connect(Address address, bool is_local_server);
166 Stuff that references the environment is valid only as
167 long as this is not called. (eg. Players)
168 If this throws a PeerNotFoundException, the connection has
171 void step(float dtime);
177 void handleCommand(NetworkPacket* pkt);
179 void handleCommand_Null(NetworkPacket* pkt) {};
180 void handleCommand_Deprecated(NetworkPacket* pkt);
181 void handleCommand_Hello(NetworkPacket* pkt);
182 void handleCommand_AuthAccept(NetworkPacket* pkt);
183 void handleCommand_AcceptSudoMode(NetworkPacket* pkt);
184 void handleCommand_DenySudoMode(NetworkPacket* pkt);
185 void handleCommand_AccessDenied(NetworkPacket* pkt);
186 void handleCommand_RemoveNode(NetworkPacket* pkt);
187 void handleCommand_AddNode(NetworkPacket* pkt);
188 void handleCommand_NodemetaChanged(NetworkPacket *pkt);
189 void handleCommand_BlockData(NetworkPacket* pkt);
190 void handleCommand_Inventory(NetworkPacket* pkt);
191 void handleCommand_TimeOfDay(NetworkPacket* pkt);
192 void handleCommand_ChatMessage(NetworkPacket *pkt);
193 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
194 void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
195 void handleCommand_Movement(NetworkPacket* pkt);
196 void handleCommand_Fov(NetworkPacket *pkt);
197 void handleCommand_HP(NetworkPacket* pkt);
198 void handleCommand_Breath(NetworkPacket* pkt);
199 void handleCommand_MovePlayer(NetworkPacket* pkt);
200 void handleCommand_DeathScreen(NetworkPacket* pkt);
201 void handleCommand_AnnounceMedia(NetworkPacket* pkt);
202 void handleCommand_Media(NetworkPacket* pkt);
203 void handleCommand_NodeDef(NetworkPacket* pkt);
204 void handleCommand_ItemDef(NetworkPacket* pkt);
205 void handleCommand_PlaySound(NetworkPacket* pkt);
206 void handleCommand_StopSound(NetworkPacket* pkt);
207 void handleCommand_FadeSound(NetworkPacket *pkt);
208 void handleCommand_Privileges(NetworkPacket* pkt);
209 void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
210 void handleCommand_DetachedInventory(NetworkPacket* pkt);
211 void handleCommand_ShowFormSpec(NetworkPacket* pkt);
212 void handleCommand_SpawnParticle(NetworkPacket* pkt);
213 void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
214 void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
215 void handleCommand_HudAdd(NetworkPacket* pkt);
216 void handleCommand_HudRemove(NetworkPacket* pkt);
217 void handleCommand_HudChange(NetworkPacket* pkt);
218 void handleCommand_HudSetFlags(NetworkPacket* pkt);
219 void handleCommand_HudSetParam(NetworkPacket* pkt);
220 void handleCommand_HudSetSky(NetworkPacket* pkt);
221 void handleCommand_HudSetSun(NetworkPacket* pkt);
222 void handleCommand_HudSetMoon(NetworkPacket* pkt);
223 void handleCommand_HudSetStars(NetworkPacket* pkt);
224 void handleCommand_CloudParams(NetworkPacket* pkt);
225 void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
226 void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
227 void handleCommand_EyeOffset(NetworkPacket* pkt);
228 void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
229 void handleCommand_ModChannelMsg(NetworkPacket *pkt);
230 void handleCommand_ModChannelSignal(NetworkPacket *pkt);
231 void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
232 void handleCommand_FormspecPrepend(NetworkPacket *pkt);
233 void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
234 void handleCommand_PlayerSpeed(NetworkPacket *pkt);
236 void ProcessData(NetworkPacket *pkt);
238 void Send(NetworkPacket* pkt);
240 void interact(InteractAction action, const PointedThing &pointed);
242 void sendNodemetaFields(v3s16 p, const std::string &formname,
243 const StringMap &fields);
244 void sendInventoryFields(const std::string &formname,
245 const StringMap &fields);
246 void sendInventoryAction(InventoryAction *a);
247 void sendChatMessage(const std::wstring &message);
248 void clearOutChatQueue();
249 void sendChangePassword(const std::string &oldpassword,
250 const std::string &newpassword);
251 void sendDamage(u16 damage);
255 ClientEnvironment& getEnv() { return m_env; }
256 ITextureSource *tsrc() { return getTextureSource(); }
257 ISoundManager *sound() { return getSoundManager(); }
258 static const std::string &getBuiltinLuaPath();
259 static const std::string &getClientModsLuaPath();
261 const std::vector<ModSpec> &getMods() const override;
262 const ModSpec* getModSpec(const std::string &modname) const override;
264 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
265 void removeNode(v3s16 p);
267 // helpers to enforce CSM restrictions
268 MapNode CSMGetNode(v3s16 p, bool *is_valid_position);
269 int CSMClampRadius(v3s16 pos, int radius);
270 v3s16 CSMClampPos(v3s16 pos);
272 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
274 void setPlayerControl(PlayerControl &control);
276 // Returns true if the inventory of the local player has been
277 // updated from the server. If it is true, it is set to false.
278 bool updateWieldedItem();
280 /* InventoryManager interface */
281 Inventory* getInventory(const InventoryLocation &loc) override;
282 void inventoryAction(InventoryAction *a) override;
284 // Send the item number 'item' as player item to the server
285 void setPlayerItem(u16 item);
287 const std::list<std::string> &getConnectedPlayerNames()
289 return m_env.getPlayerNames();
292 float getAnimationTime();
296 void setCrack(int level, v3s16 pos);
300 bool checkPrivilege(const std::string &priv) const
301 { return (m_privileges.count(priv) != 0); }
303 const std::unordered_set<std::string> &getPrivilegeList() const
304 { return m_privileges; }
306 bool getChatMessage(std::wstring &message);
307 void typeChatMessage(const std::wstring& message);
309 u64 getMapSeed(){ return m_map_seed; }
311 void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
312 // Including blocks at appropriate edges
313 void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
314 void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
316 void updateCameraOffset(v3s16 camera_offset)
317 { m_mesh_update_thread.m_camera_offset = camera_offset; }
319 bool hasClientEvents() const { return !m_client_event_queue.empty(); }
320 // Get event from queue. If queue is empty, it triggers an assertion failure.
321 ClientEvent * getClientEvent();
323 bool accessDenied() const { return m_access_denied; }
325 bool reconnectRequested() const { return m_access_denied_reconnect; }
327 void setFatalError(const std::string &reason)
329 m_access_denied = true;
330 m_access_denied_reason = reason;
333 // Renaming accessDeniedReason to better name could be good as it's used to
334 // disconnect client when CSM failed.
335 const std::string &accessDeniedReason() const { return m_access_denied_reason; }
337 const bool itemdefReceived() const
338 { return m_itemdef_received; }
339 const bool nodedefReceived() const
340 { return m_nodedef_received; }
341 const bool mediaReceived() const
342 { return !m_media_downloader; }
343 const bool activeObjectsReceived() const
344 { return m_activeobjects_received; }
346 u16 getProtoVersion()
347 { return m_proto_ver; }
349 bool connectedToServer();
350 void confirmRegistration();
351 bool m_is_registration_confirmation_state = false;
352 bool m_simple_singleplayer_mode;
354 float mediaReceiveProgress();
356 void afterContentReceived();
361 Minimap* getMinimap() { return m_minimap; }
362 void setCamera(Camera* camera) { m_camera = camera; }
364 Camera* getCamera () { return m_camera; }
366 bool shouldShowMinimap() const;
368 // IGameDef interface
369 IItemDefManager* getItemDefManager() override;
370 const NodeDefManager* getNodeDefManager() override;
371 ICraftDefManager* getCraftDefManager() override;
372 ITextureSource* getTextureSource();
373 virtual IWritableShaderSource* getShaderSource();
374 u16 allocateUnknownNodeId(const std::string &name) override;
375 virtual ISoundManager* getSoundManager();
376 MtEventManager* getEventManager();
377 virtual ParticleManager* getParticleManager();
378 bool checkLocalPrivilege(const std::string &priv)
379 { return checkPrivilege(priv); }
380 virtual scene::IAnimatedMesh* getMesh(const std::string &filename, bool cache = false);
381 const std::string* getModFile(std::string filename);
383 std::string getModStoragePath() const override;
384 bool registerModStorage(ModMetadata *meta) override;
385 void unregisterModStorage(const std::string &name) override;
387 // The following set of functions is used by ClientMediaDownloader
388 // Insert a media file appropriately into the appropriate manager
389 bool loadMedia(const std::string &data, const std::string &filename);
390 // Send a request for conventional media transfer
391 void request_media(const std::vector<std::string> &file_requests);
393 LocalClientState getState() { return m_state; }
395 void makeScreenshot();
397 inline void pushToChatQueue(ChatMessage *cec)
399 m_chat_queue.push(cec);
402 ClientScripting *getScript() { return m_script; }
403 const bool modsLoaded() const { return m_mods_loaded; }
405 void pushToEventQueue(ClientEvent *event);
407 void showMinimap(bool show = true);
409 const Address getServerAddress();
411 const std::string &getAddressName() const
413 return m_address_name;
416 inline u64 getCSMRestrictionFlags() const
418 return m_csm_restriction_flags;
421 inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const
423 return m_csm_restriction_flags & flag;
426 u32 getCSMNodeRangeLimit() const
428 return m_csm_restriction_noderange;
431 inline std::unordered_map<u32, u32> &getHUDTranslationMap()
433 return m_hud_server_to_client;
436 bool joinModChannel(const std::string &channel) override;
437 bool leaveModChannel(const std::string &channel) override;
438 bool sendModChannelMessage(const std::string &channel,
439 const std::string &message) override;
440 ModChannel *getModChannel(const std::string &channel) override;
442 const std::string &getFormspecPrepend() const
444 return m_env.getLocalPlayer()->formspec_prepend;
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);
460 void sendPlayerPos();
462 void deleteAuthData();
463 // helper method shared with clientpackethandler
464 static AuthMechanism choseAuthMech(const u32 mechs);
466 void sendInit(const std::string &playerName);
467 void promptConfirmRegistration(AuthMechanism chosen_auth_mechanism);
468 void startAuth(AuthMechanism chosen_auth_mechanism);
469 void sendDeletedBlocks(std::vector<v3s16> &blocks);
470 void sendGotBlocks(const std::vector<v3s16> &blocks);
471 void sendRemovedSounds(std::vector<s32> &soundList);
474 inline std::string getPlayerName()
475 { return m_env.getLocalPlayer()->getName(); }
477 bool canSendChatMessage() const;
479 float m_packetcounter_timer = 0.0f;
480 float m_connection_reinit_timer = 0.1f;
481 float m_avg_rtt_timer = 0.0f;
482 float m_playerpos_send_timer = 0.0f;
483 IntervalLimiter m_map_timer_and_unload_interval;
485 IWritableTextureSource *m_tsrc;
486 IWritableShaderSource *m_shsrc;
487 IWritableItemDefManager *m_itemdef;
488 NodeDefManager *m_nodedef;
489 ISoundManager *m_sound;
490 MtEventManager *m_event;
493 MeshUpdateThread m_mesh_update_thread;
494 ClientEnvironment m_env;
495 ParticleManager m_particle_manager;
496 std::unique_ptr<con::Connection> m_con;
497 std::string m_address_name;
498 Camera *m_camera = nullptr;
499 Minimap *m_minimap = nullptr;
500 bool m_minimap_disabled_by_server = false;
501 // Server serialization version
504 // Used version of the protocol with server
505 // Values smaller than 25 only mean they are smaller than 25,
506 // and aren't accurate. We simply just don't know, because
507 // the server didn't send the version back then.
508 // If 0, server init hasn't been received yet.
511 bool m_update_wielded_item = false;
512 Inventory *m_inventory_from_server = nullptr;
513 float m_inventory_from_server_age = 0.0f;
514 PacketCounter m_packetcounter;
515 // Block mesh animation parameters
516 float m_animation_time = 0.0f;
517 int m_crack_level = -1;
519 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
521 //u32 m_daynight_ratio;
522 std::queue<std::wstring> m_out_chat_queue;
523 u32 m_last_chat_message_sent;
524 float m_chat_message_allowance = 5.0f;
525 std::queue<ChatMessage *> m_chat_queue;
527 // The authentication methods we can use to enter sudo mode (=change password)
528 u32 m_sudo_auth_methods;
530 // The seed returned by the server in TOCLIENT_INIT is stored here
534 std::string m_playername;
535 std::string m_password;
536 // If set, this will be sent (and cleared) upon a TOCLIENT_ACCEPT_SUDO_MODE
537 std::string m_new_password;
538 // Usable by auth mechanisms.
539 AuthMechanism m_chosen_auth_mech;
540 void *m_auth_data = nullptr;
543 bool m_access_denied = false;
544 bool m_access_denied_reconnect = false;
545 std::string m_access_denied_reason = "";
546 std::queue<ClientEvent *> m_client_event_queue;
547 bool m_itemdef_received = false;
548 bool m_nodedef_received = false;
549 bool m_activeobjects_received = false;
550 bool m_mods_loaded = false;
551 ClientMediaDownloader *m_media_downloader;
553 // time_of_day speed approximation for old protocol
554 bool m_time_of_day_set = false;
555 float m_last_time_of_day_f = -1.0f;
556 float m_time_of_day_update_timer = 0.0f;
558 // An interval for generally sending object positions and stuff
559 float m_recommended_send_interval = 0.1f;
562 float m_removed_sounds_check_timer = 0.0f;
563 // Mapping from server sound ids to our sound ids
564 std::unordered_map<s32, int> m_sounds_server_to_client;
565 // And the other way!
566 std::unordered_map<int, s32> m_sounds_client_to_server;
567 // Relation of client id to object id
568 std::unordered_map<int, u16> m_sounds_to_objects;
570 // Map server hud ids to client hud ids
571 std::unordered_map<u32, u32> m_hud_server_to_client;
574 std::unordered_set<std::string> m_privileges;
576 // Detached inventories
578 std::unordered_map<std::string, Inventory*> m_detached_inventories;
580 // Storage for mesh data for creating multiple instances of the same mesh
581 StringMap m_mesh_data;
584 LocalClientState m_state;
588 // Used for saving server map to disk client-side
589 MapDatabase *m_localdb = nullptr;
590 IntervalLimiter m_localdb_save_interval;
591 u16 m_cache_save_interval;
594 ClientScripting *m_script = nullptr;
595 bool m_modding_enabled;
596 std::unordered_map<std::string, ModMetadata *> m_mod_storages;
597 float m_mod_storage_save_timer = 10.0f;
598 std::vector<ModSpec> m_mods;
601 bool m_shutdown = false;
603 // CSM restrictions byteflag
604 u64 m_csm_restriction_flags = CSMRestrictionFlags::CSM_RF_NONE;
605 u32 m_csm_restriction_noderange = 8;
607 std::unique_ptr<ModChannelMgr> m_modchannel_mgr;