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