# Architecture `flame_lua_runtime` separates generic runtime infrastructure from game-specific Lua packages. ## Boundary ```text RuntimeEvent -> Lua -> GameDiff / RuntimeCommand -> Flame ``` - Dart receives input, lifecycle, resource, and host events. - Dart forwards white-listed runtime events to Lua. - Lua returns a `GameDiff` and/or `RuntimeCommand` list. - Dart validates and applies diffs/commands to Flame-owned components. ## Responsibilities ### Dart / Flutter / Flame owns - Rendering tree and `Component` lifecycle. - Resource loading and cache ownership. - Audio playback. - Spine and particle object creation. - Input/event dispatch. - Package validation and activation. - Runtime command execution. - Diagnostics and error reporting. ### Lua owns - Game state transitions. - UI tree description. - Layout calculation. - Event handling decisions. - Command/node table construction. Lua should only describe desired runtime state. It must not receive or retain Dart/Flame object references. ## Key Dart areas ```text lib/runtime/models/ Protocol data models lib/runtime/protocol/ Protocol validation/parsing lib/runtime/scripting/ Lua engine boundary lib/runtime/packages/ Manifest/package loading and activation lib/runtime/rendering/ Flame render tree adapter lib/runtime/commands/ Runtime command execution lib/runtime/resources/ Resource loading and cache management lib/runtime/events/ Event dispatch and gates lib/runtime/lifecycle/ Async/session/task safety ``` ## Package loading Game packages are manifest-driven. Bundled assets and remote/downloaded packages should flow through the same package abstraction where possible. Shared Runtime Lua modules are loaded from `RuntimeOptions.runtimeLuaRoot`. Default source-tree root: ```text assets/runtime/lua ``` Package dependency root: ```text packages/flame_lua_runtime/assets/runtime/lua ``` ### Multi-package loading The runtime supports loading multiple packages in sequence, with module merging: ```text RuntimeOptions.basePackages = ['_framework'] -> load _framework package (modules: app, diff, ids, net, ...) -> load game package (modules: state, rules, main, ...) -> merge into flat _moduleScripts map -> game modules override framework modules on name collision -> execute game entry script ``` Key classes: - `RuntimeOptions.basePackages` — ordered list of framework package IDs. - `PackageActivationController._prepareCandidate()` — loads base packages first, then game package, passes combined list to `ScriptEngine.loadPackages()`. - `LuaDardoScriptEngine.loadPackages()` — iterates all packages, merges `manifest.modules` into `_moduleScripts`, executes entry from last package. - `GamePackageManifest.base` — optional metadata field declaring framework dependency. Module resolution is flat: `runtime.import("xxx")` looks up `_moduleScripts[xxx]`. Game modules and framework modules share the same namespace. Later-loaded packages win on collision. ## Safety model - Lua module loading is manifest-declared. - `runtime.import(moduleName)` is the only intended module import API. - `runtime:` module paths are restricted to `runtime:*.lua`. - Package-local scripts are restricted to `scripts/*.lua`. - Runtime protocol fields are white-listed. - Invalid diffs/commands should fail clearly instead of being silently ignored. ## Extension guidance When adding features, prefer this order: 1. Lua helper composition if it can be represented by existing nodes/commands. 2. Generic protocol field if multiple games need the capability. 3. Generic Runtime node/command if it requires Dart/Flame ownership. 4. Avoid game-specific Dart code. Examples of valid generic runtime features: - `listView` node. - `particle` node. - `toast` command. - `copy_text` command. - `play_spine_animation` command. - Button image states. Examples that should stay Lua-side: - Game board rules. - Game-specific dialog composition. - Showcase category/menu behavior. - Ludo/flight-specific animation choices.