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 "network/connection.h"
23 #include "clientenvironment.h"
24 #include "irrlichttypes_extrabloated.h"
29 #include <unordered_set>
30 #include "clientobject.h"
32 #include "inventorymanager.h"
33 #include "localplayer.h"
35 #include "particles.h"
37 #include "tileanimation.h"
38 #include "mesh_generator_thread.h"
41 #define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f
46 class IWritableTextureSource;
47 class IWritableShaderSource;
48 class IWritableItemDefManager;
49 class IWritableNodeDefManager;
50 //class IWritableCraftDefManager;
51 class ClientMediaDownloader;
52 struct MapDrawControl;
57 struct MinimapMapblock;
61 enum LocalClientState {
74 CE_SHOW_LOCAL_FORMSPEC,
76 CE_ADD_PARTICLESPAWNER,
77 CE_DELETE_PARTICLESPAWNER,
82 CE_OVERRIDE_DAY_NIGHT_RATIO,
100 bool set_camera_point_target;
101 f32 camera_point_target_x;
102 f32 camera_point_target_y;
103 f32 camera_point_target_z;
106 std::string *formspec;
107 std::string *formname;
110 //} textures_updated;
117 bool collisiondetection;
118 bool collision_removal;
120 std::string *texture;
121 struct TileAnimationParams animation;
137 bool collisiondetection;
138 bool collision_removal;
141 std::string *texture;
143 struct TileAnimationParams animation;
145 } add_particlespawner;
148 } delete_particlespawner;
177 video::SColor *bgcolor;
179 std::vector<std::string> *params;
185 } override_day_night_ratio;
205 PacketCounter() = default;
207 void add(u16 command)
209 std::map<u16, u16>::iterator n = m_packets.find(command);
210 if(n == m_packets.end())
212 m_packets[command] = 1;
222 for (auto &m_packet : m_packets) {
227 void print(std::ostream &o)
229 for (const auto &m_packet : m_packets) {
230 o << "cmd "<< m_packet.first <<" count "<< m_packet.second << std::endl;
236 std::map<u16, u16> m_packets;
239 class ClientScripting;
242 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
246 NOTE: Nothing is thread-safe here.
250 const char *playername,
251 const std::string &password,
252 const std::string &address_name,
253 MapDrawControl &control,
254 IWritableTextureSource *tsrc,
255 IWritableShaderSource *shsrc,
256 IWritableItemDefManager *itemdef,
257 IWritableNodeDefManager *nodedef,
258 ISoundManager *sound,
259 MtEventManager *event,
261 GameUIFlags *game_ui_flags
265 DISABLE_CLASS_COPY(Client);
267 // Load local mods into memory
269 void scanModSubfolder(const std::string &mod_name, const std::string &mod_path,
270 std::string mod_subpath);
271 inline void scanModIntoMemory(const std::string &mod_name, const std::string &mod_path)
273 scanModSubfolder(mod_name, mod_path, "");
280 request all threads managed by client to be stopped
288 The name of the local player should already be set when
289 calling this, as it is sent in the initialization.
291 void connect(Address address, bool is_local_server);
294 Stuff that references the environment is valid only as
295 long as this is not called. (eg. Players)
296 If this throws a PeerNotFoundException, the connection has
299 void step(float dtime);
305 void handleCommand(NetworkPacket* pkt);
307 void handleCommand_Null(NetworkPacket* pkt) {};
308 void handleCommand_Deprecated(NetworkPacket* pkt);
309 void handleCommand_Hello(NetworkPacket* pkt);
310 void handleCommand_AuthAccept(NetworkPacket* pkt);
311 void handleCommand_AcceptSudoMode(NetworkPacket* pkt);
312 void handleCommand_DenySudoMode(NetworkPacket* pkt);
313 void handleCommand_InitLegacy(NetworkPacket* pkt);
314 void handleCommand_AccessDenied(NetworkPacket* pkt);
315 void handleCommand_RemoveNode(NetworkPacket* pkt);
316 void handleCommand_AddNode(NetworkPacket* pkt);
317 void handleCommand_BlockData(NetworkPacket* pkt);
318 void handleCommand_Inventory(NetworkPacket* pkt);
319 void handleCommand_TimeOfDay(NetworkPacket* pkt);
320 void handleCommand_ChatMessageOld(NetworkPacket *pkt);
321 void handleCommand_ChatMessage(NetworkPacket *pkt);
322 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
323 void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
324 void handleCommand_Movement(NetworkPacket* pkt);
325 void handleCommand_HP(NetworkPacket* pkt);
326 void handleCommand_Breath(NetworkPacket* pkt);
327 void handleCommand_MovePlayer(NetworkPacket* pkt);
328 void handleCommand_DeathScreen(NetworkPacket* pkt);
329 void handleCommand_AnnounceMedia(NetworkPacket* pkt);
330 void handleCommand_Media(NetworkPacket* pkt);
331 void handleCommand_NodeDef(NetworkPacket* pkt);
332 void handleCommand_ItemDef(NetworkPacket* pkt);
333 void handleCommand_PlaySound(NetworkPacket* pkt);
334 void handleCommand_StopSound(NetworkPacket* pkt);
335 void handleCommand_FadeSound(NetworkPacket *pkt);
336 void handleCommand_Privileges(NetworkPacket* pkt);
337 void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
338 void handleCommand_DetachedInventory(NetworkPacket* pkt);
339 void handleCommand_ShowFormSpec(NetworkPacket* pkt);
340 void handleCommand_SpawnParticle(NetworkPacket* pkt);
341 void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
342 void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
343 void handleCommand_HudAdd(NetworkPacket* pkt);
344 void handleCommand_HudRemove(NetworkPacket* pkt);
345 void handleCommand_HudChange(NetworkPacket* pkt);
346 void handleCommand_HudSetFlags(NetworkPacket* pkt);
347 void handleCommand_HudSetParam(NetworkPacket* pkt);
348 void handleCommand_HudSetSky(NetworkPacket* pkt);
349 void handleCommand_CloudParams(NetworkPacket* pkt);
350 void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
351 void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
352 void handleCommand_EyeOffset(NetworkPacket* pkt);
353 void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
354 void handleCommand_SrpBytesSandB(NetworkPacket* pkt);
355 void handleCommand_CSMFlavourLimits(NetworkPacket *pkt);
357 void ProcessData(NetworkPacket *pkt);
359 void Send(NetworkPacket* pkt);
361 void interact(u8 action, const PointedThing& pointed);
363 void sendNodemetaFields(v3s16 p, const std::string &formname,
364 const StringMap &fields);
365 void sendInventoryFields(const std::string &formname,
366 const StringMap &fields);
367 void sendInventoryAction(InventoryAction *a);
368 void sendChatMessage(const std::wstring &message);
369 void clearOutChatQueue();
370 void sendChangePassword(const std::string &oldpassword,
371 const std::string &newpassword);
372 void sendDamage(u8 damage);
373 void sendBreath(u16 breath);
377 ClientEnvironment& getEnv() { return m_env; }
378 ITextureSource *tsrc() { return getTextureSource(); }
379 ISoundManager *sound() { return getSoundManager(); }
380 static const std::string &getBuiltinLuaPath();
381 static const std::string &getClientModsLuaPath();
383 virtual const std::vector<ModSpec> &getMods() const;
384 virtual const ModSpec* getModSpec(const std::string &modname) const;
386 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
387 void removeNode(v3s16 p);
390 * Helper function for Client Side Modding
391 * Flavour is applied there, this should not be used for core engine
393 * @param is_valid_position
396 MapNode getNode(v3s16 p, bool *is_valid_position);
397 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
399 void setPlayerControl(PlayerControl &control);
401 void selectPlayerItem(u16 item);
402 u16 getPlayerItem() const
403 { return m_playeritem; }
405 // Returns true if the inventory of the local player has been
406 // updated from the server. If it is true, it is set to false.
407 bool getLocalInventoryUpdated();
408 // Copies the inventory of the local player to parameter
409 void getLocalInventory(Inventory &dst);
411 /* InventoryManager interface */
412 Inventory* getInventory(const InventoryLocation &loc);
413 void inventoryAction(InventoryAction *a);
415 const std::list<std::string> &getConnectedPlayerNames()
417 return m_env.getPlayerNames();
420 float getAnimationTime();
424 void setCrack(int level, v3s16 pos);
428 bool checkPrivilege(const std::string &priv) const
429 { return (m_privileges.count(priv) != 0); }
431 const std::unordered_set<std::string> &getPrivilegeList() const
432 { return m_privileges; }
434 bool getChatMessage(std::wstring &message);
435 void typeChatMessage(const std::wstring& message);
437 u64 getMapSeed(){ return m_map_seed; }
439 void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
440 // Including blocks at appropriate edges
441 void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
442 void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
444 void updateCameraOffset(v3s16 camera_offset)
445 { m_mesh_update_thread.m_camera_offset = camera_offset; }
447 bool hasClientEvents() const { return !m_client_event_queue.empty(); }
448 // Get event from queue. If queue is empty, it triggers an assertion failure.
449 ClientEvent getClientEvent();
451 bool accessDenied() const { return m_access_denied; }
453 bool reconnectRequested() const { return m_access_denied_reconnect; }
455 void setFatalError(const std::string &reason)
457 m_access_denied = true;
458 m_access_denied_reason = reason;
461 // Renaming accessDeniedReason to better name could be good as it's used to
462 // disconnect client when CSM failed.
463 const std::string &accessDeniedReason() const { return m_access_denied_reason; }
465 bool itemdefReceived()
466 { return m_itemdef_received; }
467 bool nodedefReceived()
468 { return m_nodedef_received; }
470 { return !m_media_downloader; }
473 { return m_proto_ver; }
475 bool connectedToServer()
476 { return m_con.Connected(); }
478 float mediaReceiveProgress();
480 void afterContentReceived();
485 Minimap* getMinimap() { return m_minimap; }
486 void setCamera(Camera* camera) { m_camera = camera; }
488 Camera* getCamera () { return m_camera; }
490 bool shouldShowMinimap() const;
492 // IGameDef interface
493 virtual IItemDefManager* getItemDefManager();
494 virtual INodeDefManager* getNodeDefManager();
495 virtual ICraftDefManager* getCraftDefManager();
496 ITextureSource* getTextureSource();
497 virtual IShaderSource* getShaderSource();
498 IShaderSource *shsrc() { return getShaderSource(); }
499 virtual u16 allocateUnknownNodeId(const std::string &name);
500 virtual ISoundManager* getSoundManager();
501 virtual MtEventManager* getEventManager();
502 virtual ParticleManager* getParticleManager();
503 bool checkLocalPrivilege(const std::string &priv)
504 { return checkPrivilege(priv); }
505 virtual scene::IAnimatedMesh* getMesh(const std::string &filename);
506 const std::string* getModFile(const std::string &filename);
508 virtual std::string getModStoragePath() const;
509 virtual bool registerModStorage(ModMetadata *meta);
510 virtual void unregisterModStorage(const std::string &name);
512 // The following set of functions is used by ClientMediaDownloader
513 // Insert a media file appropriately into the appropriate manager
514 bool loadMedia(const std::string &data, const std::string &filename);
515 // Send a request for conventional media transfer
516 void request_media(const std::vector<std::string> &file_requests);
518 LocalClientState getState() { return m_state; }
520 void makeScreenshot();
522 inline void pushToChatQueue(ChatMessage *cec)
524 m_chat_queue.push(cec);
527 ClientScripting *getScript() { return m_script; }
528 const bool moddingEnabled() const { return m_modding_enabled; }
530 inline void pushToEventQueue(const ClientEvent &event)
532 m_client_event_queue.push(event);
535 void showGameChat(bool show = true);
536 void showGameHud(bool show = true);
537 void showMinimap(bool show = true);
538 void showProfiler(bool show = true);
539 void showGameFog(bool show = true);
540 void showGameDebug(bool show = true);
542 const Address getServerAddress()
544 return m_con.GetPeerAddress(PEER_ID_SERVER);
547 const std::string &getAddressName() const
549 return m_address_name;
552 inline bool checkCSMFlavourLimit(CSMFlavourLimit flag) const
554 return m_csm_flavour_limits & flag;
557 u32 getCSMNodeRangeLimit() const
559 return m_csm_noderange_limit;
564 // Virtual methods from con::PeerHandler
565 void peerAdded(con::Peer *peer);
566 void deletingPeer(con::Peer *peer, bool timeout);
568 void initLocalMapSaving(const Address &address,
569 const std::string &hostname,
570 bool is_local_server);
575 void sendPlayerPos();
576 // Send the item number 'item' as player item to the server
577 void sendPlayerItem(u16 item);
579 void deleteAuthData();
580 // helper method shared with clientpackethandler
581 static AuthMechanism choseAuthMech(const u32 mechs);
583 void sendLegacyInit(const char* playerName, const char* playerPassword);
584 void sendInit(const std::string &playerName);
585 void startAuth(AuthMechanism chosen_auth_mechanism);
586 void sendDeletedBlocks(std::vector<v3s16> &blocks);
587 void sendGotBlocks(v3s16 block);
588 void sendRemovedSounds(std::vector<s32> &soundList);
591 inline std::string getPlayerName()
592 { return m_env.getLocalPlayer()->getName(); }
594 bool canSendChatMessage() const;
596 float m_packetcounter_timer = 0.0f;
597 float m_connection_reinit_timer = 0.1f;
598 float m_avg_rtt_timer = 0.0f;
599 float m_playerpos_send_timer = 0.0f;
600 float m_ignore_damage_timer = 0.0f; // Used after server moves player
601 IntervalLimiter m_map_timer_and_unload_interval;
603 IWritableTextureSource *m_tsrc;
604 IWritableShaderSource *m_shsrc;
605 IWritableItemDefManager *m_itemdef;
606 IWritableNodeDefManager *m_nodedef;
607 ISoundManager *m_sound;
608 MtEventManager *m_event;
611 MeshUpdateThread m_mesh_update_thread;
612 ClientEnvironment m_env;
613 ParticleManager m_particle_manager;
614 con::Connection m_con;
615 std::string m_address_name;
616 Camera *m_camera = nullptr;
617 Minimap *m_minimap = nullptr;
618 bool m_minimap_disabled_by_server = false;
619 // Server serialization version
622 // Used version of the protocol with server
623 // Values smaller than 25 only mean they are smaller than 25,
624 // and aren't accurate. We simply just don't know, because
625 // the server didn't send the version back then.
626 // If 0, server init hasn't been received yet.
629 u16 m_playeritem = 0;
630 bool m_inventory_updated = false;
631 Inventory *m_inventory_from_server = nullptr;
632 float m_inventory_from_server_age = 0.0f;
633 PacketCounter m_packetcounter;
634 // Block mesh animation parameters
635 float m_animation_time = 0.0f;
636 int m_crack_level = -1;
638 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
640 //u32 m_daynight_ratio;
641 std::queue<std::wstring> m_out_chat_queue;
642 u32 m_last_chat_message_sent;
643 float m_chat_message_allowance = 5.0f;
644 std::queue<ChatMessage *> m_chat_queue;
646 // The authentication methods we can use to enter sudo mode (=change password)
647 u32 m_sudo_auth_methods;
649 // The seed returned by the server in TOCLIENT_INIT is stored here
653 std::string m_playername;
654 std::string m_password;
655 // If set, this will be sent (and cleared) upon a TOCLIENT_ACCEPT_SUDO_MODE
656 std::string m_new_password;
657 // Usable by auth mechanisms.
658 AuthMechanism m_chosen_auth_mech;
659 void *m_auth_data = nullptr;
662 bool m_access_denied = false;
663 bool m_access_denied_reconnect = false;
664 std::string m_access_denied_reason = "";
665 std::queue<ClientEvent> m_client_event_queue;
666 bool m_itemdef_received = false;
667 bool m_nodedef_received = false;
668 ClientMediaDownloader *m_media_downloader;
670 // time_of_day speed approximation for old protocol
671 bool m_time_of_day_set = false;
672 float m_last_time_of_day_f = -1.0f;
673 float m_time_of_day_update_timer = 0.0f;
675 // An interval for generally sending object positions and stuff
676 float m_recommended_send_interval = 0.1f;
679 float m_removed_sounds_check_timer = 0.0f;
680 // Mapping from server sound ids to our sound ids
681 std::unordered_map<s32, int> m_sounds_server_to_client;
682 // And the other way!
683 std::unordered_map<int, s32> m_sounds_client_to_server;
684 // And relations to objects
685 std::unordered_map<int, u16> m_sounds_to_objects;
688 std::unordered_set<std::string> m_privileges;
690 // Detached inventories
692 std::unordered_map<std::string, Inventory*> m_detached_inventories;
694 // Storage for mesh data for creating multiple instances of the same mesh
695 StringMap m_mesh_data;
697 StringMap m_mod_files;
700 LocalClientState m_state;
702 // Used for saving server map to disk client-side
703 MapDatabase *m_localdb = nullptr;
704 IntervalLimiter m_localdb_save_interval;
705 u16 m_cache_save_interval;
707 ClientScripting *m_script = nullptr;
708 bool m_modding_enabled;
709 std::unordered_map<std::string, ModMetadata *> m_mod_storages;
710 float m_mod_storage_save_timer = 10.0f;
711 std::vector<ModSpec> m_mods;
712 GameUIFlags *m_game_ui_flags;
714 bool m_shutdown = false;
716 // CSM flavour limits byteflag
717 u64 m_csm_flavour_limits = CSMFlavourLimit::CSM_FL_NONE;
718 u32 m_csm_noderange_limit = 8;