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 "environment.h"
25 #include "irrlichttypes_extrabloated.h"
26 #include "jthread/jmutex.h"
31 #include "clientobject.h"
33 #include "inventorymanager.h"
34 #include "localplayer.h"
36 #include "particles.h"
37 #include "network/networkpacket.h"
41 class IWritableTextureSource;
42 class IWritableShaderSource;
43 class IWritableItemDefManager;
44 class IWritableNodeDefManager;
45 //class IWritableCraftDefManager;
46 class ClientMediaDownloader;
47 struct MapDrawControl;
53 struct QueuedMeshUpdate
57 bool ack_block_to_server;
63 enum LocalClientState {
70 A thread-safe queue of mesh update tasks
80 peer_id=0 adds with nobody to send to
82 void addBlock(v3s16 p, MeshMakeData *data,
83 bool ack_block_to_server, bool urgent);
85 // Returned pointer must be deleted
86 // Returns NULL if queue is empty
87 QueuedMeshUpdate * pop();
91 JMutexAutoLock lock(m_mutex);
92 return m_queue.size();
96 std::vector<QueuedMeshUpdate*> m_queue;
97 std::set<v3s16> m_urgents;
101 struct MeshUpdateResult
105 bool ack_block_to_server;
108 p(-1338,-1338,-1338),
110 ack_block_to_server(false)
115 class MeshUpdateThread : public JThread
119 MeshUpdateThread(IGameDef *gamedef):
126 MeshUpdateQueue m_queue_in;
128 MutexedQueue<MeshUpdateResult> m_queue_out;
132 v3s16 m_camera_offset;
139 CE_PLAYER_FORCE_MOVE,
143 CE_ADD_PARTICLESPAWNER,
144 CE_DELETE_PARTICLESPAWNER,
149 CE_OVERRIDE_DAY_NIGHT_RATIO,
154 ClientEventType type;
166 bool set_camera_point_target;
167 f32 camera_point_target_x;
168 f32 camera_point_target_y;
169 f32 camera_point_target_z;
172 std::string *formspec;
173 std::string *formname;
176 //} textures_updated;
183 bool collisiondetection;
185 std::string *texture;
200 bool collisiondetection;
202 std::string *texture;
204 } add_particlespawner;
207 } delete_particlespawner;
236 video::SColor *bgcolor;
238 std::vector<std::string> *params;
243 } override_day_night_ratio;
258 void add(u16 command)
260 std::map<u16, u16>::iterator n = m_packets.find(command);
261 if(n == m_packets.end())
263 m_packets[command] = 1;
273 for(std::map<u16, u16>::iterator
274 i = m_packets.begin();
275 i != m_packets.end(); ++i)
281 void print(std::ostream &o)
283 for(std::map<u16, u16>::iterator
284 i = m_packets.begin();
285 i != m_packets.end(); ++i)
288 <<" count "<<i->second
295 std::map<u16, u16> m_packets;
298 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
302 NOTE: Nothing is thread-safe here.
306 IrrlichtDevice *device,
307 const char *playername,
308 std::string password,
309 MapDrawControl &control,
310 IWritableTextureSource *tsrc,
311 IWritableShaderSource *shsrc,
312 IWritableItemDefManager *itemdef,
313 IWritableNodeDefManager *nodedef,
314 ISoundManager *sound,
315 MtEventManager *event,
322 request all threads managed by client to be stopped
330 The name of the local player should already be set when
331 calling this, as it is sent in the initialization.
333 void connect(Address address,
334 const std::string &address_name,
335 bool is_local_server);
338 Stuff that references the environment is valid only as
339 long as this is not called. (eg. Players)
340 If this throws a PeerNotFoundException, the connection has
343 void step(float dtime);
349 void handleCommand(NetworkPacket* pkt);
351 void handleCommand_Null(NetworkPacket* pkt) {};
352 void handleCommand_Deprecated(NetworkPacket* pkt);
353 void handleCommand_Init(NetworkPacket* pkt);
354 void handleCommand_AccessDenied(NetworkPacket* pkt);
355 void handleCommand_RemoveNode(NetworkPacket* pkt);
356 void handleCommand_AddNode(NetworkPacket* pkt);
357 void handleCommand_BlockData(NetworkPacket* pkt);
358 void handleCommand_Inventory(NetworkPacket* pkt);
359 void handleCommand_TimeOfDay(NetworkPacket* pkt);
360 void handleCommand_ChatMessage(NetworkPacket* pkt);
361 void handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt);
362 void handleCommand_ActiveObjectMessages(NetworkPacket* pkt);
363 void handleCommand_Movement(NetworkPacket* pkt);
364 void handleCommand_HP(NetworkPacket* pkt);
365 void handleCommand_Breath(NetworkPacket* pkt);
366 void handleCommand_MovePlayer(NetworkPacket* pkt);
367 void handleCommand_PlayerItem(NetworkPacket* pkt);
368 void handleCommand_DeathScreen(NetworkPacket* pkt);
369 void handleCommand_AnnounceMedia(NetworkPacket* pkt);
370 void handleCommand_Media(NetworkPacket* pkt);
371 void handleCommand_ToolDef(NetworkPacket* pkt);
372 void handleCommand_NodeDef(NetworkPacket* pkt);
373 void handleCommand_CraftItemDef(NetworkPacket* pkt);
374 void handleCommand_ItemDef(NetworkPacket* pkt);
375 void handleCommand_PlaySound(NetworkPacket* pkt);
376 void handleCommand_StopSound(NetworkPacket* pkt);
377 void handleCommand_Privileges(NetworkPacket* pkt);
378 void handleCommand_InventoryFormSpec(NetworkPacket* pkt);
379 void handleCommand_DetachedInventory(NetworkPacket* pkt);
380 void handleCommand_ShowFormSpec(NetworkPacket* pkt);
381 void handleCommand_SpawnParticle(NetworkPacket* pkt);
382 void handleCommand_AddParticleSpawner(NetworkPacket* pkt);
383 void handleCommand_DeleteParticleSpawner(NetworkPacket* pkt);
384 void handleCommand_HudAdd(NetworkPacket* pkt);
385 void handleCommand_HudRemove(NetworkPacket* pkt);
386 void handleCommand_HudChange(NetworkPacket* pkt);
387 void handleCommand_HudSetFlags(NetworkPacket* pkt);
388 void handleCommand_HudSetParam(NetworkPacket* pkt);
389 void handleCommand_HudSetSky(NetworkPacket* pkt);
390 void handleCommand_OverrideDayNightRatio(NetworkPacket* pkt);
391 void handleCommand_LocalPlayerAnimations(NetworkPacket* pkt);
392 void handleCommand_EyeOffset(NetworkPacket* pkt);
394 void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id);
396 // Returns true if something was received
397 bool AsyncProcessPacket();
398 bool AsyncProcessData();
399 void Send(NetworkPacket* pkt);
401 void interact(u8 action, const PointedThing& pointed);
403 void sendNodemetaFields(v3s16 p, const std::string &formname,
404 const std::map<std::string, std::string> &fields);
405 void sendInventoryFields(const std::string &formname,
406 const std::map<std::string, std::string> &fields);
407 void sendInventoryAction(InventoryAction *a);
408 void sendChatMessage(const std::wstring &message);
409 void sendChangePassword(const std::wstring &oldpassword,
410 const std::wstring &newpassword);
411 void sendDamage(u8 damage);
412 void sendBreath(u16 breath);
416 ClientEnvironment& getEnv()
419 // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
420 void removeNode(v3s16 p);
421 void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
423 void setPlayerControl(PlayerControl &control);
425 void selectPlayerItem(u16 item);
426 u16 getPlayerItem() const
427 { return m_playeritem; }
429 // Returns true if the inventory of the local player has been
430 // updated from the server. If it is true, it is set to false.
431 bool getLocalInventoryUpdated();
432 // Copies the inventory of the local player to parameter
433 void getLocalInventory(Inventory &dst);
435 /* InventoryManager interface */
436 Inventory* getInventory(const InventoryLocation &loc);
437 void inventoryAction(InventoryAction *a);
439 // Gets closest object pointed by the shootline
440 // Returns NULL if not found
441 ClientActiveObject * getSelectedActiveObject(
443 v3f from_pos_f_on_map,
444 core::line3d<f32> shootline_on_map
447 std::list<std::string> getConnectedPlayerNames();
449 float getAnimationTime();
452 void setCrack(int level, v3s16 pos);
454 void setHighlighted(v3s16 pos, bool show_higlighted);
455 v3s16 getHighlighted(){ return m_highlighted_pos; }
460 bool checkPrivilege(const std::string &priv)
461 { return (m_privileges.count(priv) != 0); }
463 bool getChatMessage(std::wstring &message);
464 void typeChatMessage(const std::wstring& message);
466 u64 getMapSeed(){ return m_map_seed; }
468 void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
469 // Including blocks at appropriate edges
470 void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false, bool urgent=false);
471 void addUpdateMeshTaskForNode(v3s16 nodepos, bool ack_to_server=false, bool urgent=false);
473 void updateCameraOffset(v3s16 camera_offset)
474 { m_mesh_update_thread.m_camera_offset = camera_offset; }
476 // Get event from queue. CE_NONE is returned if queue is empty.
477 ClientEvent getClientEvent();
480 { return m_access_denied; }
482 std::wstring accessDeniedReason()
483 { return m_access_denied_reason; }
485 bool itemdefReceived()
486 { return m_itemdef_received; }
487 bool nodedefReceived()
488 { return m_nodedef_received; }
490 { return m_media_downloader == NULL; }
492 float mediaReceiveProgress();
494 void afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font);
497 float getCurRate(void);
498 float getAvgRate(void);
500 // IGameDef interface
501 virtual IItemDefManager* getItemDefManager();
502 virtual INodeDefManager* getNodeDefManager();
503 virtual ICraftDefManager* getCraftDefManager();
504 virtual ITextureSource* getTextureSource();
505 virtual IShaderSource* getShaderSource();
506 virtual scene::ISceneManager* getSceneManager();
507 virtual u16 allocateUnknownNodeId(const std::string &name);
508 virtual ISoundManager* getSoundManager();
509 virtual MtEventManager* getEventManager();
510 virtual ParticleManager* getParticleManager();
511 virtual bool checkLocalPrivilege(const std::string &priv)
512 { return checkPrivilege(priv); }
513 virtual scene::IAnimatedMesh* getMesh(const std::string &filename);
515 // The following set of functions is used by ClientMediaDownloader
516 // Insert a media file appropriately into the appropriate manager
517 bool loadMedia(const std::string &data, const std::string &filename);
518 // Send a request for conventional media transfer
519 void request_media(const std::vector<std::string> &file_requests);
520 // Send a notification that no conventional media transfer is needed
521 void received_media();
523 LocalClientState getState() { return m_state; }
525 void makeScreenshot(IrrlichtDevice *device);
529 // Virtual methods from con::PeerHandler
530 void peerAdded(con::Peer *peer);
531 void deletingPeer(con::Peer *peer, bool timeout);
533 void initLocalMapSaving(const Address &address,
534 const std::string &hostname,
535 bool is_local_server);
540 void sendPlayerPos();
541 // Send the item number 'item' as player item to the server
542 void sendPlayerItem(u16 item);
544 float m_packetcounter_timer;
545 float m_connection_reinit_timer;
546 float m_avg_rtt_timer;
547 float m_playerpos_send_timer;
548 float m_ignore_damage_timer; // Used after server moves player
549 IntervalLimiter m_map_timer_and_unload_interval;
551 IWritableTextureSource *m_tsrc;
552 IWritableShaderSource *m_shsrc;
553 IWritableItemDefManager *m_itemdef;
554 IWritableNodeDefManager *m_nodedef;
555 ISoundManager *m_sound;
556 MtEventManager *m_event;
559 MeshUpdateThread m_mesh_update_thread;
560 ClientEnvironment m_env;
561 ParticleManager m_particle_manager;
562 con::Connection m_con;
563 IrrlichtDevice *m_device;
564 // Server serialization version
567 bool m_inventory_updated;
568 Inventory *m_inventory_from_server;
569 float m_inventory_from_server_age;
570 std::set<v3s16> m_active_blocks;
571 PacketCounter m_packetcounter;
572 bool m_show_highlighted;
573 // Block mesh animation parameters
574 float m_animation_time;
577 v3s16 m_highlighted_pos;
578 // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
580 //u32 m_daynight_ratio;
581 std::queue<std::wstring> m_chat_queue;
582 // The seed returned by the server in TOCLIENT_INIT is stored here
584 std::string m_password;
585 bool m_access_denied;
586 std::wstring m_access_denied_reason;
587 std::queue<ClientEvent> m_client_event_queue;
588 bool m_itemdef_received;
589 bool m_nodedef_received;
590 ClientMediaDownloader *m_media_downloader;
592 // time_of_day speed approximation for old protocol
593 bool m_time_of_day_set;
594 float m_last_time_of_day_f;
595 float m_time_of_day_update_timer;
597 // An interval for generally sending object positions and stuff
598 float m_recommended_send_interval;
601 float m_removed_sounds_check_timer;
602 // Mapping from server sound ids to our sound ids
603 std::map<s32, int> m_sounds_server_to_client;
604 // And the other way!
605 std::map<int, s32> m_sounds_client_to_server;
606 // And relations to objects
607 std::map<int, u16> m_sounds_to_objects;
610 std::set<std::string> m_privileges;
612 // Detached inventories
614 std::map<std::string, Inventory*> m_detached_inventories;
616 // Storage for mesh data for creating multiple instances of the same mesh
617 std::map<std::string, std::string> m_mesh_data;
620 LocalClientState m_state;
622 // Used for saving server map to disk client-side
626 // TODO: Add callback to update these when g_settings changes
627 bool m_cache_smooth_lighting;
628 bool m_cache_enable_shaders;
631 #endif // !CLIENT_HEADER