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.
22 #include "clientiface.h"
23 #include "util/numeric.h"
24 #include "util/mathconstants.h"
28 #include "network/connection.h"
29 #include "environment.h"
32 #include "serverobject.h" // TODO this is used for cleanup of only
33 #include "main.h" // for g_settings
36 const char *ClientInterface::statenames[] = {
49 std::string ClientInterface::state2Name(ClientState state)
51 return statenames[state];
54 void RemoteClient::ResendBlockIfOnWire(v3s16 p)
56 // if this block is on wire, mark it for sending again as soon as possible
57 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
62 void RemoteClient::GetNextBlocks (
63 ServerEnvironment *env,
64 EmergeManager * emerge,
66 std::vector<PrioritySortedBlockTransfer> &dest)
68 DSTACK(__FUNCTION_NAME);
72 m_nothing_to_send_pause_timer -= dtime;
73 m_nearest_unsent_reset_timer += dtime;
75 if(m_nothing_to_send_pause_timer >= 0)
78 Player *player = env->getPlayer(peer_id);
79 // This can happen sometimes; clients and players are not in perfect sync.
83 // Won't send anything if already sending
84 if(m_blocks_sending.size() >= g_settings->getU16
85 ("max_simultaneous_block_sends_per_client"))
87 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
91 v3f playerpos = player->getPosition();
92 v3f playerspeed = player->getSpeed();
93 v3f playerspeeddir(0,0,0);
94 if(playerspeed.getLength() > 1.0*BS)
95 playerspeeddir = playerspeed / playerspeed.getLength();
96 // Predict to next block
97 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
99 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
101 v3s16 center = getNodeBlockPos(center_nodepos);
103 // Camera position and direction
104 v3f camera_pos = player->getEyePosition();
105 v3f camera_dir = v3f(0,0,1);
106 camera_dir.rotateYZBy(player->getPitch());
107 camera_dir.rotateXZBy(player->getYaw());
109 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
110 <<camera_dir.Z<<")"<<std::endl;*/
113 Get the starting value of the block finder radius.
116 if(m_last_center != center)
118 m_nearest_unsent_d = 0;
119 m_last_center = center;
122 /*infostream<<"m_nearest_unsent_reset_timer="
123 <<m_nearest_unsent_reset_timer<<std::endl;*/
125 // Reset periodically to workaround for some bugs or stuff
126 if(m_nearest_unsent_reset_timer > 20.0)
128 m_nearest_unsent_reset_timer = 0;
129 m_nearest_unsent_d = 0;
130 //infostream<<"Resetting m_nearest_unsent_d for "
131 // <<server->getPlayerName(peer_id)<<std::endl;
134 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
135 s16 d_start = m_nearest_unsent_d;
137 //infostream<<"d_start="<<d_start<<std::endl;
139 u16 max_simul_sends_setting = g_settings->getU16
140 ("max_simultaneous_block_sends_per_client");
141 u16 max_simul_sends_usually = max_simul_sends_setting;
144 Check the time from last addNode/removeNode.
146 Decrease send rate if player is building stuff.
148 m_time_from_building += dtime;
149 if(m_time_from_building < g_settings->getFloat(
150 "full_block_send_enable_min_time_from_building"))
152 max_simul_sends_usually
153 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
157 Number of blocks sending + number of blocks selected for sending
159 u32 num_blocks_selected = m_blocks_sending.size();
162 next time d will be continued from the d from which the nearest
163 unsent block was found this time.
165 This is because not necessarily any of the blocks found this
166 time are actually sent.
168 s32 new_nearest_unsent_d = -1;
170 const s16 full_d_max = g_settings->getS16("max_block_send_distance");
171 s16 d_max = full_d_max;
172 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
174 // Don't loop very much at a time
175 s16 max_d_increment_at_time = 2;
176 if(d_max > d_start + max_d_increment_at_time)
177 d_max = d_start + max_d_increment_at_time;
179 s32 nearest_emerged_d = -1;
180 s32 nearest_emergefull_d = -1;
181 s32 nearest_sent_d = -1;
182 //bool queue_is_full = false;
185 for(d = d_start; d <= d_max; d++) {
187 Get the border/face dot coordinates of a "d-radiused"
190 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
192 std::vector<v3s16>::iterator li;
193 for(li = list.begin(); li != list.end(); ++li) {
194 v3s16 p = *li + center;
198 - Don't allow too many simultaneous transfers
199 - EXCEPT when the blocks are very close
201 Also, don't send blocks that are already flying.
204 // Start with the usual maximum
205 u16 max_simul_dynamic = max_simul_sends_usually;
207 // If block is very close, allow full maximum
208 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
209 max_simul_dynamic = max_simul_sends_setting;
211 // Don't select too many blocks for sending
212 if(num_blocks_selected >= max_simul_dynamic)
214 //queue_is_full = true;
215 goto queue_full_break;
218 // Don't send blocks that are currently being transferred
219 if(m_blocks_sending.find(p) != m_blocks_sending.end())
225 if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
226 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
227 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
228 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
229 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
230 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
233 // If this is true, inexistent block will be made from scratch
234 bool generate = d <= d_max_gen;
237 /*// Limit the generating area vertically to 2/3
238 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
241 // Limit the send area vertically to 1/2
242 if(abs(p.Y - center.Y) > full_d_max / 2)
247 Don't generate or send if not in sight
248 FIXME This only works if the client uses a small enough
249 FOV setting. The default of 72 degrees is fine.
252 float camera_fov = (72.0*M_PI/180) * 4./3.;
253 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
259 Don't send already sent blocks
262 if(m_blocks_sent.find(p) != m_blocks_sent.end())
269 Check if map has this block
271 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
273 bool surely_not_found_on_disk = false;
274 bool block_is_invalid = false;
277 // Reset usage timer, this block will be of use in the future.
278 block->resetUsageTimer();
280 // Block is dummy if data doesn't exist.
281 // It means it has been not found from disk and not generated
284 surely_not_found_on_disk = true;
287 // Block is valid if lighting is up-to-date and data exists
288 if(block->isValid() == false)
290 block_is_invalid = true;
293 if(block->isGenerated() == false)
294 block_is_invalid = true;
297 If block is not close, don't send it unless it is near
300 Block is near ground level if night-time mesh
301 differs from day-time mesh.
305 if(block->getDayNightDiff() == false)
311 If block has been marked to not exist on disk (dummy)
312 and generating new ones is not wanted, skip block.
314 if(generate == false && surely_not_found_on_disk == true)
321 Add inexistent block to emerge queue.
323 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
325 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
326 if (nearest_emerged_d == -1)
327 nearest_emerged_d = d;
329 if (nearest_emergefull_d == -1)
330 nearest_emergefull_d = d;
331 goto queue_full_break;
338 if(nearest_sent_d == -1)
342 Add block to send queue
344 PrioritySortedBlockTransfer q((float)d, p, peer_id);
348 num_blocks_selected += 1;
353 // If nothing was found for sending and nothing was queued for
354 // emerging, continue next time browsing from here
355 if(nearest_emerged_d != -1){
356 new_nearest_unsent_d = nearest_emerged_d;
357 } else if(nearest_emergefull_d != -1){
358 new_nearest_unsent_d = nearest_emergefull_d;
360 if(d > g_settings->getS16("max_block_send_distance")){
361 new_nearest_unsent_d = 0;
362 m_nothing_to_send_pause_timer = 2.0;
364 if(nearest_sent_d != -1)
365 new_nearest_unsent_d = nearest_sent_d;
367 new_nearest_unsent_d = d;
371 if(new_nearest_unsent_d != -1)
372 m_nearest_unsent_d = new_nearest_unsent_d;
375 void RemoteClient::GotBlock(v3s16 p)
377 if(m_blocks_sending.find(p) != m_blocks_sending.end())
378 m_blocks_sending.erase(p);
381 m_excess_gotblocks++;
383 m_blocks_sent.insert(p);
386 void RemoteClient::SentBlock(v3s16 p)
388 if(m_blocks_sending.find(p) == m_blocks_sending.end())
389 m_blocks_sending[p] = 0.0;
391 infostream<<"RemoteClient::SentBlock(): Sent block"
392 " already in m_blocks_sending"<<std::endl;
395 void RemoteClient::SetBlockNotSent(v3s16 p)
397 m_nearest_unsent_d = 0;
399 if(m_blocks_sending.find(p) != m_blocks_sending.end())
400 m_blocks_sending.erase(p);
401 if(m_blocks_sent.find(p) != m_blocks_sent.end())
402 m_blocks_sent.erase(p);
405 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
407 m_nearest_unsent_d = 0;
409 for(std::map<v3s16, MapBlock*>::iterator
411 i != blocks.end(); ++i)
415 if(m_blocks_sending.find(p) != m_blocks_sending.end())
416 m_blocks_sending.erase(p);
417 if(m_blocks_sent.find(p) != m_blocks_sent.end())
418 m_blocks_sent.erase(p);
422 void RemoteClient::notifyEvent(ClientStateEvent event)
424 std::ostringstream myerror;
428 //intentionally do nothing
434 m_state = CS_InitSent;
437 m_state = CS_Disconnecting;
442 /* GotInit2 SetDefinitionsSent SetMediaSent */
444 myerror << "Created: Invalid client state transition! " << event;
445 throw ClientStateError(myerror.str());
449 /* don't do anything if in denied state */
455 confirmSerializationVersion();
456 m_state = CS_InitDone;
459 m_state = CS_Disconnecting;
465 /* Init SetDefinitionsSent SetMediaSent */
467 myerror << "InitSent: Invalid client state transition! " << event;
468 throw ClientStateError(myerror.str());
475 case CSE_SetDefinitionsSent:
476 m_state = CS_DefinitionsSent;
479 m_state = CS_Disconnecting;
485 /* Init GotInit2 SetMediaSent */
487 myerror << "InitDone: Invalid client state transition! " << event;
488 throw ClientStateError(myerror.str());
491 case CS_DefinitionsSent:
494 case CSE_SetClientReady:
498 m_state = CS_Disconnecting;
503 /* Init GotInit2 SetDefinitionsSent */
505 myerror << "DefinitionsSent: Invalid client state transition! " << event;
506 throw ClientStateError(myerror.str());
516 m_state = CS_Disconnecting;
518 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
520 myerror << "Active: Invalid client state transition! " << event;
521 throw ClientStateError(myerror.str());
525 case CS_Disconnecting:
526 /* we are already disconnecting */
531 u32 RemoteClient::uptime()
533 return getTime(PRECISION_SECONDS) - m_connection_time;
536 ClientInterface::ClientInterface(con::Connection* con)
540 m_print_info_timer(0.0)
544 ClientInterface::~ClientInterface()
550 JMutexAutoLock clientslock(m_clients_mutex);
552 for(std::map<u16, RemoteClient*>::iterator
553 i = m_clients.begin();
554 i != m_clients.end(); ++i)
563 std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
565 std::vector<u16> reply;
566 JMutexAutoLock clientslock(m_clients_mutex);
568 for(std::map<u16, RemoteClient*>::iterator
569 i = m_clients.begin();
570 i != m_clients.end(); ++i)
572 if (i->second->getState() >= min_state)
573 reply.push_back(i->second->peer_id);
579 std::vector<std::string> ClientInterface::getPlayerNames()
581 return m_clients_names;
585 void ClientInterface::step(float dtime)
587 m_print_info_timer += dtime;
588 if(m_print_info_timer >= 30.0)
590 m_print_info_timer = 0.0;
595 void ClientInterface::UpdatePlayerList()
599 std::vector<u16> clients = getClientIDs();
600 m_clients_names.clear();
604 infostream<<"Players:"<<std::endl;
606 for(std::vector<u16>::iterator
608 i != clients.end(); ++i) {
609 Player *player = m_env->getPlayer(*i);
614 infostream << "* " << player->getName() << "\t";
617 JMutexAutoLock clientslock(m_clients_mutex);
618 RemoteClient* client = lockedGetClientNoEx(*i);
620 client->PrintInfo(infostream);
623 m_clients_names.push_back(player->getName());
628 void ClientInterface::send(u16 peer_id, u8 channelnum,
629 NetworkPacket* pkt, bool reliable)
631 m_con->Send(peer_id, channelnum, pkt, reliable);
634 void ClientInterface::sendToAll(u16 channelnum,
635 NetworkPacket* pkt, bool reliable)
637 JMutexAutoLock clientslock(m_clients_mutex);
638 for(std::map<u16, RemoteClient*>::iterator
639 i = m_clients.begin();
640 i != m_clients.end(); ++i) {
641 RemoteClient *client = i->second;
643 if (client->net_proto_version != 0) {
644 m_con->Send(client->peer_id, channelnum, pkt, reliable);
649 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
651 JMutexAutoLock clientslock(m_clients_mutex);
652 std::map<u16, RemoteClient*>::iterator n;
653 n = m_clients.find(peer_id);
654 // The client may not exist; clients are immediately removed if their
655 // access is denied, and this event occurs later then.
656 if(n == m_clients.end())
659 if (n->second->getState() >= state_min)
665 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
667 std::map<u16, RemoteClient*>::iterator n;
668 n = m_clients.find(peer_id);
669 // The client may not exist; clients are immediately removed if their
670 // access is denied, and this event occurs later then.
671 if(n == m_clients.end())
674 if (n->second->getState() >= state_min)
680 ClientState ClientInterface::getClientState(u16 peer_id)
682 JMutexAutoLock clientslock(m_clients_mutex);
683 std::map<u16, RemoteClient*>::iterator n;
684 n = m_clients.find(peer_id);
685 // The client may not exist; clients are immediately removed if their
686 // access is denied, and this event occurs later then.
687 if(n == m_clients.end())
690 return n->second->getState();
693 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
695 JMutexAutoLock clientslock(m_clients_mutex);
696 std::map<u16, RemoteClient*>::iterator n;
697 n = m_clients.find(peer_id);
698 // The client may not exist; clients are immediately removed if their
699 // access is denied, and this event occurs later then.
700 if(n != m_clients.end())
701 n->second->setName(name);
704 void ClientInterface::DeleteClient(u16 peer_id)
706 JMutexAutoLock conlock(m_clients_mutex);
709 std::map<u16, RemoteClient*>::iterator n;
710 n = m_clients.find(peer_id);
711 // The client may not exist; clients are immediately removed if their
712 // access is denied, and this event occurs later then.
713 if(n == m_clients.end())
717 Mark objects to be not known by the client
719 //TODO this should be done by client destructor!!!
720 RemoteClient *client = n->second;
722 for(std::set<u16>::iterator
723 i = client->m_known_objects.begin();
724 i != client->m_known_objects.end(); ++i)
728 ServerActiveObject* obj = m_env->getActiveObject(id);
730 if(obj && obj->m_known_by_count > 0)
731 obj->m_known_by_count--;
735 delete m_clients[peer_id];
736 m_clients.erase(peer_id);
739 void ClientInterface::CreateClient(u16 peer_id)
741 JMutexAutoLock conlock(m_clients_mutex);
744 std::map<u16, RemoteClient*>::iterator n;
745 n = m_clients.find(peer_id);
746 // The client shouldn't already exist
747 if(n != m_clients.end()) return;
750 RemoteClient *client = new RemoteClient();
751 client->peer_id = peer_id;
752 m_clients[client->peer_id] = client;
755 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
758 JMutexAutoLock clientlock(m_clients_mutex);
761 std::map<u16, RemoteClient*>::iterator n;
762 n = m_clients.find(peer_id);
764 // No client to deliver event
765 if (n == m_clients.end())
767 n->second->notifyEvent(event);
770 if ((event == CSE_SetClientReady) ||
771 (event == CSE_Disconnect) ||
772 (event == CSE_SetDenied))
778 u16 ClientInterface::getProtocolVersion(u16 peer_id)
780 JMutexAutoLock conlock(m_clients_mutex);
783 std::map<u16, RemoteClient*>::iterator n;
784 n = m_clients.find(peer_id);
786 // No client to get version
787 if (n == m_clients.end())
790 return n->second->net_proto_version;
793 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
795 JMutexAutoLock conlock(m_clients_mutex);
798 std::map<u16, RemoteClient*>::iterator n;
799 n = m_clients.find(peer_id);
801 // No client to set versions
802 if (n == m_clients.end())
805 n->second->setVersionInfo(major,minor,patch,full);