Skip to content

Add server-side anti-cheat framework (movement/physics/spell/item det…#387

Open
Krilliac wants to merge 5 commits into
mangoszero:masterfrom
Krilliac:feature/anticheat-core
Open

Add server-side anti-cheat framework (movement/physics/spell/item det…#387
Krilliac wants to merge 5 commits into
mangoszero:masterfrom
Krilliac:feature/anticheat-core

Conversation

@Krilliac

@Krilliac Krilliac commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

…ection + enforcement)

Introduces a config-gated, server-side anti-cheat / movement-validation framework. OFF by default (AntiCheat.Enable = 0) — fully inert until enabled.

Core pieces:

  • AntiCheatMgr: central scoring manager. Detectors only observe and score via a single RecordViolation() ingress; the manager owns ALL enforcement. Score decays over time and escalates through capped actions (log -> GM alert -> rubberband to last validated position -> kick), with an optional account-level autoban accumulator (escalating ban durations, slow hourly decay).
  • MovementAnticheat: per-player validator running cheap, event-driven detectors on each movement packet — fly/flag-spoof (water-walk/hover/slow-fall/transport/ swim, aura- or grant-aware), teleport/blink, speed, acceleration gate, vertical climb, root/stun-break, opcode-legality, no-clip (VMap LoS), jump (infinite/ mid-air), fall-damage suppression, packet burst, client-timestamp regression, bot-movement heuristic, and spell-cast timing (GCD bypass + cast spam).
  • PhysicsValidator: side-effect-free terrain-plausibility stage (float-above / below-surface), invoked only on suspicion to stay off the hot path.

Integration: movement validation in the movement opcode handler; spell-injection, item-in-trade, GO-use and NPC interaction-distance hooks; cast-timing hook; server-granted movement flags recorded in the Player Set* setters so the flag-spoof detectors don't fire on legit grants; a rolling latency EWMA fed from CMSG_PING for latency-aware tolerances. GM commands: .anticheat status / report / reload / warn / jail / unjail / delete. Violations persist to character_anticheat_violation; account autoban state to account_anticheat.

Time-sync, the spoof/test GM tooling, and the violation-marker visualizer are follow-ups that build additively on this core.


This change is Reviewable

@codacy-production

codacy-production Bot commented Jun 21, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 275 complexity · 2 duplication

Metric Results
Complexity 275
Duplication 2

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

…ection + enforcement)

Introduces a config-gated, server-side anti-cheat / movement-validation
framework. OFF by default (AntiCheat.Enable = 0) — fully inert until enabled.

Core pieces:
- AntiCheatMgr: central scoring manager. Detectors only observe and score via
  a single RecordViolation() ingress; the manager owns ALL enforcement. Score
  decays over time and escalates through capped actions (log -> GM alert ->
  rubberband to last validated position -> kick), with an optional account-level
  autoban accumulator (escalating ban durations, slow hourly decay).
- MovementAnticheat: per-player validator running cheap, event-driven detectors
  on each movement packet — fly/flag-spoof (water-walk/hover/slow-fall/transport/
  swim, aura- or grant-aware), teleport/blink, speed, acceleration gate, vertical
  climb, root/stun-break, opcode-legality, no-clip (VMap LoS), jump (infinite/
  mid-air), fall-damage suppression, packet burst, client-timestamp regression,
  bot-movement heuristic, and spell-cast timing (GCD bypass + cast spam).
- PhysicsValidator: side-effect-free terrain-plausibility stage (float-above /
  below-surface), invoked only on suspicion to stay off the hot path.

Integration: movement validation in the movement opcode handler; spell-injection,
item-in-trade, GO-use and NPC interaction-distance hooks; cast-timing hook;
server-granted movement flags recorded in the Player Set* setters so the
flag-spoof detectors don't fire on legit grants; a rolling latency EWMA fed from
CMSG_PING for latency-aware tolerances. GM commands: .anticheat status / report /
reload / warn / jail / unjail / delete. Violations persist to
character_anticheat_violation; account autoban state to account_anticheat.

Time-sync, the spoof/test GM tooling, and the violation-marker visualizer are
follow-ups that build additively on this core.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@AppVeyorBot

Copy link
Copy Markdown

@billy1arm billy1arm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac all sql files should be added to the database repo as a matching pr.

