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