feat: Add cheat detection knowledge (#2034)

* feat: Add cheat detection knowledge

tested that getting kicked correctly displays the reasons why and their corresponding values
tested that a user with developer permissions is not kicked for said funness
tested that logs are correct for those funness values which i could actually trigger

* fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
David Markowitz
2026-09-18 02:30:59 -07:00
committed by GitHub
parent 8f2004c9a3
commit 057de71773
4 changed files with 89 additions and 9 deletions

View File

@@ -82,6 +82,7 @@
#include "SlashCommandHandler.h"
#include "InventoryComponent.h"
#include "Item.h"
#include "eFunnessTypes.h"
namespace Game {
Logger* logger = nullptr;
@@ -1427,16 +1428,61 @@ void HandlePacket(Packet* packet) {
//Could be insane lag, but I'mma just YEET them as it's usually speedhacking.
//This is updated to now count the amount of times we've been caught "speedhacking" to kick with a delay
//This is hopefully going to fix the random disconnects people face sometimes.
if (Game::config->GetValue("disable_anti_speedhack") == "1") {
CINSTREAM_SKIP_HEADER;
CaughtFunness funness;
inStream.Read(funness.cheatInfo);
inStream.Read(funness.cheatType);
const auto [cheatType, cheatInfo] = funness;
LOG_DEBUG("Received cheat type %s with info %f", StringifiedEnum::ToString(cheatType).data(), cheatInfo);
const auto disabledCheats = Game::config->GetValue("disable_anti_speedhack") == "1";
User* user = UserManager::Instance()->GetUser(packet->systemAddress);
if (!user) {
Game::server->Disconnect(packet->systemAddress, eServerDisconnectIdentifiers::KICK);
return;
}
User* user = UserManager::Instance()->GetUser(packet->systemAddress);
if (user) {
user->UserOutOfSync();
} else {
Game::server->Disconnect(packet->systemAddress, eServerDisconnectIdentifiers::KICK);
const auto* const character = user->GetLastUsedChar();
if (character) {
const auto dcUser = [](const User& user, const SystemAddress& sysAddr) {
if (user.GetMaxGMLevel() < eGameMasterLevel::DEVELOPER) {
Game::server->Disconnect(sysAddr, eServerDisconnectIdentifiers::KICK);
}
};
if (cheatType == eFunnessTypes::DebuggerActive) {
LOG("Player %s was detected to be using a debugger (funness thread was %f seconds longer than expected deviation).", character->GetName().c_str(), cheatInfo);
// Immediately kick unless they are a gm
if (!disabledCheats) dcUser(*user, packet->systemAddress);
} else if (cheatType == eFunnessTypes::FdbFailedChecksum) {
LOG("Player %s has failed the fdb checksum after passing it to sign into this server, highly likely cheating.", character->GetName().c_str());
// Immedately kick unless they are a gm
if (!disabledCheats) dcUser(*user, packet->systemAddress);
} else if (cheatType == eFunnessTypes::RacingBoostTimeTooLong) {
if (cheatInfo == 0.0f) LOG("Player %s has enabled a speedboost for far too long (> 3.501 seconds).", character->GetName().c_str());
else if (cheatInfo == 1.0f) LOG("Unknown racing boost/speed variable was tampered with.");
else if (cheatInfo == 2.0f) LOG("Player vehicle top speed was tampered with.");
if (!disabledCheats) dcUser(*user, packet->systemAddress);
} else if (cheatType == eFunnessTypes::SomeRacingManipCheat) {
if (cheatInfo >= 0.0f && cheatInfo <= 6.0f) LOG("Cheat RNG value A does not match what it should be %f.", cheatInfo);
else if (cheatInfo >= 7.0f && cheatInfo <= 10.0f) LOG("Cheat RNG value B does not match what it should be %f.", cheatInfo);
} else if (cheatType == eFunnessTypes::Unknown_9) {
LOG("Racing cheat 9 detected with value %f.", cheatInfo);
} else if (cheatType == eFunnessTypes::Unknown_10) {
LOG("Racing cheat 10 detected with value %f.", cheatInfo);
} else if (cheatType == eFunnessTypes::CharacterPosLength) {
LOG("Detected pos length of %f which is greater than the expected value 1.0f, not normal!", cheatInfo);
} else if (cheatType == eFunnessTypes::CharacterVelLength) {
LOG("Detected vel length of %f which is greater than the expected value 1.0f, not normal!", cheatInfo);
} else if (cheatType == eFunnessTypes::CharacterGravityScale) {
LOG("Detected gravity scale difference of %f which is greater than the expected value of 0.0f, not normal!", cheatInfo);
} else if (cheatType == eFunnessTypes::CharacterRunMultiplier) {
LOG("Detected run multiplier difference of %f which is greater than the expected value 0.0f, not normal!", cheatInfo);
}
if (!disabledCheats && user->GetMaxGMLevel() < eGameMasterLevel::DEVELOPER) user->UserOutOfSync(funness);
}
break;
}