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++)
188 Get the border/face dot coordinates of a "d-radiused"
191 std::list<v3s16> list;
192 getFacePositions(list, d);
194 std::list<v3s16>::iterator li;
195 for(li=list.begin(); li!=list.end(); ++li)
197 v3s16 p = *li + center;
201 - Don't allow too many simultaneous transfers
202 - EXCEPT when the blocks are very close
204 Also, don't send blocks that are already flying.
207 // Start with the usual maximum
208 u16 max_simul_dynamic = max_simul_sends_usually;
210 // If block is very close, allow full maximum
211 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
212 max_simul_dynamic = max_simul_sends_setting;
214 // Don't select too many blocks for sending
215 if(num_blocks_selected >= max_simul_dynamic)
217 //queue_is_full = true;
218 goto queue_full_break;
221 // Don't send blocks that are currently being transferred
222 if(m_blocks_sending.find(p) != m_blocks_sending.end())
228 if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
229 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
230 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
231 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
232 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
233 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
236 // If this is true, inexistent block will be made from scratch
237 bool generate = d <= d_max_gen;
240 /*// Limit the generating area vertically to 2/3
241 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
244 // Limit the send area vertically to 1/2
245 if(abs(p.Y - center.Y) > full_d_max / 2)
250 Don't generate or send if not in sight
251 FIXME This only works if the client uses a small enough
252 FOV setting. The default of 72 degrees is fine.
255 float camera_fov = (72.0*M_PI/180) * 4./3.;
256 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
262 Don't send already sent blocks
265 if(m_blocks_sent.find(p) != m_blocks_sent.end())
272 Check if map has this block
274 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
276 bool surely_not_found_on_disk = false;
277 bool block_is_invalid = false;
280 // Reset usage timer, this block will be of use in the future.
281 block->resetUsageTimer();
283 // Block is dummy if data doesn't exist.
284 // It means it has been not found from disk and not generated
287 surely_not_found_on_disk = true;
290 // Block is valid if lighting is up-to-date and data exists
291 if(block->isValid() == false)
293 block_is_invalid = true;
296 if(block->isGenerated() == false)
297 block_is_invalid = true;
300 If block is not close, don't send it unless it is near
303 Block is near ground level if night-time mesh
304 differs from day-time mesh.
308 if(block->getDayNightDiff() == false)
314 If block has been marked to not exist on disk (dummy)
315 and generating new ones is not wanted, skip block.
317 if(generate == false && surely_not_found_on_disk == true)
324 Add inexistent block to emerge queue.
326 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
328 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
329 if (nearest_emerged_d == -1)
330 nearest_emerged_d = d;
332 if (nearest_emergefull_d == -1)
333 nearest_emergefull_d = d;
334 goto queue_full_break;
341 if(nearest_sent_d == -1)
345 Add block to send queue
347 PrioritySortedBlockTransfer q((float)d, p, peer_id);
351 num_blocks_selected += 1;
356 // If nothing was found for sending and nothing was queued for
357 // emerging, continue next time browsing from here
358 if(nearest_emerged_d != -1){
359 new_nearest_unsent_d = nearest_emerged_d;
360 } else if(nearest_emergefull_d != -1){
361 new_nearest_unsent_d = nearest_emergefull_d;
363 if(d > g_settings->getS16("max_block_send_distance")){
364 new_nearest_unsent_d = 0;
365 m_nothing_to_send_pause_timer = 2.0;
367 if(nearest_sent_d != -1)
368 new_nearest_unsent_d = nearest_sent_d;
370 new_nearest_unsent_d = d;
374 if(new_nearest_unsent_d != -1)
375 m_nearest_unsent_d = new_nearest_unsent_d;
378 void RemoteClient::GotBlock(v3s16 p)
380 if(m_blocks_sending.find(p) != m_blocks_sending.end())
381 m_blocks_sending.erase(p);
384 m_excess_gotblocks++;
386 m_blocks_sent.insert(p);
389 void RemoteClient::SentBlock(v3s16 p)
391 if(m_blocks_sending.find(p) == m_blocks_sending.end())
392 m_blocks_sending[p] = 0.0;
394 infostream<<"RemoteClient::SentBlock(): Sent block"
395 " already in m_blocks_sending"<<std::endl;
398 void RemoteClient::SetBlockNotSent(v3s16 p)
400 m_nearest_unsent_d = 0;
402 if(m_blocks_sending.find(p) != m_blocks_sending.end())
403 m_blocks_sending.erase(p);
404 if(m_blocks_sent.find(p) != m_blocks_sent.end())
405 m_blocks_sent.erase(p);
408 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
410 m_nearest_unsent_d = 0;
412 for(std::map<v3s16, MapBlock*>::iterator
414 i != blocks.end(); ++i)
418 if(m_blocks_sending.find(p) != m_blocks_sending.end())
419 m_blocks_sending.erase(p);
420 if(m_blocks_sent.find(p) != m_blocks_sent.end())
421 m_blocks_sent.erase(p);
425 void RemoteClient::notifyEvent(ClientStateEvent event)
427 std::ostringstream myerror;
431 //intentionally do nothing
437 m_state = CS_InitSent;
440 m_state = CS_Disconnecting;
445 /* GotInit2 SetDefinitionsSent SetMediaSent */
447 myerror << "Created: Invalid client state transition! " << event;
448 throw ClientStateError(myerror.str());
452 /* don't do anything if in denied state */
458 confirmSerializationVersion();
459 m_state = CS_InitDone;
462 m_state = CS_Disconnecting;
468 /* Init SetDefinitionsSent SetMediaSent */
470 myerror << "InitSent: Invalid client state transition! " << event;
471 throw ClientStateError(myerror.str());
478 case CSE_SetDefinitionsSent:
479 m_state = CS_DefinitionsSent;
482 m_state = CS_Disconnecting;
488 /* Init GotInit2 SetMediaSent */
490 myerror << "InitDone: Invalid client state transition! " << event;
491 throw ClientStateError(myerror.str());
494 case CS_DefinitionsSent:
497 case CSE_SetClientReady:
501 m_state = CS_Disconnecting;
506 /* Init GotInit2 SetDefinitionsSent */
508 myerror << "DefinitionsSent: Invalid client state transition! " << event;
509 throw ClientStateError(myerror.str());
519 m_state = CS_Disconnecting;
521 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
523 myerror << "Active: Invalid client state transition! " << event;
524 throw ClientStateError(myerror.str());
528 case CS_Disconnecting:
529 /* we are already disconnecting */
534 u32 RemoteClient::uptime()
536 return getTime(PRECISION_SECONDS) - m_connection_time;
539 ClientInterface::ClientInterface(con::Connection* con)
543 m_print_info_timer(0.0)
547 ClientInterface::~ClientInterface()
553 JMutexAutoLock clientslock(m_clients_mutex);
555 for(std::map<u16, RemoteClient*>::iterator
556 i = m_clients.begin();
557 i != m_clients.end(); ++i)
566 std::list<u16> ClientInterface::getClientIDs(ClientState min_state)
568 std::list<u16> reply;
569 JMutexAutoLock clientslock(m_clients_mutex);
571 for(std::map<u16, RemoteClient*>::iterator
572 i = m_clients.begin();
573 i != m_clients.end(); ++i)
575 if (i->second->getState() >= min_state)
576 reply.push_back(i->second->peer_id);
582 std::vector<std::string> ClientInterface::getPlayerNames()
584 return m_clients_names;
588 void ClientInterface::step(float dtime)
590 m_print_info_timer += dtime;
591 if(m_print_info_timer >= 30.0)
593 m_print_info_timer = 0.0;
598 void ClientInterface::UpdatePlayerList()
602 std::list<u16> clients = getClientIDs();
603 m_clients_names.clear();
607 infostream<<"Players:"<<std::endl;
608 for(std::list<u16>::iterator
610 i != clients.end(); ++i)
612 Player *player = m_env->getPlayer(*i);
615 infostream<<"* "<<player->getName()<<"\t";
618 JMutexAutoLock clientslock(m_clients_mutex);
619 RemoteClient* client = lockedGetClientNoEx(*i);
621 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);