3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
27 #include "connection.h"
28 #include "environment.h"
29 #include "common_irrlicht.h"
34 struct QueuedBlockEmerge
37 // key = peer_id, value = flags
38 core::map<u16, u8> peer_ids;
42 This is a thread-safe class.
44 class BlockEmergeQueue
54 JMutexAutoLock lock(m_mutex);
56 core::list<QueuedBlockEmerge*>::Iterator i;
57 for(i=m_queue.begin(); i!=m_queue.end(); i++)
59 QueuedBlockEmerge *q = *i;
65 peer_id=0 adds with nobody to send to
67 void addBlock(u16 peer_id, v3s16 pos, u8 flags)
69 DSTACK(__FUNCTION_NAME);
71 JMutexAutoLock lock(m_mutex);
76 Find if block is already in queue.
77 If it is, update the peer to it and quit.
79 core::list<QueuedBlockEmerge*>::Iterator i;
80 for(i=m_queue.begin(); i!=m_queue.end(); i++)
82 QueuedBlockEmerge *q = *i;
85 q->peer_ids[peer_id] = flags;
94 QueuedBlockEmerge *q = new QueuedBlockEmerge;
97 q->peer_ids[peer_id] = flags;
101 // Returned pointer must be deleted
102 // Returns NULL if queue is empty
103 QueuedBlockEmerge * pop()
105 JMutexAutoLock lock(m_mutex);
107 core::list<QueuedBlockEmerge*>::Iterator i = m_queue.begin();
108 if(i == m_queue.end())
110 QueuedBlockEmerge *q = *i;
117 JMutexAutoLock lock(m_mutex);
118 return m_queue.size();
121 u32 peerItemCount(u16 peer_id)
123 JMutexAutoLock lock(m_mutex);
127 core::list<QueuedBlockEmerge*>::Iterator i;
128 for(i=m_queue.begin(); i!=m_queue.end(); i++)
130 QueuedBlockEmerge *q = *i;
131 if(q->peer_ids.find(peer_id) != NULL)
139 core::list<QueuedBlockEmerge*> m_queue;
145 class ServerThread : public SimpleThread
151 ServerThread(Server *server):
160 class EmergeThread : public SimpleThread
166 EmergeThread(Server *server):
177 if(IsRunning() == false)
187 char name[PLAYERNAME_SIZE];
193 void PrintLine(std::ostream *s);
196 u32 PIChecksum(core::list<PlayerInfo> &l);
199 Used for queueing and sorting block transfers in containers
201 Lower priority number means higher priority.
203 struct PrioritySortedBlockTransfer
205 PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
207 priority = a_priority;
211 bool operator < (PrioritySortedBlockTransfer &other)
213 return priority < other.priority;
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.
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;
234 m_time_from_building(9999),
235 m_excess_gotblocks(0)
238 serialization_version = SER_FMT_VER_INVALID;
239 pending_serialization_version = SER_FMT_VER_INVALID;
240 m_nearest_unsent_d = 0;
241 m_nearest_unsent_reset_timer = 0.0;
248 Finds block that should be sent next to the client.
249 Environment should be locked when this is called.
250 dtime is used for resetting send radius at slow interval
252 void GetNextBlocks(Server *server, float dtime,
253 core::array<PrioritySortedBlockTransfer> &dest);
256 Connection and environment should be locked when this is called.
257 steps() objects of blocks not found in active_blocks, then
258 adds those blocks to active_blocks
263 core::map<v3s16, bool> &stepped_blocks
266 void GotBlock(v3s16 p);
268 void SentBlock(v3s16 p);
270 void SetBlockNotSent(v3s16 p);
271 void SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks);
275 return m_blocks_sending.size();
278 // Increments timeouts and removes timed-out blocks from list
279 // NOTE: This doesn't fix the server-not-sending-block bug
280 // because it is related to emerging, not sending.
281 //void RunSendingTimeouts(float dtime, float timeout);
283 void PrintInfo(std::ostream &o)
285 o<<"RemoteClient "<<peer_id<<": "
286 <<", m_blocks_sent.size()="<<m_blocks_sent.size()
287 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
288 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
289 <<", m_excess_gotblocks="<<m_excess_gotblocks
291 m_excess_gotblocks = 0;
294 // Time from last placing or removing blocks
295 float m_time_from_building;
297 /*JMutex m_dig_mutex;
298 float m_dig_time_remaining;
301 v3s16 m_dig_position;*/
304 List of active objects that the client knows of.
307 core::map<u16, bool> m_known_objects;
311 Blocks that have been sent to client.
312 - These don't have to be sent again.
313 - A block is cleared from here when client says it has
314 deleted it from it's memory
316 Key is position, value is dummy.
317 No MapBlock* is stored here because the blocks can get deleted.
319 core::map<v3s16, bool> m_blocks_sent;
320 s16 m_nearest_unsent_d;
322 float m_nearest_unsent_reset_timer;
325 Blocks that are currently on the line.
326 This is used for throttling the sending of blocks.
327 - The size of this list is limited to some value
328 Block is added when it is sent with BLOCKDATA.
329 Block is removed when GOTBLOCKS is received.
330 Value is time from sending. (not used at the moment)
332 core::map<v3s16, float> m_blocks_sending;
335 Count of excess GotBlocks().
336 There is an excess amount because the client sometimes
337 gets a block so late that the server sends it again,
338 and the client then sends two GOTBLOCKs.
339 This is resetted by PrintInfo()
341 u32 m_excess_gotblocks;
344 class Server : public con::PeerHandler
348 NOTE: Every public method should be thread-safe
351 std::string mapsavedir
354 void start(unsigned short port);
356 // This is mainly a way to pass the time to the server.
357 // Actual processing is done in an another thread.
358 void step(float dtime);
359 // This is run by ServerThread and does the actual processing
362 void ProcessData(u8 *data, u32 datasize, u16 peer_id);
364 // Environment and Connection must be locked when called
365 void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
369 core::list<PlayerInfo> getPlayerInfo();
371 u32 getDayNightRatio()
374 s32 t = (((m_time_of_day.get() + 24000/d/2)%24000)/(24000/d));
375 if(t == d/4 || t == (d-d/4))
377 else if(t < d/4 || t > (d-d/4))
383 bool getShutdownRequested()
385 return m_shutdown_requested.get();
390 // Virtual methods from con::PeerHandler.
391 // As of now, these create and remove clients and players.
392 void peerAdded(con::Peer *peer);
393 void deletingPeer(con::Peer *peer, bool timeout);
395 // Envlock and conlock should be locked when calling these
396 void SendObjectData(float dtime);
397 void SendPlayerInfos();
398 void SendInventory(u16 peer_id);
399 void SendChatMessage(u16 peer_id, const std::wstring &message);
400 void BroadcastChatMessage(const std::wstring &message);
402 // Sends blocks to clients
403 void SendBlocks(float dtime);
405 // When called, connection mutex should be locked
406 RemoteClient* getClient(u16 peer_id);
408 // Connection must be locked when called
409 std::wstring getStatusString();
412 Get a player from memory or creates one.
413 If player is already connected, return NULL
415 Call with env and con locked.
417 Player *emergePlayer(const char *name, const char *password,
421 Update water pressure.
422 This also adds suitable nodes to active_nodes.
424 environment has to be locked when calling.
426 /*void UpdateBlockWaterPressure(MapBlock *block,
427 core::map<v3s16, MapBlock*> &modified_blocks);*/
429 // Locks environment and connection by its own
431 void handlePeerChange(PeerChange &c);
432 void handlePeerChanges();
434 //float m_flowwater_timer;
435 float m_liquid_transform_timer;
436 float m_print_info_timer;
437 float m_objectdata_timer;
438 float m_emergethread_trigger_timer;
439 float m_savemap_timer;
441 // NOTE: If connection and environment are both to be locked,
442 // environment shall be locked first.
444 ServerEnvironment m_env;
447 con::Connection m_con;
448 core::map<u16, RemoteClient*> m_clients; // Behind the con mutex
451 JMutex m_step_dtime_mutex;
453 ServerThread m_thread;
454 EmergeThread m_emergethread;
456 BlockEmergeQueue m_emerge_queue;
458 // Nodes that are destinations of flowing liquid at the moment
459 //core::map<v3s16, u8> m_flow_active_nodes;
462 MutexedVariable<u32> m_time_of_day;
463 // Used to buffer dtime for adding to m_time_of_day
464 float m_time_counter;
465 float m_time_of_day_send_timer;
467 MutexedVariable<double> m_uptime;
482 Queue<PeerChange> m_peer_change_queue;
484 std::string m_mapsavedir;
486 MutexedVariable<bool> m_shutdown_requested;
488 friend class EmergeThread;
489 friend class RemoteClient;
493 Runs a simple dedicated server loop.
495 Shuts down when run is set to false.
497 void dedicated_server_loop(Server &server, bool &run);