Krilliac and others added 2 commits July 2, 2026 01:30
Per project policy (CLAUDE.md) and review feedback, DB schema belongs in the
separate mangoszero/database repo as a matching migration PR, not in the server
tree. Remove account_anticheat.sql and character_anticheat_violation.sql. No
code or build references them (the tables are provisioned via the database
repo). This also clears the Codacy 'Compatibility' findings raised against the
SQL files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GD6LV6acKwGd426dDQGPDF
# Conflicts:
#	cmake/MangosParams.cmake
#	src/game/WorldHandlers/Chat.cpp
#	src/game/WorldHandlers/Chat.h
#	src/game/WorldHandlers/World.cpp
#	src/game/WorldHandlers/World.h
@AppVeyorBot

Copy link
Copy Markdown

bool AntiCheatMgr::IsExempt(Player* player) const
{
if (!player)
return true;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces

// ExemptGMLevel == 0 means "exempt nobody by level" (every account is >= 0,
// so without this guard a value of 0 would exempt everyone).
if (m_exemptGmLevel > 0 && player->GetSession() &&
player->GetSession()->GetSecurity() >= (AccountTypes)m_exemptGmLevel)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces


// A GM with .gm on is also exempt regardless of level.
if (player->isGameMaster())
return true;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces

float weight, AntiCheatContext const& ctx)
{
if (!player)
return;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces

AlertGMs(player, type, score, ctx);
// Anti-gaming autoban: count this kick against the account first.
if (m_autobanEnable)
AccumulateKick(player);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces

@billy1arm billy1arm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Multiple Coding standard violations: missing opening/closing braces

Addresses review feedback on PR mangoszero#387 (billy1arm): the project coding standard
(doc/CodingStandard.md) requires brackets around single statements. Brace every
brace-less if/else/loop body in AntiCheatMgr.cpp (IsExempt, RecordViolation
guards + weight clamp, Apply kick path, Update prune/ban loop, AccumulateKick,
LoadAccounts). No behavioural change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GD6LV6acKwGd426dDQGPDF
Krilliac added a commit to Krilliac/server-Zero that referenced this pull request Jul 2, 2026
Addresses review feedback on PR mangoszero#387 (billy1arm): the project coding standard
(doc/CodingStandard.md) requires brackets around single statements. Brace every
brace-less if/else/loop body in AntiCheatMgr.cpp (IsExempt, RecordViolation
guards + weight clamp, Apply kick path, Update prune/ban loop, AccumulateKick,
LoadAccounts). No behavioural change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GD6LV6acKwGd426dDQGPDF
Krilliac added a commit to Krilliac/server-Zero that referenced this pull request Jul 2, 2026
Addresses review feedback on PR mangoszero#387 (billy1arm): the project coding standard
(doc/CodingStandard.md) requires brackets around single statements. Brace every
brace-less if/else/loop body in AntiCheatMgr.cpp (IsExempt, RecordViolation
guards + weight clamp, Apply kick path, Update prune/ban loop, AccumulateKick,
LoadAccounts). No behavioural change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GD6LV6acKwGd426dDQGPDF

@billy1arm billy1arm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac There are quite a few Coding standard violations, mostly missing opening / closing braces

MovementInfo const& mi, const char** reason)
{
if (!player || !player->IsInWorld())
return AC_PHYS_OK;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces

// Falling/flying/swimming/transport legitimately deviate from the
// heightmap, so we do not judge them here.
if (state != AC_MOVE_GROUND)
return AC_PHYS_OK;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces, more in file

{
Player* target = getSelectedPlayer();
if (!target)
target = m_session ? m_session->GetPlayer() : NULL;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces

name = args;
ObjectGuid og = sObjectMgr.GetPlayerGuidByName(name);
if (og)
guid = og.GetCounter();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces, possibly more in file

MovementAnticheat* Player::GetMovementAnticheat()
{
if (!m_movementAnticheat)
m_movementAnticheat = new MovementAnticheat(this);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces

m_latSamples[m_latIdx] = sampleMS;
m_latIdx = (m_latIdx + 1) % LATENCY_WINDOW;
if (m_latCount < LATENCY_WINDOW)
++m_latCount;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces. More in file

// Anti-Cheat: per-player movement validation (observe + score; never rejects
// packets). Inert unless the framework is enabled in config.
if (plMover && sAntiCheatMgr->MovementEnabled() && !sAntiCheatMgr->IsExempt(plMover))
plMover->GetMovementAnticheat()->HandlePositionUpdate(opcode, movementInfo);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Krilliac Coding standard violation: missing opening / closing braces

@Krilliac

Krilliac commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

@billy1arm good now?

@AppVeyorBot

Copy link
Copy Markdown

# Conflicts:
#	src/game/Object/Player.cpp
#	src/game/WorldHandlers/World.cpp
@AppVeyorBot

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants