Initial files
[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 class RemoteClient
205 {
206 public:
207         // peer_id=0 means this client has no associated peer
208         // NOTE: If client is made allowed to exist while peer doesn't,
209         //       this has to be set to 0 when there is no peer.
210         //       Also, the client must be moved to some other container.
211         u16 peer_id;
212         // The serialization version to use with the client
213         u8 serialization_version;
214         // Version is stored in here after INIT before INIT2
215         u8 pending_serialization_version;
216
217         RemoteClient():
218                 m_time_from_building(0.0),
219                 m_num_blocks_in_emerge_queue(0)
220         {
221                 peer_id = 0;
222                 serialization_version = SER_FMT_VER_INVALID;
223                 pending_serialization_version = SER_FMT_VER_INVALID;
224                 m_nearest_unsent_d = 0;
225
226                 m_blocks_sent_mutex.Init();
227                 m_blocks_sending_mutex.Init();
228         }
229         ~RemoteClient()
230         {
231         }
232         
233         // Connection and environment should be locked when this is called
234         void SendBlocks(Server *server, float dtime);
235
236         // Connection and environment should be locked when this is called
237         // steps() objects of blocks not found in active_blocks, then
238         // adds those blocks to active_blocks
239         void SendObjectData(
240                         Server *server,
241                         float dtime,
242                         core::map<v3s16, bool> &stepped_blocks
243                 );
244
245         void GotBlock(v3s16 p);
246
247         void SentBlock(v3s16 p);
248
249         void SetBlockNotSent(v3s16 p);
250         void SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks);
251
252         void BlockEmerged();
253         
254         // Increments timeouts and removes timed-out blocks from list
255         //void RunSendingTimeouts(float dtime, float timeout);
256
257         void PrintInfo(std::ostream &o)
258         {
259                 JMutexAutoLock l2(m_blocks_sent_mutex);
260                 JMutexAutoLock l3(m_blocks_sending_mutex);
261                 o<<"RemoteClient "<<peer_id<<": "
262                                 <<"m_num_blocks_in_emerge_queue="
263                                 <<m_num_blocks_in_emerge_queue.get()
264                                 <<", m_blocks_sent.size()="<<m_blocks_sent.size()
265                                 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
266                                 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
267                                 <<std::endl;
268         }
269
270         // Time from last placing or removing blocks
271         MutexedVariable<float> m_time_from_building;
272         
273 private:
274         /*
275                 All members that are accessed by many threads should
276                 obviously be behind a mutex. The threads include:
277                 - main thread (calls step())
278                 - server thread (calls AsyncRunStep() and Receive())
279                 - emerge thread 
280         */
281         
282         //TODO: core::map<v3s16, MapBlock*> m_active_blocks
283
284         // Number of blocks in the emerge queue that have this client as
285         // a receiver. Used for throttling network usage.
286         MutexedVariable<s16> m_num_blocks_in_emerge_queue;
287
288         /*
289                 Blocks that have been sent to client.
290                 - These don't have to be sent again.
291                 - A block is cleared from here when client says it has
292                   deleted it from it's memory
293                 
294                 Key is position, value is dummy.
295                 No MapBlock* is stored here because the blocks can get deleted.
296         */
297         core::map<v3s16, bool> m_blocks_sent;
298         s16 m_nearest_unsent_d;
299         v3s16 m_last_center;
300         JMutex m_blocks_sent_mutex;
301         /*
302                 Blocks that are currently on the line.
303                 This is used for throttling the sending of blocks.
304                 - The size of this list is limited to some value
305                 Block is added when it is sent with BLOCKDATA.
306                 Block is removed when GOTBLOCKS is received.
307                 Value is time from sending. (not used at the moment)
308         */
309         core::map<v3s16, float> m_blocks_sending;
310         JMutex m_blocks_sending_mutex;
311 };
312
313 class Server : public con::PeerHandler
314 {
315 public:
316         /*
317                 NOTE: Every public method should be thread-safe
318         */
319         Server(
320                         std::string mapsavedir,
321                         bool creative_mode,
322                         MapgenParams mapgen_params
323                 );
324         ~Server();
325         void start(unsigned short port);
326         void stop();
327         void step(float dtime);
328         void AsyncRunStep();
329         void Receive();
330         void ProcessData(u8 *data, u32 datasize, u16 peer_id);
331
332         /*void Send(u16 peer_id, u16 channelnum,
333                         SharedBuffer<u8> data, bool reliable);*/
334
335         // Environment and Connection must be locked when called
336         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
337         //void SendBlock(u16 peer_id, MapBlock *block, u8 ver);
338         //TODO: Sending of many blocks in a single packet
339         
340         // Environment and Connection must be locked when called
341         //void SendSectorMeta(u16 peer_id, core::list<v2s16> ps, u8 ver);
342
343         core::list<PlayerInfo> getPlayerInfo();
344         
345 private:
346
347         // Virtual methods from con::PeerHandler.
348         // As of now, these create and remove clients and players.
349         // TODO: Make it possible to leave players on server.
350         void peerAdded(con::Peer *peer);
351         void deletingPeer(con::Peer *peer, bool timeout);
352         
353         // Envlock and conlock should be locked when calling these
354         void SendObjectData(float dtime);
355         void SendPlayerInfos();
356         void SendInventory(u16 peer_id);
357         // Sends blocks to clients
358         void SendBlocks(float dtime);
359         
360         // When called, connection mutex should be locked
361         RemoteClient* getClient(u16 peer_id);
362         
363         // NOTE: If connection and environment are both to be locked,
364         // environment shall be locked first.
365
366         JMutex m_env_mutex;
367         Environment m_env;
368
369         JMutex m_con_mutex;
370         con::Connection m_con;
371         core::map<u16, RemoteClient*> m_clients; // Behind the con mutex
372
373         float m_step_dtime;
374         JMutex m_step_dtime_mutex;
375
376         ServerThread m_thread;
377         EmergeThread m_emergethread;
378
379         BlockEmergeQueue m_emerge_queue;
380
381         bool m_creative_mode;
382
383         friend class EmergeThread;
384         friend class RemoteClient;
385 };
386
387 #endif
388