This commit is contained in:
2026-06-25 19:16:46 -05:00
parent db8c8e615d
commit db9a5d37b6
8 changed files with 328 additions and 213 deletions
+18 -12
View File
@@ -81,6 +81,12 @@ use std::collections::{HashMap, HashSet, VecDeque};
use std::rc::Rc;
use crate::player::Player;
/// The host-provided context handed to every script hook for the duration of one
/// call. Currently just the player snapshot, but it exists so more host state can
/// be threaded through the `run_*` methods without changing each signature again.
#[derive(Copy, Clone)]
pub struct ScriptState(pub Player);
/// An action promoted from an object's output queue onto the board queue, tagged
/// with the object that issued it.
pub(crate) struct BoardAction {
@@ -318,18 +324,18 @@ impl ScriptHost {
}
/// Calls `init()` on every scripted object that defines it and drains each queue.
pub fn run_init(&mut self, player: Player) {
self.run("init", |c| c.has_init, (), 0.0, player);
pub fn run_init(&mut self, state: ScriptState) {
self.run("init", |c| c.has_init, (), 0.0, state);
}
/// Calls `tick(dt)` on every scripted object that defines it, then drains queues.
pub fn run_tick(&mut self, player: Player, dt: f64) {
self.run("tick", |c| c.has_tick, (dt,), dt, player);
pub fn run_tick(&mut self, state: ScriptState, dt: f64) {
self.run("tick", |c| c.has_tick, (dt,), dt, state);
}
/// Calls `bump(id)` on the object with [`ObjectId`] `object_id`, if it defines
/// the hook. After the hook, drains the object's queue with `dt = 0`.
pub fn run_bump(&mut self, player: Player, object_id: ObjectId, bumper: i64) {
pub fn run_bump(&mut self, state: ScriptState, object_id: ObjectId, bumper: i64) {
let Some(i) = self.objects.iter().position(|o| o.object_id == object_id) else {
return;
};
@@ -349,7 +355,7 @@ impl ScriptHost {
return;
}
let options = CallFnOptions::default().with_tag(object_id as i64);
obj.scope.set_or_push("Player", player);
obj.scope.set_or_push("Player", state.0);
if let Err(err) = engine.call_fn_with_options::<()>(
options,
&mut obj.scope,
@@ -372,7 +378,7 @@ impl ScriptHost {
/// Fired when the player walks onto a grab object or a grab object is pushed
/// into the player (see [`GameState`](crate::game::GameState)). The hook
/// typically increments a player stat and removes the object via `die()`.
pub fn run_grab(&mut self, player: Player, object_id: ObjectId) {
pub fn run_grab(&mut self, state: ScriptState, object_id: ObjectId) {
let Some(i) = self.objects.iter().position(|o| o.object_id == object_id) else {
return;
};
@@ -392,7 +398,7 @@ impl ScriptHost {
return;
}
let options = CallFnOptions::default().with_tag(object_id as i64);
obj.scope.set_or_push("Player", player);
obj.scope.set_or_push("Player", state.0);
if let Err(err) = engine.call_fn_with_options::<()>(
options,
&mut obj.scope,
@@ -415,7 +421,7 @@ impl ScriptHost {
/// If the function accepts zero parameters (or arg is `None`), it is called with
/// no args. If neither arity exists, the call is silently skipped.
/// After the call, drains the object's queue with `dt = 0`.
pub(crate) fn run_send(&mut self, player: Player, target_id: ObjectId, fn_name: &str, arg: Option<ScriptArg>) {
pub(crate) fn run_send(&mut self, state: ScriptState, target_id: ObjectId, fn_name: &str, arg: Option<ScriptArg>) {
let Some(i) = self.objects.iter().position(|o| o.object_id == target_id) else {
return;
};
@@ -442,7 +448,7 @@ impl ScriptHost {
.any(|f| f.name == fn_name && f.params.is_empty());
let options = CallFnOptions::default().with_tag(obj.object_id as i64);
obj.scope.set_or_push("Player", player);
obj.scope.set_or_push("Player", state.0);
let result = if has_1 {
// Call with arg (or unit if arg is absent).
let dyn_arg: Dynamic = match &arg {
@@ -530,7 +536,7 @@ impl ScriptHost {
defined: fn(&CompiledScript) -> bool,
args: A,
drain_dt: f64,
player: Player
state: ScriptState,
) {
for i in 0..self.objects.len() {
{
@@ -546,7 +552,7 @@ impl ScriptHost {
&& defined(compiled)
{
let options = CallFnOptions::default().with_tag(obj.object_id as i64);
obj.scope.set_or_push("Player", player);
obj.scope.set_or_push("Player", state.0);
if let Err(err) = engine.call_fn_with_options::<()>(
options,
&mut obj.scope,