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