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 "server/luaentity_sao.h"
31 #include "server/player_sao.h"
34 #include "face_position_cache.h"
36 const char *ClientInterface::statenames[] = {
51 std::string ClientInterface::state2Name(ClientState state)
53 return statenames[state];
56 RemoteClient::RemoteClient() :
57 m_max_simul_sends(g_settings->getU16("max_simultaneous_block_sends_per_client")),
58 m_min_time_from_building(
59 g_settings->getFloat("full_block_send_enable_min_time_from_building")),
60 m_max_send_distance(g_settings->getS16("max_block_send_distance")),
61 m_block_optimize_distance(g_settings->getS16("block_send_optimize_distance")),
62 m_max_gen_distance(g_settings->getS16("max_block_generate_distance")),
63 m_occ_cull(g_settings->getBool("server_side_occlusion_culling"))
67 void RemoteClient::ResendBlockIfOnWire(v3s16 p)
69 // if this block is on wire, mark it for sending again as soon as possible
70 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
75 LuaEntitySAO *getAttachedObject(PlayerSAO *sao, ServerEnvironment *env)
77 if (!sao->isAttached())
84 sao->getAttachment(&id, &bone, &dummy, &dummy, &force_visible);
85 ServerActiveObject *ao = env->getActiveObject(id);
87 ao->getAttachment(&id, &bone, &dummy, &dummy, &force_visible);
89 ao = env->getActiveObject(id);
91 return dynamic_cast<LuaEntitySAO *>(ao);
94 void RemoteClient::GetNextBlocks (
95 ServerEnvironment *env,
96 EmergeManager * emerge,
98 std::vector<PrioritySortedBlockTransfer> &dest)
101 m_nothing_to_send_pause_timer -= dtime;
102 m_map_send_completion_timer += dtime;
104 if (m_nothing_to_send_pause_timer >= 0)
107 RemotePlayer *player = env->getPlayer(peer_id);
108 // This can happen sometimes; clients and players are not in perfect sync.
112 PlayerSAO *sao = player->getPlayerSAO();
116 // Won't send anything if already sending
117 if (m_blocks_sending.size() >= m_max_simul_sends) {
118 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
122 v3f playerpos = sao->getBasePosition();
123 // if the player is attached, get the velocity from the attached object
124 LuaEntitySAO *lsao = getAttachedObject(sao, env);
125 const v3f &playerspeed = lsao? lsao->getVelocity() : player->getSpeed();
126 v3f playerspeeddir(0,0,0);
127 if (playerspeed.getLength() > 1.0f * BS)
128 playerspeeddir = playerspeed / playerspeed.getLength();
129 // Predict to next block
130 v3f playerpos_predicted = playerpos + playerspeeddir * (MAP_BLOCKSIZE * BS);
132 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
134 v3s16 center = getNodeBlockPos(center_nodepos);
136 // Camera position and direction
137 v3f camera_pos = sao->getEyePosition();
138 v3f camera_dir = v3f(0,0,1);
139 camera_dir.rotateYZBy(sao->getLookPitch());
140 camera_dir.rotateXZBy(sao->getRotation().Y);
142 u16 max_simul_sends_usually = m_max_simul_sends;
145 Check the time from last addNode/removeNode.
147 Decrease send rate if player is building stuff.
149 m_time_from_building += dtime;
150 if (m_time_from_building < m_min_time_from_building) {
151 max_simul_sends_usually
152 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
156 Number of blocks sending + number of blocks selected for sending
158 u32 num_blocks_selected = m_blocks_sending.size();
161 next time d will be continued from the d from which the nearest
162 unsent block was found this time.
164 This is because not necessarily any of the blocks found this
165 time are actually sent.
167 s32 new_nearest_unsent_d = -1;
169 // Get view range and camera fov (radians) from the client
170 s16 wanted_range = sao->getWantedRange() + 1;
171 float camera_fov = sao->getFov();
174 Get the starting value of the block finder radius.
176 if (m_last_center != center) {
177 m_nearest_unsent_d = 0;
178 m_last_center = center;
180 // reset the unsent distance if the view angle has changed more that 10% of the fov
181 // (this matches isBlockInSight which allows for an extra 10%)
182 if (camera_dir.dotProduct(m_last_camera_dir) < std::cos(camera_fov * 0.1f)) {
183 m_nearest_unsent_d = 0;
184 m_last_camera_dir = camera_dir;
186 if (m_nearest_unsent_d > 0) {
187 // make sure any blocks modified since the last time we sent blocks are resent
188 for (const v3s16 &p : m_blocks_modified) {
189 m_nearest_unsent_d = std::min(m_nearest_unsent_d, center.getDistanceFrom(p));
192 m_blocks_modified.clear();
194 s16 d_start = m_nearest_unsent_d;
196 // Distrust client-sent FOV and get server-set player object property
197 // zoom FOV (degrees) as a check to avoid hacked clients using FOV to load
199 // (zoom is disabled by value 0)
200 float prop_zoom_fov = sao->getZoomFOV() < 0.001f ?
202 std::max(camera_fov, sao->getZoomFOV() * core::DEGTORAD);
204 const s16 full_d_max = std::min(adjustDist(m_max_send_distance, prop_zoom_fov),
206 const s16 d_opt = std::min(adjustDist(m_block_optimize_distance, prop_zoom_fov),
208 const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
210 s16 d_max_gen = std::min(adjustDist(m_max_gen_distance, prop_zoom_fov),
213 s16 d_max = full_d_max;
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 // cos(angle between velocity and camera) * |velocity|
221 // Limit to 0.0f in case player moves backwards.
222 f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f);
224 // Reduce the field of view when a player moves and looks forward.
225 // limit max fov effect to 50%, 60% at 20n/s fly speed
226 camera_fov = camera_fov / (1 + dot / 300.0f);
228 s32 nearest_emerged_d = -1;
229 s32 nearest_emergefull_d = -1;
230 s32 nearest_sent_d = -1;
231 //bool queue_is_full = false;
233 const v3s16 cam_pos_nodes = floatToInt(camera_pos, BS);
236 for (d = d_start; d <= d_max; d++) {
238 Get the border/face dot coordinates of a "d-radiused"
241 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
243 std::vector<v3s16>::iterator li;
244 for (li = list.begin(); li != list.end(); ++li) {
245 v3s16 p = *li + center;
249 - Don't allow too many simultaneous transfers
250 - EXCEPT when the blocks are very close
252 Also, don't send blocks that are already flying.
255 // Start with the usual maximum
256 u16 max_simul_dynamic = max_simul_sends_usually;
258 // If block is very close, allow full maximum
259 if (d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
260 max_simul_dynamic = m_max_simul_sends;
262 // Don't select too many blocks for sending
263 if (num_blocks_selected >= max_simul_dynamic) {
264 //queue_is_full = true;
265 goto queue_full_break;
268 // Don't send blocks that are currently being transferred
269 if (m_blocks_sending.find(p) != m_blocks_sending.end())
273 Do not go over max mapgen limit
275 if (blockpos_over_max_limit(p))
278 // If this is true, inexistent block will be made from scratch
279 bool generate = d <= d_max_gen;
282 Don't generate or send if not in sight
283 FIXME This only works if the client uses a small enough
284 FOV setting. The default of 72 degrees is fine.
285 Also retrieve a smaller view cone in the direction of the player's
287 (0.1 is about 4 degrees)
290 if (!(isBlockInSight(p, camera_pos, camera_dir, camera_fov,
291 d_blocks_in_sight, &dist) ||
292 (playerspeed.getLength() > 1.0f * BS &&
293 isBlockInSight(p, camera_pos, playerspeeddir, 0.1f,
294 d_blocks_in_sight)))) {
299 Check if map has this block
301 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
303 // First: Reset usage timer, this block will be of use in the future.
304 block->resetUsageTimer();
308 Don't send already sent blocks
310 if (m_blocks_sent.find(p) != m_blocks_sent.end())
313 bool block_not_found = false;
315 // Check whether the block exists (with data)
316 if (!block->isGenerated())
317 block_not_found = true;
320 If block is not close, don't send it unless it is near
323 Block is near ground level if night-time mesh
324 differs from day-time mesh.
327 if (!block->getIsUnderground() && !block->getDayNightDiff())
331 if (m_occ_cull && !block_not_found &&
332 env->getMap().isBlockOccluded(block, cam_pos_nodes)) {
338 If block has been marked to not exist on disk (dummy) or is
339 not generated and generating new ones is not wanted, skip block.
341 if (!generate && block_not_found) {
347 Add inexistent block to emerge queue.
349 if (block == NULL || block_not_found) {
350 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
351 if (nearest_emerged_d == -1)
352 nearest_emerged_d = d;
354 if (nearest_emergefull_d == -1)
355 nearest_emergefull_d = d;
356 goto queue_full_break;
363 if (nearest_sent_d == -1)
367 Add block to send queue
369 PrioritySortedBlockTransfer q((float)dist, p, peer_id);
373 num_blocks_selected += 1;
378 // If nothing was found for sending and nothing was queued for
379 // emerging, continue next time browsing from here
380 if (nearest_emerged_d != -1) {
381 new_nearest_unsent_d = nearest_emerged_d;
382 } else if (nearest_emergefull_d != -1) {
383 new_nearest_unsent_d = nearest_emergefull_d;
385 if (d > full_d_max) {
386 new_nearest_unsent_d = 0;
387 m_nothing_to_send_pause_timer = 2.0f;
388 infostream << "Server: map update for player " << m_name << " RemoteClient " << peer_id << ", time: " << m_map_send_completion_timer << "s" << std::endl;
389 m_map_send_completion_timer = 0.0f;
391 if (nearest_sent_d != -1)
392 new_nearest_unsent_d = nearest_sent_d;
394 new_nearest_unsent_d = d;
398 if (new_nearest_unsent_d != -1)
399 m_nearest_unsent_d = new_nearest_unsent_d;
402 void RemoteClient::GotBlock(v3s16 p)
404 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
405 m_blocks_sending.erase(p);
406 // only add to sent blocks if it actually was sending
407 // (it might have been modified since)
408 m_blocks_sent.insert(p);
410 m_excess_gotblocks++;
414 void RemoteClient::SentBlock(v3s16 p)
416 if (m_blocks_sending.find(p) == m_blocks_sending.end())
417 m_blocks_sending[p] = 0.0f;
419 infostream<<"RemoteClient::SentBlock(): Sent block"
420 " already in m_blocks_sending"<<std::endl;
423 void RemoteClient::SetBlockNotSent(v3s16 p)
425 m_nothing_to_send_pause_timer = 0;
427 // remove the block from sending and sent sets,
428 // and mark as modified if found
429 if (m_blocks_sending.erase(p) + m_blocks_sent.erase(p) > 0)
430 m_blocks_modified.insert(p);
433 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
435 m_nothing_to_send_pause_timer = 0;
437 for (auto &block : blocks) {
438 v3s16 p = block.first;
439 // remove the block from sending and sent sets,
440 // and mark as modified if found
441 if (m_blocks_sending.erase(p) + m_blocks_sent.erase(p) > 0)
442 m_blocks_modified.insert(p);
446 void RemoteClient::notifyEvent(ClientStateEvent event)
448 std::ostringstream myerror;
452 //intentionally do nothing
457 m_state = CS_HelloSent;
460 m_state = CS_Disconnecting;
465 /* GotInit2 SetDefinitionsSent SetMediaSent */
467 myerror << "Created: Invalid client state transition! " << event;
468 throw ClientStateError(myerror.str());
472 /* don't do anything if in denied state */
478 m_state = CS_AwaitingInit2;
482 m_state = CS_Disconnecting;
489 myerror << "HelloSent: Invalid client state transition! " << event;
490 throw ClientStateError(myerror.str());
493 case CS_AwaitingInit2:
497 confirmSerializationVersion();
498 m_state = CS_InitDone;
501 m_state = CS_Disconnecting;
507 /* Init SetDefinitionsSent SetMediaSent */
509 myerror << "InitSent: Invalid client state transition! " << event;
510 throw ClientStateError(myerror.str());
517 case CSE_SetDefinitionsSent:
518 m_state = CS_DefinitionsSent;
521 m_state = CS_Disconnecting;
527 /* Init GotInit2 SetMediaSent */
529 myerror << "InitDone: Invalid client state transition! " << event;
530 throw ClientStateError(myerror.str());
533 case CS_DefinitionsSent:
536 case CSE_SetClientReady:
540 m_state = CS_Disconnecting;
545 /* Init GotInit2 SetDefinitionsSent */
547 myerror << "DefinitionsSent: Invalid client state transition! " << event;
548 throw ClientStateError(myerror.str());
558 m_state = CS_Disconnecting;
560 case CSE_SudoSuccess:
561 m_state = CS_SudoMode;
564 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
566 myerror << "Active: Invalid client state transition! " << event;
567 throw ClientStateError(myerror.str());
578 m_state = CS_Disconnecting;
584 myerror << "Active: Invalid client state transition! " << event;
585 throw ClientStateError(myerror.str());
589 case CS_Disconnecting:
590 /* we are already disconnecting */
595 void RemoteClient::resetChosenMech()
598 srp_verifier_delete((SRPVerifier *) auth_data);
601 chosen_mech = AUTH_MECHANISM_NONE;
604 u64 RemoteClient::uptime() const
606 return porting::getTimeS() - m_connection_time;
609 ClientInterface::ClientInterface(const std::shared_ptr<con::Connection> & con)
613 m_print_info_timer(0.0f)
617 ClientInterface::~ClientInterface()
623 RecursiveMutexAutoLock clientslock(m_clients_mutex);
625 for (auto &client_it : m_clients) {
627 delete client_it.second;
632 std::vector<session_t> ClientInterface::getClientIDs(ClientState min_state)
634 std::vector<session_t> reply;
635 RecursiveMutexAutoLock clientslock(m_clients_mutex);
637 for (const auto &m_client : m_clients) {
638 if (m_client.second->getState() >= min_state)
639 reply.push_back(m_client.second->peer_id);
645 void ClientInterface::markBlockposAsNotSent(const v3s16 &pos)
647 RecursiveMutexAutoLock clientslock(m_clients_mutex);
648 for (const auto &client : m_clients) {
649 if (client.second->getState() >= CS_Active)
650 client.second->SetBlockNotSent(pos);
655 * Verify if user limit was reached.
656 * User limit count all clients from HelloSent state (MT protocol user) to Active state
657 * @return true if user limit was reached
659 bool ClientInterface::isUserLimitReached()
661 return getClientIDs(CS_HelloSent).size() >= g_settings->getU16("max_users");
664 void ClientInterface::step(float dtime)
666 m_print_info_timer += dtime;
667 if (m_print_info_timer >= 30.0f) {
668 m_print_info_timer = 0.0f;
673 void ClientInterface::UpdatePlayerList()
676 std::vector<session_t> clients = getClientIDs();
677 m_clients_names.clear();
679 if (!clients.empty())
680 infostream<<"Players:"<<std::endl;
682 for (session_t i : clients) {
683 RemotePlayer *player = m_env->getPlayer(i);
688 infostream << "* " << player->getName() << "\t";
691 RecursiveMutexAutoLock clientslock(m_clients_mutex);
692 RemoteClient* client = lockedGetClientNoEx(i);
694 client->PrintInfo(infostream);
697 m_clients_names.emplace_back(player->getName());
702 void ClientInterface::send(session_t peer_id, u8 channelnum,
703 NetworkPacket *pkt, bool reliable)
705 m_con->Send(peer_id, channelnum, pkt, reliable);
708 void ClientInterface::sendToAll(NetworkPacket *pkt)
710 RecursiveMutexAutoLock clientslock(m_clients_mutex);
711 for (auto &client_it : m_clients) {
712 RemoteClient *client = client_it.second;
714 if (client->net_proto_version != 0) {
715 m_con->Send(client->peer_id,
716 clientCommandFactoryTable[pkt->getCommand()].channel, pkt,
717 clientCommandFactoryTable[pkt->getCommand()].reliable);
722 RemoteClient* ClientInterface::getClientNoEx(session_t peer_id, ClientState state_min)
724 RecursiveMutexAutoLock clientslock(m_clients_mutex);
725 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
726 // The client may not exist; clients are immediately removed if their
727 // access is denied, and this event occurs later then.
728 if (n == m_clients.end())
731 if (n->second->getState() >= state_min)
737 RemoteClient* ClientInterface::lockedGetClientNoEx(session_t peer_id, ClientState state_min)
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 ClientState ClientInterface::getClientState(session_t peer_id)
753 RecursiveMutexAutoLock clientslock(m_clients_mutex);
754 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
755 // The client may not exist; clients are immediately removed if their
756 // access is denied, and this event occurs later then.
757 if (n == m_clients.end())
760 return n->second->getState();
763 void ClientInterface::setPlayerName(session_t peer_id, const std::string &name)
765 RecursiveMutexAutoLock clientslock(m_clients_mutex);
766 RemoteClientMap::iterator n = m_clients.find(peer_id);
767 // The client may not exist; clients are immediately removed if their
768 // access is denied, and this event occurs later then.
769 if (n != m_clients.end())
770 n->second->setName(name);
773 void ClientInterface::DeleteClient(session_t peer_id)
775 RecursiveMutexAutoLock conlock(m_clients_mutex);
778 RemoteClientMap::iterator n = m_clients.find(peer_id);
779 // The client may not exist; clients are immediately removed if their
780 // access is denied, and this event occurs later then.
781 if (n == m_clients.end())
785 Mark objects to be not known by the client
787 //TODO this should be done by client destructor!!!
788 RemoteClient *client = n->second;
790 for (u16 id : client->m_known_objects) {
792 ServerActiveObject* obj = m_env->getActiveObject(id);
794 if(obj && obj->m_known_by_count > 0)
795 obj->m_known_by_count--;
799 delete m_clients[peer_id];
800 m_clients.erase(peer_id);
803 void ClientInterface::CreateClient(session_t peer_id)
805 RecursiveMutexAutoLock conlock(m_clients_mutex);
808 RemoteClientMap::iterator n = m_clients.find(peer_id);
809 // The client shouldn't already exist
810 if (n != m_clients.end()) return;
813 RemoteClient *client = new RemoteClient();
814 client->peer_id = peer_id;
815 m_clients[client->peer_id] = client;
818 void ClientInterface::event(session_t peer_id, ClientStateEvent event)
821 RecursiveMutexAutoLock clientlock(m_clients_mutex);
824 RemoteClientMap::iterator n = m_clients.find(peer_id);
826 // No client to deliver event
827 if (n == m_clients.end())
829 n->second->notifyEvent(event);
832 if ((event == CSE_SetClientReady) ||
833 (event == CSE_Disconnect) ||
834 (event == CSE_SetDenied))
840 u16 ClientInterface::getProtocolVersion(session_t peer_id)
842 RecursiveMutexAutoLock conlock(m_clients_mutex);
845 RemoteClientMap::iterator n = m_clients.find(peer_id);
847 // No client to get version
848 if (n == m_clients.end())
851 return n->second->net_proto_version;
854 void ClientInterface::setClientVersion(session_t peer_id, u8 major, u8 minor, u8 patch,
855 const std::string &full)
857 RecursiveMutexAutoLock conlock(m_clients_mutex);
860 RemoteClientMap::iterator n = m_clients.find(peer_id);
862 // No client to set versions
863 if (n == m_clients.end())
866 n->second->setVersionInfo(major, minor, patch, full);