From 1b2d24791a4b6c625e694db83aa85afb8ed1818f Mon Sep 17 00:00:00 2001 From: Zemtzov7 <72821250+zmv7@users.noreply.github.com> Date: Fri, 11 Oct 2024 15:01:22 +0500 Subject: [PATCH] Separate anticheat settings (#15040) --- builtin/settingtypes.txt | 9 +++++++-- src/defaultsettings.cpp | 5 ++++- src/migratesettings.h | 9 +++++++++ src/network/serverpackethandler.cpp | 8 ++++---- src/server.h | 14 ++++++++++++++ src/server/player_sao.cpp | 10 +++++++++- 6 files changed, 47 insertions(+), 8 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 1813a6cdf..f7225ef62 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -884,8 +884,13 @@ default_privs (Default privileges) string interact, shout # Privileges that players with basic_privs can grant basic_privs (Basic privileges) string interact, shout -# If enabled, disable cheat prevention in multiplayer. -disable_anticheat (Disable anticheat) bool false +# Server anticheat configuration. +# Flags are positive. Uncheck the flag to disable corresponding anticheat module. +anticheat_flags (Anticheat flags) flags digging,interaction,movement digging,interaction,movement + +# Tolerance of movement cheat detector. +# Increase the value if players experience stuttery movement. +anticheat_movement_tolerance (Anticheat movement tolerance) float 1.0 1.0 # If enabled, actions are recorded for rollback. # This option is only read when server starts. diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 2915caa48..049359ef1 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "mapgen/mapgen.h" // Mapgen::setDefaultSettings #include "util/string.h" +#include "server.h" /* @@ -459,7 +460,9 @@ void set_default_settings() settings->setDefault("enable_pvp", "true"); settings->setDefault("enable_mod_channels", "false"); settings->setDefault("disallow_empty_password", "false"); - settings->setDefault("disable_anticheat", "false"); + settings->setDefault("anticheat_flags", flagdesc_anticheat, + AC_DIGGING | AC_INTERACTION | AC_MOVEMENT); + settings->setDefault("anticheat_movement_tolerance", "1.0"); settings->setDefault("enable_rollback_recording", "false"); settings->setDefault("deprecated_lua_api_handling", "log"); diff --git a/src/migratesettings.h b/src/migratesettings.h index d4488702f..5f6396914 100644 --- a/src/migratesettings.h +++ b/src/migratesettings.h @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-2.1-or-later #include "settings.h" +#include "server.h" void migrate_settings() { @@ -19,4 +20,12 @@ void migrate_settings() g_settings->setBool("touch_gui", value); g_settings->remove("enable_touch"); } + + // Disables anticheat + if (g_settings->existsLocal("disable_anticheat")) { + if (g_settings->getBool("disable_anticheat")) { + g_settings->setFlagStr("anticheat_flags", 0, flagdesc_anticheat); + } + g_settings->remove("disable_anticheat"); + } } diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index d1e1ddacb..449e164b6 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -1011,12 +1011,12 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) /* Check that target is reasonably close */ - static thread_local const bool enable_anticheat = - !g_settings->getBool("disable_anticheat"); + static thread_local const u32 anticheat_flags = + g_settings->getFlagStr("anticheat_flags", flagdesc_anticheat, nullptr); if ((action == INTERACT_START_DIGGING || action == INTERACT_DIGGING_COMPLETED || action == INTERACT_PLACE || action == INTERACT_USE) && - enable_anticheat && !isSingleplayer()) { + (anticheat_flags & AC_INTERACTION) && !isSingleplayer()) { v3f target_pos = player_pos; if (pointed.type == POINTEDTHING_NODE) { target_pos = intToFloat(pointed.node_undersurface, BS); @@ -1119,7 +1119,7 @@ void Server::handleCommand_Interact(NetworkPacket *pkt) /* Cheat prevention */ bool is_valid_dig = true; - if (enable_anticheat && !isSingleplayer()) { + if ((anticheat_flags & AC_DIGGING) && !isSingleplayer()) { v3s16 nocheat_p = playersao->getNoCheatDigPos(); float nocheat_t = playersao->getNoCheatDigTime(); playersao->noCheatDigEnd(); diff --git a/src/server.h b/src/server.h index 10db9e208..f2a9083b6 100644 --- a/src/server.h +++ b/src/server.h @@ -81,6 +81,20 @@ struct PackedValue; struct ParticleParameters; struct ParticleSpawnerParameters; +// Anticheat flags +enum { + AC_DIGGING = 0x01, + AC_INTERACTION = 0x02, + AC_MOVEMENT = 0x04 +}; + +constexpr const static FlagDesc flagdesc_anticheat[] = { + {"digging", AC_DIGGING}, + {"interaction", AC_INTERACTION}, + {"movement", AC_MOVEMENT}, + {NULL, 0} +}; + enum ClientDeletionReason { CDR_LEAVE, CDR_TIMEOUT, diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 61d328ca7..57b39d403 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -646,9 +646,12 @@ void PlayerSAO::setMaxSpeedOverride(const v3f &vel) bool PlayerSAO::checkMovementCheat() { + static thread_local const u32 anticheat_flags = + g_settings->getFlagStr("anticheat_flags", flagdesc_anticheat, nullptr); + if (m_is_singleplayer || isAttached() || - g_settings->getBool("disable_anticheat")) { + !(anticheat_flags & AC_MOVEMENT)) { m_last_good_position = m_base_position; return false; } @@ -729,6 +732,11 @@ bool PlayerSAO::checkMovementCheat() required_time = MYMAX(required_time, d_vert / s); } + static thread_local float anticheat_movement_tolerance = + std::max(g_settings->getFloat("anticheat_movement_tolerance"), 1.0f); + + required_time /= anticheat_movement_tolerance; + if (m_move_pool.grab(required_time)) { m_last_good_position = m_base_position; } else {