Claude-skill-registry dev-multiplayer-anti-cheat-validation
Input validation and anti-cheat patterns for multiplayer servers. Use when implementing server-side validation.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dev-multiplayer-anti-cheat-validation" ~/.claude/skills/majiayu000-claude-skill-registry-dev-multiplayer-anti-cheat-validation && rm -rf "$T"
manifest:
skills/data/dev-multiplayer-anti-cheat-validation/SKILL.mdsource content
Anti-Cheat Validation
Server-side validation to prevent cheating in multiplayer games.
When to Use
Use when:
- Implementing input validation on the server
- Adding shooting mechanics
- Preventing speed hacks or teleportation
Input Validation Pattern
function validateInput(input: PlayerInput, player: PlayerState): boolean { // Sanity checks - reject impossible inputs if (input.movementSpeed > 20) return false; // Speed hack if (input.jumpHeight > 10) return false; // Super jump hack // Movement constraints const dx = input.targetX - player.x; const dz = input.targetZ - player.z; const distance = Math.sqrt(dx * dx + dz * dz); // Can't move more than X meters per tick if (distance > 2) return false; return true; } onMessage(client: Client, data: any) { const player = this.state.players.get(client.sessionId); if (!player) return; if (data.type === 'player_input') { // VALIDATE before processing if (validateInput(data.input, player)) { player.pendingInput = data.input; } else { // Log potential cheater console.warn(`Suspicious input from ${client.sessionId}`); } } }
Shooting Validation
onMessage(client: Client, data: any) { if (data.type !== 'shoot') return; const shooter = this.state.players.get(client.sessionId); if (!shooter) return; // Validate shooter can shoot if (shooter.ink <= 0) return; if (Date.now() - shooter.lastShotTime < 100) return; // 100ms cooldown // Validate aim direction is reasonable const aim = data.aimDirection; const aimLength = Math.sqrt(aim.x ** 2 + aim.y ** 2 + aim.z ** 2); if (aimLength > 1.1 || aimLength < 0.9) return; // Must be normalized // Server creates paint projectile const projectile = { x: shooter.x, y: shooter.y + 1.5, z: shooter.z, dx: aim.x * 25, dy: aim.y * 25, dz: aim.z * 25, owner: client.sessionId, team: shooter.team, }; this.projectiles.push(projectile); shooter.ink -= 1; shooter.lastShotTime = Date.now(); }
Hit Detection with Lag Compensation
// Server validates hits by rewinding time function checkHit(shooter: PlayerState, targetId: string, aim: Vector3): boolean { const target = this.state.players.get(targetId); if (!target) return false; // Get target position at the time of shooting (lag compensation) const shotTime = Date.now(); const latency = this.getClientLatency(shooter.sessionId); const rewindTime = shotTime - latency; // Find where target was at rewindTime const historicalPosition = this.getPositionHistory(targetId, rewindTime); if (!historicalPosition) return false; // Raycast from shooter to historical position return this.raycastHits(shooter, historicalPosition, aim); } // Store position history for lag compensation private positionHistory: Map<string, Array<{time: number, x: number, y: number, z: number}>> = new Map(); update(dt: number) { const now = Date.now(); for (const [sessionId, player] of this.state.players) { if (!this.positionHistory.has(sessionId)) { this.positionHistory.set(sessionId, []); } const history = this.positionHistory.get(sessionId)!; // Store position for lag compensation (keep last 500ms) history.push({ time: now, x: player.x, y: player.y, z: player.z }); // Remove old entries while (history.length > 0 && history[0].time < now - 500) { history.shift(); } } }
Anti-Cheat Best Practices
- Validate all inputs - Reject impossible values
- Rate limit actions - Prevent spam exploits
- Track position history - Detect teleportation
- Checksum game state - Detect tampering
- Log suspicious activity - For analysis/banning
Testing Checklist
- Server running successfully
- Feature works through network (not just locally)
- Server logs show player actions
- State updates propagate to all clients
- Inputs are validated server-side
- Impossible inputs are rejected
- No client-authoritative position updates
Common Mistakes
| ❌ Wrong | ✅ Right |
|---|---|
| Trust client position | Validate all inputs |
| No rate limiting | Add cooldowns |
| No logging | Log suspicious activity |
| Client determines hit | Server validates hit |
Reference
- server-authoritative.md - Architecture principles
- prediction-shooting.md - Shooting prediction