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(adjustDist(m_max_send_distance, camera_fov), wanted_range);
200 const s16 d_opt = std::min(adjustDist(m_block_optimize_distance, camera_fov), 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(adjustDist(m_max_gen_distance, camera_fov), wanted_range);
207 // Don't loop very much at a time, adjust with distance,
208 // do more work per RTT with greater distances.
209 s16 max_d_increment_at_time = full_d_max / 9 + 1;
210 if (d_max > d_start + max_d_increment_at_time)
211 d_max = d_start + max_d_increment_at_time;
213 // cos(angle between velocity and camera) * |velocity|
214 // Limit to 0.0f in case player moves backwards.
215 f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f);
217 // Reduce the field of view when a player moves and looks forward.
218 // limit max fov effect to 50%, 60% at 20n/s fly speed
219 camera_fov = camera_fov / (1 + dot / 300.0f);
221 s32 nearest_emerged_d = -1;
222 s32 nearest_emergefull_d = -1;
223 s32 nearest_sent_d = -1;
224 //bool queue_is_full = false;
226 const v3s16 cam_pos_nodes = floatToInt(camera_pos, BS);
229 for (d = d_start; d <= d_max; d++) {
231 Get the border/face dot coordinates of a "d-radiused"
234 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
236 std::vector<v3s16>::iterator li;
237 for (li = list.begin(); li != list.end(); ++li) {
238 v3s16 p = *li + center;
242 - Don't allow too many simultaneous transfers
243 - EXCEPT when the blocks are very close
245 Also, don't send blocks that are already flying.
248 // Start with the usual maximum
249 u16 max_simul_dynamic = max_simul_sends_usually;
251 // If block is very close, allow full maximum
252 if (d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
253 max_simul_dynamic = m_max_simul_sends;
255 // Don't select too many blocks for sending
256 if (num_blocks_selected >= max_simul_dynamic) {
257 //queue_is_full = true;
258 goto queue_full_break;
261 // Don't send blocks that are currently being transferred
262 if (m_blocks_sending.find(p) != m_blocks_sending.end())
266 Do not go over max mapgen limit
268 if (blockpos_over_max_limit(p))
271 // If this is true, inexistent block will be made from scratch
272 bool generate = d <= d_max_gen;
275 Don't generate or send if not in sight
276 FIXME This only works if the client uses a small enough
277 FOV setting. The default of 72 degrees is fine.
278 Also retrieve a smaller view cone in the direction of the player's
280 (0.1 is about 4 degrees)
283 if (!(isBlockInSight(p, camera_pos, camera_dir, camera_fov,
284 d_blocks_in_sight, &dist) ||
285 (playerspeed.getLength() > 1.0f * BS &&
286 isBlockInSight(p, camera_pos, playerspeeddir, 0.1f,
287 d_blocks_in_sight)))) {
292 Don't send already sent blocks
294 if (m_blocks_sent.find(p) != m_blocks_sent.end())
298 Check if map has this block
300 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
302 bool surely_not_found_on_disk = false;
303 bool block_is_invalid = false;
305 // Reset usage timer, this block will be of use in the future.
306 block->resetUsageTimer();
308 // Block is dummy if data doesn't exist.
309 // It means it has been not found from disk and not generated
310 if (block->isDummy()) {
311 surely_not_found_on_disk = true;
314 if (!block->isGenerated())
315 block_is_invalid = true;
318 If block is not close, don't send it unless it is near
321 Block is near ground level if night-time mesh
322 differs from day-time mesh.
325 if (!block->getDayNightDiff())
329 if (m_occ_cull && !block_is_invalid &&
330 env->getMap().isBlockOccluded(block, cam_pos_nodes)) {
336 If block has been marked to not exist on disk (dummy)
337 and generating new ones is not wanted, skip block.
339 if (!generate && surely_not_found_on_disk) {
345 Add inexistent block to emerge queue.
347 if (block == NULL || surely_not_found_on_disk || block_is_invalid) {
348 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
349 if (nearest_emerged_d == -1)
350 nearest_emerged_d = d;
352 if (nearest_emergefull_d == -1)
353 nearest_emergefull_d = d;
354 goto queue_full_break;
361 if (nearest_sent_d == -1)
365 Add block to send queue
367 PrioritySortedBlockTransfer q((float)dist, p, peer_id);
371 num_blocks_selected += 1;
376 // If nothing was found for sending and nothing was queued for
377 // emerging, continue next time browsing from here
378 if (nearest_emerged_d != -1) {
379 new_nearest_unsent_d = nearest_emerged_d;
380 } else if (nearest_emergefull_d != -1) {
381 new_nearest_unsent_d = nearest_emergefull_d;
383 if (d > full_d_max) {
384 new_nearest_unsent_d = 0;
385 m_nothing_to_send_pause_timer = 2.0f;
387 if (nearest_sent_d != -1)
388 new_nearest_unsent_d = nearest_sent_d;
390 new_nearest_unsent_d = d;
394 if (new_nearest_unsent_d != -1)
395 m_nearest_unsent_d = new_nearest_unsent_d;
398 void RemoteClient::GotBlock(v3s16 p)
400 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
401 if (m_blocks_sending.find(p) != m_blocks_sending.end())
402 m_blocks_sending.erase(p);
404 m_excess_gotblocks++;
406 m_blocks_sent.insert(p);
410 void RemoteClient::SentBlock(v3s16 p)
412 if (m_blocks_modified.find(p) != m_blocks_modified.end())
413 m_blocks_modified.erase(p);
415 if (m_blocks_sending.find(p) == m_blocks_sending.end())
416 m_blocks_sending[p] = 0.0f;
418 infostream<<"RemoteClient::SentBlock(): Sent block"
419 " already in m_blocks_sending"<<std::endl;
422 void RemoteClient::SetBlockNotSent(v3s16 p)
424 m_nearest_unsent_d = 0;
425 m_nothing_to_send_pause_timer = 0;
427 if (m_blocks_sending.find(p) != m_blocks_sending.end())
428 m_blocks_sending.erase(p);
429 if (m_blocks_sent.find(p) != m_blocks_sent.end())
430 m_blocks_sent.erase(p);
431 m_blocks_modified.insert(p);
434 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
436 m_nearest_unsent_d = 0;
437 m_nothing_to_send_pause_timer = 0;
439 for (auto &block : blocks) {
440 v3s16 p = block.first;
441 m_blocks_modified.insert(p);
443 if (m_blocks_sending.find(p) != m_blocks_sending.end())
444 m_blocks_sending.erase(p);
445 if (m_blocks_sent.find(p) != m_blocks_sent.end())
446 m_blocks_sent.erase(p);
450 void RemoteClient::notifyEvent(ClientStateEvent event)
452 std::ostringstream myerror;
456 //intentionally do nothing
461 m_state = CS_HelloSent;
464 m_state = CS_AwaitingInit2;
467 m_state = CS_Disconnecting;
472 /* GotInit2 SetDefinitionsSent SetMediaSent */
474 myerror << "Created: Invalid client state transition! " << event;
475 throw ClientStateError(myerror.str());
479 /* don't do anything if in denied state */
485 m_state = CS_AwaitingInit2;
486 if (chosen_mech == AUTH_MECHANISM_SRP ||
487 chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
488 srp_verifier_delete((SRPVerifier *) auth_data);
489 chosen_mech = AUTH_MECHANISM_NONE;
492 m_state = CS_Disconnecting;
496 if (chosen_mech == AUTH_MECHANISM_SRP ||
497 chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
498 srp_verifier_delete((SRPVerifier *) auth_data);
499 chosen_mech = AUTH_MECHANISM_NONE;
502 myerror << "HelloSent: Invalid client state transition! " << event;
503 throw ClientStateError(myerror.str());
506 case CS_AwaitingInit2:
510 confirmSerializationVersion();
511 m_state = CS_InitDone;
514 m_state = CS_Disconnecting;
520 /* Init SetDefinitionsSent SetMediaSent */
522 myerror << "InitSent: Invalid client state transition! " << event;
523 throw ClientStateError(myerror.str());
530 case CSE_SetDefinitionsSent:
531 m_state = CS_DefinitionsSent;
534 m_state = CS_Disconnecting;
540 /* Init GotInit2 SetMediaSent */
542 myerror << "InitDone: Invalid client state transition! " << event;
543 throw ClientStateError(myerror.str());
546 case CS_DefinitionsSent:
549 case CSE_SetClientReady:
553 m_state = CS_Disconnecting;
558 /* Init GotInit2 SetDefinitionsSent */
560 myerror << "DefinitionsSent: Invalid client state transition! " << event;
561 throw ClientStateError(myerror.str());
571 m_state = CS_Disconnecting;
573 case CSE_SudoSuccess:
574 m_state = CS_SudoMode;
575 if (chosen_mech == AUTH_MECHANISM_SRP)
576 srp_verifier_delete((SRPVerifier *) auth_data);
577 chosen_mech = AUTH_MECHANISM_NONE;
579 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
581 myerror << "Active: Invalid client state transition! " << event;
582 throw ClientStateError(myerror.str());
593 m_state = CS_Disconnecting;
599 myerror << "Active: Invalid client state transition! " << event;
600 throw ClientStateError(myerror.str());
604 case CS_Disconnecting:
605 /* we are already disconnecting */
610 u64 RemoteClient::uptime() const
612 return porting::getTimeS() - m_connection_time;
615 ClientInterface::ClientInterface(const std::shared_ptr<con::Connection> & con)
619 m_print_info_timer(0.0f)
623 ClientInterface::~ClientInterface()
629 MutexAutoLock clientslock(m_clients_mutex);
631 for (auto &client_it : m_clients) {
633 delete client_it.second;
638 std::vector<session_t> ClientInterface::getClientIDs(ClientState min_state)
640 std::vector<session_t> reply;
641 MutexAutoLock clientslock(m_clients_mutex);
643 for (const auto &m_client : m_clients) {
644 if (m_client.second->getState() >= min_state)
645 reply.push_back(m_client.second->peer_id);
652 * Verify if user limit was reached.
653 * User limit count all clients from HelloSent state (MT protocol user) to Active state
654 * @return true if user limit was reached
656 bool ClientInterface::isUserLimitReached()
658 return getClientIDs(CS_HelloSent).size() >= g_settings->getU16("max_users");
661 void ClientInterface::step(float dtime)
663 m_print_info_timer += dtime;
664 if (m_print_info_timer >= 30.0f) {
665 m_print_info_timer = 0.0f;
670 void ClientInterface::UpdatePlayerList()
673 std::vector<session_t> clients = getClientIDs();
674 m_clients_names.clear();
677 if (!clients.empty())
678 infostream<<"Players:"<<std::endl;
680 for (session_t i : clients) {
681 RemotePlayer *player = m_env->getPlayer(i);
686 infostream << "* " << player->getName() << "\t";
689 MutexAutoLock clientslock(m_clients_mutex);
690 RemoteClient* client = lockedGetClientNoEx(i);
692 client->PrintInfo(infostream);
695 m_clients_names.emplace_back(player->getName());
700 void ClientInterface::send(session_t peer_id, u8 channelnum,
701 NetworkPacket *pkt, bool reliable)
703 m_con->Send(peer_id, channelnum, pkt, reliable);
706 void ClientInterface::sendToAll(NetworkPacket *pkt)
708 MutexAutoLock clientslock(m_clients_mutex);
709 for (auto &client_it : m_clients) {
710 RemoteClient *client = client_it.second;
712 if (client->net_proto_version != 0) {
713 m_con->Send(client->peer_id,
714 clientCommandFactoryTable[pkt->getCommand()].channel, pkt,
715 clientCommandFactoryTable[pkt->getCommand()].reliable);
720 void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt,
723 MutexAutoLock clientslock(m_clients_mutex);
724 for (auto &client_it : m_clients) {
725 RemoteClient *client = client_it.second;
726 NetworkPacket *pkt_to_send = nullptr;
728 if (client->net_proto_version >= min_proto_ver) {
730 } else if (client->net_proto_version != 0) {
731 pkt_to_send = legacypkt;
733 warningstream << "Client with unhandled version to handle: '"
734 << client->net_proto_version << "'";
738 m_con->Send(client->peer_id,
739 clientCommandFactoryTable[pkt_to_send->getCommand()].channel,
741 clientCommandFactoryTable[pkt_to_send->getCommand()].reliable);
745 RemoteClient* ClientInterface::getClientNoEx(session_t peer_id, ClientState state_min)
747 MutexAutoLock clientslock(m_clients_mutex);
748 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
749 // The client may not exist; clients are immediately removed if their
750 // access is denied, and this event occurs later then.
751 if (n == m_clients.end())
754 if (n->second->getState() >= state_min)
760 RemoteClient* ClientInterface::lockedGetClientNoEx(session_t peer_id, ClientState state_min)
762 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
763 // The client may not exist; clients are immediately removed if their
764 // access is denied, and this event occurs later then.
765 if (n == m_clients.end())
768 if (n->second->getState() >= state_min)
774 ClientState ClientInterface::getClientState(session_t peer_id)
776 MutexAutoLock clientslock(m_clients_mutex);
777 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
778 // The client may not exist; clients are immediately removed if their
779 // access is denied, and this event occurs later then.
780 if (n == m_clients.end())
783 return n->second->getState();
786 void ClientInterface::setPlayerName(session_t peer_id, const std::string &name)
788 MutexAutoLock clientslock(m_clients_mutex);
789 RemoteClientMap::iterator n = m_clients.find(peer_id);
790 // The client may not exist; clients are immediately removed if their
791 // access is denied, and this event occurs later then.
792 if (n != m_clients.end())
793 n->second->setName(name);
796 void ClientInterface::DeleteClient(session_t peer_id)
798 MutexAutoLock conlock(m_clients_mutex);
801 RemoteClientMap::iterator n = m_clients.find(peer_id);
802 // The client may not exist; clients are immediately removed if their
803 // access is denied, and this event occurs later then.
804 if (n == m_clients.end())
808 Mark objects to be not known by the client
810 //TODO this should be done by client destructor!!!
811 RemoteClient *client = n->second;
813 for (u16 id : client->m_known_objects) {
815 ServerActiveObject* obj = m_env->getActiveObject(id);
817 if(obj && obj->m_known_by_count > 0)
818 obj->m_known_by_count--;
822 delete m_clients[peer_id];
823 m_clients.erase(peer_id);
826 void ClientInterface::CreateClient(session_t peer_id)
828 MutexAutoLock conlock(m_clients_mutex);
831 RemoteClientMap::iterator n = m_clients.find(peer_id);
832 // The client shouldn't already exist
833 if (n != m_clients.end()) return;
836 RemoteClient *client = new RemoteClient();
837 client->peer_id = peer_id;
838 m_clients[client->peer_id] = client;
841 void ClientInterface::event(session_t peer_id, ClientStateEvent event)
844 MutexAutoLock clientlock(m_clients_mutex);
847 RemoteClientMap::iterator n = m_clients.find(peer_id);
849 // No client to deliver event
850 if (n == m_clients.end())
852 n->second->notifyEvent(event);
855 if ((event == CSE_SetClientReady) ||
856 (event == CSE_Disconnect) ||
857 (event == CSE_SetDenied))
863 u16 ClientInterface::getProtocolVersion(session_t peer_id)
865 MutexAutoLock conlock(m_clients_mutex);
868 RemoteClientMap::iterator n = m_clients.find(peer_id);
870 // No client to get version
871 if (n == m_clients.end())
874 return n->second->net_proto_version;
877 void ClientInterface::setClientVersion(session_t peer_id, u8 major, u8 minor, u8 patch,
878 const std::string &full)
880 MutexAutoLock conlock(m_clients_mutex);
883 RemoteClientMap::iterator n = m_clients.find(peer_id);
885 // No client to set versions
886 if (n == m_clients.end())
889 n->second->setVersionInfo(major, minor, patch, full);