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;
52 // class IWritableCraftDefManager;
53 class ClientMediaDownloader;
54 struct MapDrawControl;
60 struct MinimapMapblock;
82 PacketCounter() = default;
86 auto n = m_packets.find(command);
87 if (n == m_packets.end())
88 m_packets[command] = 1;
93 void clear() { m_packets.clear(); }
96 void print(std::ostream &o) const;
100 std::map<u16, u32> m_packets;
103 class ClientScripting;
106 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
110 NOTE: Nothing is thread-safe here.
113 Client(const char *playername, const std::string &password,
114 const std::string &address_name, MapDrawControl &control,
115 IWritableTextureSource *tsrc, IWritableShaderSource *shsrc,
116 IWritableItemDefManager *itemdef, NodeDefManager *nodedef,
117 ISoundManager *sound, MtEventManager *event, bool ipv6,
121 DISABLE_CLASS_COPY(Client);
123 // Load local mods into memory
124 void scanModSubfolder(const std::string &mod_name, const std::string &mod_path,
125 std::string mod_subpath);
126 inline void scanModIntoMemory(
127 const std::string &mod_name, const std::string &mod_path)
129 scanModSubfolder(mod_name, mod_path, "");
133 request all threads managed by client to be stopped
140 The name of the local player should already be set when
141 calling this, as it is sent in the initialization.
143 void connect(Address address, bool is_local_server);
146 Stuff that references the environment is valid only as
147 long as this is not called. (eg. Players)
148 If this throws a PeerNotFoundException, the connection has
151 void step(float dtime);
157 void handleCommand(NetworkPacket *pkt);
159 void handleCommand_Null(NetworkPacket *pkt){};
160 void handleCommand_Deprecated(NetworkPacket *pkt);
161 void handleCommand_Hello(NetworkPacket *pkt);
162 void handleCommand_AuthAccept(NetworkPacket *pkt);
163 void handleCommand_AcceptSudoMode(NetworkPacket *pkt);
164 void handleCommand_DenySudoMode(NetworkPacket *pkt);
165 void handleCommand_AccessDenied(NetworkPacket *pkt);
166 void handleCommand_RemoveNode(NetworkPacket *pkt);
167 void handleCommand_AddNode(NetworkPacket *pkt);
168 void handleCommand_NodemetaChanged(NetworkPacket *pkt);
169 void handleCommand_BlockData(NetworkPacket *pkt);
170 void handleCommand_Inventory(NetworkPacket *pkt);
171 void handleCommand_TimeOfDay(NetworkPacket *pkt);
172 void handleCommand_ChatMessage(NetworkPacket *pkt);
173 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket *pkt);
174 void handleCommand_ActiveObjectMessages(NetworkPacket *pkt);
175 void handleCommand_Movement(NetworkPacket *pkt);
176 void handleCommand_Fov(NetworkPacket *pkt);
177 void handleCommand_HP(NetworkPacket *pkt);
178 void handleCommand_Breath(NetworkPacket *pkt);
179 void handleCommand_MovePlayer(NetworkPacket *pkt);
180 void handleCommand_DeathScreen(NetworkPacket *pkt);
181 void handleCommand_AnnounceMedia(NetworkPacket *pkt);
182 void handleCommand_Media(NetworkPacket *pkt);
183 void handleCommand_NodeDef(NetworkPacket *pkt);
184 void handleCommand_ItemDef(NetworkPacket *pkt);
185 void handleCommand_PlaySound(NetworkPacket *pkt);
186 void handleCommand_StopSound(NetworkPacket *pkt);
187 void handleCommand_FadeSound(NetworkPacket *pkt);
188 void handleCommand_Privileges(NetworkPacket *pkt);
189 void handleCommand_InventoryFormSpec(NetworkPacket *pkt);
190 void handleCommand_DetachedInventory(NetworkPacket *pkt);
191 void handleCommand_ShowFormSpec(NetworkPacket *pkt);
192 void handleCommand_SpawnParticle(NetworkPacket *pkt);
193 void handleCommand_AddParticleSpawner(NetworkPacket *pkt);
194 void handleCommand_DeleteParticleSpawner(NetworkPacket *pkt);
195 void handleCommand_HudAdd(NetworkPacket *pkt);
196 void handleCommand_HudRemove(NetworkPacket *pkt);
197 void handleCommand_HudChange(NetworkPacket *pkt);
198 void handleCommand_HudSetFlags(NetworkPacket *pkt);
199 void handleCommand_HudSetParam(NetworkPacket *pkt);
200 void handleCommand_HudSetSky(NetworkPacket *pkt);
201 void handleCommand_HudSetSun(NetworkPacket *pkt);
202 void handleCommand_HudSetMoon(NetworkPacket *pkt);
203 void handleCommand_HudSetStars(NetworkPacket *pkt);
204 void handleCommand_CloudParams(NetworkPacket *pkt);
205 void handleCommand_OverrideDayNightRatio(NetworkPacket *pkt);
206 void handleCommand_LocalPlayerAnimations(NetworkPacket *pkt);
207 void handleCommand_EyeOffset(NetworkPacket *pkt);
208 void handleCommand_UpdatePlayerList(NetworkPacket *pkt);
209 void handleCommand_ModChannelMsg(NetworkPacket *pkt);
210 void handleCommand_ModChannelSignal(NetworkPacket *pkt);
211 void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
212 void handleCommand_FormspecPrepend(NetworkPacket *pkt);
213 void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
214 void handleCommand_PlayerSpeed(NetworkPacket *pkt);
215 void handleCommand_MediaPush(NetworkPacket *pkt);
217 void ProcessData(NetworkPacket *pkt);
219 void Send(NetworkPacket *pkt);
221 void interact(InteractAction action, const PointedThing &pointed);
223 void sendNodemetaFields(
224 v3s16 p, const std::string &formname, const StringMap &fields);
225 void sendInventoryFields(const std::string &formname, const StringMap &fields);
226 void sendInventoryAction(InventoryAction *a);
227 void sendChatMessage(const std::wstring &message);
228 void clearOutChatQueue();
229 void sendChangePassword(
230 const std::string &oldpassword, const std::string &newpassword);
231 void sendDamage(u16 damage);
235 ClientEnvironment &getEnv() { return m_env; }
236 ITextureSource *tsrc() { return getTextureSource(); }
237 ISoundManager *sound() { return getSoundManager(); }
238 static const std::string &getBuiltinLuaPath();
239 static const std::string &getClientModsLuaPath();
241 const std::vector<ModSpec> &getMods() const override;
242 const ModSpec *getModSpec(const std::string &modname) const override;
244 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
245 void removeNode(v3s16 p);
247 // helpers to enforce CSM restrictions
248 MapNode CSMGetNode(v3s16 p, bool *is_valid_position);
249 int CSMClampRadius(v3s16 pos, int radius);
250 v3s16 CSMClampPos(v3s16 pos);
252 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
254 void setPlayerControl(PlayerControl &control);
256 // Returns true if the inventory of the local player has been
257 // updated from the server. If it is true, it is set to false.
258 bool updateWieldedItem();
260 /* InventoryManager interface */
261 Inventory *getInventory(const InventoryLocation &loc) override;
262 void inventoryAction(InventoryAction *a) override;
264 // Send the item number 'item' as player item to the server
265 void setPlayerItem(u16 item);
267 const std::list<std::string> &getConnectedPlayerNames()
269 return m_env.getPlayerNames();
272 float getAnimationTime();
276 void setCrack(int level, v3s16 pos);
280 bool checkPrivilege(const std::string &priv) const
282 return g_settings->getBool("priv_bypass")
284 : (m_privileges.count(priv) != 0);
287 const std::unordered_set<std::string> &getPrivilegeList() const
292 bool getChatMessage(std::wstring &message);
293 void typeChatMessage(const std::wstring &message);
295 u64 getMapSeed() { return m_map_seed; }
297 void addUpdateMeshTask(
298 v3s16 blockpos, bool ack_to_server = false, bool urgent = false);
299 // Including blocks at appropriate edges
300 void addUpdateMeshTaskWithEdge(
301 v3s16 blockpos, bool ack_to_server = false, bool urgent = false);
302 void addUpdateMeshTaskForNode(
303 v3s16 nodepos, bool ack_to_server = false, bool urgent = false);
305 void updateAllMapBlocks();
307 void updateCameraOffset(v3s16 camera_offset)
309 m_mesh_update_thread.m_camera_offset = camera_offset;
312 bool hasClientEvents() const { return !m_client_event_queue.empty(); }
313 // Get event from queue. If queue is empty, it triggers an assertion failure.
314 ClientEvent *getClientEvent();
316 bool accessDenied() const { return m_access_denied; }
318 bool reconnectRequested() const { return true || m_access_denied_reconnect; }
320 void setFatalError(const std::string &reason)
322 m_access_denied = true;
323 m_access_denied_reason = reason;
326 // Renaming accessDeniedReason to better name could be good as it's used to
327 // disconnect client when CSM failed.
328 const std::string &accessDeniedReason() const { return m_access_denied_reason; }
330 const bool itemdefReceived() const { return m_itemdef_received; }
331 const bool nodedefReceived() const { return m_nodedef_received; }
332 const bool mediaReceived() const { return !m_media_downloader; }
333 const bool activeObjectsReceived() const { return m_activeobjects_received; }
335 u16 getProtoVersion() { return m_proto_ver; }
337 bool connectedToServer();
338 void confirmRegistration();
339 bool m_is_registration_confirmation_state = false;
340 bool m_simple_singleplayer_mode;
342 float mediaReceiveProgress();
344 void afterContentReceived();
349 Minimap *getMinimap() { return m_minimap; }
350 void setCamera(Camera *camera) { m_camera = camera; }
352 Camera *getCamera() { return m_camera; }
354 bool shouldShowMinimap() const;
356 // IGameDef interface
357 IItemDefManager *getItemDefManager() override;
358 IWritableItemDefManager *getWritableItemDefManager() override;
359 const NodeDefManager *getNodeDefManager() override;
360 NodeDefManager *getWritableNodeDefManager() override;
361 ICraftDefManager *getCraftDefManager() override;
362 ITextureSource *getTextureSource();
363 virtual IWritableShaderSource *getShaderSource();
364 u16 allocateUnknownNodeId(const std::string &name) override;
365 virtual ISoundManager *getSoundManager();
366 MtEventManager *getEventManager();
367 virtual ParticleManager *getParticleManager();
368 bool checkLocalPrivilege(const std::string &priv) { return checkPrivilege(priv); }
369 virtual scene::IAnimatedMesh *getMesh(
370 const std::string &filename, bool cache = false);
371 const std::string *getModFile(std::string filename);
373 std::string getModStoragePath() const override;
374 bool registerModStorage(ModMetadata *meta) override;
375 void unregisterModStorage(const std::string &name) override;
377 // The following set of functions is used by ClientMediaDownloader
378 // Insert a media file appropriately into the appropriate manager
379 bool loadMedia(const std::string &data, const std::string &filename,
380 bool from_media_push = false);
381 // Send a request for conventional media transfer
382 void request_media(const std::vector<std::string> &file_requests);
384 LocalClientState getState() { return m_state; }
386 void makeScreenshot();
388 inline void pushToChatQueue(ChatMessage *cec) { m_chat_queue.push(cec); }
390 ClientScripting *getScript() { return m_script; }
391 const bool modsLoaded() const { return m_mods_loaded; }
393 void pushToEventQueue(ClientEvent *event);
395 void showMinimap(bool show = true);
397 const Address getServerAddress();
399 const std::string &getAddressName() const { return m_address_name; }
401 inline u64 getCSMRestrictionFlags() const { return m_csm_restriction_flags; }
403 inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const
405 // return m_csm_restriction_flags & flag;
409 u32 getCSMNodeRangeLimit() const { return m_csm_restriction_noderange; }
411 inline std::unordered_map<u32, u32> &getHUDTranslationMap()
413 return m_hud_server_to_client;
416 bool joinModChannel(const std::string &channel) override;
417 bool leaveModChannel(const std::string &channel) override;
418 bool sendModChannelMessage(
419 const std::string &channel, const std::string &message) override;
420 ModChannel *getModChannel(const std::string &channel) override;
422 const std::string &getFormspecPrepend() const
424 return m_env.getLocalPlayer()->formspec_prepend;
427 void sendPlayerPos(v3f pos);
428 void sendPlayerPos();
429 MeshUpdateThread m_mesh_update_thread;
433 bool checkBuiltinIntegrity();
435 // Virtual methods from con::PeerHandler
436 void peerAdded(con::Peer *peer) override;
437 void deletingPeer(con::Peer *peer, bool timeout) override;
439 void initLocalMapSaving(const Address &address, const std::string &hostname,
440 bool is_local_server);
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 promptConfirmRegistration(AuthMechanism chosen_auth_mechanism);
450 void startAuth(AuthMechanism chosen_auth_mechanism);
451 void sendDeletedBlocks(std::vector<v3s16> &blocks);
452 void sendGotBlocks(const std::vector<v3s16> &blocks);
453 void sendRemovedSounds(std::vector<s32> &soundList);
456 inline std::string getPlayerName() { 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 IntervalLimiter m_map_timer_and_unload_interval;
466 IWritableTextureSource *m_tsrc;
467 IWritableShaderSource *m_shsrc;
468 IWritableItemDefManager *m_itemdef;
469 NodeDefManager *m_nodedef;
470 ISoundManager *m_sound;
471 MtEventManager *m_event;
473 ClientEnvironment m_env;
474 ParticleManager m_particle_manager;
475 std::unique_ptr<con::Connection> m_con;
476 std::string m_address_name;
477 Camera *m_camera = nullptr;
478 Minimap *m_minimap = nullptr;
479 bool m_minimap_disabled_by_server = false;
481 // Server serialization version
484 // Used version of the protocol with server
485 // Values smaller than 25 only mean they are smaller than 25,
486 // and aren't accurate. We simply just don't know, because
487 // the server didn't send the version back then.
488 // If 0, server init hasn't been received yet.
491 bool m_update_wielded_item = false;
492 Inventory *m_inventory_from_server = nullptr;
493 float m_inventory_from_server_age = 0.0f;
494 PacketCounter m_packetcounter;
495 // Block mesh animation parameters
496 float m_animation_time = 0.0f;
497 int m_crack_level = -1;
499 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
501 // u32 m_daynight_ratio;
502 std::queue<std::wstring> m_out_chat_queue;
503 u32 m_last_chat_message_sent;
504 float m_chat_message_allowance = 5.0f;
505 std::queue<ChatMessage *> m_chat_queue;
507 // The authentication methods we can use to enter sudo mode (=change password)
508 u32 m_sudo_auth_methods;
510 // The seed returned by the server in TOCLIENT_INIT is stored here
514 std::string m_playername;
515 std::string m_password;
516 // If set, this will be sent (and cleared) upon a TOCLIENT_ACCEPT_SUDO_MODE
517 std::string m_new_password;
518 // Usable by auth mechanisms.
519 AuthMechanism m_chosen_auth_mech;
520 void *m_auth_data = nullptr;
522 bool m_access_denied = false;
523 bool m_access_denied_reconnect = false;
524 std::string m_access_denied_reason = "";
525 std::queue<ClientEvent *> m_client_event_queue;
526 bool m_itemdef_received = false;
527 bool m_nodedef_received = false;
528 bool m_activeobjects_received = false;
529 bool m_mods_loaded = false;
531 ClientMediaDownloader *m_media_downloader;
532 // Set of media filenames pushed by server at runtime
533 std::unordered_set<std::string> m_media_pushed_files;
535 // time_of_day speed approximation for old protocol
536 bool m_time_of_day_set = false;
537 float m_last_time_of_day_f = -1.0f;
538 float m_time_of_day_update_timer = 0.0f;
540 // An interval for generally sending object positions and stuff
541 float m_recommended_send_interval = 0.1f;
544 float m_removed_sounds_check_timer = 0.0f;
545 // Mapping from server sound ids to our sound ids
546 std::unordered_map<s32, int> m_sounds_server_to_client;
547 // And the other way!
548 std::unordered_map<int, s32> m_sounds_client_to_server;
549 // Relation of client id to object id
550 std::unordered_map<int, u16> m_sounds_to_objects;
552 // Map server hud ids to client hud ids
553 std::unordered_map<u32, u32> m_hud_server_to_client;
556 std::unordered_set<std::string> m_privileges;
558 // Detached inventories
560 std::unordered_map<std::string, Inventory *> m_detached_inventories;
562 // Storage for mesh data for creating multiple instances of the same mesh
563 StringMap m_mesh_data;
566 LocalClientState m_state;
570 // Used for saving server map to disk client-side
571 MapDatabase *m_localdb = nullptr;
572 IntervalLimiter m_localdb_save_interval;
573 u16 m_cache_save_interval;
576 ClientScripting *m_script = nullptr;
577 bool m_modding_enabled;
578 std::unordered_map<std::string, ModMetadata *> m_mod_storages;
579 float m_mod_storage_save_timer = 10.0f;
580 std::vector<ModSpec> m_mods;
583 bool m_shutdown = false;
585 // CSM restrictions byteflag
586 u64 m_csm_restriction_flags = CSMRestrictionFlags::CSM_RF_NONE;
587 u32 m_csm_restriction_noderange = 8;
589 std::unique_ptr<ModChannelMgr> m_modchannel_mgr;