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.
22 #include "clientiface.h"
23 #include "util/numeric.h"
24 #include "util/mathconstants.h"
25 #include "remoteplayer.h"
28 #include "network/connection.h"
29 #include "environment.h"
32 #include "content_sao.h" // TODO this is used for cleanup of only
36 const char *ClientInterface::statenames[] = {
51 std::string ClientInterface::state2Name(ClientState state)
53 return statenames[state];
56 void RemoteClient::ResendBlockIfOnWire(v3s16 p)
58 // if this block is on wire, mark it for sending again as soon as possible
59 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
64 void RemoteClient::GetNextBlocks (
65 ServerEnvironment *env,
66 EmergeManager * emerge,
68 std::vector<PrioritySortedBlockTransfer> &dest)
70 DSTACK(FUNCTION_NAME);
74 m_nothing_to_send_pause_timer -= dtime;
75 m_nearest_unsent_reset_timer += dtime;
77 if(m_nothing_to_send_pause_timer >= 0)
80 RemotePlayer *player = env->getPlayer(peer_id);
81 // This can happen sometimes; clients and players are not in perfect sync.
85 PlayerSAO *sao = player->getPlayerSAO();
89 // Won't send anything if already sending
90 if(m_blocks_sending.size() >= g_settings->getU16
91 ("max_simultaneous_block_sends_per_client"))
93 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
97 v3f playerpos = sao->getBasePosition();
98 v3f playerspeed = player->getSpeed();
99 v3f playerspeeddir(0,0,0);
100 if(playerspeed.getLength() > 1.0*BS)
101 playerspeeddir = playerspeed / playerspeed.getLength();
102 // Predict to next block
103 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
105 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
107 v3s16 center = getNodeBlockPos(center_nodepos);
109 // Camera position and direction
110 v3f camera_pos = sao->getEyePosition();
111 v3f camera_dir = v3f(0,0,1);
112 camera_dir.rotateYZBy(sao->getPitch());
113 camera_dir.rotateXZBy(sao->getYaw());
115 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
116 <<camera_dir.Z<<")"<<std::endl;*/
119 Get the starting value of the block finder radius.
122 if(m_last_center != center)
124 m_nearest_unsent_d = 0;
125 m_last_center = center;
128 /*infostream<<"m_nearest_unsent_reset_timer="
129 <<m_nearest_unsent_reset_timer<<std::endl;*/
131 // Reset periodically to workaround for some bugs or stuff
132 if(m_nearest_unsent_reset_timer > 20.0)
134 m_nearest_unsent_reset_timer = 0;
135 m_nearest_unsent_d = 0;
136 //infostream<<"Resetting m_nearest_unsent_d for "
137 // <<server->getPlayerName(peer_id)<<std::endl;
140 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
141 s16 d_start = m_nearest_unsent_d;
143 //infostream<<"d_start="<<d_start<<std::endl;
145 u16 max_simul_sends_setting = g_settings->getU16
146 ("max_simultaneous_block_sends_per_client");
147 u16 max_simul_sends_usually = max_simul_sends_setting;
150 Check the time from last addNode/removeNode.
152 Decrease send rate if player is building stuff.
154 m_time_from_building += dtime;
155 if(m_time_from_building < g_settings->getFloat(
156 "full_block_send_enable_min_time_from_building"))
158 max_simul_sends_usually
159 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
163 Number of blocks sending + number of blocks selected for sending
165 u32 num_blocks_selected = m_blocks_sending.size();
168 next time d will be continued from the d from which the nearest
169 unsent block was found this time.
171 This is because not necessarily any of the blocks found this
172 time are actually sent.
174 s32 new_nearest_unsent_d = -1;
176 const s16 full_d_max = g_settings->getS16("max_block_send_distance");
177 const s16 d_opt = g_settings->getS16("block_send_optimize_distance");
179 s16 d_max = full_d_max;
180 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
182 // Don't loop very much at a time
183 s16 max_d_increment_at_time = 2;
184 if(d_max > d_start + max_d_increment_at_time)
185 d_max = d_start + max_d_increment_at_time;
187 s32 nearest_emerged_d = -1;
188 s32 nearest_emergefull_d = -1;
189 s32 nearest_sent_d = -1;
190 //bool queue_is_full = false;
193 for(d = d_start; d <= d_max; d++) {
195 Get the border/face dot coordinates of a "d-radiused"
198 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
200 std::vector<v3s16>::iterator li;
201 for(li = list.begin(); li != list.end(); ++li) {
202 v3s16 p = *li + center;
206 - Don't allow too many simultaneous transfers
207 - EXCEPT when the blocks are very close
209 Also, don't send blocks that are already flying.
212 // Start with the usual maximum
213 u16 max_simul_dynamic = max_simul_sends_usually;
215 // If block is very close, allow full maximum
216 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
217 max_simul_dynamic = max_simul_sends_setting;
219 // Don't select too many blocks for sending
220 if (num_blocks_selected >= max_simul_dynamic) {
221 //queue_is_full = true;
222 goto queue_full_break;
225 // Don't send blocks that are currently being transferred
226 if (m_blocks_sending.find(p) != m_blocks_sending.end())
232 if (blockpos_over_limit(p))
235 // If this is true, inexistent block will be made from scratch
236 bool generate = d <= d_max_gen;
239 /*// Limit the generating area vertically to 2/3
240 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
243 // Limit the send area vertically to 1/2
244 if (abs(p.Y - center.Y) > full_d_max / 2)
249 Don't generate or send if not in sight
250 FIXME This only works if the client uses a small enough
251 FOV setting. The default of 72 degrees is fine.
254 float camera_fov = (72.0*M_PI/180) * 4./3.;
255 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
261 Don't send already sent blocks
264 if(m_blocks_sent.find(p) != m_blocks_sent.end())
271 Check if map has this block
273 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
275 bool surely_not_found_on_disk = false;
276 bool block_is_invalid = false;
279 // Reset usage timer, this block will be of use in the future.
280 block->resetUsageTimer();
282 // Block is dummy if data doesn't exist.
283 // It means it has been not found from disk and not generated
286 surely_not_found_on_disk = true;
289 // Block is valid if lighting is up-to-date and data exists
290 if(block->isValid() == false)
292 block_is_invalid = true;
295 if(block->isGenerated() == false)
296 block_is_invalid = true;
299 If block is not close, don't send it unless it is near
302 Block is near ground level if night-time mesh
303 differs from day-time mesh.
307 if(block->getDayNightDiff() == false)
313 If block has been marked to not exist on disk (dummy)
314 and generating new ones is not wanted, skip block.
316 if(generate == false && surely_not_found_on_disk == true)
323 Add inexistent block to emerge queue.
325 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
327 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
328 if (nearest_emerged_d == -1)
329 nearest_emerged_d = d;
331 if (nearest_emergefull_d == -1)
332 nearest_emergefull_d = d;
333 goto queue_full_break;
340 if(nearest_sent_d == -1)
344 Add block to send queue
346 PrioritySortedBlockTransfer q((float)d, p, peer_id);
350 num_blocks_selected += 1;
355 // If nothing was found for sending and nothing was queued for
356 // emerging, continue next time browsing from here
357 if(nearest_emerged_d != -1){
358 new_nearest_unsent_d = nearest_emerged_d;
359 } else if(nearest_emergefull_d != -1){
360 new_nearest_unsent_d = nearest_emergefull_d;
362 if(d > g_settings->getS16("max_block_send_distance")){
363 new_nearest_unsent_d = 0;
364 m_nothing_to_send_pause_timer = 2.0;
366 if(nearest_sent_d != -1)
367 new_nearest_unsent_d = nearest_sent_d;
369 new_nearest_unsent_d = d;
373 if(new_nearest_unsent_d != -1)
374 m_nearest_unsent_d = new_nearest_unsent_d;
377 void RemoteClient::GotBlock(v3s16 p)
379 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
380 if (m_blocks_sending.find(p) != m_blocks_sending.end())
381 m_blocks_sending.erase(p);
383 m_excess_gotblocks++;
385 m_blocks_sent.insert(p);
389 void RemoteClient::SentBlock(v3s16 p)
391 if (m_blocks_modified.find(p) != m_blocks_modified.end())
392 m_blocks_modified.erase(p);
394 if(m_blocks_sending.find(p) == m_blocks_sending.end())
395 m_blocks_sending[p] = 0.0;
397 infostream<<"RemoteClient::SentBlock(): Sent block"
398 " already in m_blocks_sending"<<std::endl;
401 void RemoteClient::SetBlockNotSent(v3s16 p)
403 m_nearest_unsent_d = 0;
404 m_nothing_to_send_pause_timer = 0;
406 if(m_blocks_sending.find(p) != m_blocks_sending.end())
407 m_blocks_sending.erase(p);
408 if(m_blocks_sent.find(p) != m_blocks_sent.end())
409 m_blocks_sent.erase(p);
410 m_blocks_modified.insert(p);
413 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
415 m_nearest_unsent_d = 0;
416 m_nothing_to_send_pause_timer = 0;
418 for(std::map<v3s16, MapBlock*>::iterator
420 i != blocks.end(); ++i)
423 m_blocks_modified.insert(p);
425 if(m_blocks_sending.find(p) != m_blocks_sending.end())
426 m_blocks_sending.erase(p);
427 if(m_blocks_sent.find(p) != m_blocks_sent.end())
428 m_blocks_sent.erase(p);
432 void RemoteClient::notifyEvent(ClientStateEvent event)
434 std::ostringstream myerror;
438 //intentionally do nothing
443 m_state = CS_HelloSent;
446 m_state = CS_AwaitingInit2;
449 m_state = CS_Disconnecting;
454 /* GotInit2 SetDefinitionsSent SetMediaSent */
456 myerror << "Created: Invalid client state transition! " << event;
457 throw ClientStateError(myerror.str());
461 /* don't do anything if in denied state */
467 m_state = CS_AwaitingInit2;
468 if ((chosen_mech == AUTH_MECHANISM_SRP)
469 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
470 srp_verifier_delete((SRPVerifier *) auth_data);
471 chosen_mech = AUTH_MECHANISM_NONE;
474 m_state = CS_Disconnecting;
478 if ((chosen_mech == AUTH_MECHANISM_SRP)
479 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
480 srp_verifier_delete((SRPVerifier *) auth_data);
481 chosen_mech = AUTH_MECHANISM_NONE;
484 myerror << "HelloSent: Invalid client state transition! " << event;
485 throw ClientStateError(myerror.str());
488 case CS_AwaitingInit2:
492 confirmSerializationVersion();
493 m_state = CS_InitDone;
496 m_state = CS_Disconnecting;
502 /* Init SetDefinitionsSent SetMediaSent */
504 myerror << "InitSent: Invalid client state transition! " << event;
505 throw ClientStateError(myerror.str());
512 case CSE_SetDefinitionsSent:
513 m_state = CS_DefinitionsSent;
516 m_state = CS_Disconnecting;
522 /* Init GotInit2 SetMediaSent */
524 myerror << "InitDone: Invalid client state transition! " << event;
525 throw ClientStateError(myerror.str());
528 case CS_DefinitionsSent:
531 case CSE_SetClientReady:
535 m_state = CS_Disconnecting;
540 /* Init GotInit2 SetDefinitionsSent */
542 myerror << "DefinitionsSent: Invalid client state transition! " << event;
543 throw ClientStateError(myerror.str());
553 m_state = CS_Disconnecting;
555 case CSE_SudoSuccess:
556 m_state = CS_SudoMode;
557 if ((chosen_mech == AUTH_MECHANISM_SRP)
558 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
559 srp_verifier_delete((SRPVerifier *) auth_data);
560 chosen_mech = AUTH_MECHANISM_NONE;
562 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
564 myerror << "Active: Invalid client state transition! " << event;
565 throw ClientStateError(myerror.str());
576 m_state = CS_Disconnecting;
582 myerror << "Active: Invalid client state transition! " << event;
583 throw ClientStateError(myerror.str());
587 case CS_Disconnecting:
588 /* we are already disconnecting */
593 u32 RemoteClient::uptime()
595 return getTime(PRECISION_SECONDS) - m_connection_time;
598 ClientInterface::ClientInterface(con::Connection* con)
602 m_print_info_timer(0.0)
606 ClientInterface::~ClientInterface()
612 MutexAutoLock clientslock(m_clients_mutex);
614 for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
615 i != m_clients.end(); ++i) {
622 std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
624 std::vector<u16> reply;
625 MutexAutoLock clientslock(m_clients_mutex);
627 for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
628 i != m_clients.end(); ++i) {
629 if (i->second->getState() >= min_state)
630 reply.push_back(i->second->peer_id);
636 void ClientInterface::step(float dtime)
638 m_print_info_timer += dtime;
639 if(m_print_info_timer >= 30.0)
641 m_print_info_timer = 0.0;
646 void ClientInterface::UpdatePlayerList()
649 std::vector<u16> clients = getClientIDs();
650 m_clients_names.clear();
654 infostream<<"Players:"<<std::endl;
656 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
657 RemotePlayer *player = m_env->getPlayer(*i);
662 infostream << "* " << player->getName() << "\t";
665 MutexAutoLock clientslock(m_clients_mutex);
666 RemoteClient* client = lockedGetClientNoEx(*i);
668 client->PrintInfo(infostream);
671 m_clients_names.push_back(player->getName());
676 void ClientInterface::send(u16 peer_id, u8 channelnum,
677 NetworkPacket* pkt, bool reliable)
679 m_con->Send(peer_id, channelnum, pkt, reliable);
682 void ClientInterface::sendToAll(u16 channelnum,
683 NetworkPacket* pkt, bool reliable)
685 MutexAutoLock clientslock(m_clients_mutex);
686 for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
687 i != m_clients.end(); ++i) {
688 RemoteClient *client = i->second;
690 if (client->net_proto_version != 0) {
691 m_con->Send(client->peer_id, channelnum, pkt, reliable);
696 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
698 MutexAutoLock clientslock(m_clients_mutex);
699 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
700 // The client may not exist; clients are immediately removed if their
701 // access is denied, and this event occurs later then.
702 if (n == m_clients.end())
705 if (n->second->getState() >= state_min)
711 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
713 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
714 // The client may not exist; clients are immediately removed if their
715 // access is denied, and this event occurs later then.
716 if (n == m_clients.end())
719 if (n->second->getState() >= state_min)
725 ClientState ClientInterface::getClientState(u16 peer_id)
727 MutexAutoLock clientslock(m_clients_mutex);
728 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
729 // The client may not exist; clients are immediately removed if their
730 // access is denied, and this event occurs later then.
731 if (n == m_clients.end())
734 return n->second->getState();
737 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
739 MutexAutoLock clientslock(m_clients_mutex);
740 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
741 // The client may not exist; clients are immediately removed if their
742 // access is denied, and this event occurs later then.
743 if (n != m_clients.end())
744 n->second->setName(name);
747 void ClientInterface::DeleteClient(u16 peer_id)
749 MutexAutoLock conlock(m_clients_mutex);
752 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
753 // The client may not exist; clients are immediately removed if their
754 // access is denied, and this event occurs later then.
755 if (n == m_clients.end())
759 Mark objects to be not known by the client
761 //TODO this should be done by client destructor!!!
762 RemoteClient *client = n->second;
764 for(std::set<u16>::iterator
765 i = client->m_known_objects.begin();
766 i != client->m_known_objects.end(); ++i)
770 ServerActiveObject* obj = m_env->getActiveObject(id);
772 if(obj && obj->m_known_by_count > 0)
773 obj->m_known_by_count--;
777 delete m_clients[peer_id];
778 m_clients.erase(peer_id);
781 void ClientInterface::CreateClient(u16 peer_id)
783 MutexAutoLock conlock(m_clients_mutex);
786 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
787 // The client shouldn't already exist
788 if (n != m_clients.end()) return;
791 RemoteClient *client = new RemoteClient();
792 client->peer_id = peer_id;
793 m_clients[client->peer_id] = client;
796 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
799 MutexAutoLock clientlock(m_clients_mutex);
802 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
804 // No client to deliver event
805 if (n == m_clients.end())
807 n->second->notifyEvent(event);
810 if ((event == CSE_SetClientReady) ||
811 (event == CSE_Disconnect) ||
812 (event == CSE_SetDenied))
818 u16 ClientInterface::getProtocolVersion(u16 peer_id)
820 MutexAutoLock conlock(m_clients_mutex);
823 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
825 // No client to get version
826 if (n == m_clients.end())
829 return n->second->net_proto_version;
832 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
834 MutexAutoLock conlock(m_clients_mutex);
837 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
839 // No client to set versions
840 if (n == m_clients.end())
843 n->second->setVersionInfo(major,minor,patch,full);