Inventory: Restrict access from too far away
authorSmallJoker <mk939@ymail.com>
Wed, 22 Nov 2017 18:25:26 +0000 (19:25 +0100)
committerparamat <mat.gregory@virginmedia.com>
Fri, 24 Nov 2017 05:39:47 +0000 (05:39 +0000)
src/network/serverpackethandler.cpp
src/server.h

index b248b867bc85ae8a5b3b1c368c1d988ae66f3a6f..6ea58a7ecfd01af51d408e86bb184e50ebdcf627 100644 (file)
@@ -622,6 +622,18 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
                        (ma->to_inv.type == InventoryLocation::PLAYER) &&
                        (ma->to_inv.name == player->getName());
 
+               InventoryLocation *remote = from_inv_is_current_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()->getBasePosition();
+                       f32 d = player_pos.getDistanceFrom(node_pos);
+                       if (!checkInteractDistance(player, d, "inventory"))
+                               return;
+               }
+
                /*
                        Disable moving items out of craftpreview
                */
@@ -940,6 +952,37 @@ void Server::handleCommand_Respawn(NetworkPacket* pkt)
        // the previous addition has been successfully removed
 }
 
+bool Server::checkInteractDistance(RemotePlayer *player, const f32 d, const std::string what)
+{
+       PlayerSAO *playersao = player->getPlayerSAO();
+       const InventoryList *hlist = playersao->getInventory()->getList("hand");
+       const ItemDefinition &playeritem_def =
+               playersao->getWieldedItem().getDefinition(m_itemdef);
+       const ItemDefinition &hand_def =
+               hlist ? hlist->getItem(0).getDefinition(m_itemdef) : m_itemdef->get("");
+
+       float max_d = BS * playeritem_def.range;
+       float max_d_hand = BS * hand_def.range;
+
+       if (max_d < 0 && max_d_hand >= 0)
+               max_d = max_d_hand;
+       else if (max_d < 0)
+               max_d = BS * 4.0f;
+
+       // cube diagonal: sqrt(3) = 1.732
+       if (d > max_d * 1.732) {
+               actionstream << "Player " << player->getName()
+                               << " tried to access " << what
+                               << " from too far: "
+                               << "d=" << d <<", max_d=" << max_d
+                               << ". ignoring." << std::endl;
+               // Call callbacks
+               m_script->on_cheat(playersao, "interacted_too_far");
+               return false;
+       }
+       return true;
+}
+
 void Server::handleCommand_Interact(NetworkPacket* pkt)
 {
        /*
@@ -1065,33 +1108,13 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                        !g_settings->getBool("disable_anticheat");
 
        if ((action == 0 || action == 2 || action == 3 || action == 4) &&
-                       (enable_anticheat && !isSingleplayer())) {
+                       enable_anticheat && !isSingleplayer()) {
                float d = player_pos.getDistanceFrom(pointed_pos_under);
-               const ItemDefinition &playeritem_def =
-                       playersao->getWieldedItem().getDefinition(m_itemdef);
-               float max_d = BS * playeritem_def.range;
-               InventoryList *hlist = playersao->getInventory()->getList("hand");
-               const ItemDefinition &hand_def =
-                       hlist ? (hlist->getItem(0).getDefinition(m_itemdef)) : (m_itemdef->get(""));
-               float max_d_hand = BS * hand_def.range;
-               if (max_d < 0 && max_d_hand >= 0)
-                       max_d = max_d_hand;
-               else if (max_d < 0)
-                       max_d = BS * 4.0f;
-               // cube diagonal: sqrt(3) = 1.73
-               if (d > max_d * 1.73) {
-                       actionstream << "Player " << player->getName()
-                                       << " tried to access " << pointed.dump()
-                                       << " from too far: "
-                                       << "d=" << d <<", max_d=" << max_d
-                                       << ". ignoring." << std::endl;
+               if (!checkInteractDistance(player, d, pointed.dump())) {
                        // Re-send block to revert change on client-side
                        RemoteClient *client = getClient(pkt->getPeerId());
                        v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
                        client->SetBlockNotSent(blockpos);
-                       // Call callbacks
-                       m_script->on_cheat(playersao, "interacted_too_far");
-                       // Do nothing else
                        return;
                }
        }
index 86f558d544048aef0f2175c498c890dc73f8621d..ae7511bdf160de61a976ae4b052cd742f3ec303c 100644 (file)
@@ -464,6 +464,7 @@ private:
        void RespawnPlayer(session_t peer_id);
        void DeleteClient(session_t peer_id, ClientDeletionReason reason);
        void UpdateCrafting(RemotePlayer *player);
+       bool checkInteractDistance(RemotePlayer *player, const f32 d, const std::string what);
 
        void handleChatInterfaceEvent(ChatEvent *evt);