From 7832b6843e73410e15677d1324d582b4b7c7e824 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 15 Feb 2021 20:41:19 +0100 Subject: Server-side authority for attached players (#10952) The server must have authority about attachments. This commit ignores any player movement packets as long they're attached. --- src/network/serverpackethandler.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/network') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 270b8e01f..ddc6f4e47 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -488,8 +488,12 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao, pitch = modulo360f(pitch); yaw = wrapDegrees_0_360(yaw); - playersao->setBasePosition(position); - player->setSpeed(speed); + if (!playersao->isAttached()) { + // Only update player positions when moving freely + // to not interfere with attachment handling + playersao->setBasePosition(position); + player->setSpeed(speed); + } playersao->setLookPitch(pitch); playersao->setPlayerYaw(yaw); playersao->setFov(fov); -- cgit v1.2.3 From 3edb1ddb8127aa7e8de867be50c695271091cb94 Mon Sep 17 00:00:00 2001 From: savilli <78875209+savilli@users.noreply.github.com> Date: Fri, 26 Feb 2021 23:21:20 +0300 Subject: Fix hud_change and hud_remove after hud_add (#10997) --- src/client/client.h | 8 -------- src/client/game.cpp | 30 +++++++++++++++++++++--------- src/network/clientpackethandler.cpp | 37 ++++++++++++++----------------------- 3 files changed, 35 insertions(+), 40 deletions(-) (limited to 'src/network') diff --git a/src/client/client.h b/src/client/client.h index 25a1b97ba..2dba1506e 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -415,11 +415,6 @@ public: return m_csm_restriction_flags & flag; } - inline std::unordered_map &getHUDTranslationMap() - { - return m_hud_server_to_client; - } - bool joinModChannel(const std::string &channel) override; bool leaveModChannel(const std::string &channel) override; bool sendModChannelMessage(const std::string &channel, @@ -556,9 +551,6 @@ private: // Relation of client id to object id std::unordered_map m_sounds_to_objects; - // Map server hud ids to client hud ids - std::unordered_map m_hud_server_to_client; - // Privileges std::unordered_set m_privileges; diff --git a/src/client/game.cpp b/src/client/game.cpp index d4e2fe7c3..15fa2af23 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -856,6 +856,9 @@ private: Hud *hud = nullptr; Minimap *mapper = nullptr; + // Map server hud ids to client hud ids + std::unordered_map m_hud_server_to_client; + GameRunData runData; Flags m_flags; @@ -2602,12 +2605,11 @@ void Game::handleClientEvent_HandleParticleEvent(ClientEvent *event, void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam) { LocalPlayer *player = client->getEnv().getLocalPlayer(); - auto &hud_server_to_client = client->getHUDTranslationMap(); u32 server_id = event->hudadd.server_id; // ignore if we already have a HUD with that ID - auto i = hud_server_to_client.find(server_id); - if (i != hud_server_to_client.end()) { + auto i = m_hud_server_to_client.find(server_id); + if (i != m_hud_server_to_client.end()) { delete event->hudadd.pos; delete event->hudadd.name; delete event->hudadd.scale; @@ -2635,7 +2637,7 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam) e->size = *event->hudadd.size; e->z_index = event->hudadd.z_index; e->text2 = *event->hudadd.text2; - hud_server_to_client[server_id] = player->addHud(e); + m_hud_server_to_client[server_id] = player->addHud(e); delete event->hudadd.pos; delete event->hudadd.name; @@ -2651,18 +2653,28 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam) void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam) { LocalPlayer *player = client->getEnv().getLocalPlayer(); - HudElement *e = player->removeHud(event->hudrm.id); - delete e; + + auto i = m_hud_server_to_client.find(event->hudrm.id); + if (i != m_hud_server_to_client.end()) { + HudElement *e = player->removeHud(i->second); + delete e; + m_hud_server_to_client.erase(i); + } + } void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam) { LocalPlayer *player = client->getEnv().getLocalPlayer(); - u32 id = event->hudchange.id; - HudElement *e = player->getHud(id); + HudElement *e = nullptr; + + auto i = m_hud_server_to_client.find(event->hudchange.id); + if (i != m_hud_server_to_client.end()) { + e = player->getHud(i->second); + } - if (e == NULL) { + if (e == nullptr) { delete event->hudchange.v3fdata; delete event->hudchange.v2fdata; delete event->hudchange.sdata; diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 65db02300..44bd81dac 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1095,16 +1095,10 @@ void Client::handleCommand_HudRemove(NetworkPacket* pkt) *pkt >> server_id; - auto i = m_hud_server_to_client.find(server_id); - if (i != m_hud_server_to_client.end()) { - int client_id = i->second; - m_hud_server_to_client.erase(i); - - ClientEvent *event = new ClientEvent(); - event->type = CE_HUDRM; - event->hudrm.id = client_id; - m_client_event_queue.push(event); - } + ClientEvent *event = new ClientEvent(); + event->type = CE_HUDRM; + event->hudrm.id = server_id; + m_client_event_queue.push(event); } void Client::handleCommand_HudChange(NetworkPacket* pkt) @@ -1131,19 +1125,16 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt) else *pkt >> intdata; - std::unordered_map::const_iterator i = m_hud_server_to_client.find(server_id); - if (i != m_hud_server_to_client.end()) { - ClientEvent *event = new ClientEvent(); - event->type = CE_HUDCHANGE; - event->hudchange.id = i->second; - event->hudchange.stat = (HudElementStat)stat; - event->hudchange.v2fdata = new v2f(v2fdata); - event->hudchange.v3fdata = new v3f(v3fdata); - event->hudchange.sdata = new std::string(sdata); - event->hudchange.data = intdata; - event->hudchange.v2s32data = new v2s32(v2s32data); - m_client_event_queue.push(event); - } + ClientEvent *event = new ClientEvent(); + event->type = CE_HUDCHANGE; + event->hudchange.id = server_id; + event->hudchange.stat = (HudElementStat)stat; + event->hudchange.v2fdata = new v2f(v2fdata); + event->hudchange.v3fdata = new v3f(v3fdata); + event->hudchange.sdata = new std::string(sdata); + event->hudchange.data = intdata; + event->hudchange.v2s32data = new v2s32(v2s32data); + m_client_event_queue.push(event); } void Client::handleCommand_HudSetFlags(NetworkPacket* pkt) -- cgit v1.2.3 From 593d5f4465f5f181b87a1477c7072dca500a9d80 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 5 Mar 2021 12:54:53 +0100 Subject: Clean up ClientEvent hudadd/hudchange internals --- src/client/clientevent.h | 55 ++++++++-------- src/client/game.cpp | 123 ++++++++++++------------------------ src/network/clientpackethandler.cpp | 53 ++++++++-------- 3 files changed, 94 insertions(+), 137 deletions(-) (limited to 'src/network') diff --git a/src/client/clientevent.h b/src/client/clientevent.h index 9bd31efce..2215aecbd 100644 --- a/src/client/clientevent.h +++ b/src/client/clientevent.h @@ -52,6 +52,31 @@ enum ClientEventType : u8 CLIENTEVENT_MAX, }; +struct ClientEventHudAdd +{ + u32 server_id; + u8 type; + v2f pos, scale; + std::string name; + std::string text, text2; + u32 number, item, dir; + v2f align, offset; + v3f world_pos; + v2s32 size; + s16 z_index; +}; + +struct ClientEventHudChange +{ + u32 id; + HudElementStat stat; + v2f v2fdata; + std::string sdata; + u32 data; + v3f v3fdata; + v2s32 v2s32data; +}; + struct ClientEvent { ClientEventType type; @@ -93,38 +118,12 @@ struct ClientEvent { u32 id; } delete_particlespawner; - struct - { - u32 server_id; - u8 type; - v2f *pos; - std::string *name; - v2f *scale; - std::string *text; - u32 number; - u32 item; - u32 dir; - v2f *align; - v2f *offset; - v3f *world_pos; - v2s32 *size; - s16 z_index; - std::string *text2; - } hudadd; + ClientEventHudAdd *hudadd; struct { u32 id; } hudrm; - struct - { - u32 id; - HudElementStat stat; - v2f *v2fdata; - std::string *sdata; - u32 data; - v3f *v3fdata; - v2s32 *v2s32data; - } hudchange; + ClientEventHudChange *hudchange; SkyboxParams *set_sky; struct { diff --git a/src/client/game.cpp b/src/client/game.cpp index 60ecb7d3e..27eaec3b8 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2643,48 +2643,32 @@ void Game::handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam) { LocalPlayer *player = client->getEnv().getLocalPlayer(); - u32 server_id = event->hudadd.server_id; + u32 server_id = event->hudadd->server_id; // ignore if we already have a HUD with that ID auto i = m_hud_server_to_client.find(server_id); if (i != m_hud_server_to_client.end()) { - delete event->hudadd.pos; - delete event->hudadd.name; - delete event->hudadd.scale; - delete event->hudadd.text; - delete event->hudadd.align; - delete event->hudadd.offset; - delete event->hudadd.world_pos; - delete event->hudadd.size; - delete event->hudadd.text2; + delete event->hudadd; return; } HudElement *e = new HudElement; - e->type = (HudElementType)event->hudadd.type; - e->pos = *event->hudadd.pos; - e->name = *event->hudadd.name; - e->scale = *event->hudadd.scale; - e->text = *event->hudadd.text; - e->number = event->hudadd.number; - e->item = event->hudadd.item; - e->dir = event->hudadd.dir; - e->align = *event->hudadd.align; - e->offset = *event->hudadd.offset; - e->world_pos = *event->hudadd.world_pos; - e->size = *event->hudadd.size; - e->z_index = event->hudadd.z_index; - e->text2 = *event->hudadd.text2; + e->type = static_cast(event->hudadd->type); + e->pos = event->hudadd->pos; + e->name = event->hudadd->name; + e->scale = event->hudadd->scale; + e->text = event->hudadd->text; + e->number = event->hudadd->number; + e->item = event->hudadd->item; + e->dir = event->hudadd->dir; + e->align = event->hudadd->align; + e->offset = event->hudadd->offset; + e->world_pos = event->hudadd->world_pos; + e->size = event->hudadd->size; + e->z_index = event->hudadd->z_index; + e->text2 = event->hudadd->text2; m_hud_server_to_client[server_id] = player->addHud(e); - delete event->hudadd.pos; - delete event->hudadd.name; - delete event->hudadd.scale; - delete event->hudadd.text; - delete event->hudadd.align; - delete event->hudadd.offset; - delete event->hudadd.world_pos; - delete event->hudadd.size; - delete event->hudadd.text2; + delete event->hudadd; } void Game::handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam) @@ -2706,77 +2690,52 @@ void Game::handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *ca HudElement *e = nullptr; - auto i = m_hud_server_to_client.find(event->hudchange.id); + auto i = m_hud_server_to_client.find(event->hudchange->id); if (i != m_hud_server_to_client.end()) { e = player->getHud(i->second); } if (e == nullptr) { - delete event->hudchange.v3fdata; - delete event->hudchange.v2fdata; - delete event->hudchange.sdata; - delete event->hudchange.v2s32data; + delete event->hudchange; return; } - switch (event->hudchange.stat) { - case HUD_STAT_POS: - e->pos = *event->hudchange.v2fdata; - break; +#define CASE_SET(statval, prop, dataprop) \ + case statval: \ + e->prop = event->hudchange->dataprop; \ + break - case HUD_STAT_NAME: - e->name = *event->hudchange.sdata; - break; + switch (event->hudchange->stat) { + CASE_SET(HUD_STAT_POS, pos, v2fdata); - case HUD_STAT_SCALE: - e->scale = *event->hudchange.v2fdata; - break; + CASE_SET(HUD_STAT_NAME, name, sdata); - case HUD_STAT_TEXT: - e->text = *event->hudchange.sdata; - break; + CASE_SET(HUD_STAT_SCALE, scale, v2fdata); - case HUD_STAT_NUMBER: - e->number = event->hudchange.data; - break; + CASE_SET(HUD_STAT_TEXT, text, sdata); - case HUD_STAT_ITEM: - e->item = event->hudchange.data; - break; + CASE_SET(HUD_STAT_NUMBER, number, data); - case HUD_STAT_DIR: - e->dir = event->hudchange.data; - break; + CASE_SET(HUD_STAT_ITEM, item, data); - case HUD_STAT_ALIGN: - e->align = *event->hudchange.v2fdata; - break; + CASE_SET(HUD_STAT_DIR, dir, data); - case HUD_STAT_OFFSET: - e->offset = *event->hudchange.v2fdata; - break; + CASE_SET(HUD_STAT_ALIGN, align, v2fdata); - case HUD_STAT_WORLD_POS: - e->world_pos = *event->hudchange.v3fdata; - break; + CASE_SET(HUD_STAT_OFFSET, offset, v2fdata); - case HUD_STAT_SIZE: - e->size = *event->hudchange.v2s32data; - break; + CASE_SET(HUD_STAT_WORLD_POS, world_pos, v3fdata); - case HUD_STAT_Z_INDEX: - e->z_index = event->hudchange.data; - break; + CASE_SET(HUD_STAT_SIZE, size, v2s32data); - case HUD_STAT_TEXT2: - e->text2 = *event->hudchange.sdata; - break; + CASE_SET(HUD_STAT_Z_INDEX, z_index, data); + + CASE_SET(HUD_STAT_TEXT2, text2, sdata); } - delete event->hudchange.v3fdata; - delete event->hudchange.v2fdata; - delete event->hudchange.sdata; - delete event->hudchange.v2s32data; +#undef CASE_SET + + delete event->hudchange; } void Game::handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam) diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 44bd81dac..c8a160732 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1041,9 +1041,6 @@ void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt) void Client::handleCommand_HudAdd(NetworkPacket* pkt) { - std::string datastring(pkt->getString(0), pkt->getSize()); - std::istringstream is(datastring, std::ios_base::binary); - u32 server_id; u8 type; v2f pos; @@ -1070,22 +1067,23 @@ void Client::handleCommand_HudAdd(NetworkPacket* pkt) } catch(PacketError &e) {}; ClientEvent *event = new ClientEvent(); - event->type = CE_HUDADD; - event->hudadd.server_id = server_id; - event->hudadd.type = type; - event->hudadd.pos = new v2f(pos); - event->hudadd.name = new std::string(name); - event->hudadd.scale = new v2f(scale); - event->hudadd.text = new std::string(text); - event->hudadd.number = number; - event->hudadd.item = item; - event->hudadd.dir = dir; - event->hudadd.align = new v2f(align); - event->hudadd.offset = new v2f(offset); - event->hudadd.world_pos = new v3f(world_pos); - event->hudadd.size = new v2s32(size); - event->hudadd.z_index = z_index; - event->hudadd.text2 = new std::string(text2); + event->type = CE_HUDADD; + event->hudadd = new ClientEventHudAdd(); + event->hudadd->server_id = server_id; + event->hudadd->type = type; + event->hudadd->pos = pos; + event->hudadd->name = name; + event->hudadd->scale = scale; + event->hudadd->text = text; + event->hudadd->number = number; + event->hudadd->item = item; + event->hudadd->dir = dir; + event->hudadd->align = align; + event->hudadd->offset = offset; + event->hudadd->world_pos = world_pos; + event->hudadd->size = size; + event->hudadd->z_index = z_index; + event->hudadd->text2 = text2; m_client_event_queue.push(event); } @@ -1126,14 +1124,15 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt) *pkt >> intdata; ClientEvent *event = new ClientEvent(); - event->type = CE_HUDCHANGE; - event->hudchange.id = server_id; - event->hudchange.stat = (HudElementStat)stat; - event->hudchange.v2fdata = new v2f(v2fdata); - event->hudchange.v3fdata = new v3f(v3fdata); - event->hudchange.sdata = new std::string(sdata); - event->hudchange.data = intdata; - event->hudchange.v2s32data = new v2s32(v2s32data); + event->type = CE_HUDCHANGE; + event->hudchange = new ClientEventHudChange(); + event->hudchange->id = server_id; + event->hudchange->stat = static_cast(stat); + event->hudchange->v2fdata = v2fdata; + event->hudchange->v3fdata = v3fdata; + event->hudchange->sdata = sdata; + event->hudchange->data = intdata; + event->hudchange->v2s32data = v2s32data; m_client_event_queue.push(event); } -- cgit v1.2.3 From fc864029b9635106a5390aa09d227d7dac31d1a5 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 7 Mar 2021 10:04:07 +0100 Subject: Protect per-player detached inventory actions --- src/network/serverpackethandler.cpp | 6 +++++- src/server/serverinventorymgr.cpp | 12 ++++++++++++ src/server/serverinventorymgr.h | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src/network') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index ddc6f4e47..f1ed42302 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -626,7 +626,7 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) const bool player_has_interact = checkPriv(player->getName(), "interact"); - auto check_inv_access = [player, player_has_interact] ( + auto check_inv_access = [player, player_has_interact, this] ( const InventoryLocation &loc) -> bool { if (loc.type == InventoryLocation::CURRENT_PLAYER) return false; // Only used internally on the client, never sent @@ -634,6 +634,10 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) // Allow access to own inventory in all cases return loc.name == player->getName(); } + if (loc.type == InventoryLocation::DETACHED) { + if (!getInventoryMgr()->checkDetachedInventoryAccess(loc, player->getName())) + return false; + } if (!player_has_interact) { infostream << "Cannot modify foreign inventory: " diff --git a/src/server/serverinventorymgr.cpp b/src/server/serverinventorymgr.cpp index 555e01ec6..2a80c9bbe 100644 --- a/src/server/serverinventorymgr.cpp +++ b/src/server/serverinventorymgr.cpp @@ -168,6 +168,18 @@ bool ServerInventoryManager::removeDetachedInventory(const std::string &name) return true; } +bool ServerInventoryManager::checkDetachedInventoryAccess( + const InventoryLocation &loc, const std::string &player) const +{ + SANITY_CHECK(loc.type == InventoryLocation::DETACHED); + + const auto &inv_it = m_detached_inventories.find(loc.name); + if (inv_it == m_detached_inventories.end()) + return false; + + return inv_it->second.owner.empty() || inv_it->second.owner == player; +} + void ServerInventoryManager::sendDetachedInventories(const std::string &peer_name, bool incremental, std::function apply_cb) diff --git a/src/server/serverinventorymgr.h b/src/server/serverinventorymgr.h index ccf6d3b2e..0e4b72415 100644 --- a/src/server/serverinventorymgr.h +++ b/src/server/serverinventorymgr.h @@ -43,6 +43,7 @@ public: Inventory *createDetachedInventory(const std::string &name, IItemDefManager *idef, const std::string &player = ""); bool removeDetachedInventory(const std::string &name); + bool checkDetachedInventoryAccess(const InventoryLocation &loc, const std::string &player) const; void sendDetachedInventories(const std::string &peer_name, bool incremental, std::function apply_cb); -- cgit v1.2.3 From 176f5866cbc8946c55a0a9bd0978a804ad310211 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 7 Mar 2021 11:35:53 +0100 Subject: Protect dropping from far node inventories Also changes if/if to switch/case --- src/network/serverpackethandler.cpp | 47 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'src/network') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index f1ed42302..b863e1828 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -628,23 +628,34 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) auto check_inv_access = [player, player_has_interact, this] ( const InventoryLocation &loc) -> bool { - if (loc.type == InventoryLocation::CURRENT_PLAYER) - return false; // Only used internally on the client, never sent - if (loc.type == InventoryLocation::PLAYER) { - // Allow access to own inventory in all cases - return loc.name == player->getName(); - } - if (loc.type == InventoryLocation::DETACHED) { - if (!getInventoryMgr()->checkDetachedInventoryAccess(loc, player->getName())) - return false; - } - if (!player_has_interact) { + // Players without interact may modify their own inventory + if (!player_has_interact && loc.type != InventoryLocation::PLAYER) { infostream << "Cannot modify foreign inventory: " << "No interact privilege" << std::endl; return false; } - return true; + + switch (loc.type) { + case InventoryLocation::CURRENT_PLAYER: + // Only used internally on the client, never sent + return false; + case InventoryLocation::PLAYER: + // Allow access to own inventory in all cases + return loc.name == player->getName(); + case InventoryLocation::NODEMETA: + { + // Check for out-of-range interaction + v3f node_pos = intToFloat(loc.p, BS); + v3f player_pos = player->getPlayerSAO()->getEyePosition(); + f32 d = player_pos.getDistanceFrom(node_pos); + return checkInteractDistance(player, d, "inventory"); + } + case InventoryLocation::DETACHED: + return getInventoryMgr()->checkDetachedInventoryAccess(loc, player->getName()); + default: + return false; + } }; /* @@ -664,18 +675,6 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) !check_inv_access(ma->to_inv)) return; - InventoryLocation *remote = ma->from_inv.type == InventoryLocation::PLAYER ? - &ma->to_inv : &ma->from_inv; - - // Check for out-of-range interaction - if (remote->type == InventoryLocation::NODEMETA) { - v3f node_pos = intToFloat(remote->p, BS); - v3f player_pos = player->getPlayerSAO()->getEyePosition(); - f32 d = player_pos.getDistanceFrom(node_pos); - if (!checkInteractDistance(player, d, "inventory")) - return; - } - /* Disable moving items out of craftpreview */ -- cgit v1.2.3 From 492110a640dd8d01838e95aba00f650b37b7ed11 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein <54945686+EliasFleckenstein03@users.noreply.github.com> Date: Fri, 19 Mar 2021 21:45:29 +0100 Subject: Check for duplicate login in TOSERVER_INIT handler (#11017) i.e. checks for duplicate logins before sending all media data to the client. --- src/network/serverpackethandler.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/network') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index b863e1828..5b378a083 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -174,6 +174,16 @@ void Server::handleCommand_Init(NetworkPacket* pkt) return; } + RemotePlayer *player = m_env->getPlayer(playername); + + // If player is already connected, cancel + if (player && player->getPeerId() != PEER_ID_INEXISTENT) { + actionstream << "Server: Player with name \"" << playername << + "\" tried to connect, but player with same name is already connected" << std::endl; + DenyAccess(peer_id, SERVER_ACCESSDENIED_ALREADY_CONNECTED); + return; + } + m_clients.setPlayerName(peer_id, playername); //TODO (later) case insensitivity -- cgit v1.2.3