]> git.lizzy.rs Git - dragonfireclient.git/commitdiff
Various anticheat improvements
authorsfan5 <sfan5@live.de>
Thu, 22 Dec 2016 18:29:15 +0000 (19:29 +0100)
committersfan5 <sfan5@live.de>
Mon, 26 Dec 2016 21:34:29 +0000 (22:34 +0100)
* 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

doc/lua_api.txt
src/network/serverpackethandler.cpp
src/server.cpp

index 34c64b8dfc2df35eba6d8f16bdd63c874995da53..d2ddc635b3c04d9de6e50d9fce412887a34a75af 100644 (file)
@@ -2036,9 +2036,10 @@ Call these functions only at load time!
 * `minetest.register_on_cheat(func(ObjectRef, cheat))`
     * Called when a player cheats
     * `cheat`: `{type=<cheat_type>}`, where `<cheat_type>` is one of:
-        * `"moved_too_fast"`
-        * `"interacted_too_far"`
-        * `"finished_unknown_dig"`
+        * `moved_too_fast`
+        * `interacted_too_far`
+        * `interacted_while_dead`
+        * `finished_unknown_dig`
         * `dug_unbreakable`
         * `dug_too_fast`
 * `minetest.register_on_chat_message(func(name, message))`
index dca9aabc48a853fcb3a4327091201970a2879a77..f99e104ec5b7259db1a8f40758d12024ec9b7d81 100644 (file)
@@ -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<<player->getName()<<" attempted to interact with "
+                               <<pointed.dump()<<" without 'interact' privilege"
+                               <<std::endl;
+               // Re-send block to revert change on client-side
+               RemoteClient *client = getClient(pkt->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<<player->getName()<<" attempted to interact with "
-                               <<pointed.dump()<<" without 'interact' privilege"
-                               <<std::endl;
-               // Re-send block to revert change on client-side
-               RemoteClient *client = getClient(pkt->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;
 
index c9d5c7129dbe3b57d58b5209f97d00efec74ee59..fa7a838d428cfa673932ca962ab539c268baa116 100644 (file)
@@ -2557,15 +2557,15 @@ void Server::RespawnPlayer(u16 peer_id)
        playersao->setHP(PLAYER_MAX_HP);
        playersao->setBreath(PLAYER_MAX_BREATH);
 
-       SendPlayerHP(peer_id);
-       SendPlayerBreath(peer_id);
-
        bool repositioned = m_script->on_respawnplayer(playersao);
-       if(!repositioned){
+       if (!repositioned) {
                v3f pos = findSpawnPos();
                // setPos will send the new position to client
                playersao->setPos(pos);
        }
+
+       SendPlayerHP(peer_id);
+       SendPlayerBreath(peer_id);
 }