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"
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;
51 class IWritableNodeDefManager;
52 //class IWritableCraftDefManager;
53 class ClientMediaDownloader;
54 struct MapDrawControl;
59 struct MinimapMapblock;
66 enum LocalClientState {
79 PacketCounter() = default;
83 std::map<u16, u16>::iterator n = m_packets.find(command);
84 if(n == m_packets.end())
86 m_packets[command] = 1;
96 for (auto &m_packet : m_packets) {
101 void print(std::ostream &o)
103 for (const auto &m_packet : m_packets) {
104 o << "cmd "<< m_packet.first <<" count "<< m_packet.second << std::endl;
110 std::map<u16, u16> m_packets;
113 class ClientScripting;
116 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
120 NOTE: Nothing is thread-safe here.
124 const char *playername,
125 const std::string &password,
126 const std::string &address_name,
127 MapDrawControl &control,
128 IWritableTextureSource *tsrc,
129 IWritableShaderSource *shsrc,
130 IWritableItemDefManager *itemdef,
131 IWritableNodeDefManager *nodedef,
132 ISoundManager *sound,
133 MtEventManager *event,
135 GameUIFlags *game_ui_flags
139 DISABLE_CLASS_COPY(Client);
141 // Load local mods into memory
143 void scanModSubfolder(const std::string &mod_name, const std::string &mod_path,
144 std::string mod_subpath);
145 inline void scanModIntoMemory(const std::string &mod_name, const std::string &mod_path)
147 scanModSubfolder(mod_name, mod_path, "");
154 request all threads managed by client to be stopped
162 The name of the local player should already be set when
163 calling this, as it is sent in the initialization.
165 void connect(Address address, bool is_local_server);
168 Stuff that references the environment is valid only as
169 long as this is not called. (eg. Players)
170 If this throws a PeerNotFoundException, the connection has
173 void step(float dtime);
179 void handleCommand(NetworkPacket* pkt);
181 void handleCommand_Null(NetworkPacket* pkt) {};
182 void handleCommand_Deprecated(NetworkPacket* pkt);
183 void handleCommand_Hello(NetworkPacket* pkt);
184 void handleCommand_AuthAccept(NetworkPacket* pkt);
185 void handleCommand_AcceptSudoMode(NetworkPacket* pkt);
186 void handleCommand_DenySudoMode(NetworkPacket* pkt);
187 void handleCommand_AccessDenied(NetworkPacket* pkt);
188 void handleCommand_RemoveNode(NetworkPacket* pkt);
189 void handleCommand_AddNode(NetworkPacket* pkt);
190 void handleCommand_BlockData(NetworkPacket* pkt);
191 void handleCommand_Inventory(NetworkPacket* pkt);
192 void handleCommand_TimeOfDay(NetworkPacket* pkt);
193 void handleCommand_ChatMessageOld(NetworkPacket *pkt);
194 void handleCommand_ChatMessage(NetworkPacket *pkt);
195 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
196 void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
197 void handleCommand_Movement(NetworkPacket* pkt);
198 void handleCommand_HP(NetworkPacket* pkt);
199 void handleCommand_Breath(NetworkPacket* pkt);
200 void handleCommand_MovePlayer(NetworkPacket* pkt);
201 void handleCommand_DeathScreen(NetworkPacket* pkt);
202 void handleCommand_AnnounceMedia(NetworkPacket* pkt);
203 void handleCommand_Media(NetworkPacket* pkt);
204 void handleCommand_NodeDef(NetworkPacket* pkt);
205 void handleCommand_ItemDef(NetworkPacket* pkt);
206 void handleCommand_PlaySound(NetworkPacket* pkt);
207 void handleCommand_StopSound(NetworkPacket* pkt);
208 void handleCommand_FadeSound(NetworkPacket *pkt);
209 void handleCommand_Privileges(NetworkPacket* pkt);
210 void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
211 void handleCommand_DetachedInventory(NetworkPacket* pkt);
212 void handleCommand_ShowFormSpec(NetworkPacket* pkt);
213 void handleCommand_SpawnParticle(NetworkPacket* pkt);
214 void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
215 void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
216 void handleCommand_HudAdd(NetworkPacket* pkt);
217 void handleCommand_HudRemove(NetworkPacket* pkt);
218 void handleCommand_HudChange(NetworkPacket* pkt);
219 void handleCommand_HudSetFlags(NetworkPacket* pkt);
220 void handleCommand_HudSetParam(NetworkPacket* pkt);
221 void handleCommand_HudSetSky(NetworkPacket* pkt);
222 void handleCommand_CloudParams(NetworkPacket* pkt);
223 void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
224 void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
225 void handleCommand_EyeOffset(NetworkPacket* pkt);
226 void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
227 void handleCommand_SrpBytesSandB(NetworkPacket* pkt);
228 void handleCommand_CSMFlavourLimits(NetworkPacket *pkt);
230 void ProcessData(NetworkPacket *pkt);
232 void Send(NetworkPacket* pkt);
234 void interact(u8 action, const PointedThing& pointed);
236 void sendNodemetaFields(v3s16 p, const std::string &formname,
237 const StringMap &fields);
238 void sendInventoryFields(const std::string &formname,
239 const StringMap &fields);
240 void sendInventoryAction(InventoryAction *a);
241 void sendChatMessage(const std::wstring &message);
242 void clearOutChatQueue();
243 void sendChangePassword(const std::string &oldpassword,
244 const std::string &newpassword);
245 void sendDamage(u8 damage);
249 ClientEnvironment& getEnv() { return m_env; }
250 ITextureSource *tsrc() { return getTextureSource(); }
251 ISoundManager *sound() { return getSoundManager(); }
252 static const std::string &getBuiltinLuaPath();
253 static const std::string &getClientModsLuaPath();
255 virtual const std::vector<ModSpec> &getMods() const;
256 virtual const ModSpec* getModSpec(const std::string &modname) const;
258 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
259 void removeNode(v3s16 p);
262 * Helper function for Client Side Modding
263 * Flavour is applied there, this should not be used for core engine
265 * @param is_valid_position
268 MapNode getNode(v3s16 p, bool *is_valid_position);
269 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
271 void setPlayerControl(PlayerControl &control);
273 void selectPlayerItem(u16 item);
274 u16 getPlayerItem() const
275 { return m_playeritem; }
277 // Returns true if the inventory of the local player has been
278 // updated from the server. If it is true, it is set to false.
279 bool getLocalInventoryUpdated();
280 // Copies the inventory of the local player to parameter
281 void getLocalInventory(Inventory &dst);
283 /* InventoryManager interface */
284 Inventory* getInventory(const InventoryLocation &loc);
285 void inventoryAction(InventoryAction *a);
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 bool itemdefReceived()
338 { return m_itemdef_received; }
339 bool nodedefReceived()
340 { return m_nodedef_received; }
342 { return !m_media_downloader; }
345 { return m_proto_ver; }
347 bool connectedToServer();
349 float mediaReceiveProgress();
351 void afterContentReceived();
356 Minimap* getMinimap() { return m_minimap; }
357 void setCamera(Camera* camera) { m_camera = camera; }
359 Camera* getCamera () { return m_camera; }
361 bool shouldShowMinimap() const;
363 // IGameDef interface
364 virtual IItemDefManager* getItemDefManager();
365 virtual INodeDefManager* getNodeDefManager();
366 virtual ICraftDefManager* getCraftDefManager();
367 ITextureSource* getTextureSource();
368 virtual IShaderSource* getShaderSource();
369 IShaderSource *shsrc() { return getShaderSource(); }
370 virtual u16 allocateUnknownNodeId(const std::string &name);
371 virtual ISoundManager* getSoundManager();
372 virtual MtEventManager* getEventManager();
373 virtual ParticleManager* getParticleManager();
374 bool checkLocalPrivilege(const std::string &priv)
375 { return checkPrivilege(priv); }
376 virtual scene::IAnimatedMesh* getMesh(const std::string &filename);
377 const std::string* getModFile(const std::string &filename);
379 virtual std::string getModStoragePath() const;
380 virtual bool registerModStorage(ModMetadata *meta);
381 virtual void unregisterModStorage(const std::string &name);
383 // The following set of functions is used by ClientMediaDownloader
384 // Insert a media file appropriately into the appropriate manager
385 bool loadMedia(const std::string &data, const std::string &filename);
386 // Send a request for conventional media transfer
387 void request_media(const std::vector<std::string> &file_requests);
389 LocalClientState getState() { return m_state; }
391 void makeScreenshot();
393 inline void pushToChatQueue(ChatMessage *cec)
395 m_chat_queue.push(cec);
398 ClientScripting *getScript() { return m_script; }
399 const bool moddingEnabled() const { return m_modding_enabled; }
401 void pushToEventQueue(ClientEvent *event);
403 void showGameChat(bool show = true);
404 void showGameHud(bool show = true);
405 void showMinimap(bool show = true);
406 void showProfiler(bool show = true);
407 void showGameFog(bool show = true);
408 void showGameDebug(bool show = true);
410 const Address getServerAddress();
412 const std::string &getAddressName() const
414 return m_address_name;
417 inline bool checkCSMFlavourLimit(CSMFlavourLimit flag) const
419 return m_csm_flavour_limits & flag;
422 u32 getCSMNodeRangeLimit() const
424 return m_csm_noderange_limit;
429 // Virtual methods from con::PeerHandler
430 void peerAdded(con::Peer *peer);
431 void deletingPeer(con::Peer *peer, bool timeout);
433 void initLocalMapSaving(const Address &address,
434 const std::string &hostname,
435 bool is_local_server);
440 void sendPlayerPos();
441 // Send the item number 'item' as player item to the server
442 void sendPlayerItem(u16 item);
444 void deleteAuthData();
445 // helper method shared with clientpackethandler
446 static AuthMechanism choseAuthMech(const u32 mechs);
448 void sendInit(const std::string &playerName);
449 void startAuth(AuthMechanism chosen_auth_mechanism);
450 void sendDeletedBlocks(std::vector<v3s16> &blocks);
451 void sendGotBlocks(v3s16 block);
452 void sendRemovedSounds(std::vector<s32> &soundList);
455 inline std::string getPlayerName()
456 { return m_env.getLocalPlayer()->getName(); }
458 bool canSendChatMessage() const;
460 float m_packetcounter_timer = 0.0f;
461 float m_connection_reinit_timer = 0.1f;
462 float m_avg_rtt_timer = 0.0f;
463 float m_playerpos_send_timer = 0.0f;
464 float m_ignore_damage_timer = 0.0f; // Used after server moves player
465 IntervalLimiter m_map_timer_and_unload_interval;
467 IWritableTextureSource *m_tsrc;
468 IWritableShaderSource *m_shsrc;
469 IWritableItemDefManager *m_itemdef;
470 IWritableNodeDefManager *m_nodedef;
471 ISoundManager *m_sound;
472 MtEventManager *m_event;
475 MeshUpdateThread m_mesh_update_thread;
476 ClientEnvironment m_env;
477 ParticleManager m_particle_manager;
478 std::unique_ptr<con::Connection> m_con;
479 std::string m_address_name;
480 Camera *m_camera = nullptr;
481 Minimap *m_minimap = nullptr;
482 bool m_minimap_disabled_by_server = false;
483 // Server serialization version
486 // Used version of the protocol with server
487 // Values smaller than 25 only mean they are smaller than 25,
488 // and aren't accurate. We simply just don't know, because
489 // the server didn't send the version back then.
490 // If 0, server init hasn't been received yet.
493 u16 m_playeritem = 0;
494 bool m_inventory_updated = false;
495 Inventory *m_inventory_from_server = nullptr;
496 float m_inventory_from_server_age = 0.0f;
497 PacketCounter m_packetcounter;
498 // Block mesh animation parameters
499 float m_animation_time = 0.0f;
500 int m_crack_level = -1;
502 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
504 //u32 m_daynight_ratio;
505 std::queue<std::wstring> m_out_chat_queue;
506 u32 m_last_chat_message_sent;
507 float m_chat_message_allowance = 5.0f;
508 std::queue<ChatMessage *> m_chat_queue;
510 // The authentication methods we can use to enter sudo mode (=change password)
511 u32 m_sudo_auth_methods;
513 // The seed returned by the server in TOCLIENT_INIT is stored here
517 std::string m_playername;
518 std::string m_password;
519 // If set, this will be sent (and cleared) upon a TOCLIENT_ACCEPT_SUDO_MODE
520 std::string m_new_password;
521 // Usable by auth mechanisms.
522 AuthMechanism m_chosen_auth_mech;
523 void *m_auth_data = nullptr;
526 bool m_access_denied = false;
527 bool m_access_denied_reconnect = false;
528 std::string m_access_denied_reason = "";
529 std::queue<ClientEvent *> m_client_event_queue;
530 bool m_itemdef_received = false;
531 bool m_nodedef_received = false;
532 ClientMediaDownloader *m_media_downloader;
534 // time_of_day speed approximation for old protocol
535 bool m_time_of_day_set = false;
536 float m_last_time_of_day_f = -1.0f;
537 float m_time_of_day_update_timer = 0.0f;
539 // An interval for generally sending object positions and stuff
540 float m_recommended_send_interval = 0.1f;
543 float m_removed_sounds_check_timer = 0.0f;
544 // Mapping from server sound ids to our sound ids
545 std::unordered_map<s32, int> m_sounds_server_to_client;
546 // And the other way!
547 std::unordered_map<int, s32> m_sounds_client_to_server;
548 // And relations to objects
549 std::unordered_map<int, u16> m_sounds_to_objects;
552 std::unordered_set<std::string> m_privileges;
554 // Detached inventories
556 std::unordered_map<std::string, Inventory*> m_detached_inventories;
558 // Storage for mesh data for creating multiple instances of the same mesh
559 StringMap m_mesh_data;
561 StringMap m_mod_files;
564 LocalClientState m_state;
566 // Used for saving server map to disk client-side
567 MapDatabase *m_localdb = nullptr;
568 IntervalLimiter m_localdb_save_interval;
569 u16 m_cache_save_interval;
571 ClientScripting *m_script = nullptr;
572 bool m_modding_enabled;
573 std::unordered_map<std::string, ModMetadata *> m_mod_storages;
574 float m_mod_storage_save_timer = 10.0f;
575 std::vector<ModSpec> m_mods;
576 GameUIFlags *m_game_ui_flags;
578 bool m_shutdown = false;
580 // CSM flavour limits byteflag
581 u64 m_csm_flavour_limits = CSMFlavourLimit::CSM_FL_NONE;
582 u32 m_csm_noderange_limit = 8;