`GameMap.isValidRef` only checked that a `TileRef` was in range — not
that it was an integer. Since the simulation runs on every client and
intents carry raw tile refs, a single ~60-byte malformed intent with a
fractional ref (e.g. `1.5`) passed validation in executions
(`ConstructionExecution`, `TransportShipExecution`,
`MoveWarshipExecution`) and could corrupt typed-array indexing / freeze
the game for the whole lobby.
Require `Number.isInteger(ref)` in `isValidRef`, matching what
`isValidCoord` already does for x/y. This also rejects `NaN` and
`±Infinity` explicitly.
Overhead is ~3 ns per call, and `isValidRef` is boundary validation (per
intent / per path request), not inner-loop code.
New `tests/core/game/GameMap.isValidRef.test.ts`:
- in-range integer refs accepted
- out-of-range refs rejected
- in-range fractional refs rejected (the attack vector)
- `NaN` / `±Infinity` rejected
All existing tests for consumers (pathfinding, transport ship,
construction) pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>