X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fclient.h;h=2f212dad8d92ce9cf74bd7378df0462896956763;hb=392485aa454e871566a67afc61e11331f9d27397;hp=3789f4cbe7e37b4ada7d94b1cd7ddb4fb452f9c1;hpb=626ed6338aa90eb07038adee29643e692fec6545;p=minetest.git diff --git a/src/client.h b/src/client.h index 3789f4cbe..2f212dad8 100644 --- a/src/client.h +++ b/src/client.h @@ -20,11 +20,24 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef CLIENT_HEADER #define CLIENT_HEADER +#ifndef SERVER + #include "connection.h" #include "environment.h" #include "common_irrlicht.h" #include "jmutex.h" #include +#include "clientobject.h" +#include "utility.h" // For IntervalLimiter +#include "gamedef.h" + +struct MeshMakeData; +class IGameDef; +class IWritableTextureSource; +class IWritableToolDefManager; +class IWritableNodeDefManager; +//class IWritableCraftDefManager; +class IWritableCraftItemDefManager; class ClientNotReadyException : public BaseException { @@ -34,125 +47,129 @@ class ClientNotReadyException : public BaseException {} }; -class Client; - -class ClientUpdateThread : public JThread +struct QueuedMeshUpdate { - bool run; - JMutex run_mutex; + v3s16 p; + MeshMakeData *data; + bool ack_block_to_server; - Client *m_client; + QueuedMeshUpdate(); + ~QueuedMeshUpdate(); +}; +/* + A thread-safe queue of mesh update tasks +*/ +class MeshUpdateQueue +{ public: + MeshUpdateQueue(); - ClientUpdateThread(Client *client) : JThread(), run(true), m_client(client) - { - run_mutex.Init(); - } + ~MeshUpdateQueue(); + + /* + peer_id=0 adds with nobody to send to + */ + void addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server); - void * Thread(); + // Returned pointer must be deleted + // Returns NULL if queue is empty + QueuedMeshUpdate * pop(); - bool getRun() + u32 size() { - run_mutex.Lock(); - bool run_cached = run; - run_mutex.Unlock(); - return run_cached; - } - void setRun(bool a_run) - { - run_mutex.Lock(); - run = a_run; - run_mutex.Unlock(); + JMutexAutoLock lock(m_mutex); + return m_queue.size(); } + +private: + core::list m_queue; + JMutex m_mutex; }; -struct IncomingPacket +struct MeshUpdateResult { - IncomingPacket() - { - m_data = NULL; - m_datalen = 0; - m_refcount = NULL; - } - IncomingPacket(const IncomingPacket &a) + v3s16 p; + scene::SMesh *mesh; + bool ack_block_to_server; + + MeshUpdateResult(): + p(-1338,-1338,-1338), + mesh(NULL), + ack_block_to_server(false) { - m_data = a.m_data; - m_datalen = a.m_datalen; - m_refcount = a.m_refcount; - if(m_refcount != NULL) - (*m_refcount)++; - } - IncomingPacket(u8 *data, u32 datalen) - { - m_data = new u8[datalen]; - memcpy(m_data, data, datalen); - m_datalen = datalen; - m_refcount = new s32(1); - } - ~IncomingPacket() - { - if(m_refcount != NULL){ - assert(*m_refcount > 0); - (*m_refcount)--; - if(*m_refcount == 0){ - if(m_data != NULL) - delete[] m_data; - } - } } - /*IncomingPacket & operator=(IncomingPacket a) - { - m_data = a.m_data; - m_datalen = a.m_datalen; - m_refcount = a.m_refcount; - (*m_refcount)++; - return *this; - }*/ - u8 *m_data; - u32 m_datalen; - s32 *m_refcount; }; -// TODO: Remove this. It is not used as supposed. -class LazyMeshUpdater +class MeshUpdateThread : public SimpleThread { public: - LazyMeshUpdater(Environment *env) - { - m_env = env; - } - ~LazyMeshUpdater() - { - /* - TODO: This could be optimized. It will currently - double-update some blocks. - */ - for(core::map::Iterator - i = m_blocks.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); - m_env->getMap().updateMeshes(p); - } - m_blocks.clear(); - } - void add(v3s16 p) + + MeshUpdateThread(IGameDef *gamedef): + m_gamedef(gamedef) { - m_blocks.insert(p, true); } -private: - Environment *m_env; - core::map m_blocks; + + void * Thread(); + + MeshUpdateQueue m_queue_in; + + MutexedQueue m_queue_out; + + IGameDef *m_gamedef; +}; + +enum ClientEventType +{ + CE_NONE, + CE_PLAYER_DAMAGE, + CE_PLAYER_FORCE_MOVE, + CE_DEATHSCREEN, + CE_TEXTURES_UPDATED }; -class Client : public con::PeerHandler +struct ClientEvent +{ + ClientEventType type; + union{ + struct{ + } none; + struct{ + u8 amount; + } player_damage; + struct{ + f32 pitch; + f32 yaw; + } player_force_move; + struct{ + bool set_camera_point_target; + f32 camera_point_target_x; + f32 camera_point_target_y; + f32 camera_point_target_z; + } deathscreen; + struct{ + } textures_updated; + }; +}; + +class Client : public con::PeerHandler, public InventoryManager, public IGameDef { public: /* - NOTE: Every public method should be thread-safe + NOTE: Nothing is thread-safe here. */ - Client(IrrlichtDevice *device, const char *playername); + + Client( + IrrlichtDevice *device, + const char *playername, + std::string password, + MapDrawControl &control, + IWritableTextureSource *tsrc, + IWritableToolDefManager *tooldef, + IWritableNodeDefManager *nodedef, + IWritableCraftItemDefManager *craftitemdef + ); + ~Client(); /* The name of the local player should already be set when @@ -177,58 +194,63 @@ class Client : public con::PeerHandler // Called from updater thread // Returns dtime - float asyncStep(); + //float asyncStep(); void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id); // Returns true if something was received - bool AsyncProcessPacket(LazyMeshUpdater &mesh_updater); + bool AsyncProcessPacket(); bool AsyncProcessData(); void Send(u16 channelnum, SharedBuffer data, bool reliable); - //TODO: Remove - bool isFetchingBlocks(); - // Pops out a packet from the packet queue - IncomingPacket getPacket(); + //IncomingPacket getPacket(); - /*void removeNode(v3s16 nodepos); - void addNodeFromInventory(v3s16 nodepos, u16 i);*/ - void clickGround(u8 button, v3s16 nodepos_undersurface, - v3s16 nodepos_oversurface, u16 item); - void clickObject(u8 button, v3s16 blockpos, s16 id, u16 item); - void release(u8 button); + void interact(u8 action, const PointedThing& pointed); - void sendSignText(v3s16 blockpos, s16 id, std::string text); + void sendSignNodeText(v3s16 p, std::string text); + void sendInventoryAction(InventoryAction *a); + void sendChatMessage(const std::wstring &message); + void sendChangePassword(const std::wstring oldpassword, + const std::wstring newpassword); + void sendDamage(u8 damage); + void sendRespawn(); + + // locks envlock + void removeNode(v3s16 p); + // locks envlock + void addNode(v3s16 p, MapNode n); + + void updateCamera(v3f pos, v3f dir, f32 fov); - void updateCamera(v3f pos, v3f dir); + void renderPostFx(); // Returns InvalidPositionException if not found MapNode getNode(v3s16 p); - // Returns InvalidPositionException if not found - //f32 getGroundHeight(v2s16 p); - // Returns InvalidPositionException if not found - bool isNodeUnderground(v3s16 p); + // Wrapper to Map + NodeMetadata* getNodeMetadata(v3s16 p); - // Note: The players should not be exposed outside - // Return value is valid until client is destroyed - //Player * getLocalPlayer(); - // Return value is valid until step() - //core::list getPlayers(); - v3f getPlayerPosition(); + LocalPlayer* getLocalPlayer(); void setPlayerControl(PlayerControl &control); - + + void selectPlayerItem(u16 item); + u16 getPlayerItem() const + { return m_playeritem; } + // Returns true if the inventory of the local player has been // updated from the server. If it is true, it is set to false. bool getLocalInventoryUpdated(); // Copies the inventory of the local player to parameter void getLocalInventory(Inventory &dst); - // TODO: Functions for sending inventory editing commands to - // server + InventoryContext *getInventoryContext(); + + Inventory* getInventory(InventoryContext *c, std::string id); + void inventoryAction(InventoryAction *a); + // Gets closest object pointed by the shootline // Returns NULL if not found - MapBlockObject * getSelectedObject( + ClientActiveObject * getSelectedActiveObject( f32 max_d, v3f from_pos_f_on_map, core::line3d shootline_on_map @@ -236,7 +258,84 @@ class Client : public con::PeerHandler // Prints a line or two of info void printDebugInfo(std::ostream &os); + + u32 getDayNightRatio(); + + u16 getHP(); + + void setTempMod(v3s16 p, NodeMod mod); + void clearTempMod(v3s16 p); + + float getAvgRtt() + { + try{ + return m_con.GetPeerAvgRTT(PEER_ID_SERVER); + } catch(con::PeerNotFoundException){ + return 1337; + } + } + + bool getChatMessage(std::wstring &message) + { + if(m_chat_queue.size() == 0) + return false; + message = m_chat_queue.pop_front(); + return true; + } + + void addChatMessage(const std::wstring &message) + { + if (message[0] == L'/') { + m_chat_queue.push_back( + (std::wstring)L"issued command: "+message); + return; + } + + //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out + LocalPlayer *player = m_env.getLocalPlayer(); + assert(player != NULL); + std::wstring name = narrow_to_wide(player->getName()); + m_chat_queue.push_back( + (std::wstring)L"<"+name+L"> "+message); + } + + u64 getMapSeed(){ return m_map_seed; } + + void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false); + // Including blocks at appropriate edges + void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false); + + // Get event from queue. CE_NONE is returned if queue is empty. + ClientEvent getClientEvent(); + bool accessDenied() + { return m_access_denied; } + + std::wstring accessDeniedReason() + { return m_access_denied_reason; } + + float textureReceiveProgress() + { return m_texture_receive_progress; } + + bool texturesReceived() + { return m_textures_received; } + bool tooldefReceived() + { return m_tooldef_received; } + bool nodedefReceived() + { return m_nodedef_received; } + bool craftitemdefReceived() + { return m_craftitemdef_received; } + + float getRTT(void); + + // IGameDef interface + virtual IToolDefManager* getToolDefManager(); + virtual INodeDefManager* getNodeDefManager(); + virtual ICraftDefManager* getCraftDefManager(); + virtual ICraftItemDefManager* getCraftItemDefManager(); + virtual ITextureSource* getTextureSource(); + virtual u16 allocateUnknownNodeId(const std::string &name); + private: // Virtual methods from con::PeerHandler @@ -249,42 +348,52 @@ class Client : public con::PeerHandler void sendPlayerPos(); // This sends the player's current name etc to the server void sendPlayerInfo(); - - ClientUpdateThread m_thread; - - // NOTE: If connection and environment are both to be locked, - // environment shall be locked first. - - Environment m_env; - JMutex m_env_mutex; + // Send the item number 'item' as player item to the server + void sendPlayerItem(u16 item); + float m_packetcounter_timer; + float m_connection_reinit_timer; + float m_avg_rtt_timer; + float m_playerpos_send_timer; + float m_ignore_damage_timer; // Used after server moves player + IntervalLimiter m_map_timer_and_unload_interval; + + IWritableTextureSource *m_tsrc; + IWritableToolDefManager *m_tooldef; + IWritableNodeDefManager *m_nodedef; + IWritableCraftItemDefManager *m_craftitemdef; + MeshUpdateThread m_mesh_update_thread; + ClientEnvironment m_env; con::Connection m_con; - JMutex m_con_mutex; - - /*core::map m_fetchblock_history; - JMutex m_fetchblock_mutex;*/ - - core::list m_incoming_queue; - JMutex m_incoming_queue_mutex; - IrrlichtDevice *m_device; - - v3f camera_position; - v3f camera_direction; - // Server serialization version u8 m_server_ser_ver; - - float m_step_dtime; - JMutex m_step_dtime_mutex; - - // This is behind m_env_mutex. + u16 m_playeritem; bool m_inventory_updated; - core::map m_active_blocks; - PacketCounter m_packetcounter; + // Received from the server. 0-23999 + u32 m_time_of_day; + // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT + //s32 m_daynight_i; + //u32 m_daynight_ratio; + Queue m_chat_queue; + // The seed returned by the server in TOCLIENT_INIT is stored here + u64 m_map_seed; + std::string m_password; + bool m_access_denied; + std::wstring m_access_denied_reason; + InventoryContext m_inventory_context; + Queue m_client_event_queue; + float m_texture_receive_progress; + bool m_textures_received; + bool m_tooldef_received; + bool m_nodedef_received; + bool m_craftitemdef_received; + friend class FarMesh; }; -#endif +#endif // !SERVER + +#endif // !CLIENT_HEADER