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 // cos(angle between velocity and camera) * |velocity|
200 // Limit to 0.0f in case player moves backwards.
201 f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f);
203 // Reduce the field of view when a player moves and looks forward.
204 // limit max fov effect to 50%, 60% at 20n/s fly speed
205 camera_fov = camera_fov / (1 + dot / 300.0f);
207 const s16 full_d_max = std::min(m_max_send_distance, wanted_range);
208 const s16 d_opt = std::min(m_block_optimize_distance, wanted_range);
209 const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
210 //infostream << "Fov from client " << camera_fov << " full_d_max " << full_d_max << std::endl;
212 s16 d_max = full_d_max;
213 s16 d_max_gen = std::min(m_max_gen_distance, wanted_range);
215 // Don't loop very much at a time
216 s16 max_d_increment_at_time = 2;
217 if (d_max > d_start + max_d_increment_at_time)
218 d_max = d_start + max_d_increment_at_time;
220 s32 nearest_emerged_d = -1;
221 s32 nearest_emergefull_d = -1;
222 s32 nearest_sent_d = -1;
223 //bool queue_is_full = false;
225 const v3s16 cam_pos_nodes = floatToInt(camera_pos, BS);
228 for (d = d_start; d <= d_max; d++) {
230 Get the border/face dot coordinates of a "d-radiused"
233 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
235 std::vector<v3s16>::iterator li;
236 for (li = list.begin(); li != list.end(); ++li) {
237 v3s16 p = *li + center;
241 - Don't allow too many simultaneous transfers
242 - EXCEPT when the blocks are very close
244 Also, don't send blocks that are already flying.
247 // Start with the usual maximum
248 u16 max_simul_dynamic = max_simul_sends_usually;
250 // If block is very close, allow full maximum
251 if (d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
252 max_simul_dynamic = m_max_simul_sends;
254 // Don't select too many blocks for sending
255 if (num_blocks_selected >= max_simul_dynamic) {
256 //queue_is_full = true;
257 goto queue_full_break;
260 // Don't send blocks that are currently being transferred
261 if (m_blocks_sending.find(p) != m_blocks_sending.end())
265 Do not go over max mapgen limit
267 if (blockpos_over_max_limit(p))
270 // If this is true, inexistent block will be made from scratch
271 bool generate = d <= d_max_gen;
274 Don't generate or send if not in sight
275 FIXME This only works if the client uses a small enough
276 FOV setting. The default of 72 degrees is fine.
277 Also retrieve a smaller view cone in the direction of the player's
279 (0.1 is about 4 degrees)
282 if (!(isBlockInSight(p, camera_pos, camera_dir, camera_fov,
283 d_blocks_in_sight, &dist) ||
284 (playerspeed.getLength() > 1.0f * BS &&
285 isBlockInSight(p, camera_pos, playerspeeddir, 0.1f,
286 d_blocks_in_sight)))) {
291 Don't send already sent blocks
293 if (m_blocks_sent.find(p) != m_blocks_sent.end())
297 Check if map has this block
299 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
301 bool surely_not_found_on_disk = false;
302 bool block_is_invalid = false;
304 // Reset usage timer, this block will be of use in the future.
305 block->resetUsageTimer();
307 // Block is dummy if data doesn't exist.
308 // It means it has been not found from disk and not generated
309 if (block->isDummy()) {
310 surely_not_found_on_disk = true;
313 if (!block->isGenerated())
314 block_is_invalid = true;
317 If block is not close, don't send it unless it is near
320 Block is near ground level if night-time mesh
321 differs from day-time mesh.
324 if (!block->getDayNightDiff())
328 if (m_occ_cull && !block_is_invalid &&
329 env->getMap().isBlockOccluded(block, cam_pos_nodes)) {
335 If block has been marked to not exist on disk (dummy)
336 and generating new ones is not wanted, skip block.
338 if (!generate && surely_not_found_on_disk) {
344 Add inexistent block to emerge queue.
346 if (block == NULL || surely_not_found_on_disk || block_is_invalid) {
347 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
348 if (nearest_emerged_d == -1)
349 nearest_emerged_d = d;
351 if (nearest_emergefull_d == -1)
352 nearest_emergefull_d = d;
353 goto queue_full_break;
360 if (nearest_sent_d == -1)
364 Add block to send queue
366 PrioritySortedBlockTransfer q((float)dist, p, peer_id);
370 num_blocks_selected += 1;
375 // If nothing was found for sending and nothing was queued for
376 // emerging, continue next time browsing from here
377 if (nearest_emerged_d != -1) {
378 new_nearest_unsent_d = nearest_emerged_d;
379 } else if (nearest_emergefull_d != -1) {
380 new_nearest_unsent_d = nearest_emergefull_d;
382 if (d > full_d_max) {
383 new_nearest_unsent_d = 0;
384 m_nothing_to_send_pause_timer = 2.0f;
386 if (nearest_sent_d != -1)
387 new_nearest_unsent_d = nearest_sent_d;
389 new_nearest_unsent_d = d;
393 if (new_nearest_unsent_d != -1)
394 m_nearest_unsent_d = new_nearest_unsent_d;
397 void RemoteClient::GotBlock(v3s16 p)
399 if (m_blocks_modified.find(p) == m_blocks_modified.end()) {
400 if (m_blocks_sending.find(p) != m_blocks_sending.end())
401 m_blocks_sending.erase(p);
403 m_excess_gotblocks++;
405 m_blocks_sent.insert(p);
409 void RemoteClient::SentBlock(v3s16 p)
411 if (m_blocks_modified.find(p) != m_blocks_modified.end())
412 m_blocks_modified.erase(p);
414 if (m_blocks_sending.find(p) == m_blocks_sending.end())
415 m_blocks_sending[p] = 0.0f;
417 infostream<<"RemoteClient::SentBlock(): Sent block"
418 " already in m_blocks_sending"<<std::endl;
421 void RemoteClient::SetBlockNotSent(v3s16 p)
423 m_nearest_unsent_d = 0;
424 m_nothing_to_send_pause_timer = 0;
426 if (m_blocks_sending.find(p) != m_blocks_sending.end())
427 m_blocks_sending.erase(p);
428 if (m_blocks_sent.find(p) != m_blocks_sent.end())
429 m_blocks_sent.erase(p);
430 m_blocks_modified.insert(p);
433 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
435 m_nearest_unsent_d = 0;
436 m_nothing_to_send_pause_timer = 0;
438 for (auto &block : blocks) {
439 v3s16 p = block.first;
440 m_blocks_modified.insert(p);
442 if (m_blocks_sending.find(p) != m_blocks_sending.end())
443 m_blocks_sending.erase(p);
444 if (m_blocks_sent.find(p) != m_blocks_sent.end())
445 m_blocks_sent.erase(p);
449 void RemoteClient::notifyEvent(ClientStateEvent event)
451 std::ostringstream myerror;
455 //intentionally do nothing
460 m_state = CS_HelloSent;
463 m_state = CS_AwaitingInit2;
466 m_state = CS_Disconnecting;
471 /* GotInit2 SetDefinitionsSent SetMediaSent */
473 myerror << "Created: Invalid client state transition! " << event;
474 throw ClientStateError(myerror.str());
478 /* don't do anything if in denied state */
484 m_state = CS_AwaitingInit2;
485 if (chosen_mech == AUTH_MECHANISM_SRP ||
486 chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
487 srp_verifier_delete((SRPVerifier *) auth_data);
488 chosen_mech = AUTH_MECHANISM_NONE;
491 m_state = CS_Disconnecting;
495 if (chosen_mech == AUTH_MECHANISM_SRP ||
496 chosen_mech == AUTH_MECHANISM_LEGACY_PASSWORD)
497 srp_verifier_delete((SRPVerifier *) auth_data);
498 chosen_mech = AUTH_MECHANISM_NONE;
501 myerror << "HelloSent: Invalid client state transition! " << event;
502 throw ClientStateError(myerror.str());
505 case CS_AwaitingInit2:
509 confirmSerializationVersion();
510 m_state = CS_InitDone;
513 m_state = CS_Disconnecting;
519 /* Init SetDefinitionsSent SetMediaSent */
521 myerror << "InitSent: Invalid client state transition! " << event;
522 throw ClientStateError(myerror.str());
529 case CSE_SetDefinitionsSent:
530 m_state = CS_DefinitionsSent;
533 m_state = CS_Disconnecting;
539 /* Init GotInit2 SetMediaSent */
541 myerror << "InitDone: Invalid client state transition! " << event;
542 throw ClientStateError(myerror.str());
545 case CS_DefinitionsSent:
548 case CSE_SetClientReady:
552 m_state = CS_Disconnecting;
557 /* Init GotInit2 SetDefinitionsSent */
559 myerror << "DefinitionsSent: Invalid client state transition! " << event;
560 throw ClientStateError(myerror.str());
570 m_state = CS_Disconnecting;
572 case CSE_SudoSuccess:
573 m_state = CS_SudoMode;
574 if (chosen_mech == AUTH_MECHANISM_SRP)
575 srp_verifier_delete((SRPVerifier *) auth_data);
576 chosen_mech = AUTH_MECHANISM_NONE;
578 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
580 myerror << "Active: Invalid client state transition! " << event;
581 throw ClientStateError(myerror.str());
592 m_state = CS_Disconnecting;
598 myerror << "Active: Invalid client state transition! " << event;
599 throw ClientStateError(myerror.str());
603 case CS_Disconnecting:
604 /* we are already disconnecting */
609 u64 RemoteClient::uptime() const
611 return porting::getTimeS() - m_connection_time;
614 ClientInterface::ClientInterface(const std::shared_ptr<con::Connection> & con)
618 m_print_info_timer(0.0f)
622 ClientInterface::~ClientInterface()
628 MutexAutoLock clientslock(m_clients_mutex);
630 for (auto &client_it : m_clients) {
632 delete client_it.second;
637 std::vector<session_t> ClientInterface::getClientIDs(ClientState min_state)
639 std::vector<session_t> reply;
640 MutexAutoLock clientslock(m_clients_mutex);
642 for (const auto &m_client : m_clients) {
643 if (m_client.second->getState() >= min_state)
644 reply.push_back(m_client.second->peer_id);
651 * Verify if user limit was reached.
652 * User limit count all clients from HelloSent state (MT protocol user) to Active state
653 * @return true if user limit was reached
655 bool ClientInterface::isUserLimitReached()
657 return getClientIDs(CS_HelloSent).size() >= g_settings->getU16("max_users");
660 void ClientInterface::step(float dtime)
662 m_print_info_timer += dtime;
663 if (m_print_info_timer >= 30.0f) {
664 m_print_info_timer = 0.0f;
669 void ClientInterface::UpdatePlayerList()
672 std::vector<session_t> clients = getClientIDs();
673 m_clients_names.clear();
676 if (!clients.empty())
677 infostream<<"Players:"<<std::endl;
679 for (session_t i : clients) {
680 RemotePlayer *player = m_env->getPlayer(i);
685 infostream << "* " << player->getName() << "\t";
688 MutexAutoLock clientslock(m_clients_mutex);
689 RemoteClient* client = lockedGetClientNoEx(i);
691 client->PrintInfo(infostream);
694 m_clients_names.emplace_back(player->getName());
699 void ClientInterface::send(session_t peer_id, u8 channelnum,
700 NetworkPacket *pkt, bool reliable)
702 m_con->Send(peer_id, channelnum, pkt, reliable);
705 void ClientInterface::sendToAll(NetworkPacket *pkt)
707 MutexAutoLock clientslock(m_clients_mutex);
708 for (auto &client_it : m_clients) {
709 RemoteClient *client = client_it.second;
711 if (client->net_proto_version != 0) {
712 m_con->Send(client->peer_id,
713 clientCommandFactoryTable[pkt->getCommand()].channel, pkt,
714 clientCommandFactoryTable[pkt->getCommand()].reliable);
719 void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt,
722 MutexAutoLock clientslock(m_clients_mutex);
723 for (auto &client_it : m_clients) {
724 RemoteClient *client = client_it.second;
725 NetworkPacket *pkt_to_send = nullptr;
727 if (client->net_proto_version >= min_proto_ver) {
729 } else if (client->net_proto_version != 0) {
730 pkt_to_send = legacypkt;
732 warningstream << "Client with unhandled version to handle: '"
733 << client->net_proto_version << "'";
737 m_con->Send(client->peer_id,
738 clientCommandFactoryTable[pkt_to_send->getCommand()].channel,
740 clientCommandFactoryTable[pkt_to_send->getCommand()].reliable);
744 RemoteClient* ClientInterface::getClientNoEx(session_t peer_id, ClientState state_min)
746 MutexAutoLock clientslock(m_clients_mutex);
747 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
748 // The client may not exist; clients are immediately removed if their
749 // access is denied, and this event occurs later then.
750 if (n == m_clients.end())
753 if (n->second->getState() >= state_min)
759 RemoteClient* ClientInterface::lockedGetClientNoEx(session_t peer_id, ClientState state_min)
761 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
762 // The client may not exist; clients are immediately removed if their
763 // access is denied, and this event occurs later then.
764 if (n == m_clients.end())
767 if (n->second->getState() >= state_min)
773 ClientState ClientInterface::getClientState(session_t peer_id)
775 MutexAutoLock clientslock(m_clients_mutex);
776 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
777 // The client may not exist; clients are immediately removed if their
778 // access is denied, and this event occurs later then.
779 if (n == m_clients.end())
782 return n->second->getState();
785 void ClientInterface::setPlayerName(session_t peer_id, const std::string &name)
787 MutexAutoLock clientslock(m_clients_mutex);
788 RemoteClientMap::iterator n = m_clients.find(peer_id);
789 // The client may not exist; clients are immediately removed if their
790 // access is denied, and this event occurs later then.
791 if (n != m_clients.end())
792 n->second->setName(name);
795 void ClientInterface::DeleteClient(session_t peer_id)
797 MutexAutoLock conlock(m_clients_mutex);
800 RemoteClientMap::iterator n = m_clients.find(peer_id);
801 // The client may not exist; clients are immediately removed if their
802 // access is denied, and this event occurs later then.
803 if (n == m_clients.end())
807 Mark objects to be not known by the client
809 //TODO this should be done by client destructor!!!
810 RemoteClient *client = n->second;
812 for (u16 id : client->m_known_objects) {
814 ServerActiveObject* obj = m_env->getActiveObject(id);
816 if(obj && obj->m_known_by_count > 0)
817 obj->m_known_by_count--;
821 delete m_clients[peer_id];
822 m_clients.erase(peer_id);
825 void ClientInterface::CreateClient(session_t peer_id)
827 MutexAutoLock conlock(m_clients_mutex);
830 RemoteClientMap::iterator n = m_clients.find(peer_id);
831 // The client shouldn't already exist
832 if (n != m_clients.end()) return;
835 RemoteClient *client = new RemoteClient();
836 client->peer_id = peer_id;
837 m_clients[client->peer_id] = client;
840 void ClientInterface::event(session_t peer_id, ClientStateEvent event)
843 MutexAutoLock clientlock(m_clients_mutex);
846 RemoteClientMap::iterator n = m_clients.find(peer_id);
848 // No client to deliver event
849 if (n == m_clients.end())
851 n->second->notifyEvent(event);
854 if ((event == CSE_SetClientReady) ||
855 (event == CSE_Disconnect) ||
856 (event == CSE_SetDenied))
862 u16 ClientInterface::getProtocolVersion(session_t peer_id)
864 MutexAutoLock conlock(m_clients_mutex);
867 RemoteClientMap::iterator n = m_clients.find(peer_id);
869 // No client to get version
870 if (n == m_clients.end())
873 return n->second->net_proto_version;
876 void ClientInterface::setClientVersion(session_t peer_id, u8 major, u8 minor, u8 patch,
877 const std::string &full)
879 MutexAutoLock conlock(m_clients_mutex);
882 RemoteClientMap::iterator n = m_clients.find(peer_id);
884 // No client to set versions
885 if (n == m_clients.end())
888 n->second->setVersionInfo(major, minor, patch, full);