Skip to content

Add automatic punishment ladder for repeat anticheat violations - #268

Merged
Zaldaryon merged 1 commit into
indevfrom
feat/anticheat-punishment-ladder
Aug 19, 2026
Merged

Add automatic punishment ladder for repeat anticheat violations#268
Zaldaryon merged 1 commit into
indevfrom
feat/anticheat-punishment-ladder

Conversation

@Zaldaryon

@Zaldaryon Zaldaryon commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an opt-in escalation ladder for players who keep accumulating confirmed anticheat flags: inventory drop/wipe, then freeze, then jail, then a timed ban, in that order, based on a persistent per-player flag count that survives relogs and restarts.

Every action the ladder takes reuses an existing, already-tested primitive:

  • Inventory drop/wipe: InventoryBase.DropAll/Clear, same as normal death handling, skipping the creative inventory the same way EntityPlayer.WalkInventory already does.
  • Freeze: StratumStaffCommandState.Freeze, the same as /freeze.
  • Jail: a new CmdStratumStaffCommands.JailAutomatically entry point that reuses the existing TryGetJailLocation + JailSingleTarget methods unchanged, reached through a minimal internal static Instance reference since the active-jail tracking and enforcement tick loop are instance state with no prior external access point.
  • Ban: PlayerDataManager.BanPlayer + DisconnectPlayer, same as /ban.

Nothing new is invented for enforcement; only the threshold ladder and the persistent standing behind it are new.

Standing is tracked separately from StratumAnticheatReporter's existing in-memory PlayerViolations dictionary, which is intentionally rolling and prunes a player out after KeepPlayerViolationsMinutes of inactivity. A new StratumAnticheatHistory store persists TotalFlags and the highest tier already applied in CustomPlayerData, the same pattern StratumModerationStore/StratumCustodyStore already use, so a repeat offender who logs off can't reset their standing by relogging.

The escalation check runs synchronously right after RecordViolation's lock releases, in the same place every Record*Violation call site already calls DisconnectPlayer directly for KickConfirmedCheats today. That existing pattern already proves the calling context is safe for real game-state actions, not only logging, so this needed no new queue or deferred-execution scheduling.

/stratum ac <player> now also shows accumulated flags and the next tier due. StratumRuntime's config safety check gained four warnings for risky combinations: punishments enabled while anticheat itself is disabled, wipe-instead-of-drop, a very low first threshold, and a permanent (non-recovering) ban duration.

Off by default (Anticheat.Punishments.Enabled = false), same posture as KickConfirmedCheats per rule: an operator has to opt in with eyes open, since chaining these into automatic consequences on a false positive is a materially different risk than an alert or a single kick.

Type

  • New feature

Checklist

  • scripts/extract-patches.sh ran clean (no vanilla-file changes; every edit here is under sources/, no patches/ diffs touched).
  • dotnet build VintageStory.slnx -c Release is green (0 errors, 0 new warnings; verified no warnings in any touched file).
  • Every vanilla edit has a // Stratum marker. (N/A: no vanilla files touched, only Stratum-original files under sources/.)
  • No vanilla source committed.
  • Tested on a real server start, not just compilation (make smoke: PASS, reached WorldReady, no fatal errors).

Related issues

Fixes #221

Off by default (Anticheat.Punishments.Enabled). Once a player's persistent
flag count crosses a configurable threshold, escalates through inventory
drop/wipe, freeze, jail, then a timed ban, reusing the existing primitives
for each (InventoryBase.DropAll/Clear, StratumStaffCommandState.Freeze,
CmdStratumStaffCommands jailing, PlayerDataManager.BanPlayer) rather than
inventing new enforcement. Standing survives relogs and restarts via
CustomPlayerData, separately from the reporter's in-memory rolling counts.

Runs synchronously right after RecordViolation's lock releases, the same
place every Record*Violation call site already calls DisconnectPlayer for
KickConfirmedCheats today, so no new queue or scheduling was needed.

/stratum ac now shows a player's accumulated flags and the next tier due.
StratumRuntime's config safety check warns on the risky combinations
(punishments enabled with anticheat itself off, wipe instead of drop,
a very low first threshold, or a permanent ban with no recovery).

@tehtelev tehtelev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good. No complaints.

@Zaldaryon
Zaldaryon merged commit 09d4080 into indev Aug 19, 2026
2 checks passed
@Zaldaryon
Zaldaryon deleted the feat/anticheat-punishment-ladder branch August 19, 2026 17:16
@Zaldaryon Zaldaryon mentioned this pull request Aug 19, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants