Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
# game-server — Wave C-2 enhanced (delta)
## ADDED Requirements
### Requirement: Anti-Cheat Validator
`@suaveplan/game-server` SHALL expose an `AntiCheatValidator<TMove, TAction>`
class for server-authoritative validation of player movement and actions.
#### Scenario: Movement under maximum speed is accepted
- **WHEN** the validator receives two successive `MovementData` records for
a player whose Euclidean distance over the elapsed time is below
`movement.maxSpeed × movement.toleranceFactor`
- **THEN** `validateMovement` SHALL return `{ valid: true }`
- **AND** SHALL record the latest position as the player's reference for
subsequent calls.
#### Scenario: Teleport above threshold is rejected as `major`
- **WHEN** the Euclidean distance exceeds `movement.maxTeleportDistance`
- **THEN** `validateMovement` SHALL return a `ValidationResult` whose
`violation.type === "teleport"` and `violation.severity === "major"`
- **AND** SHALL emit a `violation:detected` event.
#### Scenario: Rate limit blocks bursts beyond `maxActions`
- **WHEN** more than `maxActions` actions of the matching `actionType`
(or `"all"`) arrive inside a rolling `windowMs`
- **THEN** `validateAction` SHALL return a `ValidationResult` whose
`violation.type === "rate_limit"`
- **AND** SHALL emit a `rate_limit:exceeded` event.
#### Scenario: Auto-flag triggers at threshold
- **WHEN** the player accumulates ≥ `autoFlagThreshold` violations in the
trailing 60 seconds
- **THEN** the validator SHALL flag the player automatically
- **AND** the most recent recorded violation SHALL have `autoFlagged: true`.
#### Scenario: Invalid configuration is rejected
- **WHEN** caller-supplied `AntiCheatConfig` fails Zod validation
- **THEN** the constructor SHALL throw a `GameServerError` with code
`GAME_SERVER.INVALID_ANTI_CHEAT_CONFIG`.
### Requirement: Interest Manager
`@suaveplan/game-server` SHALL expose an `InterestManager<TData>` class
that performs area-of-interest culling for broadcast scope reduction.
#### Scenario: Entity inside view distance is visible
- **WHEN** a player and an entity are within `viewDistance`
- **THEN** `getVisibleEntities` SHALL include the entity in its result.
#### Scenario: Visibility delta omits unchanged set
- **WHEN** `calculateVisibilityChanges` is called twice with no
intervening position change
- **THEN** the second call SHALL return `null`
- **AND** SHALL NOT emit a `visibility:changed` event.
#### Scenario: Rectangular zone containment
- **WHEN** a 3D point's `(x, y, z)` lies within `±width/2`, `±height/2`,
`±depth/2` of a rectangular zone's centre
- **THEN** `isInZone` SHALL return `true`.
#### Scenario: Custom zone delegates to provided predicate
- **WHEN** a `CustomZone` is registered with `containsPoint`
- **THEN** `isInZone` SHALL invoke that predicate and return its result.
#### Scenario: Invalid configuration is rejected
- **WHEN** caller-supplied `InterestManagerConfig` fails Zod validation
- **THEN** the constructor SHALL throw `GameServerError` with code
`GAME_SERVER.INVALID_INTEREST_CONFIG`.
### Requirement: Lag Compensator
`@suaveplan/game-server` SHALL expose a `LagCompensator<TState>` class for
server-side time-rewind of game state during hit validation.
#### Scenario: Bounded history pruning
- **WHEN** the number of recorded snapshots for an entity exceeds
`maxHistorySize`
- **THEN** the oldest snapshots SHALL be evicted
- **AND** the count SHALL never grow beyond `maxHistorySize`.
#### Scenario: Compensation is clamped
- **WHEN** the requested rewind exceeds `maxCompensationMs`
- **THEN** the returned `CompensatedState.compensationMs` SHALL equal
`maxCompensationMs`
- **AND** the returned `CompensatedState.clamped` SHALL be `true`.
#### Scenario: Interpolation between snapshots
- **WHEN** the rewind timestamp falls between two adjacent snapshots and
a `lerp` function is supplied
- **THEN** `getStateAtTime` SHALL invoke `lerp` to produce the returned
state
- **AND** the returned `CompensatedState.interpolated` SHALL be `true`.
#### Scenario: Hit validation requires both states
- **WHEN** the shooter or the target has no recorded state at the
perceived time
- **THEN** `validateHit` SHALL return `{ valid: false }` with a `reason`
describing the missing side.
#### Scenario: Invalid configuration is rejected
- **WHEN** caller-supplied `LagCompensatorConfig` fails Zod validation
- **THEN** the constructor SHALL throw `GameServerError` with code
`GAME_SERVER.INVALID_LAG_COMPENSATION_CONFIG`.