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];
55 void RemoteClient::ResendBlockIfOnWire(v3s16 p)
57 // if this block is on wire, mark it for sending again as soon as possible
58 if (m_blocks_sending.find(p) != m_blocks_sending.end()) {
63 void RemoteClient::GetNextBlocks(
64 ServerEnvironment *env,
65 EmergeManager * emerge,
67 std::vector<PrioritySortedBlockTransfer> &dest)
69 DSTACK(__FUNCTION_NAME);
73 m_nothing_to_send_pause_timer -= dtime;
74 m_nearest_unsent_reset_timer += dtime;
76 if(m_nothing_to_send_pause_timer >= 0)
79 Player *player = env->getPlayer(peer_id);
80 // This can happen sometimes; clients and players are not in perfect sync.
84 // Won't send anything if already sending
85 if(m_blocks_sending.size() >= g_settings->getU16
86 ("max_simultaneous_block_sends_per_client"))
88 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
92 v3f playerpos = player->getPosition();
93 v3f playerspeed = player->getSpeed();
94 v3f playerspeeddir(0,0,0);
95 if(playerspeed.getLength() > 1.0*BS)
96 playerspeeddir = playerspeed / playerspeed.getLength();
97 // Predict to next block
98 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
100 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
102 v3s16 center = getNodeBlockPos(center_nodepos);
104 // Camera position and direction
105 v3f camera_pos = player->getEyePosition();
106 v3f camera_dir = v3f(0,0,1);
107 camera_dir.rotateYZBy(player->getPitch());
108 camera_dir.rotateXZBy(player->getYaw());
110 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
111 <<camera_dir.Z<<")"<<std::endl;*/
114 Get the starting value of the block finder radius.
117 if(m_last_center != center)
119 m_nearest_unsent_d = 0;
120 m_last_center = center;
123 /*infostream<<"m_nearest_unsent_reset_timer="
124 <<m_nearest_unsent_reset_timer<<std::endl;*/
126 // Reset periodically to workaround for some bugs or stuff
127 if(m_nearest_unsent_reset_timer > 20.0)
129 m_nearest_unsent_reset_timer = 0;
130 m_nearest_unsent_d = 0;
131 //infostream<<"Resetting m_nearest_unsent_d for "
132 // <<server->getPlayerName(peer_id)<<std::endl;
135 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
136 s16 d_start = m_nearest_unsent_d;
138 //infostream<<"d_start="<<d_start<<std::endl;
140 u16 max_simul_sends_setting = g_settings->getU16
141 ("max_simultaneous_block_sends_per_client");
142 u16 max_simul_sends_usually = max_simul_sends_setting;
145 Check the time from last addNode/removeNode.
147 Decrease send rate if player is building stuff.
149 m_time_from_building += dtime;
150 if(m_time_from_building < g_settings->getFloat(
151 "full_block_send_enable_min_time_from_building"))
153 max_simul_sends_usually
154 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
158 Number of blocks sending + number of blocks selected for sending
160 u32 num_blocks_selected = m_blocks_sending.size();
163 next time d will be continued from the d from which the nearest
164 unsent block was found this time.
166 This is because not necessarily any of the blocks found this
167 time are actually sent.
169 s32 new_nearest_unsent_d = -1;
171 const s16 full_d_max = g_settings->getS16("max_block_send_distance");
172 s16 d_max = full_d_max;
173 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
175 // Don't loop very much at a time
176 s16 max_d_increment_at_time = 2;
177 if(d_max > d_start + max_d_increment_at_time)
178 d_max = d_start + max_d_increment_at_time;
180 s32 nearest_emerged_d = -1;
181 s32 nearest_emergefull_d = -1;
182 s32 nearest_sent_d = -1;
183 bool queue_is_full = false;
186 for(d = d_start; d <= d_max; d++)
189 Get the border/face dot coordinates of a "d-radiused"
192 std::list<v3s16> list;
193 getFacePositions(list, d);
195 std::list<v3s16>::iterator li;
196 for(li=list.begin(); li!=list.end(); ++li)
198 v3s16 p = *li + center;
202 - Don't allow too many simultaneous transfers
203 - EXCEPT when the blocks are very close
205 Also, don't send blocks that are already flying.
208 // Start with the usual maximum
209 u16 max_simul_dynamic = max_simul_sends_usually;
211 // If block is very close, allow full maximum
212 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
213 max_simul_dynamic = max_simul_sends_setting;
215 // Don't select too many blocks for sending
216 if(num_blocks_selected >= max_simul_dynamic)
218 queue_is_full = true;
219 goto queue_full_break;
222 // Don't send blocks that are currently being transferred
223 if(m_blocks_sending.find(p) != m_blocks_sending.end())
229 if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
230 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
231 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
232 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
233 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
234 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
237 // If this is true, inexistent block will be made from scratch
238 bool generate = d <= d_max_gen;
241 /*// Limit the generating area vertically to 2/3
242 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
245 // Limit the send area vertically to 1/2
246 if(abs(p.Y - center.Y) > full_d_max / 2)
251 Don't generate or send if not in sight
252 FIXME This only works if the client uses a small enough
253 FOV setting. The default of 72 degrees is fine.
256 float camera_fov = (72.0*M_PI/180) * 4./3.;
257 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
263 Don't send already sent blocks
266 if(m_blocks_sent.find(p) != m_blocks_sent.end())
273 Check if map has this block
275 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
277 bool surely_not_found_on_disk = false;
278 bool block_is_invalid = false;
281 // Reset usage timer, this block will be of use in the future.
282 block->resetUsageTimer();
284 // Block is dummy if data doesn't exist.
285 // It means it has been not found from disk and not generated
288 surely_not_found_on_disk = true;
291 // Block is valid if lighting is up-to-date and data exists
292 if(block->isValid() == false)
294 block_is_invalid = true;
297 if(block->isGenerated() == false)
298 block_is_invalid = true;
301 If block is not close, don't send it unless it is near
304 Block is near ground level if night-time mesh
305 differs from day-time mesh.
309 if(block->getDayNightDiff() == false)
315 If block has been marked to not exist on disk (dummy)
316 and generating new ones is not wanted, skip block.
318 if(generate == false && surely_not_found_on_disk == true)
325 Add inexistent block to emerge queue.
327 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
329 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
330 if (nearest_emerged_d == -1)
331 nearest_emerged_d = d;
333 if (nearest_emergefull_d == -1)
334 nearest_emergefull_d = d;
335 goto queue_full_break;
342 if(nearest_sent_d == -1)
346 Add block to send queue
348 PrioritySortedBlockTransfer q((float)d, p, peer_id);
352 num_blocks_selected += 1;
357 // If nothing was found for sending and nothing was queued for
358 // emerging, continue next time browsing from here
359 if(nearest_emerged_d != -1){
360 new_nearest_unsent_d = nearest_emerged_d;
361 } else if(nearest_emergefull_d != -1){
362 new_nearest_unsent_d = nearest_emergefull_d;
364 if(d > g_settings->getS16("max_block_send_distance")){
365 new_nearest_unsent_d = 0;
366 m_nothing_to_send_pause_timer = 2.0;
368 if(nearest_sent_d != -1)
369 new_nearest_unsent_d = nearest_sent_d;
371 new_nearest_unsent_d = d;
375 if(new_nearest_unsent_d != -1)
376 m_nearest_unsent_d = new_nearest_unsent_d;
379 void RemoteClient::GotBlock(v3s16 p)
381 if(m_blocks_sending.find(p) != m_blocks_sending.end())
382 m_blocks_sending.erase(p);
385 m_excess_gotblocks++;
387 m_blocks_sent.insert(p);
390 void RemoteClient::SentBlock(v3s16 p)
392 if(m_blocks_sending.find(p) == m_blocks_sending.end())
393 m_blocks_sending[p] = 0.0;
395 infostream<<"RemoteClient::SentBlock(): Sent block"
396 " already in m_blocks_sending"<<std::endl;
399 void RemoteClient::SetBlockNotSent(v3s16 p)
401 m_nearest_unsent_d = 0;
403 if(m_blocks_sending.find(p) != m_blocks_sending.end())
404 m_blocks_sending.erase(p);
405 if(m_blocks_sent.find(p) != m_blocks_sent.end())
406 m_blocks_sent.erase(p);
409 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
411 m_nearest_unsent_d = 0;
413 for(std::map<v3s16, MapBlock*>::iterator
415 i != blocks.end(); ++i)
419 if(m_blocks_sending.find(p) != m_blocks_sending.end())
420 m_blocks_sending.erase(p);
421 if(m_blocks_sent.find(p) != m_blocks_sent.end())
422 m_blocks_sent.erase(p);
426 void RemoteClient::notifyEvent(ClientStateEvent event)
428 std::ostringstream myerror;
432 //intentionally do nothing
438 m_state = CS_InitSent;
441 m_state = CS_Disconnecting;
446 /* GotInit2 SetDefinitionsSent SetMediaSent */
448 myerror << "Created: Invalid client state transition! " << event;
449 throw ClientStateError(myerror.str());
453 /* don't do anything if in denied state */
459 confirmSerializationVersion();
460 m_state = CS_InitDone;
463 m_state = CS_Disconnecting;
469 /* Init SetDefinitionsSent SetMediaSent */
471 myerror << "InitSent: Invalid client state transition! " << event;
472 throw ClientStateError(myerror.str());
479 case CSE_SetDefinitionsSent:
480 m_state = CS_DefinitionsSent;
483 m_state = CS_Disconnecting;
489 /* Init GotInit2 SetMediaSent */
491 myerror << "InitDone: Invalid client state transition! " << event;
492 throw ClientStateError(myerror.str());
495 case CS_DefinitionsSent:
498 case CSE_SetClientReady:
502 m_state = CS_Disconnecting;
507 /* Init GotInit2 SetDefinitionsSent */
509 myerror << "DefinitionsSent: Invalid client state transition! " << event;
510 throw ClientStateError(myerror.str());
520 m_state = CS_Disconnecting;
522 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
524 myerror << "Active: Invalid client state transition! " << event;
525 throw ClientStateError(myerror.str());
529 case CS_Disconnecting:
530 /* we are already disconnecting */
535 u32 RemoteClient::uptime()
537 return getTime(PRECISION_SECONDS) - m_connection_time;
540 ClientInterface::ClientInterface(con::Connection* con)
544 m_print_info_timer(0.0)
548 ClientInterface::~ClientInterface()
554 JMutexAutoLock clientslock(m_clients_mutex);
556 for(std::map<u16, RemoteClient*>::iterator
557 i = m_clients.begin();
558 i != m_clients.end(); ++i)
567 std::list<u16> ClientInterface::getClientIDs(ClientState min_state)
569 std::list<u16> reply;
570 JMutexAutoLock clientslock(m_clients_mutex);
572 for(std::map<u16, RemoteClient*>::iterator
573 i = m_clients.begin();
574 i != m_clients.end(); ++i)
576 if (i->second->getState() >= min_state)
577 reply.push_back(i->second->peer_id);
583 std::vector<std::string> ClientInterface::getPlayerNames()
585 return m_clients_names;
589 void ClientInterface::step(float dtime)
591 m_print_info_timer += dtime;
592 if(m_print_info_timer >= 30.0)
594 m_print_info_timer = 0.0;
599 void ClientInterface::UpdatePlayerList()
603 std::list<u16> clients = getClientIDs();
604 m_clients_names.clear();
607 if(clients.size() != 0)
608 infostream<<"Players:"<<std::endl;
609 for(std::list<u16>::iterator
611 i != clients.end(); ++i)
613 Player *player = m_env->getPlayer(*i);
616 infostream<<"* "<<player->getName()<<"\t";
619 JMutexAutoLock clientslock(m_clients_mutex);
620 RemoteClient* client = lockedGetClientNoEx(*i);
622 client->PrintInfo(infostream);
624 m_clients_names.push_back(player->getName());
629 void ClientInterface::send(u16 peer_id,u8 channelnum,
630 SharedBuffer<u8> data, bool reliable)
632 m_con->Send(peer_id, channelnum, data, reliable);
635 void ClientInterface::sendToAll(u16 channelnum,
636 SharedBuffer<u8> data, bool reliable)
638 JMutexAutoLock clientslock(m_clients_mutex);
639 for(std::map<u16, RemoteClient*>::iterator
640 i = m_clients.begin();
641 i != m_clients.end(); ++i)
643 RemoteClient *client = i->second;
645 if (client->net_proto_version != 0)
647 m_con->Send(client->peer_id, channelnum, data, reliable);
652 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
654 JMutexAutoLock clientslock(m_clients_mutex);
655 std::map<u16, RemoteClient*>::iterator n;
656 n = m_clients.find(peer_id);
657 // The client may not exist; clients are immediately removed if their
658 // access is denied, and this event occurs later then.
659 if(n == m_clients.end())
662 if (n->second->getState() >= state_min)
668 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
670 std::map<u16, RemoteClient*>::iterator n;
671 n = m_clients.find(peer_id);
672 // The client may not exist; clients are immediately removed if their
673 // access is denied, and this event occurs later then.
674 if(n == m_clients.end())
677 if (n->second->getState() >= state_min)
683 ClientState ClientInterface::getClientState(u16 peer_id)
685 JMutexAutoLock clientslock(m_clients_mutex);
686 std::map<u16, RemoteClient*>::iterator n;
687 n = m_clients.find(peer_id);
688 // The client may not exist; clients are immediately removed if their
689 // access is denied, and this event occurs later then.
690 if(n == m_clients.end())
693 return n->second->getState();
696 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
698 JMutexAutoLock clientslock(m_clients_mutex);
699 std::map<u16, RemoteClient*>::iterator n;
700 n = m_clients.find(peer_id);
701 // The client may not exist; clients are immediately removed if their
702 // access is denied, and this event occurs later then.
703 if(n != m_clients.end())
704 n->second->setName(name);
707 void ClientInterface::DeleteClient(u16 peer_id)
709 JMutexAutoLock conlock(m_clients_mutex);
712 std::map<u16, RemoteClient*>::iterator n;
713 n = m_clients.find(peer_id);
714 // The client may not exist; clients are immediately removed if their
715 // access is denied, and this event occurs later then.
716 if(n == m_clients.end())
720 Mark objects to be not known by the client
722 //TODO this should be done by client destructor!!!
723 RemoteClient *client = n->second;
725 for(std::set<u16>::iterator
726 i = client->m_known_objects.begin();
727 i != client->m_known_objects.end(); ++i)
731 ServerActiveObject* obj = m_env->getActiveObject(id);
733 if(obj && obj->m_known_by_count > 0)
734 obj->m_known_by_count--;
738 delete m_clients[peer_id];
739 m_clients.erase(peer_id);
742 void ClientInterface::CreateClient(u16 peer_id)
744 JMutexAutoLock conlock(m_clients_mutex);
747 std::map<u16, RemoteClient*>::iterator n;
748 n = m_clients.find(peer_id);
749 // The client shouldn't already exist
750 if(n != m_clients.end()) return;
753 RemoteClient *client = new RemoteClient();
754 client->peer_id = peer_id;
755 m_clients[client->peer_id] = client;
758 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
761 JMutexAutoLock clientlock(m_clients_mutex);
764 std::map<u16, RemoteClient*>::iterator n;
765 n = m_clients.find(peer_id);
767 // No client to deliver event
768 if (n == m_clients.end())
770 n->second->notifyEvent(event);
773 if ((event == CSE_SetClientReady) ||
774 (event == CSE_Disconnect) ||
775 (event == CSE_SetDenied))
781 u16 ClientInterface::getProtocolVersion(u16 peer_id)
783 JMutexAutoLock conlock(m_clients_mutex);
786 std::map<u16, RemoteClient*>::iterator n;
787 n = m_clients.find(peer_id);
789 // No client to get version
790 if (n == m_clients.end())
793 return n->second->net_proto_version;
796 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
798 JMutexAutoLock conlock(m_clients_mutex);
801 std::map<u16, RemoteClient*>::iterator n;
802 n = m_clients.find(peer_id);
804 // No client to set versions
805 if (n == m_clients.end())
808 n->second->setVersionInfo(major,minor,patch,full);