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 themmaster
parent
b95f543da9
commit
b16252dcae
|
@ -2036,9 +2036,10 @@ Call these functions only at load time!
|
||||||
* `minetest.register_on_cheat(func(ObjectRef, cheat))`
|
* `minetest.register_on_cheat(func(ObjectRef, cheat))`
|
||||||
* Called when a player cheats
|
* Called when a player cheats
|
||||||
* `cheat`: `{type=<cheat_type>}`, where `<cheat_type>` is one of:
|
* `cheat`: `{type=<cheat_type>}`, where `<cheat_type>` is one of:
|
||||||
* `"moved_too_fast"`
|
* `moved_too_fast`
|
||||||
* `"interacted_too_far"`
|
* `interacted_too_far`
|
||||||
* `"finished_unknown_dig"`
|
* `interacted_while_dead`
|
||||||
|
* `finished_unknown_dig`
|
||||||
* `dug_unbreakable`
|
* `dug_unbreakable`
|
||||||
* `dug_too_fast`
|
* `dug_too_fast`
|
||||||
* `minetest.register_on_chat_message(func(name, message))`
|
* `minetest.register_on_chat_message(func(name, message))`
|
||||||
|
|
|
@ -1021,6 +1021,15 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
|
||||||
delete a;
|
delete a;
|
||||||
return;
|
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
|
Handle restrictions and special cases of the craft action
|
||||||
|
@ -1313,6 +1322,7 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
|
||||||
2: digging completed
|
2: digging completed
|
||||||
3: place block or item (to abovesurface)
|
3: place block or item (to abovesurface)
|
||||||
4: use item
|
4: use item
|
||||||
|
5: rightclick air ("activate")
|
||||||
*/
|
*/
|
||||||
u8 action;
|
u8 action;
|
||||||
u16 item_i;
|
u16 item_i;
|
||||||
|
@ -1345,8 +1355,16 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playersao->isDead()) {
|
if (playersao->isDead()) {
|
||||||
verbosestream << "TOSERVER_INTERACT: " << player->getName()
|
actionstream << "Server: NoCheat: " << player->getName()
|
||||||
<< " is dead. Ignoring packet";
|
<< " 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1384,32 +1402,6 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
|
||||||
pointed_pos_above = pointed_pos_under;
|
pointed_pos_above = pointed_pos_under;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
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) &&
|
|
||||||
(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) {
|
|
||||||
actionstream << "Player " << player->getName()
|
|
||||||
<< " tried to access " << pointed.dump()
|
|
||||||
<< " from too far: "
|
|
||||||
<< "d=" << d <<", max_d=" << max_d
|
|
||||||
<< ". ignoring." << std::endl;
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Make sure the player is allowed to do it
|
Make sure the player is allowed to do it
|
||||||
*/
|
*/
|
||||||
|
@ -1432,6 +1424,39 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
|
||||||
return;
|
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 || action == 4) &&
|
||||||
|
(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;
|
||||||
|
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: "
|
||||||
|
<< "d=" << d <<", max_d=" << max_d
|
||||||
|
<< ". ignoring." << std::endl;
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If something goes wrong, this player is to blame
|
If something goes wrong, this player is to blame
|
||||||
*/
|
*/
|
||||||
|
@ -1443,11 +1468,6 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
|
||||||
*/
|
*/
|
||||||
if (action == 0) {
|
if (action == 0) {
|
||||||
if (pointed.type == POINTEDTHING_NODE) {
|
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);
|
MapNode n(CONTENT_IGNORE);
|
||||||
bool pos_ok;
|
bool pos_ok;
|
||||||
|
|
||||||
|
|
|
@ -2557,15 +2557,15 @@ void Server::RespawnPlayer(u16 peer_id)
|
||||||
playersao->setHP(PLAYER_MAX_HP);
|
playersao->setHP(PLAYER_MAX_HP);
|
||||||
playersao->setBreath(PLAYER_MAX_BREATH);
|
playersao->setBreath(PLAYER_MAX_BREATH);
|
||||||
|
|
||||||
SendPlayerHP(peer_id);
|
|
||||||
SendPlayerBreath(peer_id);
|
|
||||||
|
|
||||||
bool repositioned = m_script->on_respawnplayer(playersao);
|
bool repositioned = m_script->on_respawnplayer(playersao);
|
||||||
if(!repositioned){
|
if (!repositioned) {
|
||||||
v3f pos = findSpawnPos();
|
v3f pos = findSpawnPos();
|
||||||
// setPos will send the new position to client
|
// setPos will send the new position to client
|
||||||
playersao->setPos(pos);
|
playersao->setPos(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SendPlayerHP(peer_id);
|
||||||
|
SendPlayerBreath(peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue