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.
23 #include "network/connection.h"
24 #include "clientenvironment.h"
25 #include "irrlichttypes_extrabloated.h"
30 #include <unordered_set>
31 #include "clientobject.h"
33 #include "inventorymanager.h"
34 #include "localplayer.h"
36 #include "particles.h"
38 #include "tileanimation.h"
39 #include "mesh_generator_thread.h"
43 #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;
63 enum LocalClientState {
76 CE_SHOW_LOCAL_FORMSPEC,
78 CE_ADD_PARTICLESPAWNER,
79 CE_DELETE_PARTICLESPAWNER,
84 CE_OVERRIDE_DAY_NIGHT_RATIO,
102 bool set_camera_point_target;
103 f32 camera_point_target_x;
104 f32 camera_point_target_y;
105 f32 camera_point_target_z;
108 std::string *formspec;
109 std::string *formname;
112 //} textures_updated;
119 bool collisiondetection;
120 bool collision_removal;
122 std::string *texture;
123 struct TileAnimationParams animation;
139 bool collisiondetection;
140 bool collision_removal;
143 std::string *texture;
145 struct TileAnimationParams animation;
147 } add_particlespawner;
150 } delete_particlespawner;
179 video::SColor *bgcolor;
181 std::vector<std::string> *params;
187 } override_day_night_ratio;
207 PacketCounter() = default;
209 void add(u16 command)
211 std::map<u16, u16>::iterator n = m_packets.find(command);
212 if(n == m_packets.end())
214 m_packets[command] = 1;
224 for (auto &m_packet : m_packets) {
229 void print(std::ostream &o)
231 for (const auto &m_packet : m_packets) {
232 o << "cmd "<< m_packet.first <<" count "<< m_packet.second << std::endl;
238 std::map<u16, u16> m_packets;
241 class ClientScripting;
244 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
248 NOTE: Nothing is thread-safe here.
252 const char *playername,
253 const std::string &password,
254 const std::string &address_name,
255 MapDrawControl &control,
256 IWritableTextureSource *tsrc,
257 IWritableShaderSource *shsrc,
258 IWritableItemDefManager *itemdef,
259 IWritableNodeDefManager *nodedef,
260 ISoundManager *sound,
261 MtEventManager *event,
263 GameUIFlags *game_ui_flags
267 DISABLE_CLASS_COPY(Client);
269 // Load local mods into memory
271 void scanModSubfolder(const std::string &mod_name, const std::string &mod_path,
272 std::string mod_subpath);
273 inline void scanModIntoMemory(const std::string &mod_name, const std::string &mod_path)
275 scanModSubfolder(mod_name, mod_path, "");
282 request all threads managed by client to be stopped
290 The name of the local player should already be set when
291 calling this, as it is sent in the initialization.
293 void connect(Address address, bool is_local_server);
296 Stuff that references the environment is valid only as
297 long as this is not called. (eg. Players)
298 If this throws a PeerNotFoundException, the connection has
301 void step(float dtime);
307 void handleCommand(NetworkPacket* pkt);
309 void handleCommand_Null(NetworkPacket* pkt) {};
310 void handleCommand_Deprecated(NetworkPacket* pkt);
311 void handleCommand_Hello(NetworkPacket* pkt);
312 void handleCommand_AuthAccept(NetworkPacket* pkt);
313 void handleCommand_AcceptSudoMode(NetworkPacket* pkt);
314 void handleCommand_DenySudoMode(NetworkPacket* pkt);
315 void handleCommand_InitLegacy(NetworkPacket* pkt);
316 void handleCommand_AccessDenied(NetworkPacket* pkt);
317 void handleCommand_RemoveNode(NetworkPacket* pkt);
318 void handleCommand_AddNode(NetworkPacket* pkt);
319 void handleCommand_BlockData(NetworkPacket* pkt);
320 void handleCommand_Inventory(NetworkPacket* pkt);
321 void handleCommand_TimeOfDay(NetworkPacket* pkt);
322 void handleCommand_ChatMessageOld(NetworkPacket *pkt);
323 void handleCommand_ChatMessage(NetworkPacket *pkt);
324 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
325 void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
326 void handleCommand_Movement(NetworkPacket* pkt);
327 void handleCommand_HP(NetworkPacket* pkt);
328 void handleCommand_Breath(NetworkPacket* pkt);
329 void handleCommand_MovePlayer(NetworkPacket* pkt);
330 void handleCommand_DeathScreen(NetworkPacket* pkt);
331 void handleCommand_AnnounceMedia(NetworkPacket* pkt);
332 void handleCommand_Media(NetworkPacket* pkt);
333 void handleCommand_NodeDef(NetworkPacket* pkt);
334 void handleCommand_ItemDef(NetworkPacket* pkt);
335 void handleCommand_PlaySound(NetworkPacket* pkt);
336 void handleCommand_StopSound(NetworkPacket* pkt);
337 void handleCommand_FadeSound(NetworkPacket *pkt);
338 void handleCommand_Privileges(NetworkPacket* pkt);
339 void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
340 void handleCommand_DetachedInventory(NetworkPacket* pkt);
341 void handleCommand_ShowFormSpec(NetworkPacket* pkt);
342 void handleCommand_SpawnParticle(NetworkPacket* pkt);
343 void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
344 void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
345 void handleCommand_HudAdd(NetworkPacket* pkt);
346 void handleCommand_HudRemove(NetworkPacket* pkt);
347 void handleCommand_HudChange(NetworkPacket* pkt);
348 void handleCommand_HudSetFlags(NetworkPacket* pkt);
349 void handleCommand_HudSetParam(NetworkPacket* pkt);
350 void handleCommand_HudSetSky(NetworkPacket* pkt);
351 void handleCommand_CloudParams(NetworkPacket* pkt);
352 void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
353 void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
354 void handleCommand_EyeOffset(NetworkPacket* pkt);
355 void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
356 void handleCommand_SrpBytesSandB(NetworkPacket* pkt);
357 void handleCommand_CSMFlavourLimits(NetworkPacket *pkt);
359 void ProcessData(NetworkPacket *pkt);
361 void Send(NetworkPacket* pkt);
363 void interact(u8 action, const PointedThing& pointed);
365 void sendNodemetaFields(v3s16 p, const std::string &formname,
366 const StringMap &fields);
367 void sendInventoryFields(const std::string &formname,
368 const StringMap &fields);
369 void sendInventoryAction(InventoryAction *a);
370 void sendChatMessage(const std::wstring &message);
371 void clearOutChatQueue();
372 void sendChangePassword(const std::string &oldpassword,
373 const std::string &newpassword);
374 void sendDamage(u8 damage);
375 void sendBreath(u16 breath);
379 ClientEnvironment& getEnv() { return m_env; }
380 ITextureSource *tsrc() { return getTextureSource(); }
381 ISoundManager *sound() { return getSoundManager(); }
382 static const std::string &getBuiltinLuaPath();
383 static const std::string &getClientModsLuaPath();
385 virtual const std::vector<ModSpec> &getMods() const;
386 virtual const ModSpec* getModSpec(const std::string &modname) const;
388 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
389 void removeNode(v3s16 p);
392 * Helper function for Client Side Modding
393 * Flavour is applied there, this should not be used for core engine
395 * @param is_valid_position
398 MapNode getNode(v3s16 p, bool *is_valid_position);
399 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
401 void setPlayerControl(PlayerControl &control);
403 void selectPlayerItem(u16 item);
404 u16 getPlayerItem() const
405 { return m_playeritem; }
407 // Returns true if the inventory of the local player has been
408 // updated from the server. If it is true, it is set to false.
409 bool getLocalInventoryUpdated();
410 // Copies the inventory of the local player to parameter
411 void getLocalInventory(Inventory &dst);
413 /* InventoryManager interface */
414 Inventory* getInventory(const InventoryLocation &loc);
415 void inventoryAction(InventoryAction *a);
417 const std::list<std::string> &getConnectedPlayerNames()
419 return m_env.getPlayerNames();
422 float getAnimationTime();
426 void setCrack(int level, v3s16 pos);
430 bool checkPrivilege(const std::string &priv) const
431 { return (m_privileges.count(priv) != 0); }
433 const std::unordered_set<std::string> &getPrivilegeList() const
434 { return m_privileges; }
436 bool getChatMessage(std::wstring &message);
437 void typeChatMessage(const std::wstring& message);
439 u64 getMapSeed(){ return m_map_seed; }
441 void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
442 // Including blocks at appropriate edges
443 void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
444 void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
446 void updateCameraOffset(v3s16 camera_offset)
447 { m_mesh_update_thread.m_camera_offset = camera_offset; }
449 bool hasClientEvents() const { return !m_client_event_queue.empty(); }
450 // Get event from queue. If queue is empty, it triggers an assertion failure.
451 ClientEvent getClientEvent();
453 bool accessDenied() const { return m_access_denied; }
455 bool reconnectRequested() const { return m_access_denied_reconnect; }
457 void setFatalError(const std::string &reason)
459 m_access_denied = true;
460 m_access_denied_reason = reason;
463 // Renaming accessDeniedReason to better name could be good as it's used to
464 // disconnect client when CSM failed.
465 const std::string &accessDeniedReason() const { return m_access_denied_reason; }
467 bool itemdefReceived()
468 { return m_itemdef_received; }
469 bool nodedefReceived()
470 { return m_nodedef_received; }
472 { return !m_media_downloader; }
475 { return m_proto_ver; }
477 bool connectedToServer()
478 { return m_con.Connected(); }
480 float mediaReceiveProgress();
482 void afterContentReceived();
487 Minimap* getMinimap() { return m_minimap; }
488 void setCamera(Camera* camera) { m_camera = camera; }
490 Camera* getCamera () { return m_camera; }
492 bool shouldShowMinimap() const;
494 // IGameDef interface
495 virtual IItemDefManager* getItemDefManager();
496 virtual INodeDefManager* getNodeDefManager();
497 virtual ICraftDefManager* getCraftDefManager();
498 ITextureSource* getTextureSource();
499 virtual IShaderSource* getShaderSource();
500 IShaderSource *shsrc() { return getShaderSource(); }
501 virtual u16 allocateUnknownNodeId(const std::string &name);
502 virtual ISoundManager* getSoundManager();
503 virtual MtEventManager* getEventManager();
504 virtual ParticleManager* getParticleManager();
505 bool checkLocalPrivilege(const std::string &priv)
506 { return checkPrivilege(priv); }
507 virtual scene::IAnimatedMesh* getMesh(const std::string &filename);
508 const std::string* getModFile(const std::string &filename);
510 virtual std::string getModStoragePath() const;
511 virtual bool registerModStorage(ModMetadata *meta);
512 virtual void unregisterModStorage(const std::string &name);
514 // The following set of functions is used by ClientMediaDownloader
515 // Insert a media file appropriately into the appropriate manager
516 bool loadMedia(const std::string &data, const std::string &filename);
517 // Send a request for conventional media transfer
518 void request_media(const std::vector<std::string> &file_requests);
520 LocalClientState getState() { return m_state; }
522 void makeScreenshot();
524 inline void pushToChatQueue(ChatMessage *cec)
526 m_chat_queue.push(cec);
529 ClientScripting *getScript() { return m_script; }
530 const bool moddingEnabled() const { return m_modding_enabled; }
532 inline void pushToEventQueue(const ClientEvent &event)
534 m_client_event_queue.push(event);
537 void showGameChat(bool show = true);
538 void showGameHud(bool show = true);
539 void showMinimap(bool show = true);
540 void showProfiler(bool show = true);
541 void showGameFog(bool show = true);
542 void showGameDebug(bool show = true);
544 const Address getServerAddress()
546 return m_con.GetPeerAddress(PEER_ID_SERVER);
549 const std::string &getAddressName() const
551 return m_address_name;
554 inline bool checkCSMFlavourLimit(CSMFlavourLimit flag) const
556 return m_csm_flavour_limits & flag;
559 u32 getCSMNodeRangeLimit() const
561 return m_csm_noderange_limit;
566 // Virtual methods from con::PeerHandler
567 void peerAdded(con::Peer *peer);
568 void deletingPeer(con::Peer *peer, bool timeout);
570 void initLocalMapSaving(const Address &address,
571 const std::string &hostname,
572 bool is_local_server);
577 void sendPlayerPos();
578 // Send the item number 'item' as player item to the server
579 void sendPlayerItem(u16 item);
581 void deleteAuthData();
582 // helper method shared with clientpackethandler
583 static AuthMechanism choseAuthMech(const u32 mechs);
585 void sendLegacyInit(const char* playerName, const char* playerPassword);
586 void sendInit(const std::string &playerName);
587 void startAuth(AuthMechanism chosen_auth_mechanism);
588 void sendDeletedBlocks(std::vector<v3s16> &blocks);
589 void sendGotBlocks(v3s16 block);
590 void sendRemovedSounds(std::vector<s32> &soundList);
593 inline std::string getPlayerName()
594 { return m_env.getLocalPlayer()->getName(); }
596 bool canSendChatMessage() const;
598 float m_packetcounter_timer = 0.0f;
599 float m_connection_reinit_timer = 0.1f;
600 float m_avg_rtt_timer = 0.0f;
601 float m_playerpos_send_timer = 0.0f;
602 float m_ignore_damage_timer = 0.0f; // Used after server moves player
603 IntervalLimiter m_map_timer_and_unload_interval;
605 IWritableTextureSource *m_tsrc;
606 IWritableShaderSource *m_shsrc;
607 IWritableItemDefManager *m_itemdef;
608 IWritableNodeDefManager *m_nodedef;
609 ISoundManager *m_sound;
610 MtEventManager *m_event;
613 MeshUpdateThread m_mesh_update_thread;
614 ClientEnvironment m_env;
615 ParticleManager m_particle_manager;
616 con::Connection m_con;
617 std::string m_address_name;
618 Camera *m_camera = nullptr;
619 Minimap *m_minimap = nullptr;
620 bool m_minimap_disabled_by_server = false;
621 // Server serialization version
624 // Used version of the protocol with server
625 // Values smaller than 25 only mean they are smaller than 25,
626 // and aren't accurate. We simply just don't know, because
627 // the server didn't send the version back then.
628 // If 0, server init hasn't been received yet.
631 u16 m_playeritem = 0;
632 bool m_inventory_updated = false;
633 Inventory *m_inventory_from_server = nullptr;
634 float m_inventory_from_server_age = 0.0f;
635 PacketCounter m_packetcounter;
636 // Block mesh animation parameters
637 float m_animation_time = 0.0f;
638 int m_crack_level = -1;
640 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
642 //u32 m_daynight_ratio;
643 std::queue<std::wstring> m_out_chat_queue;
644 u32 m_last_chat_message_sent;
645 float m_chat_message_allowance = 5.0f;
646 std::queue<ChatMessage *> m_chat_queue;
648 // The authentication methods we can use to enter sudo mode (=change password)
649 u32 m_sudo_auth_methods;
651 // The seed returned by the server in TOCLIENT_INIT is stored here
655 std::string m_playername;
656 std::string m_password;
657 // If set, this will be sent (and cleared) upon a TOCLIENT_ACCEPT_SUDO_MODE
658 std::string m_new_password;
659 // Usable by auth mechanisms.
660 AuthMechanism m_chosen_auth_mech;
661 void *m_auth_data = nullptr;
664 bool m_access_denied = false;
665 bool m_access_denied_reconnect = false;
666 std::string m_access_denied_reason = "";
667 std::queue<ClientEvent> m_client_event_queue;
668 bool m_itemdef_received = false;
669 bool m_nodedef_received = false;
670 ClientMediaDownloader *m_media_downloader;
672 // time_of_day speed approximation for old protocol
673 bool m_time_of_day_set = false;
674 float m_last_time_of_day_f = -1.0f;
675 float m_time_of_day_update_timer = 0.0f;
677 // An interval for generally sending object positions and stuff
678 float m_recommended_send_interval = 0.1f;
681 float m_removed_sounds_check_timer = 0.0f;
682 // Mapping from server sound ids to our sound ids
683 std::unordered_map<s32, int> m_sounds_server_to_client;
684 // And the other way!
685 std::unordered_map<int, s32> m_sounds_client_to_server;
686 // And relations to objects
687 std::unordered_map<int, u16> m_sounds_to_objects;
690 std::unordered_set<std::string> m_privileges;
692 // Detached inventories
694 std::unordered_map<std::string, Inventory*> m_detached_inventories;
696 // Storage for mesh data for creating multiple instances of the same mesh
697 StringMap m_mesh_data;
699 StringMap m_mod_files;
702 LocalClientState m_state;
704 // Used for saving server map to disk client-side
705 MapDatabase *m_localdb = nullptr;
706 IntervalLimiter m_localdb_save_interval;
707 u16 m_cache_save_interval;
709 ClientScripting *m_script = nullptr;
710 bool m_modding_enabled;
711 std::unordered_map<std::string, ModMetadata *> m_mod_storages;
712 float m_mod_storage_save_timer = 10.0f;
713 std::vector<ModSpec> m_mods;
714 GameUIFlags *m_game_ui_flags;
716 bool m_shutdown = false;
718 // CSM flavour limits byteflag
719 u64 m_csm_flavour_limits = CSMFlavourLimit::CSM_FL_NONE;
720 u32 m_csm_noderange_limit = 8;
723 #endif // !CLIENT_HEADER