From b16252dcae8c6b0e79c20fa4c3cbddc37ad377cb Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 22 Dec 2016 19:29:15 +0100 Subject: Various anticheat improvements * Calculate maximum interact distance from wielded tool * New "interacted_while_dead" cheat_type for the Lua API * Disallow dropping items while dead * Move player to spawn before resurrecting them --- src/network/serverpackethandler.cpp | 84 +++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 32 deletions(-) (limited to 'src/network/serverpackethandler.cpp') diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index dca9aabc4..f99e104ec 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -1021,6 +1021,15 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt) delete a; return; } + + // Disallow dropping items if dead + if (playersao->isDead()) { + infostream << "Ignoring IDropAction from " + << (da->from_inv.dump()) << ":" << da->from_list + << " because player is dead." << std::endl; + delete a; + return; + } } /* Handle restrictions and special cases of the craft action @@ -1313,6 +1322,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) 2: digging completed 3: place block or item (to abovesurface) 4: use item + 5: rightclick air ("activate") */ u8 action; u16 item_i; @@ -1345,8 +1355,16 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) } if (playersao->isDead()) { - verbosestream << "TOSERVER_INTERACT: " << player->getName() - << " is dead. Ignoring packet"; + actionstream << "Server: NoCheat: " << player->getName() + << " tried to interact while dead; ignoring." << std::endl; + if (pointed.type == POINTEDTHING_NODE) { + // Re-send block to revert change on client-side + RemoteClient *client = getClient(pkt->getPeerId()); + v3s16 blockpos = getNodeBlockPos(pointed.node_undersurface); + client->SetBlockNotSent(blockpos); + } + // Call callbacks + m_script->on_cheat(playersao, "interacted_while_dead"); return; } @@ -1384,16 +1402,45 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) pointed_pos_above = pointed_pos_under; } + /* + Make sure the player is allowed to do it + */ + if (!checkPriv(player->getName(), "interact")) { + actionstream<getName()<<" attempted to interact with " + <getPeerId()); + // Digging completed -> under + if (action == 2) { + v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); + client->SetBlockNotSent(blockpos); + } + // Placement -> above + if (action == 3) { + v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS)); + client->SetBlockNotSent(blockpos); + } + return; + } + /* Check that target is reasonably close (only when digging or placing things) */ static const bool enable_anticheat = !g_settings->getBool("disable_anticheat"); - if ((action == 0 || action == 2 || action == 3) && + if ((action == 0 || action == 2 || action == 3 || action == 4) && (enable_anticheat && !isSingleplayer())) { float d = player_pos.getDistanceFrom(pointed_pos_under); - float max_d = BS * 14; // Just some large enough value - if (d > max_d) { + const ItemDefinition &playeritem_def = + playersao->getWieldedItem().getDefinition(m_itemdef); + float max_d = BS * playeritem_def.range; + float max_d_hand = BS * m_itemdef->get("").range; + if (max_d < 0 && max_d_hand >= 0) + max_d = max_d_hand; + else if (max_d < 0) + max_d = BS * 4.0; + if (d > max_d * 1.5) { actionstream << "Player " << player->getName() << " tried to access " << pointed.dump() << " from too far: " @@ -1410,28 +1457,6 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) } } - /* - Make sure the player is allowed to do it - */ - if (!checkPriv(player->getName(), "interact")) { - actionstream<getName()<<" attempted to interact with " - <getPeerId()); - // Digging completed -> under - if (action == 2) { - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS)); - client->SetBlockNotSent(blockpos); - } - // Placement -> above - if (action == 3) { - v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS)); - client->SetBlockNotSent(blockpos); - } - return; - } - /* If something goes wrong, this player is to blame */ @@ -1443,11 +1468,6 @@ void Server::handleCommand_Interact(NetworkPacket* pkt) */ if (action == 0) { if (pointed.type == POINTEDTHING_NODE) { - /* - NOTE: This can be used in the future to check if - somebody is cheating, by checking the timing. - */ - MapNode n(CONTENT_IGNORE); bool pos_ok; -- cgit v1.2.3