3 Copyright (C) 2010-2014 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 Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser 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.
20 #include "clientiface.h"
24 #include "connection.h"
25 #include "environment.h"
28 #include "serverobject.h" // TODO this is used for cleanup of only
30 #include "util/numeric.h"
31 #include "util/mathconstants.h"
33 #include "main.h" // for g_settings
35 void RemoteClient::GetNextBlocks(
36 ServerEnvironment *env,
37 EmergeManager * emerge,
39 std::vector<PrioritySortedBlockTransfer> &dest)
41 DSTACK(__FUNCTION_NAME);
45 m_nothing_to_send_pause_timer -= dtime;
46 m_nearest_unsent_reset_timer += dtime;
48 if(m_nothing_to_send_pause_timer >= 0)
51 Player *player = env->getPlayer(peer_id);
52 // This can happen sometimes; clients and players are not in perfect sync.
56 // Won't send anything if already sending
57 if(m_blocks_sending.size() >= g_settings->getU16
58 ("max_simultaneous_block_sends_per_client"))
60 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
64 v3f playerpos = player->getPosition();
65 v3f playerspeed = player->getSpeed();
66 v3f playerspeeddir(0,0,0);
67 if(playerspeed.getLength() > 1.0*BS)
68 playerspeeddir = playerspeed / playerspeed.getLength();
69 // Predict to next block
70 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
72 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
74 v3s16 center = getNodeBlockPos(center_nodepos);
76 // Camera position and direction
77 v3f camera_pos = player->getEyePosition();
78 v3f camera_dir = v3f(0,0,1);
79 camera_dir.rotateYZBy(player->getPitch());
80 camera_dir.rotateXZBy(player->getYaw());
82 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
83 <<camera_dir.Z<<")"<<std::endl;*/
86 Get the starting value of the block finder radius.
89 if(m_last_center != center)
91 m_nearest_unsent_d = 0;
92 m_last_center = center;
95 /*infostream<<"m_nearest_unsent_reset_timer="
96 <<m_nearest_unsent_reset_timer<<std::endl;*/
98 // Reset periodically to workaround for some bugs or stuff
99 if(m_nearest_unsent_reset_timer > 20.0)
101 m_nearest_unsent_reset_timer = 0;
102 m_nearest_unsent_d = 0;
103 //infostream<<"Resetting m_nearest_unsent_d for "
104 // <<server->getPlayerName(peer_id)<<std::endl;
107 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
108 s16 d_start = m_nearest_unsent_d;
110 //infostream<<"d_start="<<d_start<<std::endl;
112 u16 max_simul_sends_setting = g_settings->getU16
113 ("max_simultaneous_block_sends_per_client");
114 u16 max_simul_sends_usually = max_simul_sends_setting;
117 Check the time from last addNode/removeNode.
119 Decrease send rate if player is building stuff.
121 m_time_from_building += dtime;
122 if(m_time_from_building < g_settings->getFloat(
123 "full_block_send_enable_min_time_from_building"))
125 max_simul_sends_usually
126 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
130 Number of blocks sending + number of blocks selected for sending
132 u32 num_blocks_selected = m_blocks_sending.size();
135 next time d will be continued from the d from which the nearest
136 unsent block was found this time.
138 This is because not necessarily any of the blocks found this
139 time are actually sent.
141 s32 new_nearest_unsent_d = -1;
143 const s16 full_d_max = g_settings->getS16("max_block_send_distance");
144 s16 d_max = full_d_max;
145 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
147 // Don't loop very much at a time
148 s16 max_d_increment_at_time = 2;
149 if(d_max > d_start + max_d_increment_at_time)
150 d_max = d_start + max_d_increment_at_time;
152 s32 nearest_emerged_d = -1;
153 s32 nearest_emergefull_d = -1;
154 s32 nearest_sent_d = -1;
155 bool queue_is_full = false;
158 for(d = d_start; d <= d_max; d++)
161 Get the border/face dot coordinates of a "d-radiused"
164 std::list<v3s16> list;
165 getFacePositions(list, d);
167 std::list<v3s16>::iterator li;
168 for(li=list.begin(); li!=list.end(); ++li)
170 v3s16 p = *li + center;
174 - Don't allow too many simultaneous transfers
175 - EXCEPT when the blocks are very close
177 Also, don't send blocks that are already flying.
180 // Start with the usual maximum
181 u16 max_simul_dynamic = max_simul_sends_usually;
183 // If block is very close, allow full maximum
184 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
185 max_simul_dynamic = max_simul_sends_setting;
187 // Don't select too many blocks for sending
188 if(num_blocks_selected >= max_simul_dynamic)
190 queue_is_full = true;
191 goto queue_full_break;
194 // Don't send blocks that are currently being transferred
195 if(m_blocks_sending.find(p) != m_blocks_sending.end())
201 if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
202 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
203 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
204 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
205 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
206 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
209 // If this is true, inexistent block will be made from scratch
210 bool generate = d <= d_max_gen;
213 /*// Limit the generating area vertically to 2/3
214 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
217 // Limit the send area vertically to 1/2
218 if(abs(p.Y - center.Y) > full_d_max / 2)
223 Don't generate or send if not in sight
224 FIXME This only works if the client uses a small enough
225 FOV setting. The default of 72 degrees is fine.
228 float camera_fov = (72.0*M_PI/180) * 4./3.;
229 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
235 Don't send already sent blocks
238 if(m_blocks_sent.find(p) != m_blocks_sent.end())
245 Check if map has this block
247 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
249 bool surely_not_found_on_disk = false;
250 bool block_is_invalid = false;
253 // Reset usage timer, this block will be of use in the future.
254 block->resetUsageTimer();
256 // Block is dummy if data doesn't exist.
257 // It means it has been not found from disk and not generated
260 surely_not_found_on_disk = true;
263 // Block is valid if lighting is up-to-date and data exists
264 if(block->isValid() == false)
266 block_is_invalid = true;
269 if(block->isGenerated() == false)
270 block_is_invalid = true;
273 If block is not close, don't send it unless it is near
276 Block is near ground level if night-time mesh
277 differs from day-time mesh.
281 if(block->getDayNightDiff() == false)
287 If block has been marked to not exist on disk (dummy)
288 and generating new ones is not wanted, skip block.
290 if(generate == false && surely_not_found_on_disk == true)
297 Add inexistent block to emerge queue.
299 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
301 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
302 if (nearest_emerged_d == -1)
303 nearest_emerged_d = d;
305 if (nearest_emergefull_d == -1)
306 nearest_emergefull_d = d;
307 goto queue_full_break;
314 if(nearest_sent_d == -1)
318 Add block to send queue
320 PrioritySortedBlockTransfer q((float)d, p, peer_id);
324 num_blocks_selected += 1;
329 // If nothing was found for sending and nothing was queued for
330 // emerging, continue next time browsing from here
331 if(nearest_emerged_d != -1){
332 new_nearest_unsent_d = nearest_emerged_d;
333 } else if(nearest_emergefull_d != -1){
334 new_nearest_unsent_d = nearest_emergefull_d;
336 if(d > g_settings->getS16("max_block_send_distance")){
337 new_nearest_unsent_d = 0;
338 m_nothing_to_send_pause_timer = 2.0;
340 if(nearest_sent_d != -1)
341 new_nearest_unsent_d = nearest_sent_d;
343 new_nearest_unsent_d = d;
347 if(new_nearest_unsent_d != -1)
348 m_nearest_unsent_d = new_nearest_unsent_d;
351 void RemoteClient::GotBlock(v3s16 p)
353 if(m_blocks_sending.find(p) != m_blocks_sending.end())
354 m_blocks_sending.erase(p);
357 m_excess_gotblocks++;
359 m_blocks_sent.insert(p);
362 void RemoteClient::SentBlock(v3s16 p)
364 if(m_blocks_sending.find(p) == m_blocks_sending.end())
365 m_blocks_sending[p] = 0.0;
367 infostream<<"RemoteClient::SentBlock(): Sent block"
368 " already in m_blocks_sending"<<std::endl;
371 void RemoteClient::SetBlockNotSent(v3s16 p)
373 m_nearest_unsent_d = 0;
375 if(m_blocks_sending.find(p) != m_blocks_sending.end())
376 m_blocks_sending.erase(p);
377 if(m_blocks_sent.find(p) != m_blocks_sent.end())
378 m_blocks_sent.erase(p);
381 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
383 m_nearest_unsent_d = 0;
385 for(std::map<v3s16, MapBlock*>::iterator
387 i != blocks.end(); ++i)
391 if(m_blocks_sending.find(p) != m_blocks_sending.end())
392 m_blocks_sending.erase(p);
393 if(m_blocks_sent.find(p) != m_blocks_sent.end())
394 m_blocks_sent.erase(p);
398 void RemoteClient::notifyEvent(ClientStateEvent event)
403 assert("State update for client in invalid state" != 0);
414 m_state = Disconnecting;
421 /* GotInit2 SetDefinitionsSent SetMediaSent */
423 assert("Invalid client state transition!" == 0);
428 /* don't do anything if in denied state */
435 confirmSerializationVersion();
440 m_state = Disconnecting;
447 /* Init SetDefinitionsSent SetMediaSent */
449 assert("Invalid client state transition!" == 0);
456 case SetDefinitionsSent:
457 m_state = DefinitionsSent;
461 m_state = Disconnecting;
468 /* Init GotInit2 SetMediaSent */
470 assert("Invalid client state transition!" == 0);
474 case DefinitionsSent:
482 m_state = Disconnecting;
489 /* Init GotInit2 SetDefinitionsSent */
491 assert("Invalid client state transition!" == 0);
503 m_state = Disconnecting;
506 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
508 assert("Invalid client state transition!" == 0);
514 /* we are already disconnecting */
519 ClientInterface::ClientInterface(con::Connection* con)
523 m_print_info_timer(0.0)
527 ClientInterface::~ClientInterface()
533 JMutexAutoLock clientslock(m_clients_mutex);
535 for(std::map<u16, RemoteClient*>::iterator
536 i = m_clients.begin();
537 i != m_clients.end(); ++i)
546 std::list<u16> ClientInterface::getClientIDs(ClientState min_state)
548 std::list<u16> reply;
549 JMutexAutoLock clientslock(m_clients_mutex);
551 for(std::map<u16, RemoteClient*>::iterator
552 i = m_clients.begin();
553 i != m_clients.end(); ++i)
555 if (i->second->getState() >= min_state)
556 reply.push_back(i->second->peer_id);
562 std::vector<std::string> ClientInterface::getPlayerNames()
564 return m_clients_names;
568 void ClientInterface::step(float dtime)
570 m_print_info_timer += dtime;
571 if(m_print_info_timer >= 30.0)
573 m_print_info_timer = 0.0;
578 void ClientInterface::UpdatePlayerList()
582 std::list<u16> clients = getClientIDs();
583 m_clients_names.clear();
586 if(clients.size() != 0)
587 infostream<<"Players:"<<std::endl;
588 for(std::list<u16>::iterator
590 i != clients.end(); ++i)
592 Player *player = m_env->getPlayer(*i);
595 infostream<<"* "<<player->getName()<<"\t";
598 JMutexAutoLock clientslock(m_clients_mutex);
599 RemoteClient* client = lockedGetClientNoEx(*i);
601 client->PrintInfo(infostream);
603 m_clients_names.push_back(player->getName());
608 void ClientInterface::send(u16 peer_id,u8 channelnum,
609 SharedBuffer<u8> data, bool reliable)
611 m_con->Send(peer_id, channelnum, data, reliable);
614 void ClientInterface::sendToAll(u16 channelnum,
615 SharedBuffer<u8> data, bool reliable)
617 JMutexAutoLock clientslock(m_clients_mutex);
618 for(std::map<u16, RemoteClient*>::iterator
619 i = m_clients.begin();
620 i != m_clients.end(); ++i)
622 RemoteClient *client = i->second;
624 if (client->net_proto_version != 0)
626 m_con->Send(client->peer_id, channelnum, data, reliable);
631 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
633 JMutexAutoLock clientslock(m_clients_mutex);
634 std::map<u16, RemoteClient*>::iterator n;
635 n = m_clients.find(peer_id);
636 // The client may not exist; clients are immediately removed if their
637 // access is denied, and this event occurs later then.
638 if(n == m_clients.end())
641 if (n->second->getState() >= state_min)
647 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
649 std::map<u16, RemoteClient*>::iterator n;
650 n = m_clients.find(peer_id);
651 // The client may not exist; clients are immediately removed if their
652 // access is denied, and this event occurs later then.
653 if(n == m_clients.end())
656 if (n->second->getState() >= state_min)
662 ClientState ClientInterface::getClientState(u16 peer_id)
664 JMutexAutoLock clientslock(m_clients_mutex);
665 std::map<u16, RemoteClient*>::iterator n;
666 n = m_clients.find(peer_id);
667 // The client may not exist; clients are immediately removed if their
668 // access is denied, and this event occurs later then.
669 if(n == m_clients.end())
672 return n->second->getState();
675 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
677 JMutexAutoLock clientslock(m_clients_mutex);
678 std::map<u16, RemoteClient*>::iterator n;
679 n = m_clients.find(peer_id);
680 // The client may not exist; clients are immediately removed if their
681 // access is denied, and this event occurs later then.
682 if(n != m_clients.end())
683 n->second->setName(name);
686 void ClientInterface::DeleteClient(u16 peer_id)
688 JMutexAutoLock conlock(m_clients_mutex);
691 std::map<u16, RemoteClient*>::iterator n;
692 n = m_clients.find(peer_id);
693 // The client may not exist; clients are immediately removed if their
694 // access is denied, and this event occurs later then.
695 if(n == m_clients.end())
699 Mark objects to be not known by the client
701 //TODO this should be done by client destructor!!!
702 RemoteClient *client = n->second;
704 for(std::set<u16>::iterator
705 i = client->m_known_objects.begin();
706 i != client->m_known_objects.end(); ++i)
710 ServerActiveObject* obj = m_env->getActiveObject(id);
712 if(obj && obj->m_known_by_count > 0)
713 obj->m_known_by_count--;
717 delete m_clients[peer_id];
718 m_clients.erase(peer_id);
721 void ClientInterface::CreateClient(u16 peer_id)
723 JMutexAutoLock conlock(m_clients_mutex);
726 std::map<u16, RemoteClient*>::iterator n;
727 n = m_clients.find(peer_id);
728 // The client shouldn't already exist
729 if(n != m_clients.end()) return;
732 RemoteClient *client = new RemoteClient();
733 client->peer_id = peer_id;
734 m_clients[client->peer_id] = client;
737 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
740 JMutexAutoLock clientlock(m_clients_mutex);
743 std::map<u16, RemoteClient*>::iterator n;
744 n = m_clients.find(peer_id);
746 // No client to deliver event
747 if (n == m_clients.end())
749 n->second->notifyEvent(event);
752 if ((event == SetMediaSent) || (event == Disconnect) || (event == SetDenied))
758 u16 ClientInterface::getProtocolVersion(u16 peer_id)
760 JMutexAutoLock conlock(m_clients_mutex);
763 std::map<u16, RemoteClient*>::iterator n;
764 n = m_clients.find(peer_id);
766 // No client to deliver event
767 if (n == m_clients.end())
770 return n->second->net_proto_version;