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;
243 m_blocks_sent_mutex.Init();
244 m_blocks_sending_mutex.Init();
246 /*m_dig_mutex.Init();
247 m_dig_time_remaining = 0;
248 m_dig_tool_item = -1;*/
255 Finds block that should be sent next to the client.
256 Environment should be locked when this is called.
257 dtime is used for resetting send radius at slow interval
259 void GetNextBlocks(Server *server, float dtime,
260 core::array<PrioritySortedBlockTransfer> &dest);
263 Connection and environment should be locked when this is called.
264 steps() objects of blocks not found in active_blocks, then
265 adds those blocks to active_blocks
270 core::map<v3s16, bool> &stepped_blocks
273 void GotBlock(v3s16 p);
275 void SentBlock(v3s16 p);
277 void SetBlockNotSent(v3s16 p);
278 void SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks);
282 JMutexAutoLock lock(m_blocks_sending_mutex);
283 return m_blocks_sending.size();
286 // Increments timeouts and removes timed-out blocks from list
287 // NOTE: This doesn't fix the server-not-sending-block bug
288 // because it is related to emerging, not sending.
289 //void RunSendingTimeouts(float dtime, float timeout);
291 void PrintInfo(std::ostream &o)
293 JMutexAutoLock l2(m_blocks_sent_mutex);
294 JMutexAutoLock l3(m_blocks_sending_mutex);
295 o<<"RemoteClient "<<peer_id<<": "
296 <<", m_blocks_sent.size()="<<m_blocks_sent.size()
297 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
298 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
299 <<", m_excess_gotblocks="<<m_excess_gotblocks
301 m_excess_gotblocks = 0;
304 // Time from last placing or removing blocks
305 MutexedVariable<float> m_time_from_building;
307 /*JMutex m_dig_mutex;
308 float m_dig_time_remaining;
311 v3s16 m_dig_position;*/
315 All members that are accessed by many threads should
316 obviously be behind a mutex. The threads include:
317 - main thread (calls step())
318 - server thread (calls AsyncRunStep() and Receive())
322 //TODO: core::map<v3s16, MapBlock*> m_active_blocks
323 //NOTE: Not here, it should be server-wide!
325 // Number of blocks in the emerge queue that have this client as
326 // a receiver. Used for throttling network usage.
327 //MutexedVariable<s16> m_num_blocks_in_emerge_queue;
330 Blocks that have been sent to client.
331 - These don't have to be sent again.
332 - A block is cleared from here when client says it has
333 deleted it from it's memory
335 Key is position, value is dummy.
336 No MapBlock* is stored here because the blocks can get deleted.
338 core::map<v3s16, bool> m_blocks_sent;
339 s16 m_nearest_unsent_d;
341 float m_nearest_unsent_reset_timer;
342 JMutex m_blocks_sent_mutex;
344 Blocks that are currently on the line.
345 This is used for throttling the sending of blocks.
346 - The size of this list is limited to some value
347 Block is added when it is sent with BLOCKDATA.
348 Block is removed when GOTBLOCKS is received.
349 Value is time from sending. (not used at the moment)
351 core::map<v3s16, float> m_blocks_sending;
352 JMutex m_blocks_sending_mutex;
355 Count of excess GotBlocks().
356 There is an excess amount because the client sometimes
357 gets a block so late that the server sends it again,
358 and the client then sends two GOTBLOCKs.
359 This is resetted by PrintInfo()
361 u32 m_excess_gotblocks;
364 /*struct ServerSettings
368 creative_mode = false;
373 class Server : public con::PeerHandler
377 NOTE: Every public method should be thread-safe
380 std::string mapsavedir,
385 void start(unsigned short port);
387 // This is mainly a way to pass the time to the server.
388 // Actual processing is done in an another thread.
389 void step(float dtime);
390 // This is run by ServerThread and does the actual processing
393 void ProcessData(u8 *data, u32 datasize, u16 peer_id);
395 /*void Send(u16 peer_id, u16 channelnum,
396 SharedBuffer<u8> data, bool reliable);*/
398 // Environment and Connection must be locked when called
399 void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
401 // Environment and Connection must be locked when called
402 //void SendSectorMeta(u16 peer_id, core::list<v2s16> ps, u8 ver);
404 core::list<PlayerInfo> getPlayerInfo();
406 u32 getDayNightRatio()
409 s32 t = (((m_time_of_day.get() + 24000/d/2)%24000)/(24000/d));
410 if(t == d/4 || t == (d-d/4))
412 else if(t < d/4 || t > (d-d/4))
420 // Virtual methods from con::PeerHandler.
421 // As of now, these create and remove clients and players.
422 void peerAdded(con::Peer *peer);
423 void deletingPeer(con::Peer *peer, bool timeout);
425 // Envlock and conlock should be locked when calling these
426 void SendObjectData(float dtime);
427 void SendPlayerInfos();
428 void SendInventory(u16 peer_id);
429 void SendChatMessage(u16 peer_id, const std::wstring &message);
430 void BroadcastChatMessage(const std::wstring &message);
432 // Sends blocks to clients
433 void SendBlocks(float dtime);
435 // When called, connection mutex should be locked
436 RemoteClient* getClient(u16 peer_id);
439 Get a player from memory or creates one.
440 If player is already connected, return NULL
442 Call with env and con locked.
444 Player *emergePlayer(const char *name, const char *password,
448 Update water pressure.
449 This also adds suitable nodes to active_nodes.
451 environment has to be locked when calling.
453 /*void UpdateBlockWaterPressure(MapBlock *block,
454 core::map<v3s16, MapBlock*> &modified_blocks);*/
456 // Locks environment and connection by its own
458 void handlePeerChange(PeerChange &c);
459 void handlePeerChanges();
461 //float m_flowwater_timer;
462 float m_liquid_transform_timer;
463 float m_print_info_timer;
464 float m_objectdata_timer;
465 float m_emergethread_trigger_timer;
466 float m_savemap_timer;
468 // NOTE: If connection and environment are both to be locked,
469 // environment shall be locked first.
474 con::Connection m_con;
475 core::map<u16, RemoteClient*> m_clients; // Behind the con mutex
478 JMutex m_step_dtime_mutex;
480 ServerThread m_thread;
481 EmergeThread m_emergethread;
483 BlockEmergeQueue m_emerge_queue;
485 // Nodes that are destinations of flowing liquid at the moment
486 //core::map<v3s16, u8> m_flow_active_nodes;
489 MutexedVariable<u32> m_time_of_day;
490 // Used to buffer dtime for adding to m_time_of_day
491 float m_time_counter;
492 float m_time_of_day_send_timer;
494 MutexedVariable<double> m_uptime;
509 Queue<PeerChange> m_peer_change_queue;
511 std::string m_mapsavedir;
513 friend class EmergeThread;
514 friend class RemoteClient;
518 Runs a simple dedicated server loop
520 void dedicated_server_loop(Server &server);