Add server-side anti-cheat evidence scoring
This commit is contained in:
@@ -347,6 +347,9 @@ void CHARACTER::Initialize()
|
||||
m_dwLastComboTime = 0;
|
||||
m_bComboIndex = 0;
|
||||
m_iComboHackCount = 0;
|
||||
m_iAntiCheatScore = 0;
|
||||
m_dwLastAntiCheatScoreTime = 0;
|
||||
m_dwLastAntiCheatPersistTime = 0;
|
||||
m_dwSkipComboAttackByTime = 0;
|
||||
|
||||
m_dwMountTime = 0;
|
||||
@@ -7238,6 +7241,68 @@ void CHARACTER::ResetComboHackCount()
|
||||
m_iComboHackCount = 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr int kAntiCheatMaxScore = 1000;
|
||||
constexpr int kAntiCheatDisconnectScore = 100;
|
||||
constexpr DWORD kAntiCheatDecayIntervalMs = 15000;
|
||||
constexpr DWORD kAntiCheatPersistIntervalMs = 5000;
|
||||
}
|
||||
|
||||
void CHARACTER::DecayAntiCheatScore(DWORD dwNow)
|
||||
{
|
||||
if (0 == m_dwLastAntiCheatScoreTime)
|
||||
{
|
||||
m_dwLastAntiCheatScoreTime = dwNow;
|
||||
return;
|
||||
}
|
||||
|
||||
const DWORD dwElapsed = dwNow - m_dwLastAntiCheatScoreTime;
|
||||
if (dwElapsed < kAntiCheatDecayIntervalMs)
|
||||
return;
|
||||
|
||||
const int iDecaySteps = dwElapsed / kAntiCheatDecayIntervalMs;
|
||||
m_iAntiCheatScore = MAX(0, m_iAntiCheatScore - iDecaySteps);
|
||||
m_dwLastAntiCheatScoreTime += iDecaySteps * kAntiCheatDecayIntervalMs;
|
||||
}
|
||||
|
||||
void CHARACTER::RecordAntiCheatViolation(const char* category, int score, const char* detail, bool forcePersist)
|
||||
{
|
||||
const DWORD dwNow = get_dword_time();
|
||||
DecayAntiCheatScore(dwNow);
|
||||
|
||||
if (score <= 0)
|
||||
score = 1;
|
||||
|
||||
m_iAntiCheatScore = MIN(kAntiCheatMaxScore, m_iAntiCheatScore + score);
|
||||
|
||||
char szReason[512];
|
||||
snprintf(szReason,
|
||||
sizeof(szReason),
|
||||
"ANTI_CHEAT[%s] score=%d map=%ld pos=(%ld,%ld) detail=%s",
|
||||
category ? category : "UNKNOWN",
|
||||
m_iAntiCheatScore,
|
||||
static_cast<long>(GetMapIndex()),
|
||||
static_cast<long>(GetX()),
|
||||
static_cast<long>(GetY()),
|
||||
detail ? detail : "-");
|
||||
|
||||
sys_log(0, "%s pid=%u name=%s", szReason, GetPlayerID(), GetName());
|
||||
|
||||
const bool shouldPersist = forcePersist || (GetDesc() && dwNow - m_dwLastAntiCheatPersistTime >= kAntiCheatPersistIntervalMs);
|
||||
if (shouldPersist && GetDesc())
|
||||
{
|
||||
LogManager::instance().HackLog(szReason, this);
|
||||
m_dwLastAntiCheatPersistTime = dwNow;
|
||||
}
|
||||
|
||||
if (GetDesc() && m_iAntiCheatScore >= kAntiCheatDisconnectScore)
|
||||
{
|
||||
if (GetDesc()->DelayedDisconnect(number(3, 8)))
|
||||
sys_log(0, "ANTI_CHEAT_DISCONNECT: %s score=%d", GetName(), m_iAntiCheatScore);
|
||||
}
|
||||
}
|
||||
|
||||
void CHARACTER::SkipComboAttackByTime(int interval)
|
||||
{
|
||||
m_dwSkipComboAttackByTime = get_dword_time() + interval;
|
||||
|
||||
Reference in New Issue
Block a user