better scripting api

This commit is contained in:
2026-06-09 22:38:17 -05:00
parent 9c854bc1b9
commit c2168b992d
8 changed files with 1199 additions and 300 deletions
+20 -5
View File
@@ -1,10 +1,11 @@
use crate::action::Action;
use crate::log::LogLine;
use crate::script::ScriptHost;
use std::cell::{Ref, RefCell, RefMut};
use std::rc::Rc;
use std::time::Duration;
use crate::board::Board;
use crate::utils::{Action, Direction, ObjectId, Solid};
use crate::utils::{Direction, ObjectId, ScriptArg, Solid};
/// How long a `say()` speech bubble stays on screen, in seconds.
pub const SAY_DURATION: f64 = 3.0;
@@ -105,17 +106,19 @@ impl GameState {
}
/// Resolves the board queue: applies each promoted action to the board, then fires
/// the `bump` hooks the moves triggered.
/// the `bump` and `send` hooks the moves triggered.
///
/// Done in two phases so no `board_mut` borrow is held while `bump` scripts run
/// Done in two phases so no `board_mut` borrow is held while scripts run
/// (they read the board through its getters): phase A mutates the board and records
/// `(bumped_object, bumper)` pairs; phase B fires the bumps after the borrow drops.
/// `(bumped, bumper)` and `(send_target, fn_name, arg)` tuples; phase B fires the
/// hooks after the borrow drops.
fn resolve(&mut self) {
let actions = self.scripts.take_board_queue();
// Logs are collected here rather than pushed inline, since the board borrow
// below also borrows `self`.
let mut logs: Vec<LogLine> = Vec::new();
let mut bumps: Vec<(ObjectId, i64)> = Vec::new();
let mut sends: Vec<(ObjectId, String, Option<ScriptArg>)> = Vec::new();
let mut new_bubbles: Vec<SpeechBubble> = Vec::new();
{
let mut board = self.board_mut();
@@ -146,7 +149,16 @@ impl GameState {
}),
// Delays are consumed by ScriptHost::drain and never reach the board queue.
Action::Delay(_) => {}
Action::SetColor { fg, bg } => {
if let Some(obj) = board.objects.get_mut(&ba.source) {
if let Some(c) = fg { obj.glyph.fg = c; }
if let Some(c) = bg { obj.glyph.bg = c; }
}
}
// Collected and fired after the board borrow drops, like bumps.
Action::Send { target, fn_name, arg } => {
sends.push((target, fn_name, arg));
}
}
}
}
@@ -159,6 +171,9 @@ impl GameState {
for (bumped, bumper) in bumps {
self.scripts.run_bump(bumped, bumper);
}
for (target, fn_name, arg) in sends {
self.scripts.run_send(target, &fn_name, arg);
}
self.drain_errors();
}