object scripting wip

This commit is contained in:
2026-05-30 18:48:41 -05:00
parent 212297ecf9
commit 96ec8e8e92
7 changed files with 547 additions and 57 deletions
+27 -9
View File
@@ -1,5 +1,6 @@
use eframe::egui::Color32;
use serde::Deserialize;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// The visual representation of a single board cell.
///
@@ -87,7 +88,7 @@ pub struct Behavior {
/// rather than from this enum. [`Board::is_passable`] will need a special branch
/// at that point. `ErrorBlock` is used as a sentinel for unrecognized archetype
/// names in map files — it should never appear in a valid board.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Archetype {
/// An open cell; the player and other entities can pass through it.
Empty,
@@ -196,17 +197,23 @@ pub const ALL_ARCHETYPES: &[Archetype] = &[Archetype::Empty, Archetype::Wall, Ar
/// tile. Objects are parsed from `[[objects]]` entries in `.toml` map files
/// and stored on [`Board`].
///
/// Script text lives in [`Board::scripts`]; this struct holds only the name
/// used to look it up. Two `ObjectDef`s with the same `script_name` share
/// source text but will run with independent Rhai scopes (independent local
/// variables) when the scripting runtime is wired.
///
/// **Not yet runtime-wired.** Objects are loaded and stored but their scripts
/// are not yet executed. Scripting dispatch is a future feature.
#[derive(Deserialize)]
#[allow(dead_code)]
#[derive(Deserialize, Serialize)]
pub struct ObjectDef {
/// Column of this object on the board (0-indexed).
pub x: usize,
/// Row of this object on the board (0-indexed).
pub y: usize,
/// The Rhai script source for this object.
pub script: String,
/// Name of the Rhai script in [`Board::scripts`] that drives this object.
/// `None` means this object has no script yet.
#[serde(default)]
pub script_name: Option<String>,
}
/// A portal that teleports the player to a named entry point on another board.
@@ -217,8 +224,7 @@ pub struct ObjectDef {
///
/// **Not yet runtime-wired.** Portal navigation (multi-board loading and
/// switching) is a future feature.
#[derive(Deserialize)]
#[allow(dead_code)]
#[derive(Deserialize, Serialize)]
pub struct PortalDef {
/// Column of this portal on the board (0-indexed).
pub x: usize,
@@ -262,8 +268,9 @@ pub struct Player {
/// separate element palette or index indirection. Access cells with
/// [`Board::get`] and [`Board::get_mut`] using `(x, y)` coordinates.
/// Use [`Board::is_passable`] for collision checks.
#[allow(dead_code)]
pub struct Board {
/// Human-readable name for this board, loaded from the map file and round-tripped on save.
pub name: String,
/// Width of the board in cells.
pub width: usize,
/// Height of the board in cells.
@@ -279,6 +286,17 @@ pub struct Board {
pub portals: Vec<PortalDef>,
/// Optional font override for this board. When `None`, the app default is used.
pub font: Option<FontSpec>,
/// Named Rhai scripts available on this board: script name → source text.
///
/// All script source lives here; [`ObjectDef`]s and [`Board::board_script_name`]
/// reference entries by name. This means multiple objects can share the same
/// source while each running instance gets its own Rhai scope at runtime.
pub scripts: HashMap<String, String>,
/// Name of the board-level script in [`Board::scripts`], if any.
///
/// A board script runs on the board as a whole (e.g. `on_enter`, `on_tick`)
/// rather than being tied to a specific object cell.
pub board_script_name: Option<String>,
}
impl Board {