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, bool deletepkt)
631 m_con->Send(peer_id, channelnum, pkt, reliable);
637 void ClientInterface::sendToAll(u16 channelnum,
638 NetworkPacket* pkt, bool reliable)
640 JMutexAutoLock clientslock(m_clients_mutex);
641 for(std::map<u16, RemoteClient*>::iterator
642 i = m_clients.begin();
643 i != m_clients.end(); ++i) {
644 RemoteClient *client = i->second;
646 if (client->net_proto_version != 0) {
647 m_con->Send(client->peer_id, channelnum, pkt, reliable);
654 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
656 JMutexAutoLock clientslock(m_clients_mutex);
657 std::map<u16, RemoteClient*>::iterator n;
658 n = m_clients.find(peer_id);
659 // The client may not exist; clients are immediately removed if their
660 // access is denied, and this event occurs later then.
661 if(n == m_clients.end())
664 if (n->second->getState() >= state_min)
670 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
672 std::map<u16, RemoteClient*>::iterator n;
673 n = m_clients.find(peer_id);
674 // The client may not exist; clients are immediately removed if their
675 // access is denied, and this event occurs later then.
676 if(n == m_clients.end())
679 if (n->second->getState() >= state_min)
685 ClientState ClientInterface::getClientState(u16 peer_id)
687 JMutexAutoLock clientslock(m_clients_mutex);
688 std::map<u16, RemoteClient*>::iterator n;
689 n = m_clients.find(peer_id);
690 // The client may not exist; clients are immediately removed if their
691 // access is denied, and this event occurs later then.
692 if(n == m_clients.end())
695 return n->second->getState();
698 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
700 JMutexAutoLock clientslock(m_clients_mutex);
701 std::map<u16, RemoteClient*>::iterator n;
702 n = m_clients.find(peer_id);
703 // The client may not exist; clients are immediately removed if their
704 // access is denied, and this event occurs later then.
705 if(n != m_clients.end())
706 n->second->setName(name);
709 void ClientInterface::DeleteClient(u16 peer_id)
711 JMutexAutoLock conlock(m_clients_mutex);
714 std::map<u16, RemoteClient*>::iterator n;
715 n = m_clients.find(peer_id);
716 // The client may not exist; clients are immediately removed if their
717 // access is denied, and this event occurs later then.
718 if(n == m_clients.end())
722 Mark objects to be not known by the client
724 //TODO this should be done by client destructor!!!
725 RemoteClient *client = n->second;
727 for(std::set<u16>::iterator
728 i = client->m_known_objects.begin();
729 i != client->m_known_objects.end(); ++i)
733 ServerActiveObject* obj = m_env->getActiveObject(id);
735 if(obj && obj->m_known_by_count > 0)
736 obj->m_known_by_count--;
740 delete m_clients[peer_id];
741 m_clients.erase(peer_id);
744 void ClientInterface::CreateClient(u16 peer_id)
746 JMutexAutoLock conlock(m_clients_mutex);
749 std::map<u16, RemoteClient*>::iterator n;
750 n = m_clients.find(peer_id);
751 // The client shouldn't already exist
752 if(n != m_clients.end()) return;
755 RemoteClient *client = new RemoteClient();
756 client->peer_id = peer_id;
757 m_clients[client->peer_id] = client;
760 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
763 JMutexAutoLock clientlock(m_clients_mutex);
766 std::map<u16, RemoteClient*>::iterator n;
767 n = m_clients.find(peer_id);
769 // No client to deliver event
770 if (n == m_clients.end())
772 n->second->notifyEvent(event);
775 if ((event == CSE_SetClientReady) ||
776 (event == CSE_Disconnect) ||
777 (event == CSE_SetDenied))
783 u16 ClientInterface::getProtocolVersion(u16 peer_id)
785 JMutexAutoLock conlock(m_clients_mutex);
788 std::map<u16, RemoteClient*>::iterator n;
789 n = m_clients.find(peer_id);
791 // No client to get version
792 if (n == m_clients.end())
795 return n->second->net_proto_version;
798 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
800 JMutexAutoLock conlock(m_clients_mutex);
803 std::map<u16, RemoteClient*>::iterator n;
804 n = m_clients.find(peer_id);
806 // No client to set versions
807 if (n == m_clients.end())
810 n->second->setVersionInfo(major,minor,patch,full);