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 s16 d_max = g_settings->getS16("max_block_send_distance");
144 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
146 // Don't loop very much at a time
147 s16 max_d_increment_at_time = 2;
148 if(d_max > d_start + max_d_increment_at_time)
149 d_max = d_start + max_d_increment_at_time;
151 s32 nearest_emerged_d = -1;
152 s32 nearest_emergefull_d = -1;
153 s32 nearest_sent_d = -1;
154 bool queue_is_full = false;
157 for(d = d_start; d <= d_max; d++)
160 Get the border/face dot coordinates of a "d-radiused"
163 std::list<v3s16> list;
164 getFacePositions(list, d);
166 std::list<v3s16>::iterator li;
167 for(li=list.begin(); li!=list.end(); ++li)
169 v3s16 p = *li + center;
173 - Don't allow too many simultaneous transfers
174 - EXCEPT when the blocks are very close
176 Also, don't send blocks that are already flying.
179 // Start with the usual maximum
180 u16 max_simul_dynamic = max_simul_sends_usually;
182 // If block is very close, allow full maximum
183 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
184 max_simul_dynamic = max_simul_sends_setting;
186 // Don't select too many blocks for sending
187 if(num_blocks_selected >= max_simul_dynamic)
189 queue_is_full = true;
190 goto queue_full_break;
193 // Don't send blocks that are currently being transferred
194 if(m_blocks_sending.find(p) != m_blocks_sending.end())
200 if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
201 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
202 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
203 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
204 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
205 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
208 // If this is true, inexistent block will be made from scratch
209 bool generate = d <= d_max_gen;
212 /*// Limit the generating area vertically to 2/3
213 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
216 // Limit the send area vertically to 1/2
217 if(abs(p.Y - center.Y) > d_max / 2)
222 Don't generate or send if not in sight
223 FIXME This only works if the client uses a small enough
224 FOV setting. The default of 72 degrees is fine.
227 float camera_fov = (72.0*M_PI/180) * 4./3.;
228 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
234 Don't send already sent blocks
237 if(m_blocks_sent.find(p) != m_blocks_sent.end())
244 Check if map has this block
246 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
248 bool surely_not_found_on_disk = false;
249 bool block_is_invalid = false;
252 // Reset usage timer, this block will be of use in the future.
253 block->resetUsageTimer();
255 // Block is dummy if data doesn't exist.
256 // It means it has been not found from disk and not generated
259 surely_not_found_on_disk = true;
262 // Block is valid if lighting is up-to-date and data exists
263 if(block->isValid() == false)
265 block_is_invalid = true;
268 if(block->isGenerated() == false)
269 block_is_invalid = true;
272 If block is not close, don't send it unless it is near
275 Block is near ground level if night-time mesh
276 differs from day-time mesh.
280 if(block->getDayNightDiff() == false)
286 If block has been marked to not exist on disk (dummy)
287 and generating new ones is not wanted, skip block.
289 if(generate == false && surely_not_found_on_disk == true)
296 Add inexistent block to emerge queue.
298 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
300 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
301 if (nearest_emerged_d == -1)
302 nearest_emerged_d = d;
304 if (nearest_emergefull_d == -1)
305 nearest_emergefull_d = d;
306 goto queue_full_break;
313 if(nearest_sent_d == -1)
317 Add block to send queue
319 PrioritySortedBlockTransfer q((float)d, p, peer_id);
323 num_blocks_selected += 1;
328 // If nothing was found for sending and nothing was queued for
329 // emerging, continue next time browsing from here
330 if(nearest_emerged_d != -1){
331 new_nearest_unsent_d = nearest_emerged_d;
332 } else if(nearest_emergefull_d != -1){
333 new_nearest_unsent_d = nearest_emergefull_d;
335 if(d > g_settings->getS16("max_block_send_distance")){
336 new_nearest_unsent_d = 0;
337 m_nothing_to_send_pause_timer = 2.0;
339 if(nearest_sent_d != -1)
340 new_nearest_unsent_d = nearest_sent_d;
342 new_nearest_unsent_d = d;
346 if(new_nearest_unsent_d != -1)
347 m_nearest_unsent_d = new_nearest_unsent_d;
350 void RemoteClient::GotBlock(v3s16 p)
352 if(m_blocks_sending.find(p) != m_blocks_sending.end())
353 m_blocks_sending.erase(p);
356 m_excess_gotblocks++;
358 m_blocks_sent.insert(p);
361 void RemoteClient::SentBlock(v3s16 p)
363 if(m_blocks_sending.find(p) == m_blocks_sending.end())
364 m_blocks_sending[p] = 0.0;
366 infostream<<"RemoteClient::SentBlock(): Sent block"
367 " already in m_blocks_sending"<<std::endl;
370 void RemoteClient::SetBlockNotSent(v3s16 p)
372 m_nearest_unsent_d = 0;
374 if(m_blocks_sending.find(p) != m_blocks_sending.end())
375 m_blocks_sending.erase(p);
376 if(m_blocks_sent.find(p) != m_blocks_sent.end())
377 m_blocks_sent.erase(p);
380 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
382 m_nearest_unsent_d = 0;
384 for(std::map<v3s16, MapBlock*>::iterator
386 i != blocks.end(); ++i)
390 if(m_blocks_sending.find(p) != m_blocks_sending.end())
391 m_blocks_sending.erase(p);
392 if(m_blocks_sent.find(p) != m_blocks_sent.end())
393 m_blocks_sent.erase(p);
397 void RemoteClient::notifyEvent(ClientStateEvent event)
402 assert("State update for client in invalid state" != 0);
413 m_state = Disconnecting;
420 /* GotInit2 SetDefinitionsSent SetMediaSent */
422 assert("Invalid client state transition!" == 0);
427 /* don't do anything if in denied state */
434 confirmSerializationVersion();
439 m_state = Disconnecting;
446 /* Init SetDefinitionsSent SetMediaSent */
448 assert("Invalid client state transition!" == 0);
455 case SetDefinitionsSent:
456 m_state = DefinitionsSent;
460 m_state = Disconnecting;
467 /* Init GotInit2 SetMediaSent */
469 assert("Invalid client state transition!" == 0);
473 case DefinitionsSent:
481 m_state = Disconnecting;
488 /* Init GotInit2 SetDefinitionsSent */
490 assert("Invalid client state transition!" == 0);
502 m_state = Disconnecting;
505 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
507 assert("Invalid client state transition!" == 0);
513 /* we are already disconnecting */
518 ClientInterface::ClientInterface(con::Connection* con)
522 m_print_info_timer(0.0)
526 ClientInterface::~ClientInterface()
532 JMutexAutoLock clientslock(m_clients_mutex);
534 for(std::map<u16, RemoteClient*>::iterator
535 i = m_clients.begin();
536 i != m_clients.end(); ++i)
545 std::list<u16> ClientInterface::getClientIDs(ClientState min_state)
547 std::list<u16> reply;
548 JMutexAutoLock clientslock(m_clients_mutex);
550 for(std::map<u16, RemoteClient*>::iterator
551 i = m_clients.begin();
552 i != m_clients.end(); ++i)
554 if (i->second->getState() >= min_state)
555 reply.push_back(i->second->peer_id);
561 std::vector<std::string> ClientInterface::getPlayerNames()
563 return m_clients_names;
567 void ClientInterface::step(float dtime)
569 m_print_info_timer += dtime;
570 if(m_print_info_timer >= 30.0)
572 m_print_info_timer = 0.0;
577 void ClientInterface::UpdatePlayerList()
581 std::list<u16> clients = getClientIDs();
582 m_clients_names.clear();
585 if(clients.size() != 0)
586 infostream<<"Players:"<<std::endl;
587 for(std::list<u16>::iterator
589 i != clients.end(); ++i)
591 Player *player = m_env->getPlayer(*i);
594 infostream<<"* "<<player->getName()<<"\t";
597 JMutexAutoLock clientslock(m_clients_mutex);
598 RemoteClient* client = lockedGetClientNoEx(*i);
600 client->PrintInfo(infostream);
602 m_clients_names.push_back(player->getName());
607 void ClientInterface::send(u16 peer_id,u8 channelnum,
608 SharedBuffer<u8> data, bool reliable)
610 m_con->Send(peer_id, channelnum, data, reliable);
613 void ClientInterface::sendToAll(u16 channelnum,
614 SharedBuffer<u8> data, bool reliable)
616 JMutexAutoLock clientslock(m_clients_mutex);
617 for(std::map<u16, RemoteClient*>::iterator
618 i = m_clients.begin();
619 i != m_clients.end(); ++i)
621 RemoteClient *client = i->second;
623 if (client->net_proto_version != 0)
625 m_con->Send(client->peer_id, channelnum, data, reliable);
630 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
632 JMutexAutoLock clientslock(m_clients_mutex);
633 std::map<u16, RemoteClient*>::iterator n;
634 n = m_clients.find(peer_id);
635 // The client may not exist; clients are immediately removed if their
636 // access is denied, and this event occurs later then.
637 if(n == m_clients.end())
640 if (n->second->getState() >= state_min)
646 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
648 std::map<u16, RemoteClient*>::iterator n;
649 n = m_clients.find(peer_id);
650 // The client may not exist; clients are immediately removed if their
651 // access is denied, and this event occurs later then.
652 if(n == m_clients.end())
655 if (n->second->getState() >= state_min)
661 ClientState ClientInterface::getClientState(u16 peer_id)
663 JMutexAutoLock clientslock(m_clients_mutex);
664 std::map<u16, RemoteClient*>::iterator n;
665 n = m_clients.find(peer_id);
666 // The client may not exist; clients are immediately removed if their
667 // access is denied, and this event occurs later then.
668 if(n == m_clients.end())
671 return n->second->getState();
674 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
676 JMutexAutoLock clientslock(m_clients_mutex);
677 std::map<u16, RemoteClient*>::iterator n;
678 n = m_clients.find(peer_id);
679 // The client may not exist; clients are immediately removed if their
680 // access is denied, and this event occurs later then.
681 if(n != m_clients.end())
682 n->second->setName(name);
685 void ClientInterface::DeleteClient(u16 peer_id)
687 JMutexAutoLock conlock(m_clients_mutex);
690 std::map<u16, RemoteClient*>::iterator n;
691 n = m_clients.find(peer_id);
692 // The client may not exist; clients are immediately removed if their
693 // access is denied, and this event occurs later then.
694 if(n == m_clients.end())
698 Mark objects to be not known by the client
700 //TODO this should be done by client destructor!!!
701 RemoteClient *client = n->second;
703 for(std::set<u16>::iterator
704 i = client->m_known_objects.begin();
705 i != client->m_known_objects.end(); ++i)
709 ServerActiveObject* obj = m_env->getActiveObject(id);
711 if(obj && obj->m_known_by_count > 0)
712 obj->m_known_by_count--;
716 delete m_clients[peer_id];
717 m_clients.erase(peer_id);
720 void ClientInterface::CreateClient(u16 peer_id)
722 JMutexAutoLock conlock(m_clients_mutex);
725 std::map<u16, RemoteClient*>::iterator n;
726 n = m_clients.find(peer_id);
727 // The client shouldn't already exist
728 if(n != m_clients.end()) return;
731 RemoteClient *client = new RemoteClient();
732 client->peer_id = peer_id;
733 m_clients[client->peer_id] = client;
736 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
739 JMutexAutoLock clientlock(m_clients_mutex);
742 std::map<u16, RemoteClient*>::iterator n;
743 n = m_clients.find(peer_id);
745 // No client to deliver event
746 if (n == m_clients.end())
748 n->second->notifyEvent(event);
751 if ((event == SetMediaSent) || (event == Disconnect) || (event == SetDenied))
757 u16 ClientInterface::getProtocolVersion(u16 peer_id)
759 JMutexAutoLock conlock(m_clients_mutex);
762 std::map<u16, RemoteClient*>::iterator n;
763 n = m_clients.find(peer_id);
765 // No client to deliver event
766 if (n == m_clients.end())
769 return n->second->net_proto_version;