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 auto n = m_packets.find(command);
86 if (n == m_packets.end())
87 m_packets[command] = 1;
98 void print(std::ostream &o) const;
102 std::map<u16, u32> m_packets;
105 class ClientScripting;
108 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
112 NOTE: Nothing is thread-safe here.
116 const char *playername,
117 const std::string &password,
118 const std::string &address_name,
119 MapDrawControl &control,
120 IWritableTextureSource *tsrc,
121 IWritableShaderSource *shsrc,
122 IWritableItemDefManager *itemdef,
123 NodeDefManager *nodedef,
124 ISoundManager *sound,
125 MtEventManager *event,
131 DISABLE_CLASS_COPY(Client);
133 // Load local mods into memory
134 void scanModSubfolder(const std::string &mod_name, const std::string &mod_path,
135 std::string mod_subpath);
136 inline void scanModIntoMemory(const std::string &mod_name, const std::string &mod_path)
138 scanModSubfolder(mod_name, mod_path, "");
142 request all threads managed by client to be stopped
150 The name of the local player should already be set when
151 calling this, as it is sent in the initialization.
153 void connect(Address address, bool is_local_server);
156 Stuff that references the environment is valid only as
157 long as this is not called. (eg. Players)
158 If this throws a PeerNotFoundException, the connection has
161 void step(float dtime);
167 void handleCommand(NetworkPacket* pkt);
169 void handleCommand_Null(NetworkPacket* pkt) {};
170 void handleCommand_Deprecated(NetworkPacket* pkt);
171 void handleCommand_Hello(NetworkPacket* pkt);
172 void handleCommand_AuthAccept(NetworkPacket* pkt);
173 void handleCommand_AcceptSudoMode(NetworkPacket* pkt);
174 void handleCommand_DenySudoMode(NetworkPacket* pkt);
175 void handleCommand_AccessDenied(NetworkPacket* pkt);
176 void handleCommand_RemoveNode(NetworkPacket* pkt);
177 void handleCommand_AddNode(NetworkPacket* pkt);
178 void handleCommand_NodemetaChanged(NetworkPacket *pkt);
179 void handleCommand_BlockData(NetworkPacket* pkt);
180 void handleCommand_Inventory(NetworkPacket* pkt);
181 void handleCommand_TimeOfDay(NetworkPacket* pkt);
182 void handleCommand_ChatMessage(NetworkPacket *pkt);
183 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
184 void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
185 void handleCommand_Movement(NetworkPacket* pkt);
186 void handleCommand_Fov(NetworkPacket *pkt);
187 void handleCommand_HP(NetworkPacket* pkt);
188 void handleCommand_Breath(NetworkPacket* pkt);
189 void handleCommand_MovePlayer(NetworkPacket* pkt);
190 void handleCommand_DeathScreen(NetworkPacket* pkt);
191 void handleCommand_AnnounceMedia(NetworkPacket* pkt);
192 void handleCommand_Media(NetworkPacket* pkt);
193 void handleCommand_NodeDef(NetworkPacket* pkt);
194 void handleCommand_ItemDef(NetworkPacket* pkt);
195 void handleCommand_PlaySound(NetworkPacket* pkt);
196 void handleCommand_StopSound(NetworkPacket* pkt);
197 void handleCommand_FadeSound(NetworkPacket *pkt);
198 void handleCommand_Privileges(NetworkPacket* pkt);
199 void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
200 void handleCommand_DetachedInventory(NetworkPacket* pkt);
201 void handleCommand_ShowFormSpec(NetworkPacket* pkt);
202 void handleCommand_SpawnParticle(NetworkPacket* pkt);
203 void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
204 void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
205 void handleCommand_HudAdd(NetworkPacket* pkt);
206 void handleCommand_HudRemove(NetworkPacket* pkt);
207 void handleCommand_HudChange(NetworkPacket* pkt);
208 void handleCommand_HudSetFlags(NetworkPacket* pkt);
209 void handleCommand_HudSetParam(NetworkPacket* pkt);
210 void handleCommand_HudSetSky(NetworkPacket* pkt);
211 void handleCommand_HudSetSun(NetworkPacket* pkt);
212 void handleCommand_HudSetMoon(NetworkPacket* pkt);
213 void handleCommand_HudSetStars(NetworkPacket* pkt);
214 void handleCommand_CloudParams(NetworkPacket* pkt);
215 void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
216 void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
217 void handleCommand_EyeOffset(NetworkPacket* pkt);
218 void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
219 void handleCommand_ModChannelMsg(NetworkPacket *pkt);
220 void handleCommand_ModChannelSignal(NetworkPacket *pkt);
221 void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
222 void handleCommand_FormspecPrepend(NetworkPacket *pkt);
223 void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
224 void handleCommand_PlayerSpeed(NetworkPacket *pkt);
225 void handleCommand_MediaPush(NetworkPacket *pkt);
227 void ProcessData(NetworkPacket *pkt);
229 void Send(NetworkPacket* pkt);
231 void interact(InteractAction action, const PointedThing &pointed);
233 void sendNodemetaFields(v3s16 p, const std::string &formname,
234 const StringMap &fields);
235 void sendInventoryFields(const std::string &formname,
236 const StringMap &fields);
237 void sendInventoryAction(InventoryAction *a);
238 void sendChatMessage(const std::wstring &message);
239 void clearOutChatQueue();
240 void sendChangePassword(const std::string &oldpassword,
241 const std::string &newpassword);
242 void sendDamage(u16 damage);
246 ClientEnvironment& getEnv() { return m_env; }
247 ITextureSource *tsrc() { return getTextureSource(); }
248 ISoundManager *sound() { return getSoundManager(); }
249 static const std::string &getBuiltinLuaPath();
250 static const std::string &getClientModsLuaPath();
252 const std::vector<ModSpec> &getMods() const override;
253 const ModSpec* getModSpec(const std::string &modname) const override;
255 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
256 void removeNode(v3s16 p);
258 // helpers to enforce CSM restrictions
259 MapNode CSMGetNode(v3s16 p, bool *is_valid_position);
260 int CSMClampRadius(v3s16 pos, int radius);
261 v3s16 CSMClampPos(v3s16 pos);
263 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
265 void setPlayerControl(PlayerControl &control);
267 // Returns true if the inventory of the local player has been
268 // updated from the server. If it is true, it is set to false.
269 bool updateWieldedItem();
271 /* InventoryManager interface */
272 Inventory* getInventory(const InventoryLocation &loc) override;
273 void inventoryAction(InventoryAction *a) override;
275 // Send the item number 'item' as player item to the server
276 void setPlayerItem(u16 item);
278 const std::list<std::string> &getConnectedPlayerNames()
280 return m_env.getPlayerNames();
283 float getAnimationTime();
287 void setCrack(int level, v3s16 pos);
291 bool checkPrivilege(const std::string &priv) const
292 { return (m_privileges.count(priv) != 0); }
294 const std::unordered_set<std::string> &getPrivilegeList() const
295 { return m_privileges; }
297 bool getChatMessage(std::wstring &message);
298 void typeChatMessage(const std::wstring& message);
300 u64 getMapSeed(){ return m_map_seed; }
302 void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
303 // Including blocks at appropriate edges
304 void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
305 void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
307 void updateCameraOffset(v3s16 camera_offset)
308 { m_mesh_update_thread.m_camera_offset = camera_offset; }
310 bool hasClientEvents() const { return !m_client_event_queue.empty(); }
311 // Get event from queue. If queue is empty, it triggers an assertion failure.
312 ClientEvent * getClientEvent();
314 bool accessDenied() const { return m_access_denied; }
316 bool reconnectRequested() const { return m_access_denied_reconnect; }
318 void setFatalError(const std::string &reason)
320 m_access_denied = true;
321 m_access_denied_reason = reason;
324 // Renaming accessDeniedReason to better name could be good as it's used to
325 // disconnect client when CSM failed.
326 const std::string &accessDeniedReason() const { return m_access_denied_reason; }
328 const bool itemdefReceived() const
329 { return m_itemdef_received; }
330 const bool nodedefReceived() const
331 { return m_nodedef_received; }
332 const bool mediaReceived() const
333 { return !m_media_downloader; }
334 const bool activeObjectsReceived() const
335 { return m_activeobjects_received; }
337 u16 getProtoVersion()
338 { return m_proto_ver; }
340 bool connectedToServer();
341 void confirmRegistration();
342 bool m_is_registration_confirmation_state = false;
343 bool m_simple_singleplayer_mode;
345 float mediaReceiveProgress();
347 void afterContentReceived();
352 Minimap* getMinimap() { return m_minimap; }
353 void setCamera(Camera* camera) { m_camera = camera; }
355 Camera* getCamera () { return m_camera; }
357 bool shouldShowMinimap() const;
359 // IGameDef interface
360 IItemDefManager* getItemDefManager() override;
361 const NodeDefManager* getNodeDefManager() override;
362 ICraftDefManager* getCraftDefManager() override;
363 ITextureSource* getTextureSource();
364 virtual IWritableShaderSource* getShaderSource();
365 u16 allocateUnknownNodeId(const std::string &name) override;
366 virtual ISoundManager* getSoundManager();
367 MtEventManager* getEventManager();
368 virtual ParticleManager* getParticleManager();
369 bool checkLocalPrivilege(const std::string &priv)
370 { return checkPrivilege(priv); }
371 virtual scene::IAnimatedMesh* getMesh(const std::string &filename, bool cache = false);
372 const std::string* getModFile(std::string filename);
374 std::string getModStoragePath() const override;
375 bool registerModStorage(ModMetadata *meta) override;
376 void unregisterModStorage(const std::string &name) override;
378 // The following set of functions is used by ClientMediaDownloader
379 // Insert a media file appropriately into the appropriate manager
380 bool loadMedia(const std::string &data, const std::string &filename,
381 bool from_media_push = false);
382 // Send a request for conventional media transfer
383 void request_media(const std::vector<std::string> &file_requests);
385 LocalClientState getState() { return m_state; }
387 void makeScreenshot();
389 inline void pushToChatQueue(ChatMessage *cec)
391 m_chat_queue.push(cec);
394 ClientScripting *getScript() { return m_script; }
395 const bool modsLoaded() const { return m_mods_loaded; }
397 void pushToEventQueue(ClientEvent *event);
399 void showMinimap(bool show = true);
401 const Address getServerAddress();
403 const std::string &getAddressName() const
405 return m_address_name;
408 inline u64 getCSMRestrictionFlags() const
410 return m_csm_restriction_flags;
413 inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const
415 return m_csm_restriction_flags & flag;
418 u32 getCSMNodeRangeLimit() const
420 return m_csm_restriction_noderange;
423 inline std::unordered_map<u32, u32> &getHUDTranslationMap()
425 return m_hud_server_to_client;
428 bool joinModChannel(const std::string &channel) override;
429 bool leaveModChannel(const std::string &channel) override;
430 bool sendModChannelMessage(const std::string &channel,
431 const std::string &message) override;
432 ModChannel *getModChannel(const std::string &channel) override;
434 const std::string &getFormspecPrepend() const
436 return m_env.getLocalPlayer()->formspec_prepend;
440 bool checkBuiltinIntegrity();
442 // Virtual methods from con::PeerHandler
443 void peerAdded(con::Peer *peer) override;
444 void deletingPeer(con::Peer *peer, bool timeout) override;
446 void initLocalMapSaving(const Address &address,
447 const std::string &hostname,
448 bool is_local_server);
452 void sendPlayerPos();
454 void deleteAuthData();
455 // helper method shared with clientpackethandler
456 static AuthMechanism choseAuthMech(const u32 mechs);
458 void sendInit(const std::string &playerName);
459 void promptConfirmRegistration(AuthMechanism chosen_auth_mechanism);
460 void startAuth(AuthMechanism chosen_auth_mechanism);
461 void sendDeletedBlocks(std::vector<v3s16> &blocks);
462 void sendGotBlocks(const std::vector<v3s16> &blocks);
463 void sendRemovedSounds(std::vector<s32> &soundList);
466 inline std::string getPlayerName()
467 { return m_env.getLocalPlayer()->getName(); }
469 bool canSendChatMessage() const;
471 float m_packetcounter_timer = 0.0f;
472 float m_connection_reinit_timer = 0.1f;
473 float m_avg_rtt_timer = 0.0f;
474 float m_playerpos_send_timer = 0.0f;
475 IntervalLimiter m_map_timer_and_unload_interval;
477 IWritableTextureSource *m_tsrc;
478 IWritableShaderSource *m_shsrc;
479 IWritableItemDefManager *m_itemdef;
480 NodeDefManager *m_nodedef;
481 ISoundManager *m_sound;
482 MtEventManager *m_event;
485 MeshUpdateThread m_mesh_update_thread;
486 ClientEnvironment m_env;
487 ParticleManager m_particle_manager;
488 std::unique_ptr<con::Connection> m_con;
489 std::string m_address_name;
490 Camera *m_camera = nullptr;
491 Minimap *m_minimap = nullptr;
492 bool m_minimap_disabled_by_server = false;
494 // Server serialization version
497 // Used version of the protocol with server
498 // Values smaller than 25 only mean they are smaller than 25,
499 // and aren't accurate. We simply just don't know, because
500 // the server didn't send the version back then.
501 // If 0, server init hasn't been received yet.
504 bool m_update_wielded_item = false;
505 Inventory *m_inventory_from_server = nullptr;
506 float m_inventory_from_server_age = 0.0f;
507 PacketCounter m_packetcounter;
508 // Block mesh animation parameters
509 float m_animation_time = 0.0f;
510 int m_crack_level = -1;
512 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
514 //u32 m_daynight_ratio;
515 std::queue<std::wstring> m_out_chat_queue;
516 u32 m_last_chat_message_sent;
517 float m_chat_message_allowance = 5.0f;
518 std::queue<ChatMessage *> m_chat_queue;
520 // The authentication methods we can use to enter sudo mode (=change password)
521 u32 m_sudo_auth_methods;
523 // The seed returned by the server in TOCLIENT_INIT is stored here
527 std::string m_playername;
528 std::string m_password;
529 // If set, this will be sent (and cleared) upon a TOCLIENT_ACCEPT_SUDO_MODE
530 std::string m_new_password;
531 // Usable by auth mechanisms.
532 AuthMechanism m_chosen_auth_mech;
533 void *m_auth_data = nullptr;
535 bool m_access_denied = false;
536 bool m_access_denied_reconnect = false;
537 std::string m_access_denied_reason = "";
538 std::queue<ClientEvent *> m_client_event_queue;
539 bool m_itemdef_received = false;
540 bool m_nodedef_received = false;
541 bool m_activeobjects_received = false;
542 bool m_mods_loaded = false;
544 ClientMediaDownloader *m_media_downloader;
545 // Set of media filenames pushed by server at runtime
546 std::unordered_set<std::string> m_media_pushed_files;
548 // time_of_day speed approximation for old protocol
549 bool m_time_of_day_set = false;
550 float m_last_time_of_day_f = -1.0f;
551 float m_time_of_day_update_timer = 0.0f;
553 // An interval for generally sending object positions and stuff
554 float m_recommended_send_interval = 0.1f;
557 float m_removed_sounds_check_timer = 0.0f;
558 // Mapping from server sound ids to our sound ids
559 std::unordered_map<s32, int> m_sounds_server_to_client;
560 // And the other way!
561 std::unordered_map<int, s32> m_sounds_client_to_server;
562 // Relation of client id to object id
563 std::unordered_map<int, u16> m_sounds_to_objects;
565 // Map server hud ids to client hud ids
566 std::unordered_map<u32, u32> m_hud_server_to_client;
569 std::unordered_set<std::string> m_privileges;
571 // Detached inventories
573 std::unordered_map<std::string, Inventory*> m_detached_inventories;
575 // Storage for mesh data for creating multiple instances of the same mesh
576 StringMap m_mesh_data;
579 LocalClientState m_state;
583 // Used for saving server map to disk client-side
584 MapDatabase *m_localdb = nullptr;
585 IntervalLimiter m_localdb_save_interval;
586 u16 m_cache_save_interval;
589 ClientScripting *m_script = nullptr;
590 bool m_modding_enabled;
591 std::unordered_map<std::string, ModMetadata *> m_mod_storages;
592 float m_mod_storage_save_timer = 10.0f;
593 std::vector<ModSpec> m_mods;
596 bool m_shutdown = false;
598 // CSM restrictions byteflag
599 u64 m_csm_restriction_flags = CSMRestrictionFlags::CSM_RF_NONE;
600 u32 m_csm_restriction_noderange = 8;
602 std::unique_ptr<ModChannelMgr> m_modchannel_mgr;