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"
26 #include "connection.h"
27 #include "environment.h"
30 #include "serverobject.h" // TODO this is used for cleanup of only
32 #include "util/numeric.h"
33 #include "util/mathconstants.h"
35 #include "main.h" // for g_settings
37 const char *ClientInterface::statenames[] = {
50 std::string ClientInterface::state2Name(ClientState state)
52 return statenames[state];
56 void RemoteClient::GetNextBlocks(
57 ServerEnvironment *env,
58 EmergeManager * emerge,
60 std::vector<PrioritySortedBlockTransfer> &dest)
62 DSTACK(__FUNCTION_NAME);
66 m_nothing_to_send_pause_timer -= dtime;
67 m_nearest_unsent_reset_timer += dtime;
69 if(m_nothing_to_send_pause_timer >= 0)
72 Player *player = env->getPlayer(peer_id);
73 // This can happen sometimes; clients and players are not in perfect sync.
77 // Won't send anything if already sending
78 if(m_blocks_sending.size() >= g_settings->getU16
79 ("max_simultaneous_block_sends_per_client"))
81 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
85 v3f playerpos = player->getPosition();
86 v3f playerspeed = player->getSpeed();
87 v3f playerspeeddir(0,0,0);
88 if(playerspeed.getLength() > 1.0*BS)
89 playerspeeddir = playerspeed / playerspeed.getLength();
90 // Predict to next block
91 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
93 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
95 v3s16 center = getNodeBlockPos(center_nodepos);
97 // Camera position and direction
98 v3f camera_pos = player->getEyePosition();
99 v3f camera_dir = v3f(0,0,1);
100 camera_dir.rotateYZBy(player->getPitch());
101 camera_dir.rotateXZBy(player->getYaw());
103 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
104 <<camera_dir.Z<<")"<<std::endl;*/
107 Get the starting value of the block finder radius.
110 if(m_last_center != center)
112 m_nearest_unsent_d = 0;
113 m_last_center = center;
116 /*infostream<<"m_nearest_unsent_reset_timer="
117 <<m_nearest_unsent_reset_timer<<std::endl;*/
119 // Reset periodically to workaround for some bugs or stuff
120 if(m_nearest_unsent_reset_timer > 20.0)
122 m_nearest_unsent_reset_timer = 0;
123 m_nearest_unsent_d = 0;
124 //infostream<<"Resetting m_nearest_unsent_d for "
125 // <<server->getPlayerName(peer_id)<<std::endl;
128 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
129 s16 d_start = m_nearest_unsent_d;
131 //infostream<<"d_start="<<d_start<<std::endl;
133 u16 max_simul_sends_setting = g_settings->getU16
134 ("max_simultaneous_block_sends_per_client");
135 u16 max_simul_sends_usually = max_simul_sends_setting;
138 Check the time from last addNode/removeNode.
140 Decrease send rate if player is building stuff.
142 m_time_from_building += dtime;
143 if(m_time_from_building < g_settings->getFloat(
144 "full_block_send_enable_min_time_from_building"))
146 max_simul_sends_usually
147 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
151 Number of blocks sending + number of blocks selected for sending
153 u32 num_blocks_selected = m_blocks_sending.size();
156 next time d will be continued from the d from which the nearest
157 unsent block was found this time.
159 This is because not necessarily any of the blocks found this
160 time are actually sent.
162 s32 new_nearest_unsent_d = -1;
164 const s16 full_d_max = g_settings->getS16("max_block_send_distance");
165 s16 d_max = full_d_max;
166 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
168 // Don't loop very much at a time
169 s16 max_d_increment_at_time = 2;
170 if(d_max > d_start + max_d_increment_at_time)
171 d_max = d_start + max_d_increment_at_time;
173 s32 nearest_emerged_d = -1;
174 s32 nearest_emergefull_d = -1;
175 s32 nearest_sent_d = -1;
176 bool queue_is_full = false;
179 for(d = d_start; d <= d_max; d++)
182 Get the border/face dot coordinates of a "d-radiused"
185 std::list<v3s16> list;
186 getFacePositions(list, d);
188 std::list<v3s16>::iterator li;
189 for(li=list.begin(); li!=list.end(); ++li)
191 v3s16 p = *li + center;
195 - Don't allow too many simultaneous transfers
196 - EXCEPT when the blocks are very close
198 Also, don't send blocks that are already flying.
201 // Start with the usual maximum
202 u16 max_simul_dynamic = max_simul_sends_usually;
204 // If block is very close, allow full maximum
205 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
206 max_simul_dynamic = max_simul_sends_setting;
208 // Don't select too many blocks for sending
209 if(num_blocks_selected >= max_simul_dynamic)
211 queue_is_full = true;
212 goto queue_full_break;
215 // Don't send blocks that are currently being transferred
216 if(m_blocks_sending.find(p) != m_blocks_sending.end())
222 if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
223 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
224 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
225 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
226 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
227 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
230 // If this is true, inexistent block will be made from scratch
231 bool generate = d <= d_max_gen;
234 /*// Limit the generating area vertically to 2/3
235 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
238 // Limit the send area vertically to 1/2
239 if(abs(p.Y - center.Y) > full_d_max / 2)
244 Don't generate or send if not in sight
245 FIXME This only works if the client uses a small enough
246 FOV setting. The default of 72 degrees is fine.
249 float camera_fov = (72.0*M_PI/180) * 4./3.;
250 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
256 Don't send already sent blocks
259 if(m_blocks_sent.find(p) != m_blocks_sent.end())
266 Check if map has this block
268 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
270 bool surely_not_found_on_disk = false;
271 bool block_is_invalid = false;
274 // Reset usage timer, this block will be of use in the future.
275 block->resetUsageTimer();
277 // Block is dummy if data doesn't exist.
278 // It means it has been not found from disk and not generated
281 surely_not_found_on_disk = true;
284 // Block is valid if lighting is up-to-date and data exists
285 if(block->isValid() == false)
287 block_is_invalid = true;
290 if(block->isGenerated() == false)
291 block_is_invalid = true;
294 If block is not close, don't send it unless it is near
297 Block is near ground level if night-time mesh
298 differs from day-time mesh.
302 if(block->getDayNightDiff() == false)
308 If block has been marked to not exist on disk (dummy)
309 and generating new ones is not wanted, skip block.
311 if(generate == false && surely_not_found_on_disk == true)
318 Add inexistent block to emerge queue.
320 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
322 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
323 if (nearest_emerged_d == -1)
324 nearest_emerged_d = d;
326 if (nearest_emergefull_d == -1)
327 nearest_emergefull_d = d;
328 goto queue_full_break;
335 if(nearest_sent_d == -1)
339 Add block to send queue
341 PrioritySortedBlockTransfer q((float)d, p, peer_id);
345 num_blocks_selected += 1;
350 // If nothing was found for sending and nothing was queued for
351 // emerging, continue next time browsing from here
352 if(nearest_emerged_d != -1){
353 new_nearest_unsent_d = nearest_emerged_d;
354 } else if(nearest_emergefull_d != -1){
355 new_nearest_unsent_d = nearest_emergefull_d;
357 if(d > g_settings->getS16("max_block_send_distance")){
358 new_nearest_unsent_d = 0;
359 m_nothing_to_send_pause_timer = 2.0;
361 if(nearest_sent_d != -1)
362 new_nearest_unsent_d = nearest_sent_d;
364 new_nearest_unsent_d = d;
368 if(new_nearest_unsent_d != -1)
369 m_nearest_unsent_d = new_nearest_unsent_d;
372 void RemoteClient::GotBlock(v3s16 p)
374 if(m_blocks_sending.find(p) != m_blocks_sending.end())
375 m_blocks_sending.erase(p);
378 m_excess_gotblocks++;
380 m_blocks_sent.insert(p);
383 void RemoteClient::SentBlock(v3s16 p)
385 if(m_blocks_sending.find(p) == m_blocks_sending.end())
386 m_blocks_sending[p] = 0.0;
388 infostream<<"RemoteClient::SentBlock(): Sent block"
389 " already in m_blocks_sending"<<std::endl;
392 void RemoteClient::SetBlockNotSent(v3s16 p)
394 m_nearest_unsent_d = 0;
396 if(m_blocks_sending.find(p) != m_blocks_sending.end())
397 m_blocks_sending.erase(p);
398 if(m_blocks_sent.find(p) != m_blocks_sent.end())
399 m_blocks_sent.erase(p);
402 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
404 m_nearest_unsent_d = 0;
406 for(std::map<v3s16, MapBlock*>::iterator
408 i != blocks.end(); ++i)
412 if(m_blocks_sending.find(p) != m_blocks_sending.end())
413 m_blocks_sending.erase(p);
414 if(m_blocks_sent.find(p) != m_blocks_sent.end())
415 m_blocks_sent.erase(p);
419 void RemoteClient::notifyEvent(ClientStateEvent event)
421 std::ostringstream myerror;
425 //intentionally do nothing
431 m_state = CS_InitSent;
434 m_state = CS_Disconnecting;
439 /* GotInit2 SetDefinitionsSent SetMediaSent */
441 myerror << "Created: Invalid client state transition! " << event;
442 throw ClientStateError(myerror.str());
446 /* don't do anything if in denied state */
452 confirmSerializationVersion();
453 m_state = CS_InitDone;
456 m_state = CS_Disconnecting;
462 /* Init SetDefinitionsSent SetMediaSent */
464 myerror << "InitSent: Invalid client state transition! " << event;
465 throw ClientStateError(myerror.str());
472 case CSE_SetDefinitionsSent:
473 m_state = CS_DefinitionsSent;
476 m_state = CS_Disconnecting;
482 /* Init GotInit2 SetMediaSent */
484 myerror << "InitDone: Invalid client state transition! " << event;
485 throw ClientStateError(myerror.str());
488 case CS_DefinitionsSent:
491 case CSE_SetClientReady:
495 m_state = CS_Disconnecting;
500 /* Init GotInit2 SetDefinitionsSent */
502 myerror << "DefinitionsSent: Invalid client state transition! " << event;
503 throw ClientStateError(myerror.str());
513 m_state = CS_Disconnecting;
515 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
517 myerror << "Active: Invalid client state transition! " << event;
518 throw ClientStateError(myerror.str());
522 case CS_Disconnecting:
523 /* we are already disconnecting */
528 u32 RemoteClient::uptime()
530 return getTime(PRECISION_SECONDS) - m_connection_time;
533 ClientInterface::ClientInterface(con::Connection* con)
537 m_print_info_timer(0.0)
541 ClientInterface::~ClientInterface()
547 JMutexAutoLock clientslock(m_clients_mutex);
549 for(std::map<u16, RemoteClient*>::iterator
550 i = m_clients.begin();
551 i != m_clients.end(); ++i)
560 std::list<u16> ClientInterface::getClientIDs(ClientState min_state)
562 std::list<u16> reply;
563 JMutexAutoLock clientslock(m_clients_mutex);
565 for(std::map<u16, RemoteClient*>::iterator
566 i = m_clients.begin();
567 i != m_clients.end(); ++i)
569 if (i->second->getState() >= min_state)
570 reply.push_back(i->second->peer_id);
576 std::vector<std::string> ClientInterface::getPlayerNames()
578 return m_clients_names;
582 void ClientInterface::step(float dtime)
584 m_print_info_timer += dtime;
585 if(m_print_info_timer >= 30.0)
587 m_print_info_timer = 0.0;
592 void ClientInterface::UpdatePlayerList()
596 std::list<u16> clients = getClientIDs();
597 m_clients_names.clear();
600 if(clients.size() != 0)
601 infostream<<"Players:"<<std::endl;
602 for(std::list<u16>::iterator
604 i != clients.end(); ++i)
606 Player *player = m_env->getPlayer(*i);
609 infostream<<"* "<<player->getName()<<"\t";
612 JMutexAutoLock clientslock(m_clients_mutex);
613 RemoteClient* client = lockedGetClientNoEx(*i);
615 client->PrintInfo(infostream);
617 m_clients_names.push_back(player->getName());
622 void ClientInterface::send(u16 peer_id,u8 channelnum,
623 SharedBuffer<u8> data, bool reliable)
625 m_con->Send(peer_id, channelnum, data, reliable);
628 void ClientInterface::sendToAll(u16 channelnum,
629 SharedBuffer<u8> data, bool reliable)
631 JMutexAutoLock clientslock(m_clients_mutex);
632 for(std::map<u16, RemoteClient*>::iterator
633 i = m_clients.begin();
634 i != m_clients.end(); ++i)
636 RemoteClient *client = i->second;
638 if (client->net_proto_version != 0)
640 m_con->Send(client->peer_id, channelnum, data, reliable);
645 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
647 JMutexAutoLock clientslock(m_clients_mutex);
648 std::map<u16, RemoteClient*>::iterator n;
649 n = m_clients.find(peer_id);
650 // The client may not exist; clients are immediately removed if their
651 // access is denied, and this event occurs later then.
652 if(n == m_clients.end())
655 if (n->second->getState() >= state_min)
661 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
663 std::map<u16, RemoteClient*>::iterator n;
664 n = m_clients.find(peer_id);
665 // The client may not exist; clients are immediately removed if their
666 // access is denied, and this event occurs later then.
667 if(n == m_clients.end())
670 if (n->second->getState() >= state_min)
676 ClientState ClientInterface::getClientState(u16 peer_id)
678 JMutexAutoLock clientslock(m_clients_mutex);
679 std::map<u16, RemoteClient*>::iterator n;
680 n = m_clients.find(peer_id);
681 // The client may not exist; clients are immediately removed if their
682 // access is denied, and this event occurs later then.
683 if(n == m_clients.end())
686 return n->second->getState();
689 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
691 JMutexAutoLock clientslock(m_clients_mutex);
692 std::map<u16, RemoteClient*>::iterator n;
693 n = m_clients.find(peer_id);
694 // The client may not exist; clients are immediately removed if their
695 // access is denied, and this event occurs later then.
696 if(n != m_clients.end())
697 n->second->setName(name);
700 void ClientInterface::DeleteClient(u16 peer_id)
702 JMutexAutoLock conlock(m_clients_mutex);
705 std::map<u16, RemoteClient*>::iterator n;
706 n = m_clients.find(peer_id);
707 // The client may not exist; clients are immediately removed if their
708 // access is denied, and this event occurs later then.
709 if(n == m_clients.end())
713 Mark objects to be not known by the client
715 //TODO this should be done by client destructor!!!
716 RemoteClient *client = n->second;
718 for(std::set<u16>::iterator
719 i = client->m_known_objects.begin();
720 i != client->m_known_objects.end(); ++i)
724 ServerActiveObject* obj = m_env->getActiveObject(id);
726 if(obj && obj->m_known_by_count > 0)
727 obj->m_known_by_count--;
731 delete m_clients[peer_id];
732 m_clients.erase(peer_id);
735 void ClientInterface::CreateClient(u16 peer_id)
737 JMutexAutoLock conlock(m_clients_mutex);
740 std::map<u16, RemoteClient*>::iterator n;
741 n = m_clients.find(peer_id);
742 // The client shouldn't already exist
743 if(n != m_clients.end()) return;
746 RemoteClient *client = new RemoteClient();
747 client->peer_id = peer_id;
748 m_clients[client->peer_id] = client;
751 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
754 JMutexAutoLock clientlock(m_clients_mutex);
757 std::map<u16, RemoteClient*>::iterator n;
758 n = m_clients.find(peer_id);
760 // No client to deliver event
761 if (n == m_clients.end())
763 n->second->notifyEvent(event);
766 if ((event == CSE_SetClientReady) ||
767 (event == CSE_Disconnect) ||
768 (event == CSE_SetDenied))
774 u16 ClientInterface::getProtocolVersion(u16 peer_id)
776 JMutexAutoLock conlock(m_clients_mutex);
779 std::map<u16, RemoteClient*>::iterator n;
780 n = m_clients.find(peer_id);
782 // No client to get version
783 if (n == m_clients.end())
786 return n->second->net_proto_version;
789 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
791 JMutexAutoLock conlock(m_clients_mutex);
794 std::map<u16, RemoteClient*>::iterator n;
795 n = m_clients.find(peer_id);
797 // No client to set versions
798 if (n == m_clients.end())
801 n->second->setVersionInfo(major,minor,patch,full);