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())
332 Check occlusion cache first.
334 if (m_blocks_occ.find(p) != m_blocks_occ.end())
337 if (m_occ_cull && !block_not_found &&
338 env->getMap().isBlockOccluded(block, cam_pos_nodes)) {
339 m_blocks_occ.insert(p);
345 If block has been marked to not exist on disk (dummy) or is
346 not generated and generating new ones is not wanted, skip block.
348 if (!generate && block_not_found) {
354 Add inexistent block to emerge queue.
356 if (block == NULL || block_not_found) {
357 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
358 if (nearest_emerged_d == -1)
359 nearest_emerged_d = d;
361 if (nearest_emergefull_d == -1)
362 nearest_emergefull_d = d;
363 goto queue_full_break;
370 if (nearest_sent_d == -1)
374 Add block to send queue
376 PrioritySortedBlockTransfer q((float)dist, p, peer_id);
380 num_blocks_selected += 1;
385 // If nothing was found for sending and nothing was queued for
386 // emerging, continue next time browsing from here
387 if (nearest_emerged_d != -1) {
388 new_nearest_unsent_d = nearest_emerged_d;
389 } else if (nearest_emergefull_d != -1) {
390 new_nearest_unsent_d = nearest_emergefull_d;
392 if (d > full_d_max) {
393 new_nearest_unsent_d = 0;
394 m_nothing_to_send_pause_timer = 2.0f;
395 infostream << "Server: Player " << m_name << ", RemoteClient " << peer_id << ": full map send completed after " << m_map_send_completion_timer << "s, restarting" << std::endl;
396 m_map_send_completion_timer = 0.0f;
398 if (nearest_sent_d != -1)
399 new_nearest_unsent_d = nearest_sent_d;
401 new_nearest_unsent_d = d;
405 if (new_nearest_unsent_d != -1 && m_nearest_unsent_d != new_nearest_unsent_d) {
406 m_nearest_unsent_d = new_nearest_unsent_d;
407 // if the distance has changed, clear the occlusion cache
408 m_blocks_occ.clear();
412 void RemoteClient::GotBlock(v3s16 p)
414 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
415 m_blocks_sending.erase(p);
416 // only add to sent blocks if it actually was sending
417 // (it might have been modified since)
418 m_blocks_sent.insert(p);
420 m_excess_gotblocks++;
424 void RemoteClient::SentBlock(v3s16 p)
426 if (m_blocks_sending.find(p) == m_blocks_sending.end())
427 m_blocks_sending[p] = 0.0f;
429 infostream<<"RemoteClient::SentBlock(): Sent block"
430 " already in m_blocks_sending"<<std::endl;
433 void RemoteClient::SetBlockNotSent(v3s16 p)
435 m_nothing_to_send_pause_timer = 0;
437 // remove the block from sending and sent sets,
438 // and mark as modified if found
439 if (m_blocks_sending.erase(p) + m_blocks_sent.erase(p) > 0)
440 m_blocks_modified.insert(p);
443 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
445 m_nothing_to_send_pause_timer = 0;
447 for (auto &block : blocks) {
448 v3s16 p = block.first;
449 // remove the block from sending and sent sets,
450 // and mark as modified if found
451 if (m_blocks_sending.erase(p) + m_blocks_sent.erase(p) > 0)
452 m_blocks_modified.insert(p);
456 void RemoteClient::notifyEvent(ClientStateEvent event)
458 std::ostringstream myerror;
462 //intentionally do nothing
467 m_state = CS_HelloSent;
470 m_state = CS_Disconnecting;
475 /* GotInit2 SetDefinitionsSent SetMediaSent */
477 myerror << "Created: Invalid client state transition! " << event;
478 throw ClientStateError(myerror.str());
482 /* don't do anything if in denied state */
488 m_state = CS_AwaitingInit2;
492 m_state = CS_Disconnecting;
499 myerror << "HelloSent: Invalid client state transition! " << event;
500 throw ClientStateError(myerror.str());
503 case CS_AwaitingInit2:
507 confirmSerializationVersion();
508 m_state = CS_InitDone;
511 m_state = CS_Disconnecting;
517 /* Init SetDefinitionsSent SetMediaSent */
519 myerror << "InitSent: Invalid client state transition! " << event;
520 throw ClientStateError(myerror.str());
527 case CSE_SetDefinitionsSent:
528 m_state = CS_DefinitionsSent;
531 m_state = CS_Disconnecting;
537 /* Init GotInit2 SetMediaSent */
539 myerror << "InitDone: Invalid client state transition! " << event;
540 throw ClientStateError(myerror.str());
543 case CS_DefinitionsSent:
546 case CSE_SetClientReady:
550 m_state = CS_Disconnecting;
555 /* Init GotInit2 SetDefinitionsSent */
557 myerror << "DefinitionsSent: Invalid client state transition! " << event;
558 throw ClientStateError(myerror.str());
568 m_state = CS_Disconnecting;
570 case CSE_SudoSuccess:
571 m_state = CS_SudoMode;
574 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
576 myerror << "Active: Invalid client state transition! " << event;
577 throw ClientStateError(myerror.str());
588 m_state = CS_Disconnecting;
594 myerror << "Active: Invalid client state transition! " << event;
595 throw ClientStateError(myerror.str());
599 case CS_Disconnecting:
600 /* we are already disconnecting */
605 void RemoteClient::resetChosenMech()
608 srp_verifier_delete((SRPVerifier *) auth_data);
611 chosen_mech = AUTH_MECHANISM_NONE;
614 u64 RemoteClient::uptime() const
616 return porting::getTimeS() - m_connection_time;
619 ClientInterface::ClientInterface(const std::shared_ptr<con::Connection> & con)
623 m_print_info_timer(0.0f)
627 ClientInterface::~ClientInterface()
633 RecursiveMutexAutoLock clientslock(m_clients_mutex);
635 for (auto &client_it : m_clients) {
637 delete client_it.second;
642 std::vector<session_t> ClientInterface::getClientIDs(ClientState min_state)
644 std::vector<session_t> reply;
645 RecursiveMutexAutoLock clientslock(m_clients_mutex);
647 for (const auto &m_client : m_clients) {
648 if (m_client.second->getState() >= min_state)
649 reply.push_back(m_client.second->peer_id);
655 void ClientInterface::markBlockposAsNotSent(const v3s16 &pos)
657 RecursiveMutexAutoLock clientslock(m_clients_mutex);
658 for (const auto &client : m_clients) {
659 if (client.second->getState() >= CS_Active)
660 client.second->SetBlockNotSent(pos);
665 * Verify if user limit was reached.
666 * User limit count all clients from HelloSent state (MT protocol user) to Active state
667 * @return true if user limit was reached
669 bool ClientInterface::isUserLimitReached()
671 return getClientIDs(CS_HelloSent).size() >= g_settings->getU16("max_users");
674 void ClientInterface::step(float dtime)
676 m_print_info_timer += dtime;
677 if (m_print_info_timer >= 30.0f) {
678 m_print_info_timer = 0.0f;
683 void ClientInterface::UpdatePlayerList()
686 std::vector<session_t> clients = getClientIDs();
687 m_clients_names.clear();
689 if (!clients.empty())
690 infostream<<"Players:"<<std::endl;
692 for (session_t i : clients) {
693 RemotePlayer *player = m_env->getPlayer(i);
698 infostream << "* " << player->getName() << "\t";
701 RecursiveMutexAutoLock clientslock(m_clients_mutex);
702 RemoteClient* client = lockedGetClientNoEx(i);
704 client->PrintInfo(infostream);
707 m_clients_names.emplace_back(player->getName());
712 void ClientInterface::send(session_t peer_id, u8 channelnum,
713 NetworkPacket *pkt, bool reliable)
715 m_con->Send(peer_id, channelnum, pkt, reliable);
718 void ClientInterface::sendToAll(NetworkPacket *pkt)
720 RecursiveMutexAutoLock clientslock(m_clients_mutex);
721 for (auto &client_it : m_clients) {
722 RemoteClient *client = client_it.second;
724 if (client->net_proto_version != 0) {
725 m_con->Send(client->peer_id,
726 clientCommandFactoryTable[pkt->getCommand()].channel, pkt,
727 clientCommandFactoryTable[pkt->getCommand()].reliable);
732 RemoteClient* ClientInterface::getClientNoEx(session_t peer_id, ClientState state_min)
734 RecursiveMutexAutoLock clientslock(m_clients_mutex);
735 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
736 // The client may not exist; clients are immediately removed if their
737 // access is denied, and this event occurs later then.
738 if (n == m_clients.end())
741 if (n->second->getState() >= state_min)
747 RemoteClient* ClientInterface::lockedGetClientNoEx(session_t peer_id, ClientState state_min)
749 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
750 // The client may not exist; clients are immediately removed if their
751 // access is denied, and this event occurs later then.
752 if (n == m_clients.end())
755 if (n->second->getState() >= state_min)
761 ClientState ClientInterface::getClientState(session_t peer_id)
763 RecursiveMutexAutoLock clientslock(m_clients_mutex);
764 RemoteClientMap::const_iterator n = m_clients.find(peer_id);
765 // The client may not exist; clients are immediately removed if their
766 // access is denied, and this event occurs later then.
767 if (n == m_clients.end())
770 return n->second->getState();
773 void ClientInterface::setPlayerName(session_t peer_id, const std::string &name)
775 RecursiveMutexAutoLock clientslock(m_clients_mutex);
776 RemoteClientMap::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())
780 n->second->setName(name);
783 void ClientInterface::DeleteClient(session_t peer_id)
785 RecursiveMutexAutoLock conlock(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())
795 Mark objects to be not known by the client
797 //TODO this should be done by client destructor!!!
798 RemoteClient *client = n->second;
800 for (u16 id : client->m_known_objects) {
802 ServerActiveObject* obj = m_env->getActiveObject(id);
804 if(obj && obj->m_known_by_count > 0)
805 obj->m_known_by_count--;
809 delete m_clients[peer_id];
810 m_clients.erase(peer_id);
813 void ClientInterface::CreateClient(session_t peer_id)
815 RecursiveMutexAutoLock conlock(m_clients_mutex);
818 RemoteClientMap::iterator n = m_clients.find(peer_id);
819 // The client shouldn't already exist
820 if (n != m_clients.end()) return;
823 RemoteClient *client = new RemoteClient();
824 client->peer_id = peer_id;
825 m_clients[client->peer_id] = client;
828 void ClientInterface::event(session_t peer_id, ClientStateEvent event)
831 RecursiveMutexAutoLock clientlock(m_clients_mutex);
834 RemoteClientMap::iterator n = m_clients.find(peer_id);
836 // No client to deliver event
837 if (n == m_clients.end())
839 n->second->notifyEvent(event);
842 if ((event == CSE_SetClientReady) ||
843 (event == CSE_Disconnect) ||
844 (event == CSE_SetDenied))
850 u16 ClientInterface::getProtocolVersion(session_t peer_id)
852 RecursiveMutexAutoLock conlock(m_clients_mutex);
855 RemoteClientMap::iterator n = m_clients.find(peer_id);
857 // No client to get version
858 if (n == m_clients.end())
861 return n->second->net_proto_version;
864 void ClientInterface::setClientVersion(session_t peer_id, u8 major, u8 minor, u8 patch,
865 const std::string &full)
867 RecursiveMutexAutoLock conlock(m_clients_mutex);
870 RemoteClientMap::iterator n = m_clients.find(peer_id);
872 // No client to set versions
873 if (n == m_clients.end())
876 n->second->setVersionInfo(major, minor, patch, full);