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