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