aboutsummaryrefslogtreecommitdiff
path: root/src/server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.cpp')
-rw-r--r--src/server.cpp277
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)