diff options
-rw-r--r-- | doc/lua_api.txt | 7 | ||||
-rw-r--r-- | src/network/serverpackethandler.cpp | 84 | ||||
-rw-r--r-- | src/server.cpp | 8 |
3 files changed, 60 insertions, 39 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 34c64b8df..d2ddc635b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -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))` 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; } @@ -1385,15 +1403,44 @@ 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; + } + + /* 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: " @@ -1411,28 +1458,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 */ RollbackScopeActor rollback_scope(m_rollback, @@ -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; diff --git a/src/server.cpp b/src/server.cpp index c9d5c7129..fa7a838d4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -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); } |