]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/network/serverpackethandler.cpp
Various anticheat improvements
[dragonfireclient.git] / src / network / serverpackethandler.cpp
index d56424b75f076ee558ee76515df7c9476f49ebf2..f99e104ec5b7259db1a8f40758d12024ec9b7d81 100644 (file)
@@ -782,6 +782,7 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
 
        v3s32 ps, ss;
        s32 f32pitch, f32yaw;
+       u8 f32fov;
 
        *pkt >> ps;
        *pkt >> ss;
@@ -792,8 +793,18 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
        f32 yaw = (f32)f32yaw / 100.0;
        u32 keyPressed = 0;
 
+       // default behavior (in case an old client doesn't send these)
+       f32 fov = 0;
+       u8 wanted_range = 0;
+
        if (pkt->getRemainingBytes() >= 4)
                *pkt >> keyPressed;
+       if (pkt->getRemainingBytes() >= 1) {
+               *pkt >> f32fov;
+               fov = (f32)f32fov / 80.0;
+       }
+       if (pkt->getRemainingBytes() >= 1)
+               *pkt >> wanted_range;
 
        v3f position((f32)ps.X / 100.0, (f32)ps.Y / 100.0, (f32)ps.Z / 100.0);
        v3f speed((f32)ss.X / 100.0, (f32)ss.Y / 100.0, (f32)ss.Z / 100.0);
@@ -805,6 +816,8 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
        player->setSpeed(speed);
        playersao->setPitch(pitch);
        playersao->setYaw(yaw);
+       playersao->setFov(fov);
+       playersao->setWantedRange(wanted_range);
        player->keyPressed = keyPressed;
        player->control.up = (keyPressed & 1);
        player->control.down = (keyPressed & 2);
@@ -1008,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
@@ -1300,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;
@@ -1332,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;
        }
 
@@ -1371,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: "
@@ -1397,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
        */
@@ -1430,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;
 
@@ -1529,10 +1562,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
                                        m_script->on_cheat(playersao, "finished_unknown_dig");
                                }
                                // Get player's wielded item
-                               ItemStack playeritem;
-                               InventoryList *mlist = playersao->getInventory()->getList("main");
-                               if (mlist != NULL)
-                                       playeritem = mlist->getItem(playersao->getWieldIndex());
+                               ItemStack playeritem = playersao->getWieldedItem();
                                ToolCapabilities playeritem_toolcap =
                                                playeritem.getToolCapabilities(m_itemdef);
                                // Get diggability and expected digging time