]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.h
851a5ba67ab7e7e2c5a2f0cf4f3817f1a446ba2e
[dragonfireclient.git] / src / server.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 /*
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
22 */
23
24 #ifndef SERVER_HEADER
25 #define SERVER_HEADER
26
27 #include "connection.h"
28 #include "environment.h"
29 #include "common_irrlicht.h"
30 #include <string>
31
32 #ifdef _WIN32
33         #include <windows.h>
34         #define sleep_ms(x) Sleep(x)
35 #else
36         #include <unistd.h>
37         #define sleep_ms(x) usleep(x*1000)
38 #endif
39
40 struct QueuedBlockEmerge
41 {
42         v3s16 pos;
43         // key = peer_id, value = flags
44         core::map<u16, u8> peer_ids;
45 };
46
47 /*
48         This is a thread-safe class.
49 */
50 class BlockEmergeQueue
51 {
52 public:
53         BlockEmergeQueue()
54         {
55                 m_mutex.Init();
56         }
57
58         ~BlockEmergeQueue()
59         {
60                 JMutexAutoLock lock(m_mutex);
61
62                 core::list<QueuedBlockEmerge*>::Iterator i;
63                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
64                 {
65                         QueuedBlockEmerge *q = *i;
66                         delete q;
67                 }
68         }
69         
70         /*
71                 peer_id=0 adds with nobody to send to
72         */
73         void addBlock(u16 peer_id, v3s16 pos, u8 flags)
74         {
75                 DSTACK(__FUNCTION_NAME);
76         
77                 JMutexAutoLock lock(m_mutex);
78
79                 if(peer_id != 0)
80                 {
81                         /*
82                                 Find if block is already in queue.
83                                 If it is, update the peer to it and quit.
84                         */
85                         core::list<QueuedBlockEmerge*>::Iterator i;
86                         for(i=m_queue.begin(); i!=m_queue.end(); i++)
87                         {
88                                 QueuedBlockEmerge *q = *i;
89                                 if(q->pos == pos)
90                                 {
91                                         q->peer_ids[peer_id] = flags;
92                                         return;
93                                 }
94                         }
95                 }
96                 
97                 /*
98                         Add the block
99                 */
100                 QueuedBlockEmerge *q = new QueuedBlockEmerge;
101                 q->pos = pos;
102                 if(peer_id != 0)
103                         q->peer_ids[peer_id] = flags;
104                 m_queue.push_back(q);
105         }
106
107         // Returned pointer must be deleted
108         // Returns NULL if queue is empty
109         QueuedBlockEmerge * pop()
110         {
111                 JMutexAutoLock lock(m_mutex);
112
113                 core::list<QueuedBlockEmerge*>::Iterator i = m_queue.begin();
114                 if(i == m_queue.end())
115                         return NULL;
116                 QueuedBlockEmerge *q = *i;
117                 m_queue.erase(i);
118                 return q;
119         }
120
121         u32 size()
122         {
123                 JMutexAutoLock lock(m_mutex);
124                 return m_queue.size();
125         }
126         
127         u32 peerItemCount(u16 peer_id)
128         {
129                 JMutexAutoLock lock(m_mutex);
130
131                 u32 count = 0;
132
133                 core::list<QueuedBlockEmerge*>::Iterator i;
134                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
135                 {
136                         QueuedBlockEmerge *q = *i;
137                         if(q->peer_ids.find(peer_id) != NULL)
138                                 count++;
139                 }
140
141                 return count;
142         }
143
144 private:
145         core::list<QueuedBlockEmerge*> m_queue;
146         JMutex m_mutex;
147 };
148
149 class SimpleThread : public JThread
150 {
151         bool run;
152         JMutex run_mutex;
153
154 public:
155
156         SimpleThread():
157                 JThread(),
158                 run(true)
159         {
160                 run_mutex.Init();
161         }
162
163         virtual ~SimpleThread()
164         {}
165
166         virtual void * Thread() = 0;
167
168         bool getRun()
169         {
170                 JMutexAutoLock lock(run_mutex);
171                 return run;
172         }
173         void setRun(bool a_run)
174         {
175                 JMutexAutoLock lock(run_mutex);
176                 run = a_run;
177         }
178
179         void stop()
180         {
181                 setRun(false);
182                 while(IsRunning())
183                         sleep_ms(100);
184         }
185 };
186
187 class Server;
188
189 class ServerThread : public SimpleThread
190 {
191         Server *m_server;
192
193 public:
194
195         ServerThread(Server *server):
196                 SimpleThread(),
197                 m_server(server)
198         {
199         }
200
201         void * Thread();
202 };
203
204 class EmergeThread : public SimpleThread
205 {
206         Server *m_server;
207
208 public:
209
210         EmergeThread(Server *server):
211                 SimpleThread(),
212                 m_server(server)
213         {
214         }
215
216         void * Thread();
217
218         void trigger()
219         {
220                 setRun(true);
221                 if(IsRunning() == false)
222                 {
223                         Start();
224                 }
225         }
226 };
227
228 struct PlayerInfo
229 {
230         u16 id;
231         char name[PLAYERNAME_SIZE];
232         v3f position;
233         Address address;
234         float avg_rtt;
235
236         PlayerInfo();
237         void PrintLine(std::ostream *s);
238 };
239
240 u32 PIChecksum(core::list<PlayerInfo> &l);
241
242 /*
243         Used for queueing and sorting block transfers in containers
244         
245         Lower priority number means higher priority.
246 */
247 struct PrioritySortedBlockTransfer
248 {
249         PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
250         {
251                 priority = a_priority;
252                 pos = a_pos;
253                 peer_id = a_peer_id;
254         }
255         bool operator < (PrioritySortedBlockTransfer &other)
256         {
257                 return priority < other.priority;
258         }
259         float priority;
260         v3s16 pos;
261         u16 peer_id;
262 };
263
264 class RemoteClient
265 {
266 public:
267         // peer_id=0 means this client has no associated peer
268         // NOTE: If client is made allowed to exist while peer doesn't,
269         //       this has to be set to 0 when there is no peer.
270         //       Also, the client must be moved to some other container.
271         u16 peer_id;
272         // The serialization version to use with the client
273         u8 serialization_version;
274         // Version is stored in here after INIT before INIT2
275         u8 pending_serialization_version;
276
277         RemoteClient():
278                 m_time_from_building(9999)
279         {
280                 peer_id = 0;
281                 serialization_version = SER_FMT_VER_INVALID;
282                 pending_serialization_version = SER_FMT_VER_INVALID;
283                 m_nearest_unsent_d = 0;
284
285                 m_blocks_sent_mutex.Init();
286                 m_blocks_sending_mutex.Init();
287                 
288                 m_dig_mutex.Init();
289                 m_dig_time_remaining = 0;
290                 m_dig_tool_item = -1;
291         }
292         ~RemoteClient()
293         {
294         }
295         
296         /*
297                 Finds block that should be sent next to the client.
298                 Environment should be locked when this is called.
299                 dtime is used for resetting send radius at slow interval
300         */
301         void GetNextBlocks(Server *server, float dtime,
302                         core::array<PrioritySortedBlockTransfer> &dest);
303
304         // Connection and environment should be locked when this is called
305         // steps() objects of blocks not found in active_blocks, then
306         // adds those blocks to active_blocks
307         void SendObjectData(
308                         Server *server,
309                         float dtime,
310                         core::map<v3s16, bool> &stepped_blocks
311                 );
312
313         void GotBlock(v3s16 p);
314
315         void SentBlock(v3s16 p);
316
317         void SetBlockNotSent(v3s16 p);
318         void SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks);
319
320         //void BlockEmerged();
321
322         /*bool IsSendingBlock(v3s16 p)
323         {
324                 JMutexAutoLock lock(m_blocks_sending_mutex);
325                 return (m_blocks_sending.find(p) != NULL);
326         }*/
327
328         s32 SendingCount()
329         {
330                 JMutexAutoLock lock(m_blocks_sending_mutex);
331                 return m_blocks_sending.size();
332         }
333         
334         // Increments timeouts and removes timed-out blocks from list
335         // NOTE: This doesn't fix the server-not-sending-block bug
336         //       because it is related to emerging, not sending.
337         //void RunSendingTimeouts(float dtime, float timeout);
338
339         void PrintInfo(std::ostream &o)
340         {
341                 JMutexAutoLock l2(m_blocks_sent_mutex);
342                 JMutexAutoLock l3(m_blocks_sending_mutex);
343                 o<<"RemoteClient "<<peer_id<<": "
344                                 <<", m_blocks_sent.size()="<<m_blocks_sent.size()
345                                 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
346                                 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
347                                 <<std::endl;
348         }
349
350         // Time from last placing or removing blocks
351         MutexedVariable<float> m_time_from_building;
352         
353         JMutex m_dig_mutex;
354         float m_dig_time_remaining;
355         // -1 = not digging
356         s16 m_dig_tool_item;
357         v3s16 m_dig_position;
358
359 private:
360         /*
361                 All members that are accessed by many threads should
362                 obviously be behind a mutex. The threads include:
363                 - main thread (calls step())
364                 - server thread (calls AsyncRunStep() and Receive())
365                 - emerge thread 
366         */
367         
368         //TODO: core::map<v3s16, MapBlock*> m_active_blocks
369         //NOTE: Not here, it should be server-wide!
370
371         // Number of blocks in the emerge queue that have this client as
372         // a receiver. Used for throttling network usage.
373         //MutexedVariable<s16> m_num_blocks_in_emerge_queue;
374
375         /*
376                 Blocks that have been sent to client.
377                 - These don't have to be sent again.
378                 - A block is cleared from here when client says it has
379                   deleted it from it's memory
380                 
381                 Key is position, value is dummy.
382                 No MapBlock* is stored here because the blocks can get deleted.
383         */
384         core::map<v3s16, bool> m_blocks_sent;
385         s16 m_nearest_unsent_d;
386         v3s16 m_last_center;
387         JMutex m_blocks_sent_mutex;
388         /*
389                 Blocks that are currently on the line.
390                 This is used for throttling the sending of blocks.
391                 - The size of this list is limited to some value
392                 Block is added when it is sent with BLOCKDATA.
393                 Block is removed when GOTBLOCKS is received.
394                 Value is time from sending. (not used at the moment)
395         */
396         core::map<v3s16, float> m_blocks_sending;
397         JMutex m_blocks_sending_mutex;
398 };
399
400 /*struct ServerSettings
401 {
402         ServerSettings()
403         {
404                 creative_mode = false;
405         }
406         bool creative_mode;
407 };*/
408
409 class Server : public con::PeerHandler
410 {
411 public:
412         /*
413                 NOTE: Every public method should be thread-safe
414         */
415         Server(
416                 std::string mapsavedir,
417                 HMParams hm_params,
418                 MapParams map_params
419         );
420         ~Server();
421         void start(unsigned short port);
422         void stop();
423         // This is mainly a way to pass the time to the server.
424         // Actual processing is done in an another thread.
425         void step(float dtime);
426         // This is run by ServerThread and does the actual processing
427         void AsyncRunStep();
428         void Receive();
429         void ProcessData(u8 *data, u32 datasize, u16 peer_id);
430
431         /*void Send(u16 peer_id, u16 channelnum,
432                         SharedBuffer<u8> data, bool reliable);*/
433
434         // Environment and Connection must be locked when called
435         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
436         //TODO: Sending of many blocks in a single packet
437         
438         // Environment and Connection must be locked when called
439         //void SendSectorMeta(u16 peer_id, core::list<v2s16> ps, u8 ver);
440
441         core::list<PlayerInfo> getPlayerInfo();
442         
443 private:
444
445         // Virtual methods from con::PeerHandler.
446         // As of now, these create and remove clients and players.
447         // TODO: Make it possible to leave players on server.
448         void peerAdded(con::Peer *peer);
449         void deletingPeer(con::Peer *peer, bool timeout);
450         
451         // Envlock and conlock should be locked when calling these
452         void SendObjectData(float dtime);
453         void SendPlayerInfos();
454         void SendInventory(u16 peer_id);
455         // Sends blocks to clients
456         void SendBlocks(float dtime);
457         
458         // When called, connection mutex should be locked
459         RemoteClient* getClient(u16 peer_id);
460
461         /*
462                 Update water pressure.
463                 This also adds suitable nodes to active_nodes.
464
465                 environment has to be locked when calling.
466         */
467         void UpdateBlockWaterPressure(MapBlock *block,
468                         core::map<v3s16, MapBlock*> &modified_blocks);
469         
470         // NOTE: If connection and environment are both to be locked,
471         // environment shall be locked first.
472         JMutex m_env_mutex;
473         Environment m_env;
474
475         JMutex m_con_mutex;
476         con::Connection m_con;
477         core::map<u16, RemoteClient*> m_clients; // Behind the con mutex
478
479         float m_step_dtime;
480         JMutex m_step_dtime_mutex;
481
482         ServerThread m_thread;
483         EmergeThread m_emergethread;
484
485         BlockEmergeQueue m_emerge_queue;
486         
487         // Nodes that are destinations of flowing liquid at the moment
488         core::map<v3s16, u8> m_flow_active_nodes;
489         
490         friend class EmergeThread;
491         friend class RemoteClient;
492 };
493
494 #endif
495