]> git.lizzy.rs Git - minetest.git/blob - src/server.h
tuned error reporting a bit
[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 #include "map.h"
34 #include "inventory.h"
35
36 /*
37         Some random functions
38 */
39 v3f findSpawnPos(ServerMap &map);
40
41 /*
42         A structure containing the data needed for queueing the fetching
43         of blocks.
44 */
45 struct QueuedBlockEmerge
46 {
47         v3s16 pos;
48         // key = peer_id, value = flags
49         core::map<u16, u8> peer_ids;
50 };
51
52 /*
53         This is a thread-safe class.
54 */
55 class BlockEmergeQueue
56 {
57 public:
58         BlockEmergeQueue()
59         {
60                 m_mutex.Init();
61         }
62
63         ~BlockEmergeQueue()
64         {
65                 JMutexAutoLock lock(m_mutex);
66
67                 core::list<QueuedBlockEmerge*>::Iterator i;
68                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
69                 {
70                         QueuedBlockEmerge *q = *i;
71                         delete q;
72                 }
73         }
74         
75         /*
76                 peer_id=0 adds with nobody to send to
77         */
78         void addBlock(u16 peer_id, v3s16 pos, u8 flags)
79         {
80                 DSTACK(__FUNCTION_NAME);
81         
82                 JMutexAutoLock lock(m_mutex);
83
84                 if(peer_id != 0)
85                 {
86                         /*
87                                 Find if block is already in queue.
88                                 If it is, update the peer to it and quit.
89                         */
90                         core::list<QueuedBlockEmerge*>::Iterator i;
91                         for(i=m_queue.begin(); i!=m_queue.end(); i++)
92                         {
93                                 QueuedBlockEmerge *q = *i;
94                                 if(q->pos == pos)
95                                 {
96                                         q->peer_ids[peer_id] = flags;
97                                         return;
98                                 }
99                         }
100                 }
101                 
102                 /*
103                         Add the block
104                 */
105                 QueuedBlockEmerge *q = new QueuedBlockEmerge;
106                 q->pos = pos;
107                 if(peer_id != 0)
108                         q->peer_ids[peer_id] = flags;
109                 m_queue.push_back(q);
110         }
111
112         // Returned pointer must be deleted
113         // Returns NULL if queue is empty
114         QueuedBlockEmerge * pop()
115         {
116                 JMutexAutoLock lock(m_mutex);
117
118                 core::list<QueuedBlockEmerge*>::Iterator i = m_queue.begin();
119                 if(i == m_queue.end())
120                         return NULL;
121                 QueuedBlockEmerge *q = *i;
122                 m_queue.erase(i);
123                 return q;
124         }
125
126         u32 size()
127         {
128                 JMutexAutoLock lock(m_mutex);
129                 return m_queue.size();
130         }
131         
132         u32 peerItemCount(u16 peer_id)
133         {
134                 JMutexAutoLock lock(m_mutex);
135
136                 u32 count = 0;
137
138                 core::list<QueuedBlockEmerge*>::Iterator i;
139                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
140                 {
141                         QueuedBlockEmerge *q = *i;
142                         if(q->peer_ids.find(peer_id) != NULL)
143                                 count++;
144                 }
145
146                 return count;
147         }
148
149 private:
150         core::list<QueuedBlockEmerge*> m_queue;
151         JMutex m_mutex;
152 };
153
154 class Server;
155
156 class ServerThread : public SimpleThread
157 {
158         Server *m_server;
159
160 public:
161
162         ServerThread(Server *server):
163                 SimpleThread(),
164                 m_server(server)
165         {
166         }
167
168         void * Thread();
169 };
170
171 class EmergeThread : public SimpleThread
172 {
173         Server *m_server;
174
175 public:
176
177         EmergeThread(Server *server):
178                 SimpleThread(),
179                 m_server(server)
180         {
181         }
182
183         void * Thread();
184
185         void trigger()
186         {
187                 setRun(true);
188                 if(IsRunning() == false)
189                 {
190                         Start();
191                 }
192         }
193 };
194
195 struct PlayerInfo
196 {
197         u16 id;
198         char name[PLAYERNAME_SIZE];
199         v3f position;
200         Address address;
201         float avg_rtt;
202
203         PlayerInfo();
204         void PrintLine(std::ostream *s);
205 };
206
207 u32 PIChecksum(core::list<PlayerInfo> &l);
208
209 /*
210         Used for queueing and sorting block transfers in containers
211         
212         Lower priority number means higher priority.
213 */
214 struct PrioritySortedBlockTransfer
215 {
216         PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
217         {
218                 priority = a_priority;
219                 pos = a_pos;
220                 peer_id = a_peer_id;
221         }
222         bool operator < (PrioritySortedBlockTransfer &other)
223         {
224                 return priority < other.priority;
225         }
226         float priority;
227         v3s16 pos;
228         u16 peer_id;
229 };
230
231 class RemoteClient
232 {
233 public:
234         // peer_id=0 means this client has no associated peer
235         // NOTE: If client is made allowed to exist while peer doesn't,
236         //       this has to be set to 0 when there is no peer.
237         //       Also, the client must be moved to some other container.
238         u16 peer_id;
239         // The serialization version to use with the client
240         u8 serialization_version;
241         // Version is stored in here after INIT before INIT2
242         u8 pending_serialization_version;
243
244         RemoteClient():
245                 m_time_from_building(9999),
246                 m_excess_gotblocks(0)
247         {
248                 peer_id = 0;
249                 serialization_version = SER_FMT_VER_INVALID;
250                 pending_serialization_version = SER_FMT_VER_INVALID;
251                 m_nearest_unsent_d = 0;
252                 m_nearest_unsent_reset_timer = 0.0;
253         }
254         ~RemoteClient()
255         {
256         }
257         
258         /*
259                 Finds block that should be sent next to the client.
260                 Environment should be locked when this is called.
261                 dtime is used for resetting send radius at slow interval
262         */
263         void GetNextBlocks(Server *server, float dtime,
264                         core::array<PrioritySortedBlockTransfer> &dest);
265
266         /*
267                 Connection and environment should be locked when this is called.
268                 steps() objects of blocks not found in active_blocks, then
269                 adds those blocks to active_blocks
270         */
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         s32 SendingCount()
285         {
286                 return m_blocks_sending.size();
287         }
288         
289         // Increments timeouts and removes timed-out blocks from list
290         // NOTE: This doesn't fix the server-not-sending-block bug
291         //       because it is related to emerging, not sending.
292         //void RunSendingTimeouts(float dtime, float timeout);
293
294         void PrintInfo(std::ostream &o)
295         {
296                 o<<"RemoteClient "<<peer_id<<": "
297                                 <<"m_blocks_sent.size()="<<m_blocks_sent.size()
298                                 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
299                                 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
300                                 <<", m_excess_gotblocks="<<m_excess_gotblocks
301                                 <<std::endl;
302                 m_excess_gotblocks = 0;
303         }
304
305         // Time from last placing or removing blocks
306         float m_time_from_building;
307         
308         /*JMutex m_dig_mutex;
309         float m_dig_time_remaining;
310         // -1 = not digging
311         s16 m_dig_tool_item;
312         v3s16 m_dig_position;*/
313         
314         /*
315                 List of active objects that the client knows of.
316                 Value is dummy.
317         */
318         core::map<u16, bool> m_known_objects;
319
320 private:
321         /*
322                 Blocks that have been sent to client.
323                 - These don't have to be sent again.
324                 - A block is cleared from here when client says it has
325                   deleted it from it's memory
326                 
327                 Key is position, value is dummy.
328                 No MapBlock* is stored here because the blocks can get deleted.
329         */
330         core::map<v3s16, bool> m_blocks_sent;
331         s16 m_nearest_unsent_d;
332         v3s16 m_last_center;
333         float m_nearest_unsent_reset_timer;
334         
335         /*
336                 Blocks that are currently on the line.
337                 This is used for throttling the sending of blocks.
338                 - The size of this list is limited to some value
339                 Block is added when it is sent with BLOCKDATA.
340                 Block is removed when GOTBLOCKS is received.
341                 Value is time from sending. (not used at the moment)
342         */
343         core::map<v3s16, float> m_blocks_sending;
344
345         /*
346                 Count of excess GotBlocks().
347                 There is an excess amount because the client sometimes
348                 gets a block so late that the server sends it again,
349                 and the client then sends two GOTBLOCKs.
350                 This is resetted by PrintInfo()
351         */
352         u32 m_excess_gotblocks;
353 };
354
355 class Server : public con::PeerHandler, public MapEventReceiver,
356                 public InventoryManager
357 {
358 public:
359         /*
360                 NOTE: Every public method should be thread-safe
361         */
362
363         Server(
364                 std::string mapsavedir
365         );
366         ~Server();
367         void start(unsigned short port);
368         void stop();
369         // This is mainly a way to pass the time to the server.
370         // Actual processing is done in an another thread.
371         void step(float dtime);
372         // This is run by ServerThread and does the actual processing
373         void AsyncRunStep();
374         void Receive();
375         void ProcessData(u8 *data, u32 datasize, u16 peer_id);
376
377         core::list<PlayerInfo> getPlayerInfo();
378
379         u32 getDayNightRatio()
380         {
381                 return time_to_daynight_ratio(m_time_of_day.get());
382         }
383
384         bool getShutdownRequested()
385         {
386                 return m_shutdown_requested.get();
387         }
388         
389         /*
390                 Shall be called with the environment locked.
391                 This is accessed by the map, which is inside the environment,
392                 so it shouldn't be a problem.
393         */
394         void onMapEditEvent(MapEditEvent *event);
395
396         /*
397                 Shall be called with the environment and the connection locked.
398         */
399         Inventory* getInventory(InventoryContext *c, std::string id);
400         void inventoryModified(InventoryContext *c, std::string id);
401
402 private:
403
404         // Virtual methods from con::PeerHandler.
405         // As of now, these create and remove clients and players.
406         void peerAdded(con::Peer *peer);
407         void deletingPeer(con::Peer *peer, bool timeout);
408         
409         /*
410                 Static send methods
411         */
412         
413         static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
414         
415         /*
416                 Non-static send methods
417         */
418
419         // Envlock and conlock should be locked when calling these
420         void SendObjectData(float dtime);
421         void SendPlayerInfos();
422         void SendInventory(u16 peer_id);
423         void SendChatMessage(u16 peer_id, const std::wstring &message);
424         void BroadcastChatMessage(const std::wstring &message);
425         void SendPlayerHP(Player *player);
426         void SendMovePlayer(Player *player);
427         /*
428                 Send a node removal/addition event to all clients except ignore_id.
429                 Additionally, if far_players!=NULL, players further away than
430                 far_d_nodes are ignored and their peer_ids are added to far_players
431         */
432         void sendRemoveNode(v3s16 p, u16 ignore_id=0,
433                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
434         void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
435                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
436         
437         // Environment and Connection must be locked when  called
438         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
439         
440         // Sends blocks to clients
441         void SendBlocks(float dtime);
442
443         /*
444                 Something random
445         */
446         
447         void UpdateCrafting(u16 peer_id);
448         
449         // When called, connection mutex should be locked
450         RemoteClient* getClient(u16 peer_id);
451         
452         // Connection must be locked when called
453         std::wstring getStatusString();
454         
455         /*
456                 Get a player from memory or creates one.
457                 If player is already connected, return NULL
458
459                 Call with env and con locked.
460         */
461         Player *emergePlayer(const char *name, const char *password,
462                         u16 peer_id);
463
464         /*
465                 Update water pressure.
466                 This also adds suitable nodes to active_nodes.
467
468                 environment has to be locked when calling.
469         */
470         /*void UpdateBlockWaterPressure(MapBlock *block,
471                         core::map<v3s16, MapBlock*> &modified_blocks);*/
472         
473         // Locks environment and connection by its own
474         struct PeerChange;
475         void handlePeerChange(PeerChange &c);
476         void handlePeerChanges();
477         
478         //float m_flowwater_timer;
479         float m_liquid_transform_timer;
480         float m_print_info_timer;
481         float m_objectdata_timer;
482         float m_emergethread_trigger_timer;
483         float m_savemap_timer;
484         
485         // NOTE: If connection and environment are both to be locked,
486         // environment shall be locked first.
487         JMutex m_env_mutex;
488         ServerEnvironment m_env;
489
490         JMutex m_con_mutex;
491         con::Connection m_con;
492         core::map<u16, RemoteClient*> m_clients; // Behind the con mutex
493
494         float m_step_dtime;
495         JMutex m_step_dtime_mutex;
496
497         ServerThread m_thread;
498         EmergeThread m_emergethread;
499
500         BlockEmergeQueue m_emerge_queue;
501         
502         // Nodes that are destinations of flowing liquid at the moment
503         //core::map<v3s16, u8> m_flow_active_nodes;
504
505         // 0-23999
506         MutexedVariable<u32> m_time_of_day;
507         // Used to buffer dtime for adding to m_time_of_day
508         float m_time_counter;
509         float m_time_of_day_send_timer;
510         
511         MutexedVariable<double> m_uptime;
512         
513         enum PeerChangeType
514         {
515                 PEER_ADDED,
516                 PEER_REMOVED
517         };
518
519         struct PeerChange
520         {
521                 PeerChangeType type;
522                 u16 peer_id;
523                 bool timeout;
524         };
525         
526         Queue<PeerChange> m_peer_change_queue;
527
528         std::string m_mapsavedir;
529
530         MutexedVariable<bool> m_shutdown_requested;
531         
532         /*
533                 Queue of map edits from the environment for sending to the clients
534                 This is behind m_env_mutex
535         */
536         Queue<MapEditEvent*> m_unsent_map_edit_queue;
537         /*
538                 Set to true when the server itself is modifying the map and does
539                 all sending of information by itself.
540                 This is behind m_env_mutex
541         */
542         bool m_ignore_map_edit_events;
543         /*
544                 If set to !=0, the incoming MapEditEvents are modified to have
545                 this peed id as the disabled recipient
546                 This is behind m_env_mutex
547         */
548         u16 m_ignore_map_edit_events_peer_id;
549
550         friend class EmergeThread;
551         friend class RemoteClient;
552 };
553
554 /*
555         Runs a simple dedicated server loop.
556
557         Shuts down when run is set to false.
558 */
559 void dedicated_server_loop(Server &server, bool &run);
560
561 #endif
562