Skip to content

@modoki/engine / index / GameDefinition

Interface: GameDefinition

Game Definition & Services

description?

optional description?: string


editorPanels?

optional editorPanels?: () => EditorPanelDef[] | Promise<EditorPanelDef[]>

Register game-specific dockable editor panels (e.g. a level painter). Called once at editor init; the returned components are merged into the editor's panel registry + Window menu. MUST be a lazy loader — () => import('./editor/X') .then(m => [{ id, name, component: m.X, openByDefault: true }]) — so the panel module (and its @modoki/engine/editor imports) stays off the production game bundle. Editor-only; never called in the game runtime.

Returns

EditorPanelDef[] | Promise<EditorPanelDef[]>


id

id: string


loadConfig

loadConfig: () => Promise<GameConfig>

Returns

Promise<GameConfig>


name

name: string


onSceneReady?

optional onSceneReady?: (world) => void | Promise<void>

Async warm-up run AFTER the boot scene has loaded but BEFORE the loading screen is dismissed (runtime only; the editor has its own flow). Await here anything the first painted frame must already show that ISN'T reachable through the scene's resources manifest — e.g. RUNTIME-GENERATED content: load its assets and instantiate it now, so it doesn't pop in a few frames after the game appears. world is the freshly-loaded world. Best-effort: a rejection is logged and boot continues.

Parameters

world

World

Returns

void | Promise<void>


registerAppServices?

optional registerAppServices?: () => void | Promise<void>

Register this game's app-service implementations (analytics/crashlytics/ads/ attribution) with the engine via registerAppServices(). These are native-SDK wrappers that live in the GAME (not the engine) — see runtime/appServices.ts. Called during the game's bootstrap; the engine then drives ads/attribution init (native only) and crashlytics hooks. No-op for games without services.

Returns

void | Promise<void>


registerEditorBindings?

optional registerEditorBindings?: () => void | Promise<void>

Register game-specific editor-only glue — e.g. UIRenderer store-binding hooks so the editor's default UI layer can resolve this game's bindings, or a registerCreatableAsset() call (@modoki/engine/editor) adding a "Create X" entry to the Assets panel for a game-specific asset kind (e.g. sling's Level/Wave charts). Called once at editor init for every game; not called in the game runtime — put the @modoki/engine/editor import behind a lazy loader (like editorPanels below) so it never reaches the production game bundle.

Returns

void | Promise<void>


registerPostprocessors?

optional registerPostprocessors?: () => void | Promise<void>

Returns

void | Promise<void>


registerSystems?

optional registerSystems?: () => void | Promise<void>

Register game-specific ECS systems and trait editor metadata.

Returns

void | Promise<void>


resetPhase?

optional resetPhase?: (world) => void

Reset game state on error recovery (called by ErrorBoundary).

Parameters

world

World

Returns

void


thumbnailUrl?

optional thumbnailUrl?: string

Thumbnail asset GUID (resolved via the manifest), or an external URL. Stored into UIElement.imageSrc, which is GUID-only — never a literal path.


UIComponent?

optional UIComponent?: ComponentType<{ }> | LazyExoticComponent<ComponentType<{ }>>

Custom React UI layer for this game. When set, rendered instead of the default ECS UIRenderer. The component receives no props — use Zustand stores or ECS queries internally.

Lazy-load with: UIComponent: () => import('./ui/ChatUI').then(m => m.ChatUI)


unregisterSystems?

optional unregisterSystems?: () => void | Promise<void>

Unregister game-specific systems and UI actions. Called on game switch before the next game's registerSystems(). Engine systems are not affected.

Returns

void | Promise<void>

Built with Modoki.