Files
skills/docs/gaming/games/game-server/src/integrations/enhanced-server/enhanced-server.md
2026-05-29 08:20:56 +01:00

4.7 KiB

EnhancedGameServer

(no submodules)

Purpose

EnhancedGameServer is the top-of-stack integration layer for @suaveplan/game-server. Waves B and C-1 shipped the engine, plugin manager, and eight concrete plugins, but consumers still had to wire the loop, manager, engine, and every plugin by hand on each boot. This module collapses that boilerplate behind a single bootstrap(options) entry point and returns a typed handle exposing both the wired GameEngine and the bundle of installed plugins for direct access.

The integration is deliberately universal — zero browser, React, or DOM dependencies. The upstream React lobby shell is explicitly deferred to a future react-game-server package. All collaborators are injected through the structural contracts in @suaveplan/types (Clock, IdGenerator, LoggerLike, TimersLike, EventBusLike, Rng, StorageLike) plus the public APIs of @suaveplan/feature-flags, @suaveplan/rules, and @suaveplan/workflow.

Features

  • Single bootstrap(options) entry point — no manual wiring.
  • Pre-installs every built-in plugin (logging, analytics, persistence, feature-flags, rules, workflow, ab-test) via PluginManager.installAll so dependency order is honoured.
  • Enables every plugin after install so callers can opt-out by disabling individual plugins post-bootstrap rather than skipping them entirely.
  • Caller-supplied extraPlugins are installed last and enabled in the same pass.
  • BOOTSTRAP_FAILED wraps any plugin install failure with the original cause chain intact.
  • ALREADY_BOOTSTRAPPED prevents accidental double-wiring.
  • start() / tick() / stop() / dispose() delegate to the underlying GameEngine so existing engine codes (ENGINE_NOT_STARTED, ENGINE_DISPOSED) propagate unchanged.

Usage: Basic

import { EnhancedGameServer } from "@suaveplan/game-server/integrations/enhanced-server";

const server = new EnhancedGameServer({
    clock: () => Date.now(),
    timers,
    idGenerator,
    logger,
    events,
    emitter,
    flagManager,
    ruleEngine,
    rng,
    storage,
    analyticsSink: (event) => console.log(event),
});

const { engine, plugins } = await server.bootstrap();
server.start();
await server.tick();
server.stop();
await server.dispose();

Usage: Advanced

Install extra plugins after the canonical seven and configure tick rate:

class TelemetryPlugin extends BasePlugin {
    public readonly name = "telemetry";
    public readonly version = "1.0.0";
}

const handle = await server.bootstrap({
    autoStartLoop: false,
    tickRate: 30,
    extraPlugins: [new TelemetryPlugin()],
});

// Disable analytics without uninstalling the rest.
await handle.engine.getPlugin("analytics");
// Direct typed access for per-plugin configuration:
handle.plugins.featureFlag.evaluate("dark-mode", "player-1");

API Reference

  • class EnhancedGameServer(deps: EnhancedGameServerDeps) — constructor.
  • bootstrap(options?: EnhancedServerBootstrapOptions) — returns Promise<EnhancedServerHandle>. Throws ALREADY_BOOTSTRAPPED on the second call and wraps install failures in BOOTSTRAP_FAILED.
  • start() — delegates to GameEngine.start().
  • tick() — delegates to GameEngine.tick().
  • stop() — delegates to GameEngine.stop().
  • dispose() — idempotent; safe before bootstrap.
  • isBootstrapped() — predicate.
  • getHandle() — returns the typed handle; throws if not bootstrapped.

EnhancedServerHandle exposes the wired engine and a strongly-typed plugins bundle ({ abTest, analytics, featureFlag, logging, persistence, rules, workflow, extras }).

Implementation Notes

  • Plugins are installed in an order that satisfies their declared dependencies. The current canonical set declares none, so the order is determined by the integration: log-first so subsequent installs are recorded, analytics next to capture session events, then persistence, feature-flags, rules, workflow, and finally A/B-test.
  • Bootstrap calls PluginManager.installAll (which topoSorts its argument) for an atomic batch install. After install, each plugin is individually enabled — PluginManager.enable is idempotent so the second-pass loop is safe.
  • The shared EventBusLike<EnhancedServerEventMap> is intersection-typed across the loop, manager, and engine maps so a single bus services all three subsystems without per-subsystem adapters.
  • All error wrapping preserves the original cause so consumers can walk the cause chain via @suaveplan/error's utilities.
  • The class never holds React or DOM references; every concrete dependency is injected through a structural contract, keeping the package universal.