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"
28 #include "network/connection.h"
29 #include "environment.h"
32 #include "serverobject.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 // Won't send anything if already sending
86 if(m_blocks_sending.size() >= g_settings->getU16
87 ("max_simultaneous_block_sends_per_client"))
89 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
93 v3f playerpos = player->getPosition();
94 v3f playerspeed = player->getSpeed();
95 v3f playerspeeddir(0,0,0);
96 if(playerspeed.getLength() > 1.0*BS)
97 playerspeeddir = playerspeed / playerspeed.getLength();
98 // Predict to next block
99 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
101 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
103 v3s16 center = getNodeBlockPos(center_nodepos);
105 // Camera position and direction
106 v3f camera_pos = player->getEyePosition();
107 v3f camera_dir = v3f(0,0,1);
108 camera_dir.rotateYZBy(player->getPitch());
109 camera_dir.rotateXZBy(player->getYaw());
111 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
112 <<camera_dir.Z<<")"<<std::endl;*/
115 Get the starting value of the block finder radius.
118 if(m_last_center != center)
120 m_nearest_unsent_d = 0;
121 m_last_center = center;
124 /*infostream<<"m_nearest_unsent_reset_timer="
125 <<m_nearest_unsent_reset_timer<<std::endl;*/
127 // Reset periodically to workaround for some bugs or stuff
128 if(m_nearest_unsent_reset_timer > 20.0)
130 m_nearest_unsent_reset_timer = 0;
131 m_nearest_unsent_d = 0;
132 //infostream<<"Resetting m_nearest_unsent_d for "
133 // <<server->getPlayerName(peer_id)<<std::endl;
136 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
137 s16 d_start = m_nearest_unsent_d;
139 //infostream<<"d_start="<<d_start<<std::endl;
141 u16 max_simul_sends_setting = g_settings->getU16
142 ("max_simultaneous_block_sends_per_client");
143 u16 max_simul_sends_usually = max_simul_sends_setting;
146 Check the time from last addNode/removeNode.
148 Decrease send rate if player is building stuff.
150 m_time_from_building += dtime;
151 if(m_time_from_building < g_settings->getFloat(
152 "full_block_send_enable_min_time_from_building"))
154 max_simul_sends_usually
155 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
159 Number of blocks sending + number of blocks selected for sending
161 u32 num_blocks_selected = m_blocks_sending.size();
164 next time d will be continued from the d from which the nearest
165 unsent block was found this time.
167 This is because not necessarily any of the blocks found this
168 time are actually sent.
170 s32 new_nearest_unsent_d = -1;
172 const s16 full_d_max = g_settings->getS16("max_block_send_distance");
173 s16 d_max = full_d_max;
174 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
176 // Don't loop very much at a time
177 s16 max_d_increment_at_time = 2;
178 if(d_max > d_start + max_d_increment_at_time)
179 d_max = d_start + max_d_increment_at_time;
181 s32 nearest_emerged_d = -1;
182 s32 nearest_emergefull_d = -1;
183 s32 nearest_sent_d = -1;
184 //bool queue_is_full = false;
187 for(d = d_start; d <= d_max; d++) {
189 Get the border/face dot coordinates of a "d-radiused"
192 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
194 std::vector<v3s16>::iterator li;
195 for(li = list.begin(); li != list.end(); ++li) {
196 v3s16 p = *li + center;
200 - Don't allow too many simultaneous transfers
201 - EXCEPT when the blocks are very close
203 Also, don't send blocks that are already flying.
206 // Start with the usual maximum
207 u16 max_simul_dynamic = max_simul_sends_usually;
209 // If block is very close, allow full maximum
210 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
211 max_simul_dynamic = max_simul_sends_setting;
213 // Don't select too many blocks for sending
214 if (num_blocks_selected >= max_simul_dynamic) {
215 //queue_is_full = true;
216 goto queue_full_break;
219 // Don't send blocks that are currently being transferred
220 if (m_blocks_sending.find(p) != m_blocks_sending.end())
226 if (blockpos_over_limit(p))
229 // If this is true, inexistent block will be made from scratch
230 bool generate = d <= d_max_gen;
233 /*// Limit the generating area vertically to 2/3
234 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
237 // Limit the send area vertically to 1/2
238 if (abs(p.Y - center.Y) > full_d_max / 2)
243 Don't generate or send if not in sight
244 FIXME This only works if the client uses a small enough
245 FOV setting. The default of 72 degrees is fine.
248 float camera_fov = (72.0*M_PI/180) * 4./3.;
249 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
255 Don't send already sent blocks
258 if(m_blocks_sent.find(p) != m_blocks_sent.end())
265 Check if map has this block
267 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
269 bool surely_not_found_on_disk = false;
270 bool block_is_invalid = false;
273 // Reset usage timer, this block will be of use in the future.
274 block->resetUsageTimer();
276 // Block is dummy if data doesn't exist.
277 // It means it has been not found from disk and not generated
280 surely_not_found_on_disk = true;
283 // Block is valid if lighting is up-to-date and data exists
284 if(block->isValid() == false)
286 block_is_invalid = true;
289 if(block->isGenerated() == false)
290 block_is_invalid = true;
293 If block is not close, don't send it unless it is near
296 Block is near ground level if night-time mesh
297 differs from day-time mesh.
301 if(block->getDayNightDiff() == false)
307 If block has been marked to not exist on disk (dummy)
308 and generating new ones is not wanted, skip block.
310 if(generate == false && surely_not_found_on_disk == true)
317 Add inexistent block to emerge queue.
319 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
321 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
322 if (nearest_emerged_d == -1)
323 nearest_emerged_d = d;
325 if (nearest_emergefull_d == -1)
326 nearest_emergefull_d = d;
327 goto queue_full_break;
334 if(nearest_sent_d == -1)
338 Add block to send queue
340 PrioritySortedBlockTransfer q((float)d, p, peer_id);
344 num_blocks_selected += 1;
349 // If nothing was found for sending and nothing was queued for
350 // emerging, continue next time browsing from here
351 if(nearest_emerged_d != -1){
352 new_nearest_unsent_d = nearest_emerged_d;
353 } else if(nearest_emergefull_d != -1){
354 new_nearest_unsent_d = nearest_emergefull_d;
356 if(d > g_settings->getS16("max_block_send_distance")){
357 new_nearest_unsent_d = 0;
358 m_nothing_to_send_pause_timer = 2.0;
360 if(nearest_sent_d != -1)
361 new_nearest_unsent_d = nearest_sent_d;
363 new_nearest_unsent_d = d;
367 if(new_nearest_unsent_d != -1)
368 m_nearest_unsent_d = new_nearest_unsent_d;
371 void RemoteClient::GotBlock(v3s16 p)
373 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
374 if (m_blocks_sending.find(p) != m_blocks_sending.end())
375 m_blocks_sending.erase(p);
377 m_excess_gotblocks++;
379 m_blocks_sent.insert(p);
383 void RemoteClient::SentBlock(v3s16 p)
385 if (m_blocks_modified.find(p) != m_blocks_modified.end())
386 m_blocks_modified.erase(p);
388 if(m_blocks_sending.find(p) == m_blocks_sending.end())
389 m_blocks_sending[p] = 0.0;
391 infostream<<"RemoteClient::SentBlock(): Sent block"
392 " already in m_blocks_sending"<<std::endl;
395 void RemoteClient::SetBlockNotSent(v3s16 p)
397 m_nearest_unsent_d = 0;
398 m_nothing_to_send_pause_timer = 0;
400 if(m_blocks_sending.find(p) != m_blocks_sending.end())
401 m_blocks_sending.erase(p);
402 if(m_blocks_sent.find(p) != m_blocks_sent.end())
403 m_blocks_sent.erase(p);
404 m_blocks_modified.insert(p);
407 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
409 m_nearest_unsent_d = 0;
410 m_nothing_to_send_pause_timer = 0;
412 for(std::map<v3s16, MapBlock*>::iterator
414 i != blocks.end(); ++i)
417 m_blocks_modified.insert(p);
419 if(m_blocks_sending.find(p) != m_blocks_sending.end())
420 m_blocks_sending.erase(p);
421 if(m_blocks_sent.find(p) != m_blocks_sent.end())
422 m_blocks_sent.erase(p);
426 void RemoteClient::notifyEvent(ClientStateEvent event)
428 std::ostringstream myerror;
432 //intentionally do nothing
437 m_state = CS_HelloSent;
440 m_state = CS_AwaitingInit2;
443 m_state = CS_Disconnecting;
448 /* GotInit2 SetDefinitionsSent SetMediaSent */
450 myerror << "Created: Invalid client state transition! " << event;
451 throw ClientStateError(myerror.str());
455 /* don't do anything if in denied state */
461 m_state = CS_AwaitingInit2;
462 if ((chosen_mech == AUTH_MECHANISM_SRP)
463 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
464 srp_verifier_delete((SRPVerifier *) auth_data);
465 chosen_mech = AUTH_MECHANISM_NONE;
468 m_state = CS_Disconnecting;
472 if ((chosen_mech == AUTH_MECHANISM_SRP)
473 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
474 srp_verifier_delete((SRPVerifier *) auth_data);
475 chosen_mech = AUTH_MECHANISM_NONE;
478 myerror << "HelloSent: Invalid client state transition! " << event;
479 throw ClientStateError(myerror.str());
482 case CS_AwaitingInit2:
486 confirmSerializationVersion();
487 m_state = CS_InitDone;
490 m_state = CS_Disconnecting;
496 /* Init SetDefinitionsSent SetMediaSent */
498 myerror << "InitSent: Invalid client state transition! " << event;
499 throw ClientStateError(myerror.str());
506 case CSE_SetDefinitionsSent:
507 m_state = CS_DefinitionsSent;
510 m_state = CS_Disconnecting;
516 /* Init GotInit2 SetMediaSent */
518 myerror << "InitDone: Invalid client state transition! " << event;
519 throw ClientStateError(myerror.str());
522 case CS_DefinitionsSent:
525 case CSE_SetClientReady:
529 m_state = CS_Disconnecting;
534 /* Init GotInit2 SetDefinitionsSent */
536 myerror << "DefinitionsSent: Invalid client state transition! " << event;
537 throw ClientStateError(myerror.str());
547 m_state = CS_Disconnecting;
549 case CSE_SudoSuccess:
550 m_state = CS_SudoMode;
551 if ((chosen_mech == AUTH_MECHANISM_SRP)
552 || (chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD))
553 srp_verifier_delete((SRPVerifier *) auth_data);
554 chosen_mech = AUTH_MECHANISM_NONE;
556 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
558 myerror << "Active: Invalid client state transition! " << event;
559 throw ClientStateError(myerror.str());
570 m_state = CS_Disconnecting;
576 myerror << "Active: Invalid client state transition! " << event;
577 throw ClientStateError(myerror.str());
581 case CS_Disconnecting:
582 /* we are already disconnecting */
587 u32 RemoteClient::uptime()
589 return getTime(PRECISION_SECONDS) - m_connection_time;
592 ClientInterface::ClientInterface(con::Connection* con)
596 m_print_info_timer(0.0)
600 ClientInterface::~ClientInterface()
606 MutexAutoLock clientslock(m_clients_mutex);
608 for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
609 i != m_clients.end(); ++i) {
616 std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
618 std::vector<u16> reply;
619 MutexAutoLock clientslock(m_clients_mutex);
621 for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
622 i != m_clients.end(); ++i) {
623 if (i->second->getState() >= min_state)
624 reply.push_back(i->second->peer_id);
630 void ClientInterface::step(float dtime)
632 m_print_info_timer += dtime;
633 if(m_print_info_timer >= 30.0)
635 m_print_info_timer = 0.0;
640 void ClientInterface::UpdatePlayerList()
643 std::vector<u16> clients = getClientIDs();
644 m_clients_names.clear();
648 infostream<<"Players:"<<std::endl;
650 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
651 RemotePlayer *player = m_env->getPlayer(*i);
656 infostream << "* " << player->getName() << "\t";
659 MutexAutoLock clientslock(m_clients_mutex);
660 RemoteClient* client = lockedGetClientNoEx(*i);
662 client->PrintInfo(infostream);
665 m_clients_names.push_back(player->getName());
670 void ClientInterface::send(u16 peer_id, u8 channelnum,
671 NetworkPacket* pkt, bool reliable)
673 m_con->Send(peer_id, channelnum, pkt, reliable);
676 void ClientInterface::sendToAll(u16 channelnum,
677 NetworkPacket* pkt, bool reliable)
679 MutexAutoLock clientslock(m_clients_mutex);
680 for(UNORDERED_MAP<u16, RemoteClient*>::iterator i = m_clients.begin();
681 i != m_clients.end(); ++i) {
682 RemoteClient *client = i->second;
684 if (client->net_proto_version != 0) {
685 m_con->Send(client->peer_id, channelnum, pkt, reliable);
690 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
692 MutexAutoLock clientslock(m_clients_mutex);
693 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
694 // The client may not exist; clients are immediately removed if their
695 // access is denied, and this event occurs later then.
696 if (n == m_clients.end())
699 if (n->second->getState() >= state_min)
705 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
707 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
708 // The client may not exist; clients are immediately removed if their
709 // access is denied, and this event occurs later then.
710 if (n == m_clients.end())
713 if (n->second->getState() >= state_min)
719 ClientState ClientInterface::getClientState(u16 peer_id)
721 MutexAutoLock clientslock(m_clients_mutex);
722 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
723 // The client may not exist; clients are immediately removed if their
724 // access is denied, and this event occurs later then.
725 if (n == m_clients.end())
728 return n->second->getState();
731 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
733 MutexAutoLock clientslock(m_clients_mutex);
734 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
735 // The client may not exist; clients are immediately removed if their
736 // access is denied, and this event occurs later then.
737 if (n != m_clients.end())
738 n->second->setName(name);
741 void ClientInterface::DeleteClient(u16 peer_id)
743 MutexAutoLock conlock(m_clients_mutex);
746 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
747 // The client may not exist; clients are immediately removed if their
748 // access is denied, and this event occurs later then.
749 if (n == m_clients.end())
753 Mark objects to be not known by the client
755 //TODO this should be done by client destructor!!!
756 RemoteClient *client = n->second;
758 for(std::set<u16>::iterator
759 i = client->m_known_objects.begin();
760 i != client->m_known_objects.end(); ++i)
764 ServerActiveObject* obj = m_env->getActiveObject(id);
766 if(obj && obj->m_known_by_count > 0)
767 obj->m_known_by_count--;
771 delete m_clients[peer_id];
772 m_clients.erase(peer_id);
775 void ClientInterface::CreateClient(u16 peer_id)
777 MutexAutoLock conlock(m_clients_mutex);
780 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
781 // The client shouldn't already exist
782 if (n != m_clients.end()) return;
785 RemoteClient *client = new RemoteClient();
786 client->peer_id = peer_id;
787 m_clients[client->peer_id] = client;
790 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
793 MutexAutoLock clientlock(m_clients_mutex);
796 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
798 // No client to deliver event
799 if (n == m_clients.end())
801 n->second->notifyEvent(event);
804 if ((event == CSE_SetClientReady) ||
805 (event == CSE_Disconnect) ||
806 (event == CSE_SetDenied))
812 u16 ClientInterface::getProtocolVersion(u16 peer_id)
814 MutexAutoLock conlock(m_clients_mutex);
817 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
819 // No client to get version
820 if (n == m_clients.end())
823 return n->second->net_proto_version;
826 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
828 MutexAutoLock conlock(m_clients_mutex);
831 UNORDERED_MAP<u16, RemoteClient*>::iterator n = m_clients.find(peer_id);
833 // No client to set versions
834 if (n == m_clients.end())
837 n->second->setVersionInfo(major,minor,patch,full);