]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.h
license stuff
[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(0.0)
279                 //m_num_blocks_in_emerge_queue(0)
280         {
281                 peer_id = 0;
282                 serialization_version = SER_FMT_VER_INVALID;
283                 pending_serialization_version = SER_FMT_VER_INVALID;
284                 m_nearest_unsent_d = 0;
285
286                 m_blocks_sent_mutex.Init();
287                 m_blocks_sending_mutex.Init();
288         }
289         ~RemoteClient()
290         {
291         }
292         
293         /*
294                 Finds block that should be sent next to the client.
295                 Environment should be locked when this is called.
296                 dtime is used for resetting send radius at slow interval
297         */
298         void GetNextBlocks(Server *server, float dtime,
299                         core::array<PrioritySortedBlockTransfer> &dest);
300
301         // Connection and environment should be locked when this is called
302         // steps() objects of blocks not found in active_blocks, then
303         // adds those blocks to active_blocks
304         void SendObjectData(
305                         Server *server,
306                         float dtime,
307                         core::map<v3s16, bool> &stepped_blocks
308                 );
309
310         void GotBlock(v3s16 p);
311
312         void SentBlock(v3s16 p);
313
314         void SetBlockNotSent(v3s16 p);
315         void SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks);
316
317         //void BlockEmerged();
318
319         /*bool IsSendingBlock(v3s16 p)
320         {
321                 JMutexAutoLock lock(m_blocks_sending_mutex);
322                 return (m_blocks_sending.find(p) != NULL);
323         }*/
324
325         s32 SendingCount()
326         {
327                 JMutexAutoLock lock(m_blocks_sending_mutex);
328                 return m_blocks_sending.size();
329         }
330         
331         // Increments timeouts and removes timed-out blocks from list
332         // NOTE: This doesn't fix the server-not-sending-block bug
333         //       because it is related to emerging, not sending.
334         //void RunSendingTimeouts(float dtime, float timeout);
335
336         void PrintInfo(std::ostream &o)
337         {
338                 JMutexAutoLock l2(m_blocks_sent_mutex);
339                 JMutexAutoLock l3(m_blocks_sending_mutex);
340                 o<<"RemoteClient "<<peer_id<<": "
341                                 /*<<"m_num_blocks_in_emerge_queue="
342                                 <<m_num_blocks_in_emerge_queue.get()*/
343                                 <<", m_blocks_sent.size()="<<m_blocks_sent.size()
344                                 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
345                                 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
346                                 <<std::endl;
347         }
348
349         // Time from last placing or removing blocks
350         MutexedVariable<float> m_time_from_building;
351         
352 private:
353         /*
354                 All members that are accessed by many threads should
355                 obviously be behind a mutex. The threads include:
356                 - main thread (calls step())
357                 - server thread (calls AsyncRunStep() and Receive())
358                 - emerge thread 
359         */
360         
361         //TODO: core::map<v3s16, MapBlock*> m_active_blocks
362         //NOTE: Not here, it should be server-wide!
363
364         // Number of blocks in the emerge queue that have this client as
365         // a receiver. Used for throttling network usage.
366         //MutexedVariable<s16> m_num_blocks_in_emerge_queue;
367
368         /*
369                 Blocks that have been sent to client.
370                 - These don't have to be sent again.
371                 - A block is cleared from here when client says it has
372                   deleted it from it's memory
373                 
374                 Key is position, value is dummy.
375                 No MapBlock* is stored here because the blocks can get deleted.
376         */
377         core::map<v3s16, bool> m_blocks_sent;
378         s16 m_nearest_unsent_d;
379         v3s16 m_last_center;
380         JMutex m_blocks_sent_mutex;
381         /*
382                 Blocks that are currently on the line.
383                 This is used for throttling the sending of blocks.
384                 - The size of this list is limited to some value
385                 Block is added when it is sent with BLOCKDATA.
386                 Block is removed when GOTBLOCKS is received.
387                 Value is time from sending. (not used at the moment)
388         */
389         core::map<v3s16, float> m_blocks_sending;
390         JMutex m_blocks_sending_mutex;
391 };
392
393 /*struct ServerSettings
394 {
395         ServerSettings()
396         {
397                 creative_mode = false;
398         }
399         bool creative_mode;
400 };*/
401
402 class Server : public con::PeerHandler
403 {
404 public:
405         /*
406                 NOTE: Every public method should be thread-safe
407         */
408         Server(
409                 std::string mapsavedir,
410                 HMParams hm_params,
411                 MapParams map_params
412         );
413         ~Server();
414         void start(unsigned short port);
415         void stop();
416         // This is mainly a way to pass the time to the server.
417         // Actual processing is done in an another thread.
418         void step(float dtime);
419         // This is run by ServerThread and does the actual processing
420         void AsyncRunStep();
421         void Receive();
422         void ProcessData(u8 *data, u32 datasize, u16 peer_id);
423
424         /*void Send(u16 peer_id, u16 channelnum,
425                         SharedBuffer<u8> data, bool reliable);*/
426
427         // Environment and Connection must be locked when called
428         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
429         //TODO: Sending of many blocks in a single packet
430         
431         // Environment and Connection must be locked when called
432         //void SendSectorMeta(u16 peer_id, core::list<v2s16> ps, u8 ver);
433
434         core::list<PlayerInfo> getPlayerInfo();
435         
436 private:
437
438         // Virtual methods from con::PeerHandler.
439         // As of now, these create and remove clients and players.
440         // TODO: Make it possible to leave players on server.
441         void peerAdded(con::Peer *peer);
442         void deletingPeer(con::Peer *peer, bool timeout);
443         
444         // Envlock and conlock should be locked when calling these
445         void SendObjectData(float dtime);
446         void SendPlayerInfos();
447         void SendInventory(u16 peer_id);
448         // Sends blocks to clients
449         void SendBlocks(float dtime);
450         
451         // When called, connection mutex should be locked
452         RemoteClient* getClient(u16 peer_id);
453         
454         // NOTE: If connection and environment are both to be locked,
455         // environment shall be locked first.
456
457         JMutex m_env_mutex;
458         Environment m_env;
459
460         JMutex m_con_mutex;
461         con::Connection m_con;
462         core::map<u16, RemoteClient*> m_clients; // Behind the con mutex
463
464         float m_step_dtime;
465         JMutex m_step_dtime_mutex;
466
467         ServerThread m_thread;
468         EmergeThread m_emergethread;
469
470         BlockEmergeQueue m_emerge_queue;
471         
472         friend class EmergeThread;
473         friend class RemoteClient;
474 };
475
476 #endif
477