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.
21 #include "clientiface.h"
22 #include "network/connection.h"
23 #include "network/serveropcodes.h"
24 #include "remoteplayer.h"
27 #include "serverenvironment.h"
30 #include "content_sao.h" // TODO this is used for cleanup of only
33 #include "face_position_cache.h"
35 const char *ClientInterface::statenames[] = {
50 std::string ClientInterface::state2Name(ClientState state)
52 return statenames[state];
55 RemoteClient::RemoteClient() :
56 m_max_simul_sends(g_settings->getU16("max_simultaneous_block_sends_per_client")),
57 m_min_time_from_building(
58 g_settings->getFloat("full_block_send_enable_min_time_from_building")),
59 m_max_send_distance(g_settings->getS16("max_block_send_distance")),
60 m_block_optimize_distance(g_settings->getS16("block_send_optimize_distance")),
61 m_max_gen_distance(g_settings->getS16("max_block_generate_distance")),
62 m_occ_cull(g_settings->getBool("server_side_occlusion_culling"))
66 void RemoteClient::ResendBlockIfOnWire(v3s16 p)
68 // if this block is on wire, mark it for sending again as soon as possible
69 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
74 LuaEntitySAO *getAttachedObject(PlayerSAO *sao, ServerEnvironment *env)
76 if (!sao->isAttached())
82 sao->getAttachment(&id, &bone, &dummy, &dummy);
83 ServerActiveObject *ao = env->getActiveObject(id);
85 ao->getAttachment(&id, &bone, &dummy, &dummy);
87 ao = env->getActiveObject(id);
89 return dynamic_cast<LuaEntitySAO *>(ao);
92 void RemoteClient::GetNextBlocks (
93 ServerEnvironment *env,
94 EmergeManager * emerge,
96 std::vector<PrioritySortedBlockTransfer> &dest)
99 m_nothing_to_send_pause_timer -= dtime;
100 m_nearest_unsent_reset_timer += dtime;
102 if (m_nothing_to_send_pause_timer >= 0)
105 RemotePlayer *player = env->getPlayer(peer_id);
106 // This can happen sometimes; clients and players are not in perfect sync.
110 PlayerSAO *sao = player->getPlayerSAO();
114 // Won't send anything if already sending
115 if (m_blocks_sending.size() >= m_max_simul_sends) {
116 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
120 v3f playerpos = sao->getBasePosition();
121 // if the player is attached, get the velocity from the attached object
122 LuaEntitySAO *lsao = getAttachedObject(sao, env);
123 const v3f &playerspeed = lsao? lsao->getVelocity() : player->getSpeed();
124 v3f playerspeeddir(0,0,0);
125 if (playerspeed.getLength() > 1.0f * BS)
126 playerspeeddir = playerspeed / playerspeed.getLength();
127 // Predict to next block
128 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
130 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
132 v3s16 center = getNodeBlockPos(center_nodepos);
134 // Camera position and direction
135 v3f camera_pos = sao->getEyePosition();
136 v3f camera_dir = v3f(0,0,1);
137 camera_dir.rotateYZBy(sao->getPitch());
138 camera_dir.rotateXZBy(sao->getYaw());
140 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
141 <<camera_dir.Z<<")"<<std::endl;*/
144 Get the starting value of the block finder radius.
147 if (m_last_center != center) {
148 m_nearest_unsent_d = 0;
149 m_last_center = center;
152 /*infostream<<"m_nearest_unsent_reset_timer="
153 <<m_nearest_unsent_reset_timer<<std::endl;*/
155 // Reset periodically to workaround for some bugs or stuff
156 if (m_nearest_unsent_reset_timer > 20.0f) {
157 m_nearest_unsent_reset_timer = 0.0f;
158 m_nearest_unsent_d = 0;
159 //infostream<<"Resetting m_nearest_unsent_d for "
160 // <<server->getPlayerName(peer_id)<<std::endl;
163 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
164 s16 d_start = m_nearest_unsent_d;
166 //infostream<<"d_start="<<d_start<<std::endl;
168 u16 max_simul_sends_usually = m_max_simul_sends;
171 Check the time from last addNode/removeNode.
173 Decrease send rate if player is building stuff.
175 m_time_from_building += dtime;
176 if (m_time_from_building < m_min_time_from_building) {
177 max_simul_sends_usually
178 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
182 Number of blocks sending + number of blocks selected for sending
184 u32 num_blocks_selected = m_blocks_sending.size();
187 next time d will be continued from the d from which the nearest
188 unsent block was found this time.
190 This is because not necessarily any of the blocks found this
191 time are actually sent.
193 s32 new_nearest_unsent_d = -1;
195 // get view range and camera fov from the client
196 s16 wanted_range = sao->getWantedRange() + 1;
197 float camera_fov = sao->getFov();
199 const s16 full_d_max = std::min(m_max_send_distance, wanted_range);
200 const s16 d_opt = std::min(m_block_optimize_distance, wanted_range);
201 const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
202 //infostream << "Fov from client " << camera_fov << " full_d_max " << full_d_max << std::endl;
204 s16 d_max = full_d_max;
205 s16 d_max_gen = std::min(m_max_gen_distance, wanted_range);
207 // Don't loop very much at a time
208 s16 max_d_increment_at_time = 1;
209 if (d_max > d_start + max_d_increment_at_time)
210 d_max = d_start + max_d_increment_at_time;
212 s32 nearest_emerged_d = -1;
213 s32 nearest_emergefull_d = -1;
214 s32 nearest_sent_d = -1;
215 //bool queue_is_full = false;
217 const v3s16 cam_pos_nodes = floatToInt(camera_pos, BS);
220 for (d = d_start; d <= d_max; d++) {
222 Get the border/face dot coordinates of a "d-radiused"
225 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
227 std::vector<v3s16>::iterator li;
228 for (li = list.begin(); li != list.end(); ++li) {
229 v3s16 p = *li + center;
233 - Don't allow too many simultaneous transfers
234 - EXCEPT when the blocks are very close
236 Also, don't send blocks that are already flying.
239 // Start with the usual maximum
240 u16 max_simul_dynamic = max_simul_sends_usually;
242 // If block is very close, allow full maximum
243 if (d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
244 max_simul_dynamic = m_max_simul_sends;
246 // Don't select too many blocks for sending
247 if (num_blocks_selected >= max_simul_dynamic) {
248 //queue_is_full = true;
249 goto queue_full_break;
252 // Don't send blocks that are currently being transferred
253 if (m_blocks_sending.find(p) != m_blocks_sending.end())
257 Do not go over max mapgen limit
259 if (blockpos_over_max_limit(p))
262 // If this is true, inexistent block will be made from scratch
263 bool generate = d <= d_max_gen;
266 Don't generate or send if not in sight
267 FIXME This only works if the client uses a small enough
268 FOV setting. The default of 72 degrees is fine.
269 Also retrieve a smaller view cone in the direction of the player's
271 (0.1 is about 4 degrees)
274 if (!(isBlockInSight(p, camera_pos, camera_dir, camera_fov,
275 d_blocks_in_sight, &dist) ||
276 (playerspeed.getLength() > 1.0f * BS &&
277 isBlockInSight(p, camera_pos, playerspeeddir, 0.1f,
278 d_blocks_in_sight)))) {
283 Don't send already sent blocks
285 if (m_blocks_sent.find(p) != m_blocks_sent.end())
289 Check if map has this block
291 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
293 bool surely_not_found_on_disk = false;
294 bool block_is_invalid = false;
296 // Reset usage timer, this block will be of use in the future.
297 block->resetUsageTimer();
299 // Block is dummy if data doesn't exist.
300 // It means it has been not found from disk and not generated
301 if (block->isDummy()) {
302 surely_not_found_on_disk = true;
305 if (!block->isGenerated())
306 block_is_invalid = true;
309 If block is not close, don't send it unless it is near
312 Block is near ground level if night-time mesh
313 differs from day-time mesh.
316 if (!block->getDayNightDiff())
320 if (m_occ_cull && !block_is_invalid &&
321 env->getMap().isBlockOccluded(block, cam_pos_nodes)) {
327 If block has been marked to not exist on disk (dummy)
328 and generating new ones is not wanted, skip block.
330 if (!generate && surely_not_found_on_disk) {
336 Add inexistent block to emerge queue.
338 if (block == NULL || surely_not_found_on_disk || block_is_invalid) {
339 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
340 if (nearest_emerged_d == -1)
341 nearest_emerged_d = d;
343 if (nearest_emergefull_d == -1)
344 nearest_emergefull_d = d;
345 goto queue_full_break;
352 if (nearest_sent_d == -1)
356 Add block to send queue
358 PrioritySortedBlockTransfer q((float)dist, p, peer_id);
362 num_blocks_selected += 1;
367 // If nothing was found for sending and nothing was queued for
368 // emerging, continue next time browsing from here
369 if (nearest_emerged_d != -1) {
370 new_nearest_unsent_d = nearest_emerged_d;
371 } else if (nearest_emergefull_d != -1) {
372 new_nearest_unsent_d = nearest_emergefull_d;
374 if (d > full_d_max) {
375 new_nearest_unsent_d = 0;
376 m_nothing_to_send_pause_timer = 2.0f;
378 if (nearest_sent_d != -1)
379 new_nearest_unsent_d = nearest_sent_d;
381 new_nearest_unsent_d = d;
385 if (new_nearest_unsent_d != -1)
386 m_nearest_unsent_d = new_nearest_unsent_d;
389 void RemoteClient::GotBlock(v3s16 p)
391 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
392 if (m_blocks_sending.find(p) != m_blocks_sending.end())
393 m_blocks_sending.erase(p);
395 m_excess_gotblocks++;
397 m_blocks_sent.insert(p);
401 void RemoteClient::SentBlock(v3s16 p)
403 if (m_blocks_modified.find(p) != m_blocks_modified.end())
404 m_blocks_modified.erase(p);
406 if (m_blocks_sending.find(p) == m_blocks_sending.end())
407 m_blocks_sending[p] = 0.0f;
409 infostream<<"RemoteClient::SentBlock(): Sent block"
410 " already in m_blocks_sending"<<std::endl;
413 void RemoteClient::SetBlockNotSent(v3s16 p)
415 m_nearest_unsent_d = 0;
416 m_nothing_to_send_pause_timer = 0;
418 if (m_blocks_sending.find(p) != m_blocks_sending.end())
419 m_blocks_sending.erase(p);
420 if (m_blocks_sent.find(p) != m_blocks_sent.end())
421 m_blocks_sent.erase(p);
422 m_blocks_modified.insert(p);
425 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
427 m_nearest_unsent_d = 0;
428 m_nothing_to_send_pause_timer = 0;
430 for (auto &block : blocks) {
431 v3s16 p = block.first;
432 m_blocks_modified.insert(p);
434 if (m_blocks_sending.find(p) != m_blocks_sending.end())
435 m_blocks_sending.erase(p);
436 if (m_blocks_sent.find(p) != m_blocks_sent.end())
437 m_blocks_sent.erase(p);
441 void RemoteClient::notifyEvent(ClientStateEvent event)
443 std::ostringstream myerror;
447 //intentionally do nothing
452 m_state = CS_HelloSent;
455 m_state = CS_AwaitingInit2;
458 m_state = CS_Disconnecting;
463 /* GotInit2 SetDefinitionsSent SetMediaSent */
465 myerror << "Created: Invalid client state transition! " << event;
466 throw ClientStateError(myerror.str());
470 /* don't do anything if in denied state */
476 m_state = CS_AwaitingInit2;
477 if (chosen_mech == AUTH_MECHANISM_SRP ||
478 chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
479 srp_verifier_delete((SRPVerifier *) auth_data);
480 chosen_mech = AUTH_MECHANISM_NONE;
483 m_state = CS_Disconnecting;
487 if (chosen_mech == AUTH_MECHANISM_SRP ||
488 chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
489 srp_verifier_delete((SRPVerifier *) auth_data);
490 chosen_mech = AUTH_MECHANISM_NONE;
493 myerror << "HelloSent: Invalid client state transition! " << event;
494 throw ClientStateError(myerror.str());
497 case CS_AwaitingInit2:
501 confirmSerializationVersion();
502 m_state = CS_InitDone;
505 m_state = CS_Disconnecting;
511 /* Init SetDefinitionsSent SetMediaSent */
513 myerror << "InitSent: Invalid client state transition! " << event;
514 throw ClientStateError(myerror.str());
521 case CSE_SetDefinitionsSent:
522 m_state = CS_DefinitionsSent;
525 m_state = CS_Disconnecting;
531 /* Init GotInit2 SetMediaSent */
533 myerror << "InitDone: Invalid client state transition! " << event;
534 throw ClientStateError(myerror.str());
537 case CS_DefinitionsSent:
540 case CSE_SetClientReady:
544 m_state = CS_Disconnecting;
549 /* Init GotInit2 SetDefinitionsSent */
551 myerror << "DefinitionsSent: Invalid client state transition! " << event;
552 throw ClientStateError(myerror.str());
562 m_state = CS_Disconnecting;
564 case CSE_SudoSuccess:
565 m_state = CS_SudoMode;
566 if (chosen_mech == AUTH_MECHANISM_SRP)
567 srp_verifier_delete((SRPVerifier *) auth_data);
568 chosen_mech = AUTH_MECHANISM_NONE;
570 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
572 myerror << "Active: Invalid client state transition! " << event;
573 throw ClientStateError(myerror.str());
584 m_state = CS_Disconnecting;
590 myerror << "Active: Invalid client state transition! " << event;
591 throw ClientStateError(myerror.str());
595 case CS_Disconnecting:
596 /* we are already disconnecting */
601 u64 RemoteClient::uptime() const
603 return porting::getTimeS() - m_connection_time;
606 ClientInterface::ClientInterface(const std::shared_ptr<con::Connection> & con)
610 m_print_info_timer(0.0f)
614 ClientInterface::~ClientInterface()
620 MutexAutoLock clientslock(m_clients_mutex);
622 for (auto &client_it : m_clients) {
624 delete client_it.second;
629 std::vector<session_t> ClientInterface::getClientIDs(ClientState min_state)
631 std::vector<session_t> reply;
632 MutexAutoLock clientslock(m_clients_mutex);
634 for (const auto &m_client : m_clients) {
635 if (m_client.second->getState() >= min_state)
636 reply.push_back(m_client.second->peer_id);
643 * Verify if user limit was reached.
644 * User limit count all clients from HelloSent state (MT protocol user) to Active state
645 * @return true if user limit was reached
647 bool ClientInterface::isUserLimitReached()
649 return getClientIDs(CS_HelloSent).size() >= g_settings->getU16("max_users");
652 void ClientInterface::step(float dtime)
654 m_print_info_timer += dtime;
655 if (m_print_info_timer >= 30.0f) {
656 m_print_info_timer = 0.0f;
661 void ClientInterface::UpdatePlayerList()
664 std::vector<session_t> clients = getClientIDs();
665 m_clients_names.clear();
668 if (!clients.empty())
669 infostream<<"Players:"<<std::endl;
671 for (session_t i : clients) {
672 RemotePlayer *player = m_env->getPlayer(i);
677 infostream << "* " << player->getName() << "\t";
680 MutexAutoLock clientslock(m_clients_mutex);
681 RemoteClient* client = lockedGetClientNoEx(i);
683 client->PrintInfo(infostream);
686 m_clients_names.emplace_back(player->getName());
691 void ClientInterface::send(session_t peer_id, u8 channelnum,
692 NetworkPacket *pkt, bool reliable)
694 m_con->Send(peer_id, channelnum, pkt, reliable);
697 void ClientInterface::sendToAll(NetworkPacket *pkt)
699 MutexAutoLock clientslock(m_clients_mutex);
700 for (auto &client_it : m_clients) {
701 RemoteClient *client = client_it.second;
703 if (client->net_proto_version != 0) {
704 m_con->Send(client->peer_id,
705 clientCommandFactoryTable[pkt->getCommand()].channel, pkt,
706 clientCommandFactoryTable[pkt->getCommand()].reliable);
711 void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt,
714 MutexAutoLock clientslock(m_clients_mutex);
715 for (auto &client_it : m_clients) {
716 RemoteClient *client = client_it.second;
717 NetworkPacket *pkt_to_send = nullptr;
719 if (client->net_proto_version >= min_proto_ver) {
721 } else if (client->net_proto_version != 0) {
722 pkt_to_send = legacypkt;
724 warningstream << "Client with unhandled version to handle: '"
725 << client->net_proto_version << "'";
729 m_con->Send(client->peer_id,
730 clientCommandFactoryTable[pkt_to_send->getCommand()].channel,
732 clientCommandFactoryTable[pkt_to_send->getCommand()].reliable);
736 RemoteClient* ClientInterface::getClientNoEx(session_t peer_id, ClientState state_min)
738 MutexAutoLock clientslock(m_clients_mutex);
739 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
740 // The client may not exist; clients are immediately removed if their
741 // access is denied, and this event occurs later then.
742 if (n == m_clients.end())
745 if (n->second->getState() >= state_min)
751 RemoteClient* ClientInterface::lockedGetClientNoEx(session_t peer_id, ClientState state_min)
753 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
754 // The client may not exist; clients are immediately removed if their
755 // access is denied, and this event occurs later then.
756 if (n == m_clients.end())
759 if (n->second->getState() >= state_min)
765 ClientState ClientInterface::getClientState(session_t peer_id)
767 MutexAutoLock clientslock(m_clients_mutex);
768 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
769 // The client may not exist; clients are immediately removed if their
770 // access is denied, and this event occurs later then.
771 if (n == m_clients.end())
774 return n->second->getState();
777 void ClientInterface::setPlayerName(session_t peer_id, const std::string &name)
779 MutexAutoLock clientslock(m_clients_mutex);
780 RemoteClientMap::iterator n = m_clients.find(peer_id);
781 // The client may not exist; clients are immediately removed if their
782 // access is denied, and this event occurs later then.
783 if (n != m_clients.end())
784 n->second->setName(name);
787 void ClientInterface::DeleteClient(session_t peer_id)
789 MutexAutoLock conlock(m_clients_mutex);
792 RemoteClientMap::iterator n = m_clients.find(peer_id);
793 // The client may not exist; clients are immediately removed if their
794 // access is denied, and this event occurs later then.
795 if (n == m_clients.end())
799 Mark objects to be not known by the client
801 //TODO this should be done by client destructor!!!
802 RemoteClient *client = n->second;
804 for (u16 id : client->m_known_objects) {
806 ServerActiveObject* obj = m_env->getActiveObject(id);
808 if(obj && obj->m_known_by_count > 0)
809 obj->m_known_by_count--;
813 delete m_clients[peer_id];
814 m_clients.erase(peer_id);
817 void ClientInterface::CreateClient(session_t peer_id)
819 MutexAutoLock conlock(m_clients_mutex);
822 RemoteClientMap::iterator n = m_clients.find(peer_id);
823 // The client shouldn't already exist
824 if (n != m_clients.end()) return;
827 RemoteClient *client = new RemoteClient();
828 client->peer_id = peer_id;
829 m_clients[client->peer_id] = client;
832 void ClientInterface::event(session_t peer_id, ClientStateEvent event)
835 MutexAutoLock clientlock(m_clients_mutex);
838 RemoteClientMap::iterator n = m_clients.find(peer_id);
840 // No client to deliver event
841 if (n == m_clients.end())
843 n->second->notifyEvent(event);
846 if ((event == CSE_SetClientReady) ||
847 (event == CSE_Disconnect) ||
848 (event == CSE_SetDenied))
854 u16 ClientInterface::getProtocolVersion(session_t peer_id)
856 MutexAutoLock conlock(m_clients_mutex);
859 RemoteClientMap::iterator n = m_clients.find(peer_id);
861 // No client to get version
862 if (n == m_clients.end())
865 return n->second->net_proto_version;
868 void ClientInterface::setClientVersion(session_t peer_id, u8 major, u8 minor, u8 patch,
869 const std::string &full)
871 MutexAutoLock conlock(m_clients_mutex);
874 RemoteClientMap::iterator n = m_clients.find(peer_id);
876 // No client to set versions
877 if (n == m_clients.end())
880 n->second->setVersionInfo(major, minor, patch, full);