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;
60 struct MinimapMapblock;
67 enum LocalClientState {
80 PacketCounter() = default;
84 std::map<u16, u16>::iterator n = m_packets.find(command);
85 if(n == m_packets.end())
87 m_packets[command] = 1;
97 for (auto &m_packet : m_packets) {
102 void print(std::ostream &o)
104 for (const auto &m_packet : m_packets) {
105 o << "cmd "<< m_packet.first <<" count "<< m_packet.second << std::endl;
111 std::map<u16, u16> m_packets;
114 class ClientScripting;
117 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
121 NOTE: Nothing is thread-safe here.
125 const char *playername,
126 const std::string &password,
127 const std::string &address_name,
128 MapDrawControl &control,
129 IWritableTextureSource *tsrc,
130 IWritableShaderSource *shsrc,
131 IWritableItemDefManager *itemdef,
132 IWritableNodeDefManager *nodedef,
133 ISoundManager *sound,
134 MtEventManager *event,
136 GameUIFlags *game_ui_flags
140 DISABLE_CLASS_COPY(Client);
142 // 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, "");
155 request all threads managed by client to be stopped
163 The name of the local player should already be set when
164 calling this, as it is sent in the initialization.
166 void connect(Address address, bool is_local_server);
169 Stuff that references the environment is valid only as
170 long as this is not called. (eg. Players)
171 If this throws a PeerNotFoundException, the connection has
174 void step(float dtime);
180 void handleCommand(NetworkPacket* pkt);
182 void handleCommand_Null(NetworkPacket* pkt) {};
183 void handleCommand_Deprecated(NetworkPacket* pkt);
184 void handleCommand_Hello(NetworkPacket* pkt);
185 void handleCommand_AuthAccept(NetworkPacket* pkt);
186 void handleCommand_AcceptSudoMode(NetworkPacket* pkt);
187 void handleCommand_DenySudoMode(NetworkPacket* pkt);
188 void handleCommand_AccessDenied(NetworkPacket* pkt);
189 void handleCommand_RemoveNode(NetworkPacket* pkt);
190 void handleCommand_AddNode(NetworkPacket* pkt);
191 void handleCommand_BlockData(NetworkPacket* pkt);
192 void handleCommand_Inventory(NetworkPacket* pkt);
193 void handleCommand_TimeOfDay(NetworkPacket* pkt);
194 void handleCommand_ChatMessageOld(NetworkPacket *pkt);
195 void handleCommand_ChatMessage(NetworkPacket *pkt);
196 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
197 void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
198 void handleCommand_Movement(NetworkPacket* pkt);
199 void handleCommand_HP(NetworkPacket* pkt);
200 void handleCommand_Breath(NetworkPacket* pkt);
201 void handleCommand_MovePlayer(NetworkPacket* pkt);
202 void handleCommand_DeathScreen(NetworkPacket* pkt);
203 void handleCommand_AnnounceMedia(NetworkPacket* pkt);
204 void handleCommand_Media(NetworkPacket* pkt);
205 void handleCommand_NodeDef(NetworkPacket* pkt);
206 void handleCommand_ItemDef(NetworkPacket* pkt);
207 void handleCommand_PlaySound(NetworkPacket* pkt);
208 void handleCommand_StopSound(NetworkPacket* pkt);
209 void handleCommand_FadeSound(NetworkPacket *pkt);
210 void handleCommand_Privileges(NetworkPacket* pkt);
211 void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
212 void handleCommand_DetachedInventory(NetworkPacket* pkt);
213 void handleCommand_ShowFormSpec(NetworkPacket* pkt);
214 void handleCommand_SpawnParticle(NetworkPacket* pkt);
215 void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
216 void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
217 void handleCommand_HudAdd(NetworkPacket* pkt);
218 void handleCommand_HudRemove(NetworkPacket* pkt);
219 void handleCommand_HudChange(NetworkPacket* pkt);
220 void handleCommand_HudSetFlags(NetworkPacket* pkt);
221 void handleCommand_HudSetParam(NetworkPacket* pkt);
222 void handleCommand_HudSetSky(NetworkPacket* pkt);
223 void handleCommand_CloudParams(NetworkPacket* pkt);
224 void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
225 void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
226 void handleCommand_EyeOffset(NetworkPacket* pkt);
227 void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
228 void handleCommand_ModChannelMsg(NetworkPacket *pkt);
229 void handleCommand_ModChannelSignal(NetworkPacket *pkt);
230 void handleCommand_SrpBytesSandB(NetworkPacket* pkt);
231 void handleCommand_CSMFlavourLimits(NetworkPacket *pkt);
233 void ProcessData(NetworkPacket *pkt);
235 void Send(NetworkPacket* pkt);
237 void interact(u8 action, const PointedThing& pointed);
239 void sendNodemetaFields(v3s16 p, const std::string &formname,
240 const StringMap &fields);
241 void sendInventoryFields(const std::string &formname,
242 const StringMap &fields);
243 void sendInventoryAction(InventoryAction *a);
244 void sendChatMessage(const std::wstring &message);
245 void clearOutChatQueue();
246 void sendChangePassword(const std::string &oldpassword,
247 const std::string &newpassword);
248 void sendDamage(u8 damage);
252 ClientEnvironment& getEnv() { return m_env; }
253 ITextureSource *tsrc() { return getTextureSource(); }
254 ISoundManager *sound() { return getSoundManager(); }
255 static const std::string &getBuiltinLuaPath();
256 static const std::string &getClientModsLuaPath();
258 virtual const std::vector<ModSpec> &getMods() const;
259 virtual const ModSpec* getModSpec(const std::string &modname) const;
261 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
262 void removeNode(v3s16 p);
265 * Helper function for Client Side Modding
266 * Flavour is applied there, this should not be used for core engine
268 * @param is_valid_position
271 MapNode getNode(v3s16 p, bool *is_valid_position);
272 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
274 void setPlayerControl(PlayerControl &control);
276 void selectPlayerItem(u16 item);
277 u16 getPlayerItem() const
278 { return m_playeritem; }
280 // Returns true if the inventory of the local player has been
281 // updated from the server. If it is true, it is set to false.
282 bool getLocalInventoryUpdated();
283 // Copies the inventory of the local player to parameter
284 void getLocalInventory(Inventory &dst);
286 /* InventoryManager interface */
287 Inventory* getInventory(const InventoryLocation &loc);
288 void inventoryAction(InventoryAction *a);
290 const std::list<std::string> &getConnectedPlayerNames()
292 return m_env.getPlayerNames();
295 float getAnimationTime();
299 void setCrack(int level, v3s16 pos);
303 bool checkPrivilege(const std::string &priv) const
304 { return (m_privileges.count(priv) != 0); }
306 const std::unordered_set<std::string> &getPrivilegeList() const
307 { return m_privileges; }
309 bool getChatMessage(std::wstring &message);
310 void typeChatMessage(const std::wstring& message);
312 u64 getMapSeed(){ return m_map_seed; }
314 void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
315 // Including blocks at appropriate edges
316 void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
317 void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
319 void updateCameraOffset(v3s16 camera_offset)
320 { m_mesh_update_thread.m_camera_offset = camera_offset; }
322 bool hasClientEvents() const { return !m_client_event_queue.empty(); }
323 // Get event from queue. If queue is empty, it triggers an assertion failure.
324 ClientEvent * getClientEvent();
326 bool accessDenied() const { return m_access_denied; }
328 bool reconnectRequested() const { return m_access_denied_reconnect; }
330 void setFatalError(const std::string &reason)
332 m_access_denied = true;
333 m_access_denied_reason = reason;
336 // Renaming accessDeniedReason to better name could be good as it's used to
337 // disconnect client when CSM failed.
338 const std::string &accessDeniedReason() const { return m_access_denied_reason; }
340 bool itemdefReceived()
341 { return m_itemdef_received; }
342 bool nodedefReceived()
343 { return m_nodedef_received; }
345 { return !m_media_downloader; }
348 { return m_proto_ver; }
350 bool connectedToServer();
352 float mediaReceiveProgress();
354 void afterContentReceived();
359 Minimap* getMinimap() { return m_minimap; }
360 void setCamera(Camera* camera) { m_camera = camera; }
362 Camera* getCamera () { return m_camera; }
364 bool shouldShowMinimap() const;
366 // IGameDef interface
367 virtual IItemDefManager* getItemDefManager();
368 virtual INodeDefManager* getNodeDefManager();
369 virtual ICraftDefManager* getCraftDefManager();
370 ITextureSource* getTextureSource();
371 virtual IShaderSource* getShaderSource();
372 IShaderSource *shsrc() { return getShaderSource(); }
373 virtual u16 allocateUnknownNodeId(const std::string &name);
374 virtual ISoundManager* getSoundManager();
375 virtual MtEventManager* getEventManager();
376 virtual ParticleManager* getParticleManager();
377 bool checkLocalPrivilege(const std::string &priv)
378 { return checkPrivilege(priv); }
379 virtual scene::IAnimatedMesh* getMesh(const std::string &filename);
380 const std::string* getModFile(const std::string &filename);
382 virtual std::string getModStoragePath() const;
383 virtual bool registerModStorage(ModMetadata *meta);
384 virtual void unregisterModStorage(const std::string &name);
386 // The following set of functions is used by ClientMediaDownloader
387 // Insert a media file appropriately into the appropriate manager
388 bool loadMedia(const std::string &data, const std::string &filename);
389 // Send a request for conventional media transfer
390 void request_media(const std::vector<std::string> &file_requests);
392 LocalClientState getState() { return m_state; }
394 void makeScreenshot();
396 inline void pushToChatQueue(ChatMessage *cec)
398 m_chat_queue.push(cec);
401 ClientScripting *getScript() { return m_script; }
402 const bool moddingEnabled() const { return m_modding_enabled; }
404 void pushToEventQueue(ClientEvent *event);
406 void showGameChat(bool show = true);
407 void showGameHud(bool show = true);
408 void showMinimap(bool show = true);
409 void showProfiler(bool show = true);
410 void showGameFog(bool show = true);
411 void showGameDebug(bool show = true);
413 const Address getServerAddress();
415 const std::string &getAddressName() const
417 return m_address_name;
420 inline bool checkCSMFlavourLimit(CSMFlavourLimit flag) const
422 return m_csm_flavour_limits & flag;
425 u32 getCSMNodeRangeLimit() const
427 return m_csm_noderange_limit;
430 bool joinModChannel(const std::string &channel);
431 bool leaveModChannel(const std::string &channel);
432 bool sendModChannelMessage(const std::string &channel, const std::string &message);
433 ModChannel *getModChannel(const std::string &channel);
437 // Virtual methods from con::PeerHandler
438 void peerAdded(con::Peer *peer);
439 void deletingPeer(con::Peer *peer, bool timeout);
441 void initLocalMapSaving(const Address &address,
442 const std::string &hostname,
443 bool is_local_server);
448 void sendPlayerPos();
449 // Send the item number 'item' as player item to the server
450 void sendPlayerItem(u16 item);
452 void deleteAuthData();
453 // helper method shared with clientpackethandler
454 static AuthMechanism choseAuthMech(const u32 mechs);
456 void sendInit(const std::string &playerName);
457 void startAuth(AuthMechanism chosen_auth_mechanism);
458 void sendDeletedBlocks(std::vector<v3s16> &blocks);
459 void sendGotBlocks(v3s16 block);
460 void sendRemovedSounds(std::vector<s32> &soundList);
463 inline std::string getPlayerName()
464 { return m_env.getLocalPlayer()->getName(); }
466 bool canSendChatMessage() const;
468 float m_packetcounter_timer = 0.0f;
469 float m_connection_reinit_timer = 0.1f;
470 float m_avg_rtt_timer = 0.0f;
471 float m_playerpos_send_timer = 0.0f;
472 float m_ignore_damage_timer = 0.0f; // Used after server moves player
473 IntervalLimiter m_map_timer_and_unload_interval;
475 IWritableTextureSource *m_tsrc;
476 IWritableShaderSource *m_shsrc;
477 IWritableItemDefManager *m_itemdef;
478 IWritableNodeDefManager *m_nodedef;
479 ISoundManager *m_sound;
480 MtEventManager *m_event;
483 MeshUpdateThread m_mesh_update_thread;
484 ClientEnvironment m_env;
485 ParticleManager m_particle_manager;
486 std::unique_ptr<con::Connection> m_con;
487 std::string m_address_name;
488 Camera *m_camera = nullptr;
489 Minimap *m_minimap = nullptr;
490 bool m_minimap_disabled_by_server = false;
491 // Server serialization version
494 // Used version of the protocol with server
495 // Values smaller than 25 only mean they are smaller than 25,
496 // and aren't accurate. We simply just don't know, because
497 // the server didn't send the version back then.
498 // If 0, server init hasn't been received yet.
501 u16 m_playeritem = 0;
502 bool m_inventory_updated = false;
503 Inventory *m_inventory_from_server = nullptr;
504 float m_inventory_from_server_age = 0.0f;
505 PacketCounter m_packetcounter;
506 // Block mesh animation parameters
507 float m_animation_time = 0.0f;
508 int m_crack_level = -1;
510 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
512 //u32 m_daynight_ratio;
513 std::queue<std::wstring> m_out_chat_queue;
514 u32 m_last_chat_message_sent;
515 float m_chat_message_allowance = 5.0f;
516 std::queue<ChatMessage *> m_chat_queue;
518 // The authentication methods we can use to enter sudo mode (=change password)
519 u32 m_sudo_auth_methods;
521 // The seed returned by the server in TOCLIENT_INIT is stored here
525 std::string m_playername;
526 std::string m_password;
527 // If set, this will be sent (and cleared) upon a TOCLIENT_ACCEPT_SUDO_MODE
528 std::string m_new_password;
529 // Usable by auth mechanisms.
530 AuthMechanism m_chosen_auth_mech;
531 void *m_auth_data = nullptr;
534 bool m_access_denied = false;
535 bool m_access_denied_reconnect = false;
536 std::string m_access_denied_reason = "";
537 std::queue<ClientEvent *> m_client_event_queue;
538 bool m_itemdef_received = false;
539 bool m_nodedef_received = false;
540 ClientMediaDownloader *m_media_downloader;
542 // time_of_day speed approximation for old protocol
543 bool m_time_of_day_set = false;
544 float m_last_time_of_day_f = -1.0f;
545 float m_time_of_day_update_timer = 0.0f;
547 // An interval for generally sending object positions and stuff
548 float m_recommended_send_interval = 0.1f;
551 float m_removed_sounds_check_timer = 0.0f;
552 // Mapping from server sound ids to our sound ids
553 std::unordered_map<s32, int> m_sounds_server_to_client;
554 // And the other way!
555 std::unordered_map<int, s32> m_sounds_client_to_server;
556 // And relations to objects
557 std::unordered_map<int, u16> m_sounds_to_objects;
560 std::unordered_set<std::string> m_privileges;
562 // Detached inventories
564 std::unordered_map<std::string, Inventory*> m_detached_inventories;
566 // Storage for mesh data for creating multiple instances of the same mesh
567 StringMap m_mesh_data;
569 StringMap m_mod_files;
572 LocalClientState m_state;
574 // Used for saving server map to disk client-side
575 MapDatabase *m_localdb = nullptr;
576 IntervalLimiter m_localdb_save_interval;
577 u16 m_cache_save_interval;
579 ClientScripting *m_script = nullptr;
580 bool m_modding_enabled;
581 std::unordered_map<std::string, ModMetadata *> m_mod_storages;
582 float m_mod_storage_save_timer = 10.0f;
583 std::vector<ModSpec> m_mods;
584 GameUIFlags *m_game_ui_flags;
586 bool m_shutdown = false;
588 // CSM flavour limits byteflag
589 u64 m_csm_flavour_limits = CSMFlavourLimit::CSM_FL_NONE;
590 u32 m_csm_noderange_limit = 8;
592 std::unique_ptr<ModChannelMgr> m_modchannel_mgr;