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 void RemoteClient::GetNextBlocks(
38 ServerEnvironment *env,
39 EmergeManager * emerge,
41 std::vector<PrioritySortedBlockTransfer> &dest)
43 DSTACK(__FUNCTION_NAME);
47 m_nothing_to_send_pause_timer -= dtime;
48 m_nearest_unsent_reset_timer += dtime;
50 if(m_nothing_to_send_pause_timer >= 0)
53 Player *player = env->getPlayer(peer_id);
54 // This can happen sometimes; clients and players are not in perfect sync.
58 // Won't send anything if already sending
59 if(m_blocks_sending.size() >= g_settings->getU16
60 ("max_simultaneous_block_sends_per_client"))
62 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
66 v3f playerpos = player->getPosition();
67 v3f playerspeed = player->getSpeed();
68 v3f playerspeeddir(0,0,0);
69 if(playerspeed.getLength() > 1.0*BS)
70 playerspeeddir = playerspeed / playerspeed.getLength();
71 // Predict to next block
72 v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
74 v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
76 v3s16 center = getNodeBlockPos(center_nodepos);
78 // Camera position and direction
79 v3f camera_pos = player->getEyePosition();
80 v3f camera_dir = v3f(0,0,1);
81 camera_dir.rotateYZBy(player->getPitch());
82 camera_dir.rotateXZBy(player->getYaw());
84 /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
85 <<camera_dir.Z<<")"<<std::endl;*/
88 Get the starting value of the block finder radius.
91 if(m_last_center != center)
93 m_nearest_unsent_d = 0;
94 m_last_center = center;
97 /*infostream<<"m_nearest_unsent_reset_timer="
98 <<m_nearest_unsent_reset_timer<<std::endl;*/
100 // Reset periodically to workaround for some bugs or stuff
101 if(m_nearest_unsent_reset_timer > 20.0)
103 m_nearest_unsent_reset_timer = 0;
104 m_nearest_unsent_d = 0;
105 //infostream<<"Resetting m_nearest_unsent_d for "
106 // <<server->getPlayerName(peer_id)<<std::endl;
109 //s16 last_nearest_unsent_d = m_nearest_unsent_d;
110 s16 d_start = m_nearest_unsent_d;
112 //infostream<<"d_start="<<d_start<<std::endl;
114 u16 max_simul_sends_setting = g_settings->getU16
115 ("max_simultaneous_block_sends_per_client");
116 u16 max_simul_sends_usually = max_simul_sends_setting;
119 Check the time from last addNode/removeNode.
121 Decrease send rate if player is building stuff.
123 m_time_from_building += dtime;
124 if(m_time_from_building < g_settings->getFloat(
125 "full_block_send_enable_min_time_from_building"))
127 max_simul_sends_usually
128 = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
132 Number of blocks sending + number of blocks selected for sending
134 u32 num_blocks_selected = m_blocks_sending.size();
137 next time d will be continued from the d from which the nearest
138 unsent block was found this time.
140 This is because not necessarily any of the blocks found this
141 time are actually sent.
143 s32 new_nearest_unsent_d = -1;
145 const s16 full_d_max = g_settings->getS16("max_block_send_distance");
146 s16 d_max = full_d_max;
147 s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
149 // Don't loop very much at a time
150 s16 max_d_increment_at_time = 2;
151 if(d_max > d_start + max_d_increment_at_time)
152 d_max = d_start + max_d_increment_at_time;
154 s32 nearest_emerged_d = -1;
155 s32 nearest_emergefull_d = -1;
156 s32 nearest_sent_d = -1;
157 bool queue_is_full = false;
160 for(d = d_start; d <= d_max; d++)
163 Get the border/face dot coordinates of a "d-radiused"
166 std::list<v3s16> list;
167 getFacePositions(list, d);
169 std::list<v3s16>::iterator li;
170 for(li=list.begin(); li!=list.end(); ++li)
172 v3s16 p = *li + center;
176 - Don't allow too many simultaneous transfers
177 - EXCEPT when the blocks are very close
179 Also, don't send blocks that are already flying.
182 // Start with the usual maximum
183 u16 max_simul_dynamic = max_simul_sends_usually;
185 // If block is very close, allow full maximum
186 if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
187 max_simul_dynamic = max_simul_sends_setting;
189 // Don't select too many blocks for sending
190 if(num_blocks_selected >= max_simul_dynamic)
192 queue_is_full = true;
193 goto queue_full_break;
196 // Don't send blocks that are currently being transferred
197 if(m_blocks_sending.find(p) != m_blocks_sending.end())
203 if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
204 || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
205 || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
206 || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
207 || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
208 || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
211 // If this is true, inexistent block will be made from scratch
212 bool generate = d <= d_max_gen;
215 /*// Limit the generating area vertically to 2/3
216 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
219 // Limit the send area vertically to 1/2
220 if(abs(p.Y - center.Y) > full_d_max / 2)
225 Don't generate or send if not in sight
226 FIXME This only works if the client uses a small enough
227 FOV setting. The default of 72 degrees is fine.
230 float camera_fov = (72.0*M_PI/180) * 4./3.;
231 if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
237 Don't send already sent blocks
240 if(m_blocks_sent.find(p) != m_blocks_sent.end())
247 Check if map has this block
249 MapBlock *block = env->getMap().getBlockNoCreateNoEx(p);
251 bool surely_not_found_on_disk = false;
252 bool block_is_invalid = false;
255 // Reset usage timer, this block will be of use in the future.
256 block->resetUsageTimer();
258 // Block is dummy if data doesn't exist.
259 // It means it has been not found from disk and not generated
262 surely_not_found_on_disk = true;
265 // Block is valid if lighting is up-to-date and data exists
266 if(block->isValid() == false)
268 block_is_invalid = true;
271 if(block->isGenerated() == false)
272 block_is_invalid = true;
275 If block is not close, don't send it unless it is near
278 Block is near ground level if night-time mesh
279 differs from day-time mesh.
283 if(block->getDayNightDiff() == false)
289 If block has been marked to not exist on disk (dummy)
290 and generating new ones is not wanted, skip block.
292 if(generate == false && surely_not_found_on_disk == true)
299 Add inexistent block to emerge queue.
301 if(block == NULL || surely_not_found_on_disk || block_is_invalid)
303 if (emerge->enqueueBlockEmerge(peer_id, p, generate)) {
304 if (nearest_emerged_d == -1)
305 nearest_emerged_d = d;
307 if (nearest_emergefull_d == -1)
308 nearest_emergefull_d = d;
309 goto queue_full_break;
316 if(nearest_sent_d == -1)
320 Add block to send queue
322 PrioritySortedBlockTransfer q((float)d, p, peer_id);
326 num_blocks_selected += 1;
331 // If nothing was found for sending and nothing was queued for
332 // emerging, continue next time browsing from here
333 if(nearest_emerged_d != -1){
334 new_nearest_unsent_d = nearest_emerged_d;
335 } else if(nearest_emergefull_d != -1){
336 new_nearest_unsent_d = nearest_emergefull_d;
338 if(d > g_settings->getS16("max_block_send_distance")){
339 new_nearest_unsent_d = 0;
340 m_nothing_to_send_pause_timer = 2.0;
342 if(nearest_sent_d != -1)
343 new_nearest_unsent_d = nearest_sent_d;
345 new_nearest_unsent_d = d;
349 if(new_nearest_unsent_d != -1)
350 m_nearest_unsent_d = new_nearest_unsent_d;
353 void RemoteClient::GotBlock(v3s16 p)
355 if(m_blocks_sending.find(p) != m_blocks_sending.end())
356 m_blocks_sending.erase(p);
359 m_excess_gotblocks++;
361 m_blocks_sent.insert(p);
364 void RemoteClient::SentBlock(v3s16 p)
366 if(m_blocks_sending.find(p) == m_blocks_sending.end())
367 m_blocks_sending[p] = 0.0;
369 infostream<<"RemoteClient::SentBlock(): Sent block"
370 " already in m_blocks_sending"<<std::endl;
373 void RemoteClient::SetBlockNotSent(v3s16 p)
375 m_nearest_unsent_d = 0;
377 if(m_blocks_sending.find(p) != m_blocks_sending.end())
378 m_blocks_sending.erase(p);
379 if(m_blocks_sent.find(p) != m_blocks_sent.end())
380 m_blocks_sent.erase(p);
383 void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
385 m_nearest_unsent_d = 0;
387 for(std::map<v3s16, MapBlock*>::iterator
389 i != blocks.end(); ++i)
393 if(m_blocks_sending.find(p) != m_blocks_sending.end())
394 m_blocks_sending.erase(p);
395 if(m_blocks_sent.find(p) != m_blocks_sent.end())
396 m_blocks_sent.erase(p);
400 void RemoteClient::notifyEvent(ClientStateEvent event)
402 std::ostringstream myerror;
406 //intentionally do nothing
417 m_state = Disconnecting;
424 /* GotInit2 SetDefinitionsSent SetMediaSent */
426 myerror << "Created: Invalid client state transition! " << event;
427 throw ClientStateError(myerror.str());
432 /* don't do anything if in denied state */
439 confirmSerializationVersion();
444 m_state = Disconnecting;
451 /* Init SetDefinitionsSent SetMediaSent */
453 myerror << "InitSent: Invalid client state transition! " << event;
454 throw ClientStateError(myerror.str());
461 case SetDefinitionsSent:
462 m_state = DefinitionsSent;
466 m_state = Disconnecting;
473 /* Init GotInit2 SetMediaSent */
475 myerror << "InitDone: Invalid client state transition! " << event;
476 throw ClientStateError(myerror.str());
480 case DefinitionsSent:
488 m_state = Disconnecting;
495 /* Init GotInit2 SetDefinitionsSent */
497 myerror << "DefinitionsSent: Invalid client state transition! " << event;
498 throw ClientStateError(myerror.str());
510 m_state = Disconnecting;
513 /* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
515 myerror << "Active: Invalid client state transition! " << event;
516 throw ClientStateError(myerror.str());
522 /* we are already disconnecting */
527 u32 RemoteClient::uptime()
529 return getTime(PRECISION_SECONDS) - m_connection_time;
532 ClientInterface::ClientInterface(con::Connection* con)
536 m_print_info_timer(0.0)
540 ClientInterface::~ClientInterface()
546 JMutexAutoLock clientslock(m_clients_mutex);
548 for(std::map<u16, RemoteClient*>::iterator
549 i = m_clients.begin();
550 i != m_clients.end(); ++i)
559 std::list<u16> ClientInterface::getClientIDs(ClientState min_state)
561 std::list<u16> reply;
562 JMutexAutoLock clientslock(m_clients_mutex);
564 for(std::map<u16, RemoteClient*>::iterator
565 i = m_clients.begin();
566 i != m_clients.end(); ++i)
568 if (i->second->getState() >= min_state)
569 reply.push_back(i->second->peer_id);
575 std::vector<std::string> ClientInterface::getPlayerNames()
577 return m_clients_names;
581 void ClientInterface::step(float dtime)
583 m_print_info_timer += dtime;
584 if(m_print_info_timer >= 30.0)
586 m_print_info_timer = 0.0;
591 void ClientInterface::UpdatePlayerList()
595 std::list<u16> clients = getClientIDs();
596 m_clients_names.clear();
599 if(clients.size() != 0)
600 infostream<<"Players:"<<std::endl;
601 for(std::list<u16>::iterator
603 i != clients.end(); ++i)
605 Player *player = m_env->getPlayer(*i);
608 infostream<<"* "<<player->getName()<<"\t";
611 JMutexAutoLock clientslock(m_clients_mutex);
612 RemoteClient* client = lockedGetClientNoEx(*i);
614 client->PrintInfo(infostream);
616 m_clients_names.push_back(player->getName());
621 void ClientInterface::send(u16 peer_id,u8 channelnum,
622 SharedBuffer<u8> data, bool reliable)
624 m_con->Send(peer_id, channelnum, data, reliable);
627 void ClientInterface::sendToAll(u16 channelnum,
628 SharedBuffer<u8> data, bool reliable)
630 JMutexAutoLock clientslock(m_clients_mutex);
631 for(std::map<u16, RemoteClient*>::iterator
632 i = m_clients.begin();
633 i != m_clients.end(); ++i)
635 RemoteClient *client = i->second;
637 if (client->net_proto_version != 0)
639 m_con->Send(client->peer_id, channelnum, data, reliable);
644 RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min)
646 JMutexAutoLock clientslock(m_clients_mutex);
647 std::map<u16, RemoteClient*>::iterator n;
648 n = m_clients.find(peer_id);
649 // The client may not exist; clients are immediately removed if their
650 // access is denied, and this event occurs later then.
651 if(n == m_clients.end())
654 if (n->second->getState() >= state_min)
660 RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState state_min)
662 std::map<u16, RemoteClient*>::iterator n;
663 n = m_clients.find(peer_id);
664 // The client may not exist; clients are immediately removed if their
665 // access is denied, and this event occurs later then.
666 if(n == m_clients.end())
669 if (n->second->getState() >= state_min)
675 ClientState ClientInterface::getClientState(u16 peer_id)
677 JMutexAutoLock clientslock(m_clients_mutex);
678 std::map<u16, RemoteClient*>::iterator n;
679 n = m_clients.find(peer_id);
680 // The client may not exist; clients are immediately removed if their
681 // access is denied, and this event occurs later then.
682 if(n == m_clients.end())
685 return n->second->getState();
688 void ClientInterface::setPlayerName(u16 peer_id,std::string name)
690 JMutexAutoLock clientslock(m_clients_mutex);
691 std::map<u16, RemoteClient*>::iterator n;
692 n = m_clients.find(peer_id);
693 // The client may not exist; clients are immediately removed if their
694 // access is denied, and this event occurs later then.
695 if(n != m_clients.end())
696 n->second->setName(name);
699 void ClientInterface::DeleteClient(u16 peer_id)
701 JMutexAutoLock conlock(m_clients_mutex);
704 std::map<u16, RemoteClient*>::iterator n;
705 n = m_clients.find(peer_id);
706 // The client may not exist; clients are immediately removed if their
707 // access is denied, and this event occurs later then.
708 if(n == m_clients.end())
712 Mark objects to be not known by the client
714 //TODO this should be done by client destructor!!!
715 RemoteClient *client = n->second;
717 for(std::set<u16>::iterator
718 i = client->m_known_objects.begin();
719 i != client->m_known_objects.end(); ++i)
723 ServerActiveObject* obj = m_env->getActiveObject(id);
725 if(obj && obj->m_known_by_count > 0)
726 obj->m_known_by_count--;
730 delete m_clients[peer_id];
731 m_clients.erase(peer_id);
734 void ClientInterface::CreateClient(u16 peer_id)
736 JMutexAutoLock conlock(m_clients_mutex);
739 std::map<u16, RemoteClient*>::iterator n;
740 n = m_clients.find(peer_id);
741 // The client shouldn't already exist
742 if(n != m_clients.end()) return;
745 RemoteClient *client = new RemoteClient();
746 client->peer_id = peer_id;
747 m_clients[client->peer_id] = client;
750 void ClientInterface::event(u16 peer_id, ClientStateEvent event)
753 JMutexAutoLock clientlock(m_clients_mutex);
756 std::map<u16, RemoteClient*>::iterator n;
757 n = m_clients.find(peer_id);
759 // No client to deliver event
760 if (n == m_clients.end())
762 n->second->notifyEvent(event);
765 if ((event == SetClientReady) || (event == Disconnect) || (event == SetDenied))
771 u16 ClientInterface::getProtocolVersion(u16 peer_id)
773 JMutexAutoLock conlock(m_clients_mutex);
776 std::map<u16, RemoteClient*>::iterator n;
777 n = m_clients.find(peer_id);
779 // No client to get version
780 if (n == m_clients.end())
783 return n->second->net_proto_version;
786 void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
788 JMutexAutoLock conlock(m_clients_mutex);
791 std::map<u16, RemoteClient*>::iterator n;
792 n = m_clients.find(peer_id);
794 // No client to set versions
795 if (n == m_clients.end())
798 n->second->setVersionInfo(major,minor,patch,full);