49794acf585b16d4050024172ebec96c3809bcdc
[oweals/minetest.git] / src / client.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
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 General Public License for more details.
14
15 You should have received a copy of the GNU 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.
18 */
19
20 #ifndef CLIENT_HEADER
21 #define CLIENT_HEADER
22
23 #ifndef SERVER
24
25 #include "connection.h"
26 #include "environment.h"
27 #include "common_irrlicht.h"
28 #include "jmutex.h"
29 #include <ostream>
30 #include "clientobject.h"
31 #include "utility.h" // For IntervalLimiter
32 #include "gamedef.h"
33 #include "inventorymanager.h"
34 #include "filesys.h"
35
36 struct MeshMakeData;
37 class IGameDef;
38 class IWritableTextureSource;
39 class IWritableToolDefManager;
40 class IWritableNodeDefManager;
41 //class IWritableCraftDefManager;
42 class IWritableCraftItemDefManager;
43
44 class ClientNotReadyException : public BaseException
45 {
46 public:
47         ClientNotReadyException(const char *s):
48                 BaseException(s)
49         {}
50 };
51
52 struct QueuedMeshUpdate
53 {
54         v3s16 p;
55         MeshMakeData *data;
56         bool ack_block_to_server;
57
58         QueuedMeshUpdate();
59         ~QueuedMeshUpdate();
60 };
61
62 /*
63         A thread-safe queue of mesh update tasks
64 */
65 class MeshUpdateQueue
66 {
67 public:
68         MeshUpdateQueue();
69
70         ~MeshUpdateQueue();
71         
72         /*
73                 peer_id=0 adds with nobody to send to
74         */
75         void addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_server);
76
77         // Returned pointer must be deleted
78         // Returns NULL if queue is empty
79         QueuedMeshUpdate * pop();
80
81         u32 size()
82         {
83                 JMutexAutoLock lock(m_mutex);
84                 return m_queue.size();
85         }
86         
87 private:
88         core::list<QueuedMeshUpdate*> m_queue;
89         JMutex m_mutex;
90 };
91
92 struct MeshUpdateResult
93 {
94         v3s16 p;
95         scene::SMesh *mesh;
96         bool ack_block_to_server;
97
98         MeshUpdateResult():
99                 p(-1338,-1338,-1338),
100                 mesh(NULL),
101                 ack_block_to_server(false)
102         {
103         }
104 };
105
106 class MeshUpdateThread : public SimpleThread
107 {
108 public:
109
110         MeshUpdateThread(IGameDef *gamedef):
111                 m_gamedef(gamedef)
112         {
113         }
114
115         void * Thread();
116
117         MeshUpdateQueue m_queue_in;
118
119         MutexedQueue<MeshUpdateResult> m_queue_out;
120
121         IGameDef *m_gamedef;
122 };
123
124 enum ClientEventType
125 {
126         CE_NONE,
127         CE_PLAYER_DAMAGE,
128         CE_PLAYER_FORCE_MOVE,
129         CE_DEATHSCREEN,
130         CE_TEXTURES_UPDATED
131 };
132
133 struct ClientEvent
134 {
135         ClientEventType type;
136         union{
137                 struct{
138                 } none;
139                 struct{
140                         u8 amount;
141                 } player_damage;
142                 struct{
143                         f32 pitch;
144                         f32 yaw;
145                 } player_force_move;
146                 struct{
147                         bool set_camera_point_target;
148                         f32 camera_point_target_x;
149                         f32 camera_point_target_y;
150                         f32 camera_point_target_z;
151                 } deathscreen;
152                 struct{
153                 } textures_updated;
154         };
155 };
156
157 class Client : public con::PeerHandler, public InventoryManager, public IGameDef
158 {
159 public:
160         /*
161                 NOTE: Nothing is thread-safe here.
162         */
163
164         Client(
165                         IrrlichtDevice *device,
166                         const char *playername,
167                         std::string password,
168                         MapDrawControl &control,
169                         IWritableTextureSource *tsrc,
170                         IWritableToolDefManager *tooldef,
171                         IWritableNodeDefManager *nodedef,
172                         IWritableCraftItemDefManager *craftitemdef
173         );
174         
175         ~Client();
176         /*
177                 The name of the local player should already be set when
178                 calling this, as it is sent in the initialization.
179         */
180         void connect(Address address);
181         /*
182                 returns true when
183                         m_con.Connected() == true
184                         AND m_server_ser_ver != SER_FMT_VER_INVALID
185                 throws con::PeerNotFoundException if connection has been deleted,
186                 eg. timed out.
187         */
188         bool connectedAndInitialized();
189         /*
190                 Stuff that references the environment is valid only as
191                 long as this is not called. (eg. Players)
192                 If this throws a PeerNotFoundException, the connection has
193                 timed out.
194         */
195         void step(float dtime);
196
197         // Called from updater thread
198         // Returns dtime
199         //float asyncStep();
200
201         void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id);
202         // Returns true if something was received
203         bool AsyncProcessPacket();
204         bool AsyncProcessData();
205         void Send(u16 channelnum, SharedBuffer<u8> data, bool reliable);
206
207         // Pops out a packet from the packet queue
208         //IncomingPacket getPacket();
209
210         void interact(u8 action, const PointedThing& pointed);
211
212         void sendSignNodeText(v3s16 p, std::string text);
213         void sendInventoryAction(InventoryAction *a);
214         void sendChatMessage(const std::wstring &message);
215         void sendChangePassword(const std::wstring oldpassword,
216                 const std::wstring newpassword);
217         void sendDamage(u8 damage);
218         void sendRespawn();
219         
220         // locks envlock
221         void removeNode(v3s16 p);
222         // locks envlock
223         void addNode(v3s16 p, MapNode n);
224         
225         void updateCamera(v3f pos, v3f dir, f32 fov);
226         
227         void renderPostFx();
228         
229         // Returns InvalidPositionException if not found
230         MapNode getNode(v3s16 p);
231         // Wrapper to Map
232         NodeMetadata* getNodeMetadata(v3s16 p);
233
234         LocalPlayer* getLocalPlayer();
235
236         void setPlayerControl(PlayerControl &control);
237
238         void selectPlayerItem(u16 item);
239         u16 getPlayerItem() const
240         { return m_playeritem; }
241
242         // Returns true if the inventory of the local player has been
243         // updated from the server. If it is true, it is set to false.
244         bool getLocalInventoryUpdated();
245         // Copies the inventory of the local player to parameter
246         void getLocalInventory(Inventory &dst);
247         
248         InventoryContext *getInventoryContext();
249
250         /* InventoryManager interface */
251         Inventory* getInventory(const InventoryLocation &loc);
252         //Inventory* getInventory(InventoryContext *c, std::string id);
253         void inventoryAction(InventoryAction *a);
254
255         // Gets closest object pointed by the shootline
256         // Returns NULL if not found
257         ClientActiveObject * getSelectedActiveObject(
258                         f32 max_d,
259                         v3f from_pos_f_on_map,
260                         core::line3d<f32> shootline_on_map
261         );
262
263         // Prints a line or two of info
264         void printDebugInfo(std::ostream &os);
265
266         u32 getDayNightRatio();
267
268         u16 getHP();
269
270         void setTempMod(v3s16 p, NodeMod mod);
271         void clearTempMod(v3s16 p);
272
273         float getAvgRtt()
274         {
275                 try{
276                         return m_con.GetPeerAvgRTT(PEER_ID_SERVER);
277                 } catch(con::PeerNotFoundException){
278                         return 1337;
279                 }
280         }
281
282         bool getChatMessage(std::wstring &message)
283         {
284                 if(m_chat_queue.size() == 0)
285                         return false;
286                 message = m_chat_queue.pop_front();
287                 return true;
288         }
289
290         void addChatMessage(const std::wstring &message)
291         {
292                 if (message[0] == L'/') {
293                         m_chat_queue.push_back(
294                                 (std::wstring)L"issued command: "+message);
295                         return;
296                 }
297
298                 //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out
299                 LocalPlayer *player = m_env.getLocalPlayer();
300                 assert(player != NULL);
301                 std::wstring name = narrow_to_wide(player->getName());
302                 m_chat_queue.push_back(
303                                 (std::wstring)L"<"+name+L"> "+message);
304         }
305
306         u64 getMapSeed(){ return m_map_seed; }
307
308         void addUpdateMeshTask(v3s16 blockpos, bool ack_to_server=false);
309         // Including blocks at appropriate edges
310         void addUpdateMeshTaskWithEdge(v3s16 blockpos, bool ack_to_server=false);
311
312         // Get event from queue. CE_NONE is returned if queue is empty.
313         ClientEvent getClientEvent();
314         
315         bool accessDenied()
316         { return m_access_denied; }
317
318         std::wstring accessDeniedReason()
319         { return m_access_denied_reason; }
320
321         float textureReceiveProgress()
322         { return m_texture_receive_progress; }
323
324         bool texturesReceived()
325         { return m_textures_received; }
326         bool tooldefReceived()
327         { return m_tooldef_received; }
328         bool nodedefReceived()
329         { return m_nodedef_received; }
330         bool craftitemdefReceived()
331         { return m_craftitemdef_received; }
332         
333         float getRTT(void);
334
335         // IGameDef interface
336         virtual IToolDefManager* getToolDefManager();
337         virtual INodeDefManager* getNodeDefManager();
338         virtual ICraftDefManager* getCraftDefManager();
339         virtual ICraftItemDefManager* getCraftItemDefManager();
340         virtual ITextureSource* getTextureSource();
341         virtual u16 allocateUnknownNodeId(const std::string &name);
342
343 private:
344         
345         // Virtual methods from con::PeerHandler
346         void peerAdded(con::Peer *peer);
347         void deletingPeer(con::Peer *peer, bool timeout);
348         
349         void ReceiveAll();
350         void Receive();
351         
352         void sendPlayerPos();
353         // This sends the player's current name etc to the server
354         void sendPlayerInfo();
355         // Send the item number 'item' as player item to the server
356         void sendPlayerItem(u16 item);
357         
358         float m_packetcounter_timer;
359         float m_connection_reinit_timer;
360         float m_avg_rtt_timer;
361         float m_playerpos_send_timer;
362         float m_ignore_damage_timer; // Used after server moves player
363         IntervalLimiter m_map_timer_and_unload_interval;
364
365         IWritableTextureSource *m_tsrc;
366         IWritableToolDefManager *m_tooldef;
367         IWritableNodeDefManager *m_nodedef;
368         IWritableCraftItemDefManager *m_craftitemdef;
369         MeshUpdateThread m_mesh_update_thread;
370         ClientEnvironment m_env;
371         con::Connection m_con;
372         IrrlichtDevice *m_device;
373         // Server serialization version
374         u8 m_server_ser_ver;
375         u16 m_playeritem;
376         bool m_inventory_updated;
377         core::map<v3s16, bool> m_active_blocks;
378         PacketCounter m_packetcounter;
379         // Received from the server. 0-23999
380         u32 m_time_of_day;
381         // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
382         //s32 m_daynight_i;
383         //u32 m_daynight_ratio;
384         Queue<std::wstring> m_chat_queue;
385         // The seed returned by the server in TOCLIENT_INIT is stored here
386         u64 m_map_seed;
387         std::string m_password;
388         bool m_access_denied;
389         std::wstring m_access_denied_reason;
390         InventoryContext m_inventory_context;
391         Queue<ClientEvent> m_client_event_queue;
392         float m_texture_receive_progress;
393         bool m_textures_received;
394         bool m_tooldef_received;
395         bool m_nodedef_received;
396         bool m_craftitemdef_received;
397         friend class FarMesh;
398 };
399
400 #endif // !SERVER
401
402 #endif // !CLIENT_HEADER
403