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
35 const char *ClientInterface::statenames[] = {
48 std::string ClientInterface::state2Name(ClientState state)
50 return statenames[state];
53 void RemoteClient::ResendBlockIfOnWire(v3s16 p)
55 // if this block is on wire, mark it for sending again as soon as possible
56 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
61 void RemoteClient::GetNextBlocks (
62 ServerEnvironment *env,
63 EmergeManager * emerge,
65 std::vector<PrioritySortedBlockTransfer> &dest)
67 DSTACK(__FUNCTION_NAME);
71 m_nothing_to_send_pause_timer -= dtime;
72 m_nearest_unsent_reset_timer += dtime;
74 if(m_nothing_to_send_pause_timer >= 0)
77 Player *player = env->getPlayer(peer_id);
78 // This can happen sometimes; clients and players are not in perfect sync.
82 // Won't send anything if already sending
83 if(m_blocks_sending.size() >= g_settings->getU16
84 ("max_simultaneous_block_sends_per_client"))
86 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
90 v3f playerpos = player->getPosition();
91 v3f playerspeed = player->getSpeed();
92 v3f playerspeeddir(0,0,0);
93 if(playerspeed.getLength() > 1.0*BS)
94 playerspeeddir = playerspeed / playerspeed.getLength();
95 // Predict to next block
96 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
98 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
100 v3s16 center = getNodeBlockPos(center_nodepos);
102 // Camera position and direction
103 v3f camera_pos = player->getEyePosition();
104 v3f camera_dir = v3f(0,0,1);
105 camera_dir.rotateYZBy(player->getPitch());
106 camera_dir.rotateXZBy(player->getYaw());
108 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
109 <<camera_dir.Z<<")"<<std::endl;*/
112 Get the starting value of the block finder radius.
115 if(m_last_center != center)
117 m_nearest_unsent_d = 0;
118 m_last_center = center;
121 /*infostream<<"m_nearest_unsent_reset_timer="
122 <<m_nearest_unsent_reset_timer<<std::endl;*/
124 // Reset periodically to workaround for some bugs or stuff
125 if(m_nearest_unsent_reset_timer > 20.0)
127 m_nearest_unsent_reset_timer = 0;
128 m_nearest_unsent_d = 0;
129 //infostream<<"Resetting m_nearest_unsent_d for "
130 // <<server->getPlayerName(peer_id)<<std::endl;
133 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
134 s16 d_start = m_nearest_unsent_d;
136 //infostream<<"d_start="<<d_start<<std::endl;
138 u16 max_simul_sends_setting = g_settings->getU16
139 ("max_simultaneous_block_sends_per_client");
140 u16 max_simul_sends_usually = max_simul_sends_setting;
143 Check the time from last addNode/removeNode.
145 Decrease send rate if player is building stuff.
147 m_time_from_building += dtime;
148 if(m_time_from_building < g_settings->getFloat(
149 "full_block_send_enable_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 const s16 full_d_max = g_settings->getS16("max_block_send_distance");
170 s16 d_max = full_d_max;
171 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
173 // Don't loop very much at a time
174 s16 max_d_increment_at_time = 2;
175 if(d_max > d_start + max_d_increment_at_time)
176 d_max = d_start + max_d_increment_at_time;
178 s32 nearest_emerged_d = -1;
179 s32 nearest_emergefull_d = -1;
180 s32 nearest_sent_d = -1;
181 //bool queue_is_full = false;
184 for(d = d_start; d <= d_max; d++) {
186 Get the border/face dot coordinates of a "d-radiused"
189 std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
191 std::vector<v3s16>::iterator li;
192 for(li = list.begin(); li != list.end(); ++li) {
193 v3s16 p = *li + center;
197 - Don't allow too many simultaneous transfers
198 - EXCEPT when the blocks are very close
200 Also, don't send blocks that are already flying.
203 // Start with the usual maximum
204 u16 max_simul_dynamic = max_simul_sends_usually;
206 // If block is very close, allow full maximum
207 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
208 max_simul_dynamic = max_simul_sends_setting;
210 // Don't select too many blocks for sending
211 if(num_blocks_selected >= max_simul_dynamic)
213 //queue_is_full = true;
214 goto queue_full_break;
217 // Don't send blocks that are currently being transferred
218 if(m_blocks_sending.find(p) != m_blocks_sending.end())
224 if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
225 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
226 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
227 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
228 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
229 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
232 // If this is true, inexistent block will be made from scratch
233 bool generate = d <= d_max_gen;
236 /*// Limit the generating area vertically to 2/3
237 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
240 // Limit the send area vertically to 1/2
241 if(abs(p.Y - center.Y) > full_d_max / 2)
246 Don't generate or send if not in sight
247 FIXME This only works if the client uses a small enough
248 FOV setting. The default of 72 degrees is fine.
251 float camera_fov = (72.0*M_PI/180) * 4./3.;
252 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
258 Don't send already sent blocks
261 if(m_blocks_sent.find(p) != m_blocks_sent.end())
268 Check if map has this block
270 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
272 bool surely_not_found_on_disk = false;
273 bool block_is_invalid = false;
276 // Reset usage timer, this block will be of use in the future.
277 block->resetUsageTimer();
279 // Block is dummy if data doesn't exist.
280 // It means it has been not found from disk and not generated
283 surely_not_found_on_disk = true;
286 // Block is valid if lighting is up-to-date and data exists
287 if(block->isValid() == false)
289 block_is_invalid = true;
292 if(block->isGenerated() == false)
293 block_is_invalid = true;
296 If block is not close, don't send it unless it is near
299 Block is near ground level if night-time mesh
300 differs from day-time mesh.
304 if(block->getDayNightDiff() == false)
310 If block has been marked to not exist on disk (dummy)
311 and generating new ones is not wanted, skip block.
313 if(generate == false && surely_not_found_on_disk == true)
320 Add inexistent block to emerge queue.
322 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
324 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
325 if (nearest_emerged_d == -1)
326 nearest_emerged_d = d;
328 if (nearest_emergefull_d == -1)
329 nearest_emergefull_d = d;
330 goto queue_full_break;
337 if(nearest_sent_d == -1)
341 Add block to send queue
343 PrioritySortedBlockTransfer q((float)d, p, peer_id);
347 num_blocks_selected += 1;
352 // If nothing was found for sending and nothing was queued for
353 // emerging, continue next time browsing from here
354 if(nearest_emerged_d != -1){
355 new_nearest_unsent_d = nearest_emerged_d;
356 } else if(nearest_emergefull_d != -1){
357 new_nearest_unsent_d = nearest_emergefull_d;
359 if(d > g_settings->getS16("max_block_send_distance")){
360 new_nearest_unsent_d = 0;
361 m_nothing_to_send_pause_timer = 2.0;
363 if(nearest_sent_d != -1)
364 new_nearest_unsent_d = nearest_sent_d;
366 new_nearest_unsent_d = d;
370 if(new_nearest_unsent_d != -1)
371 m_nearest_unsent_d = new_nearest_unsent_d;
374 void RemoteClient::GotBlock(v3s16 p)
376 if(m_blocks_sending.find(p) != m_blocks_sending.end())
377 m_blocks_sending.erase(p);
380 m_excess_gotblocks++;
382 m_blocks_sent.insert(p);
385 void RemoteClient::SentBlock(v3s16 p)
387 if(m_blocks_sending.find(p) == m_blocks_sending.end())
388 m_blocks_sending[p] = 0.0;
390 infostream<<"RemoteClient::SentBlock(): Sent block"
391 " already in m_blocks_sending"<<std::endl;
394 void RemoteClient::SetBlockNotSent(v3s16 p)
396 m_nearest_unsent_d = 0;
398 if(m_blocks_sending.find(p) != m_blocks_sending.end())
399 m_blocks_sending.erase(p);
400 if(m_blocks_sent.find(p) != m_blocks_sent.end())
401 m_blocks_sent.erase(p);
404 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
406 m_nearest_unsent_d = 0;
408 for(std::map<v3s16, MapBlock*>::iterator
410 i != blocks.end(); ++i)
414 if(m_blocks_sending.find(p) != m_blocks_sending.end())
415 m_blocks_sending.erase(p);
416 if(m_blocks_sent.find(p) != m_blocks_sent.end())
417 m_blocks_sent.erase(p);
421 void RemoteClient::notifyEvent(ClientStateEvent event)
423 std::ostringstream myerror;
427 //intentionally do nothing
433 m_state = CS_InitSent;
436 m_state = CS_Disconnecting;
441 /* GotInit2 SetDefinitionsSent SetMediaSent */
443 myerror << "Created: Invalid client state transition! " << event;
444 throw ClientStateError(myerror.str());
448 /* don't do anything if in denied state */
454 confirmSerializationVersion();
455 m_state = CS_InitDone;
458 m_state = CS_Disconnecting;
464 /* Init SetDefinitionsSent SetMediaSent */
466 myerror << "InitSent: Invalid client state transition! " << event;
467 throw ClientStateError(myerror.str());
474 case CSE_SetDefinitionsSent:
475 m_state = CS_DefinitionsSent;
478 m_state = CS_Disconnecting;
484 /* Init GotInit2 SetMediaSent */
486 myerror << "InitDone: Invalid client state transition! " << event;
487 throw ClientStateError(myerror.str());
490 case CS_DefinitionsSent:
493 case CSE_SetClientReady:
497 m_state = CS_Disconnecting;
502 /* Init GotInit2 SetDefinitionsSent */
504 myerror << "DefinitionsSent: Invalid client state transition! " << event;
505 throw ClientStateError(myerror.str());
515 m_state = CS_Disconnecting;
517 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
519 myerror << "Active: Invalid client state transition! " << event;
520 throw ClientStateError(myerror.str());
524 case CS_Disconnecting:
525 /* we are already disconnecting */
530 u32 RemoteClient::uptime()
532 return getTime(PRECISION_SECONDS) - m_connection_time;
535 ClientInterface::ClientInterface(con::Connection* con)
539 m_print_info_timer(0.0)
543 ClientInterface::~ClientInterface()
549 JMutexAutoLock clientslock(m_clients_mutex);
551 for(std::map<u16, RemoteClient*>::iterator
552 i = m_clients.begin();
553 i != m_clients.end(); ++i)
562 std::vector<u16> ClientInterface::getClientIDs(ClientState min_state)
564 std::vector<u16> reply;
565 JMutexAutoLock clientslock(m_clients_mutex);
567 for(std::map<u16, RemoteClient*>::iterator
568 i = m_clients.begin();
569 i != m_clients.end(); ++i)
571 if (i->second->getState() >= min_state)
572 reply.push_back(i->second->peer_id);
578 std::vector<std::string> ClientInterface::getPlayerNames()
580 return m_clients_names;
584 void ClientInterface::step(float dtime)
586 m_print_info_timer += dtime;
587 if(m_print_info_timer >= 30.0)
589 m_print_info_timer = 0.0;
594 void ClientInterface::UpdatePlayerList()
598 std::vector<u16> clients = getClientIDs();
599 m_clients_names.clear();
603 infostream<<"Players:"<<std::endl;
605 for(std::vector<u16>::iterator
607 i != clients.end(); ++i) {
608 Player *player = m_env->getPlayer(*i);
613 infostream << "* " << player->getName() << "\t";
616 JMutexAutoLock clientslock(m_clients_mutex);
617 RemoteClient* client = lockedGetClientNoEx(*i);
619 client->PrintInfo(infostream);
622 m_clients_names.push_back(player->getName());
627 void ClientInterface::send(u16 peer_id, u8 channelnum,
628 NetworkPacket* pkt, bool reliable)
630 m_con->Send(peer_id, channelnum, pkt, reliable);
633 void ClientInterface::sendToAll(u16 channelnum,
634 NetworkPacket* pkt, bool reliable)
636 JMutexAutoLock clientslock(m_clients_mutex);
637 for(std::map<u16, RemoteClient*>::iterator
638 i = m_clients.begin();
639 i != m_clients.end(); ++i) {
640 RemoteClient *client = i->second;
642 if (client->net_proto_version != 0) {
643 m_con->Send(client->peer_id, channelnum, pkt, reliable);
648 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
650 JMutexAutoLock clientslock(m_clients_mutex);
651 std::map<u16, RemoteClient*>::iterator n;
652 n = m_clients.find(peer_id);
653 // The client may not exist; clients are immediately removed if their
654 // access is denied, and this event occurs later then.
655 if(n == m_clients.end())
658 if (n->second->getState() >= state_min)
664 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
666 std::map<u16, RemoteClient*>::iterator n;
667 n = m_clients.find(peer_id);
668 // The client may not exist; clients are immediately removed if their
669 // access is denied, and this event occurs later then.
670 if(n == m_clients.end())
673 if (n->second->getState() >= state_min)
679 ClientState ClientInterface::getClientState(u16 peer_id)
681 JMutexAutoLock clientslock(m_clients_mutex);
682 std::map<u16, RemoteClient*>::iterator n;
683 n = m_clients.find(peer_id);
684 // The client may not exist; clients are immediately removed if their
685 // access is denied, and this event occurs later then.
686 if(n == m_clients.end())
689 return n->second->getState();
692 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
694 JMutexAutoLock clientslock(m_clients_mutex);
695 std::map<u16, RemoteClient*>::iterator n;
696 n = m_clients.find(peer_id);
697 // The client may not exist; clients are immediately removed if their
698 // access is denied, and this event occurs later then.
699 if(n != m_clients.end())
700 n->second->setName(name);
703 void ClientInterface::DeleteClient(u16 peer_id)
705 JMutexAutoLock conlock(m_clients_mutex);
708 std::map<u16, RemoteClient*>::iterator n;
709 n = m_clients.find(peer_id);
710 // The client may not exist; clients are immediately removed if their
711 // access is denied, and this event occurs later then.
712 if(n == m_clients.end())
716 Mark objects to be not known by the client
718 //TODO this should be done by client destructor!!!
719 RemoteClient *client = n->second;
721 for(std::set<u16>::iterator
722 i = client->m_known_objects.begin();
723 i != client->m_known_objects.end(); ++i)
727 ServerActiveObject* obj = m_env->getActiveObject(id);
729 if(obj && obj->m_known_by_count > 0)
730 obj->m_known_by_count--;
734 delete m_clients[peer_id];
735 m_clients.erase(peer_id);
738 void ClientInterface::CreateClient(u16 peer_id)
740 JMutexAutoLock conlock(m_clients_mutex);
743 std::map<u16, RemoteClient*>::iterator n;
744 n = m_clients.find(peer_id);
745 // The client shouldn't already exist
746 if(n != m_clients.end()) return;
749 RemoteClient *client = new RemoteClient();
750 client->peer_id = peer_id;
751 m_clients[client->peer_id] = client;
754 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
757 JMutexAutoLock clientlock(m_clients_mutex);
760 std::map<u16, RemoteClient*>::iterator n;
761 n = m_clients.find(peer_id);
763 // No client to deliver event
764 if (n == m_clients.end())
766 n->second->notifyEvent(event);
769 if ((event == CSE_SetClientReady) ||
770 (event == CSE_Disconnect) ||
771 (event == CSE_SetDenied))
777 u16 ClientInterface::getProtocolVersion(u16 peer_id)
779 JMutexAutoLock conlock(m_clients_mutex);
782 std::map<u16, RemoteClient*>::iterator n;
783 n = m_clients.find(peer_id);
785 // No client to get version
786 if (n == m_clients.end())
789 return n->second->net_proto_version;
792 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
794 JMutexAutoLock conlock(m_clients_mutex);
797 std::map<u16, RemoteClient*>::iterator n;
798 n = m_clients.find(peer_id);
800 // No client to set versions
801 if (n == m_clients.end())
804 n->second->setVersionInfo(major,minor,patch,full);