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,81 @@
# game-server-engine-core — GameEngine + GameLoop + PluginManager
**Package**: `@suaveplan/game-server`
**Status**: PROPOSED
**Type**: feature (Wave B-1 migration slice)
- **Design**: see this file (no separate design.md required for a thin orchestrator slice)
- **Spec delta**: ./specs/game-server/spec.md
## Why
Wave A landed the foundations (`errors`, `types`, `engine/di-container`). The
broader package still has no engine top-level — there is no `GameEngine` to
orchestrate services, no `GameLoop` to drive deterministic ticks, and no
`PluginManager` to wire third-party extensions. Without these the package is
unusable for actual game work.
This slice (Wave B-1) ships the three engine primitives in dependency order
so Wave B-2 (sessions/player-manager) and later state/network/matchmaking
slices have a stable top-level to bind to. The migration is verbatim in
intent (preserve upstream lifecycle + statistics surface) but recast at
genesis bar — injectable `Clock`/`TimersLike`/`IdGenerator`, typed
`GameServerError` codes, Zod-validated boundaries, OTel counters and
histograms with real `MeterProvider` assertions, kebab-case `<feature>/`
layout, 100/100/100/100 coverage.
## What changes
- ADDED: `GameEngine` (in `./engine/game-engine`) — top-level orchestrator wiring DI-injected services with `start`/`stop`/`tick`/`dispose` lifecycle.
- ADDED: `GameLoop` (in `./engine/game-loop`) — deterministic fixed-step loop with `Clock`/`TimersLike` injection, `tick-based`/`event-driven`/`hybrid` modes, pause/resume, `tick()` manual driver.
- ADDED: `PluginManager` (in `./engine/plugin-manager`) — typed `EnginePlugin` registry with `install`/`uninstall`/`enable`/`disable`/`get` + lifecycle-hook execution wrapped in `PLUGIN_LIFECYCLE_FAILED`.
- ADDED: `GAME_SERVER.*` codes — `ENGINE_NOT_STARTED`, `ENGINE_ALREADY_STARTED`, `ENGINE_DISPOSED`, `INVALID_ENGINE_OPTIONS`, `INVALID_GAME_LOOP_OPTIONS`, `GAME_LOOP_NOT_RUNNING`, `GAME_LOOP_ALREADY_RUNNING`, `PLUGIN_NOT_FOUND`, `DUPLICATE_PLUGIN`, `PLUGIN_LIFECYCLE_FAILED`.
- ADDED: subpath exports `./engine/game-engine`, `./engine/game-loop`, `./engine/plugin-manager`.
## Out of scope
- `SessionManager`, `PlayerManager`, `SessionTree` (Wave B-2 — orchestrator consumes them as opaque structural service interfaces only).
- `StateManager`, `NetworkAdapter`, `MatchmakingEngine`, `QueueManager` (later waves).
- Game-logic strategy concretes (`AbstractGameLogic`) — the engine accepts an opaque `IGameLogicLike` slot per upstream contract.
## Source mapping
This change derives from upstream files on `/mnt/s/web/suaveplan`:
| Requirement | Source lines | Notes |
|---|---|---|
| GameEngine orchestrator | `packages/universal/game-server/src/engine/GameEngine.ts` L60–L497 | Recast — drops session/state/network constructor wiring (Wave B-2+ scope); preserves DI-service registration + start/stop/dispose lifecycle. |
| GameLoop deterministic ticks | `packages/universal/game-server/src/engine/GameLoop.ts` L36–L358 | Recast — `Date.now()` replaced by injectable `Clock`; `setInterval/clearInterval` replaced by `TimersLike`. |
| PluginManager lifecycle | `packages/universal/game-server/src/engine/PluginManager.ts` L27–L355 | Recast — plain `Error` → `GameServerError`; dependency-aware topo sort preserved. |
### Requirements with no source line
| Requirement | Justification |
|---|---|
| OTel counters + histograms | Genesis bar — upstream had no OTel; this slice adds `game_server.engine.lifecycle_total`, `game_server.loop.tick_duration_ms`, `game_server.plugin.lifecycle_total` to match the package quality bar (mirrors `@suaveplan/ecs`). |
| Zod-validated option boundaries | Genesis bar — every public option boundary parses through Zod before reaching state. |
| Typed `GameServerError` everywhere | Genesis bar — upstream threw plain `Error` for lifecycle violations. |
## Verification approach
- `src/engine/game-engine/game-engine.test.ts` — covers GameEngine lifecycle, DI wiring, plugin handoff, OTel emission.
- `src/engine/game-loop/game-loop.test.ts` — covers loop modes, deterministic ticking via injected Clock/TimersLike, pause/resume, error propagation.
- `src/engine/plugin-manager/plugin-manager.test.ts` — covers install/uninstall/enable/disable, duplicate detection, dependency topo sort, hook execution.
- `src/errors/game-server-error.test.ts` — extended to assert every new code.
## Impact
### Affected dependents
Run `bunx turbo ls --filter=...@suaveplan/game-server` to enumerate. The
package has no shipped dependents on genesis at the time of this change
(verified: `bunx turbo ls --filter=...@suaveplan/game-server` returns only
the package itself).
- No dependents — additive surface only.
## Migration impact
None — additive only. Existing `./errors`, `./types`, `./engine/di-container`
surfaces are unchanged. The `GAME_SERVER_CODES` registry is **extended**;
the existing 4 codes are preserved.