4.4 KiB
4.4 KiB
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
MovementDatarecords for a player whose Euclidean distance over the elapsed time is belowmovement.maxSpeed × movement.toleranceFactor - THEN
validateMovementSHALL 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
validateMovementSHALL return aValidationResultwhoseviolation.type === "teleport"andviolation.severity === "major" - AND SHALL emit a
violation:detectedevent.
Scenario: Rate limit blocks bursts beyond maxActions
- WHEN more than
maxActionsactions of the matchingactionType(or"all") arrive inside a rollingwindowMs - THEN
validateActionSHALL return aValidationResultwhoseviolation.type === "rate_limit" - AND SHALL emit a
rate_limit:exceededevent.
Scenario: Auto-flag triggers at threshold
- WHEN the player accumulates ≥
autoFlagThresholdviolations 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
AntiCheatConfigfails Zod validation - THEN the constructor SHALL throw a
GameServerErrorwith codeGAME_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
getVisibleEntitiesSHALL include the entity in its result.
Scenario: Visibility delta omits unchanged set
- WHEN
calculateVisibilityChangesis called twice with no intervening position change - THEN the second call SHALL return
null - AND SHALL NOT emit a
visibility:changedevent.
Scenario: Rectangular zone containment
- WHEN a 3D point's
(x, y, z)lies within±width/2,±height/2,±depth/2of a rectangular zone's centre - THEN
isInZoneSHALL returntrue.
Scenario: Custom zone delegates to provided predicate
- WHEN a
CustomZoneis registered withcontainsPoint - THEN
isInZoneSHALL invoke that predicate and return its result.
Scenario: Invalid configuration is rejected
- WHEN caller-supplied
InterestManagerConfigfails Zod validation - THEN the constructor SHALL throw
GameServerErrorwith codeGAME_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.compensationMsSHALL equalmaxCompensationMs - AND the returned
CompensatedState.clampedSHALL betrue.
Scenario: Interpolation between snapshots
- WHEN the rewind timestamp falls between two adjacent snapshots and
a
lerpfunction is supplied - THEN
getStateAtTimeSHALL invokelerpto produce the returned state - AND the returned
CompensatedState.interpolatedSHALL betrue.
Scenario: Hit validation requires both states
- WHEN the shooter or the target has no recorded state at the perceived time
- THEN
validateHitSHALL return{ valid: false }with areasondescribing the missing side.
Scenario: Invalid configuration is rejected
- WHEN caller-supplied
LagCompensatorConfigfails Zod validation - THEN the constructor SHALL throw
GameServerErrorwith codeGAME_SERVER.INVALID_LAG_COMPENSATION_CONFIG.