- Add RuntimeOptions.basePackages for loading framework packages before game package - Add ScriptEngine.loadPackages() for multi-package module merging - LuaDardoScriptEngine merges modules from all packages, game overrides framework - PackageActivationController loads base packages first, then game package - GamePackageManifest parses optional 'base' field - Update docs: README, quick-start, lua-package-format, architecture - Update all test mocks with loadPackages() implementation
126 lines
4.0 KiB
Markdown
126 lines
4.0 KiB
Markdown
# 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.
|