# Runtime protocol The runtime protocol is the stable boundary between Lua and Dart. ```text RuntimeEvent -> Lua -> GameDiff / RuntimeCommand -> Flame ``` ## RuntimeEvent Dart sends white-listed events to Lua. Events represent input, lifecycle, command/resource outcomes, and host/runtime notifications. Lua should treat events as data and return explicit state changes. ## GameDiff A `GameDiff` describes desired changes to the runtime render tree. Typical operations include creating, updating, and removing runtime nodes. Dart validates node fields before applying them to Flame components. ## RuntimeNode Runtime nodes are generic render descriptions. They are not Flame objects. Supported node concepts include: - Containers/panels. - Text. - Sprites/images. - Buttons. - List views. - Particles. - Spine nodes. Lua may compose higher-level widgets, but those widgets must normalize into supported runtime nodes. ### Color and alpha `RuntimeNode.color` supports `#RRGGBB` and `#AARRGGBB`. When the alpha channel is present in the color, it is multiplied with `RuntimeNode.alpha` and any runtime animation alpha. ```text Final opacity = color alpha × node alpha × runtime animation alpha ``` `#RRGGBB` colors behave as fully opaque colors. `#00000000` is fully transparent. ### Text shadow Text-capable nodes may use flat shadow fields: - `textShadowColor`: `#RRGGBB` or `#AARRGGBB` shadow color. - `textShadowOffsetX` / `textShadowOffsetY`: shadow offset in runtime pixels. - `textShadowBlur`: non-negative blur radius. The shadow color alpha is multiplied by `RuntimeNode.alpha` and any runtime animation alpha. ### Image regions and nine-slice Image-capable nodes (`image`, `sprite`, and image-backed `button`) may draw only part of an asset. For manual atlas regions, set source fields in image pixels: - `sourceX` / `sourceY`: top-left source position inside the loaded image. - `sourceWidth` / `sourceHeight`: source region size. For TexturePacker JSON atlases, declare `atlas` on an image resource and set `frame` on the node. Image-backed buttons may also use `pressedFrame` and `disabledFrame`. The runtime supports TexturePacker JSON Hash and JSON Array `frames` formats with non-rotated frames. `rotated: true` frames are rejected. When frame/source fields are omitted, the full image is used. Image-capable nodes may also use nine-slice scaling with source-pixel insets: - `sliceLeft` / `sliceTop` / `sliceRight` / `sliceBottom`. Nine-slice keeps corners unscaled, stretches edges on one axis, and stretches the center on both axes. Insets are clamped to the selected source region and destination size. ## RuntimeCommand Runtime commands request generic side effects owned by Dart/Flame. Examples: - `move_path` - `move_to` - `fade_to` - `scale_to` - `rotate_to` - `remove_node` - `sequence` - `parallel` - `delay` - `toast` - `play_sound` - `play_bgm` - `pause_bgm` - `resume_bgm` - `stop_bgm` - `preload_resources` - `evict_resources` - `cancel_commands` - `play_spine_animation` - `copy_text` Commands must remain generic. Do not add commands like `roll_ludo_dice` or `move_airplane_piece`; those belong in Lua game logic. ## Validation expectations - Unknown protocol fields should not become implicit behavior. - Required fields should fail clearly when absent. - Helper-only aliases must be normalized before Dart protocol validation. - Runtime code should not silently convert invalid game state into fake success. ## Where to change protocol code ```text lib/runtime/models/ Data models lib/runtime/protocol/ Protocol validation lib/runtime/commands/ Command validation/execution lib/runtime/rendering/ Runtime node to Flame component mapping assets/runtime/lua/ Lua helper constructors/aliases ``` When protocol changes affect Lua authoring, update: ```text tool/lua_runtime_defs_common.lua ``` Then run: ```bash dart run tool/generate_lua_runtime_defs.dart ```