@modoki/engine / index / GameDefinition
Interface: GameDefinition
Game Definition & Services
description?
optionaldescription?:string
editorPanels?
optionaleditorPanels?: () =>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?
optionalonSceneReady?: (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?
optionalregisterAppServices?: () =>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?
optionalregisterEditorBindings?: () =>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?
optionalregisterPostprocessors?: () =>void|Promise<void>
Returns
void | Promise<void>
registerSystems?
optionalregisterSystems?: () =>void|Promise<void>
Register game-specific ECS systems and trait editor metadata.
Returns
void | Promise<void>
resetPhase?
optionalresetPhase?: (world) =>void
Reset game state on error recovery (called by ErrorBoundary).
Parameters
world
World
Returns
void
thumbnailUrl?
optionalthumbnailUrl?: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?
optionalUIComponent?: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?
optionalunregisterSystems?: () =>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>