diff options
Diffstat (limited to 'src/server.cpp')
-rw-r--r-- | src/server.cpp | 277 |
1 files changed, 187 insertions, 90 deletions
diff --git a/src/server.cpp b/src/server.cpp index ba7ac1ece..ebb76b087 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1191,6 +1191,111 @@ void Server::Receive() m_env->removePlayer(peer_id);*/ } + catch(ClientStateError &e) + { + errorstream << "ProcessData: peer=" << peer_id << e.what() << std::endl; + DenyAccess(peer_id, L"Your client sent something server didn't expect." + L"Try reconnecting or updating your client"); + } +} + +PlayerSAO* Server::StageTwoClientInit(u16 peer_id) +{ + std::string playername = ""; + PlayerSAO *playersao = NULL; + m_clients.Lock(); + RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id,InitDone); + if (client != NULL) { + playername = client->getName(); + playersao = emergePlayer(playername.c_str(), peer_id); + } + m_clients.Unlock(); + + RemotePlayer *player = + static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str())); + + // If failed, cancel + if((playersao == NULL) || (player == NULL)) + { + if(player && player->peer_id != 0){ + errorstream<<"Server: "<<playername<<": Failed to emerge player" + <<" (player allocated to an another client)"<<std::endl; + DenyAccess(peer_id, L"Another client is connected with this " + L"name. If your client closed unexpectedly, try again in " + L"a minute."); + } else { + errorstream<<"Server: "<<playername<<": Failed to emerge player" + <<std::endl; + DenyAccess(peer_id, L"Could not allocate player."); + } + return NULL; + } + + /* + Send complete position information + */ + SendMovePlayer(peer_id); + + // Send privileges + SendPlayerPrivileges(peer_id); + + // Send inventory formspec + SendPlayerInventoryFormspec(peer_id); + + // Send inventory + UpdateCrafting(peer_id); + SendInventory(peer_id); + + // Send HP + if(g_settings->getBool("enable_damage")) + SendPlayerHP(peer_id); + + // Send Breath + SendPlayerBreath(peer_id); + + // Show death screen if necessary + if(player->hp == 0) + SendDeathscreen(peer_id, false, v3f(0,0,0)); + + // Note things in chat if not in simple singleplayer mode + if(!m_simple_singleplayer_mode) + { + // Send information about server to player in chat + SendChatMessage(peer_id, getStatusString()); + + // Send information about joining in chat + { + std::wstring name = L"unknown"; + Player *player = m_env->getPlayer(peer_id); + if(player != NULL) + name = narrow_to_wide(player->getName()); + + std::wstring message; + message += L"*** "; + message += name; + message += L" joined the game."; + SendChatMessage(PEER_ID_INEXISTENT,message); + } + } + + actionstream<<player->getName() <<" joins game. " << std::endl; + /* + Print out action + */ + { + std::vector<std::string> names = m_clients.getPlayerNames(); + + actionstream<<player->getName() <<" joins game. List of players: "; + + for (std::vector<std::string>::iterator i = names.begin(); + i != names.end(); i++) + { + actionstream << *i << " "; + } + + actionstream<<std::endl; + } + return playersao; } void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) @@ -1543,6 +1648,21 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) m_clients.event(peer_id, GotInit2); u16 protocol_version = m_clients.getProtocolVersion(peer_id); + + ///// begin compatibility code + PlayerSAO* playersao = NULL; + if (protocol_version <= 22) { + playersao = StageTwoClientInit(peer_id); + + if (playersao == NULL) { + errorstream + << "TOSERVER_INIT2 stage 2 client init failed for peer " + << peer_id << std::endl; + return; + } + } + ///// end compatibility code + /* Send some initialization data */ @@ -1572,6 +1692,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) float time_speed = g_settings->getFloat("time_speed"); SendTimeOfDay(peer_id, time, time_speed); + ///// begin compatibility code + if (protocol_version <= 22) { + m_clients.event(peer_id, SetClientReady); + m_script->on_joinplayer(playersao); + } + ///// end compatibility code + // Warnings about protocol version can be issued here if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION) { @@ -1583,6 +1710,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } u8 peer_ser_ver = getClient(peer_id,InitDone)->serialization_version; + u16 peer_proto_ver = getClient(peer_id,InitDone)->net_proto_version; if(peer_ser_ver == SER_FMT_VER_INVALID) { @@ -1615,105 +1743,34 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } else if(command == TOSERVER_RECEIVED_MEDIA) { - std::string playername = ""; - PlayerSAO *playersao = NULL; - m_clients.Lock(); - RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id,DefinitionsSent); - if (client != NULL) { - playername = client->getName(); - playersao = emergePlayer(playername.c_str(), peer_id); - } - m_clients.Unlock(); + return; + } + else if(command == TOSERVER_CLIENT_READY) { + // clients <= protocol version 22 did not send ready message, + // they're already initialized + assert(peer_proto_ver > 22); - RemotePlayer *player = - static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str())); + PlayerSAO* playersao = StageTwoClientInit(peer_id); - // If failed, cancel - if((playersao == NULL) || (player == NULL)) - { - if(player && player->peer_id != 0){ - errorstream<<"Server: "<<playername<<": Failed to emerge player" - <<" (player allocated to an another client)"<<std::endl; - DenyAccess(peer_id, L"Another client is connected with this " - L"name. If your client closed unexpectedly, try again in " - L"a minute."); - } else { - errorstream<<"Server: "<<playername<<": Failed to emerge player" - <<std::endl; - DenyAccess(peer_id, L"Could not allocate player."); - } + if (playersao == NULL) { + errorstream + << "TOSERVER_CLIENT_READY stage 2 client init failed for peer " + << peer_id << std::endl; return; } - /* - Send complete position information - */ - SendMovePlayer(peer_id); - - // Send privileges - SendPlayerPrivileges(peer_id); - - // Send inventory formspec - SendPlayerInventoryFormspec(peer_id); - - // Send inventory - UpdateCrafting(peer_id); - SendInventory(peer_id); - - // Send HP - if(g_settings->getBool("enable_damage")) - SendPlayerHP(peer_id); - - // Send Breath - SendPlayerBreath(peer_id); - - // Show death screen if necessary - if(player->hp == 0) - SendDeathscreen(peer_id, false, v3f(0,0,0)); - - // Note things in chat if not in simple singleplayer mode - if(!m_simple_singleplayer_mode) - { - // Send information about server to player in chat - SendChatMessage(peer_id, getStatusString()); - - // Send information about joining in chat - { - std::wstring name = L"unknown"; - Player *player = m_env->getPlayer(peer_id); - if(player != NULL) - name = narrow_to_wide(player->getName()); - - std::wstring message; - message += L"*** "; - message += name; - message += L" joined the game."; - SendChatMessage(PEER_ID_INEXISTENT,message); - } - } - - actionstream<<player->getName()<<" ["<<addr_s<<"] "<<"joins game. " << std::endl; - /* - Print out action - */ - { - std::vector<std::string> names = m_clients.getPlayerNames(); - - actionstream<<player->getName()<<" ["<<addr_s<<"] " - <<"joins game. List of players: "; - for (std::vector<std::string>::iterator i = names.begin(); - i != names.end(); i++) - { - actionstream << *i << " "; - } + if(datasize < 2+8) + return; - actionstream<<std::endl; - } + m_clients.setClientVersion( + peer_id, + data[2], data[3], data[4], + std::string((char*) &data[8],(u16) data[6])); - m_clients.event(peer_id,SetMediaSent); + m_clients.event(peer_id, SetClientReady); m_script->on_joinplayer(playersao); - return; + } else if(command == TOSERVER_GOTBLOCKS) { @@ -2809,6 +2866,46 @@ void Server::deletingPeer(con::Peer *peer, bool timeout) m_peer_change_queue.push_back(c); } +bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval) +{ + *retval = m_con.getPeerStat(peer_id,type); + if (*retval == -1) return false; + return true; +} + +bool Server::getClientInfo( + u16 peer_id, + ClientState* state, + u32* uptime, + u8* ser_vers, + u16* prot_vers, + u8* major, + u8* minor, + u8* patch, + std::string* vers_string + ) +{ + *state = m_clients.getClientState(peer_id); + m_clients.Lock(); + RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id,Invalid); + + if (client == NULL) + return false; + + *uptime = client->uptime(); + *ser_vers = client->serialization_version; + *prot_vers = client->net_proto_version; + + *major = client->getMajor(); + *minor = client->getMinor(); + *patch = client->getPatch(); + *vers_string = client->getPatch(); + + m_clients.Unlock(); + + return true; +} + void Server::handlePeerChanges() { while(m_peer_change_queue.size() > 0) |