aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsfan5 <sfan5@live.de>2016-12-22 19:29:15 +0100
committersfan5 <sfan5@live.de>2016-12-26 22:34:29 +0100
commitb16252dcae8c6b0e79c20fa4c3cbddc37ad377cb (patch)
treeef25171c52f75d86150a0e607579dc0ec6e5a073
parentb95f543da9d56974c4db8e34ce93e6f3bf7e776c (diff)
downloadminetest-b16252dcae8c6b0e79c20fa4c3cbddc37ad377cb.tar.gz
minetest-b16252dcae8c6b0e79c20fa4c3cbddc37ad377cb.tar.bz2
minetest-b16252dcae8c6b0e79c20fa4c3cbddc37ad377cb.zip
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
-rw-r--r--doc/lua_api.txt7
-rw-r--r--src/network/serverpackethandler.cpp84
-rw-r--r--src/server.cpp8
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);
}