no need for scriptstate any more
This commit is contained in:
+35
-41
@@ -35,7 +35,7 @@ use crate::game::SAY_DURATION;
|
||||
use crate::log::LogLine;
|
||||
use crate::map_file::parse_color;
|
||||
use crate::object_def::ObjectDef;
|
||||
use crate::utils::{Direction, ErrorSink, Hook, ObjectId, RegistryValue};
|
||||
use crate::utils::{Direction, ErrorSink, Hook, ObjectId};
|
||||
use rhai::{
|
||||
Array, CallFnOptions, Dynamic, Engine, ImmutableString, Module, NativeCallContext,
|
||||
Scope, AST,
|
||||
@@ -48,9 +48,9 @@ use crate::api::object_info::ObjectInfo;
|
||||
use crate::api::player::PlayerWithPos;
|
||||
use crate::api::queue::ObjQueue;
|
||||
use crate::api::registry::Registry;
|
||||
use crate::api::state::ScriptState;
|
||||
use crate::glyph::Glyph;
|
||||
use crate::keys::Keyring;
|
||||
use crate::player::PlayerRef;
|
||||
|
||||
/// Types which can be registered to be sent to Rhai
|
||||
pub trait Registerable {
|
||||
@@ -100,6 +100,7 @@ pub struct ScriptHost {
|
||||
scopes: HashMap<ObjectId, Scope<'static>>,
|
||||
board_queue: BoardQueue,
|
||||
errors: ErrorSink,
|
||||
board: BoardRef
|
||||
}
|
||||
|
||||
impl ScriptHost {
|
||||
@@ -110,7 +111,7 @@ impl ScriptHost {
|
||||
///
|
||||
/// `scripts` is the world-level script pool (script name → Rhai source); it is
|
||||
/// read only during construction and not retained afterward.
|
||||
pub fn new(board_cell: &BoardRef, script_sources: &HashMap<String, String>) -> Self {
|
||||
pub fn new(board_ref: BoardRef, player: PlayerRef, script_sources: &HashMap<String, String>) -> Self {
|
||||
let board_queue: BoardQueue = Rc::new(RefCell::new(Vec::new()));
|
||||
let errors = ErrorSink::new();
|
||||
let mut scopes = HashMap::new();
|
||||
@@ -120,16 +121,15 @@ impl ScriptHost {
|
||||
PlayerWithPos::register(&mut engine, errors.clone());
|
||||
Keyring::register(&mut engine, errors.clone());
|
||||
BoardRef::register(&mut engine, errors.clone());
|
||||
ScriptState::register(&mut engine, errors.clone());
|
||||
ObjectInfo::register(&mut engine, errors.clone());
|
||||
Glyph::register(&mut engine, errors.clone());
|
||||
ObjQueue::register(&mut engine, errors.clone());
|
||||
Registry::register(&mut engine, errors.clone());
|
||||
|
||||
register_write_api(&mut engine, board_cell.clone());
|
||||
register_global_constants(&mut engine, board_cell.clone());
|
||||
register_write_api(&mut engine, board_ref.clone());
|
||||
register_global_constants(&mut engine, board_ref.clone(), player.clone());
|
||||
|
||||
let board = board_cell.borrow();
|
||||
let board = board_ref.borrow();
|
||||
|
||||
// Compile each referenced script once, keyed by `script_key` (the object's
|
||||
// `script_name`: a world-pool name for named scripts, or a synthetic
|
||||
@@ -166,10 +166,10 @@ impl ScriptHost {
|
||||
scripts.insert(
|
||||
key,
|
||||
CompiledScript {
|
||||
has_init: defines("init", 2),
|
||||
has_tick: defines("tick", 3),
|
||||
has_bump: defines("bump", 3),
|
||||
has_grab: defines("grab", 2),
|
||||
has_init: defines("init", 1),
|
||||
has_tick: defines("tick", 2),
|
||||
has_bump: defines("bump", 2),
|
||||
has_grab: defines("grab", 1),
|
||||
ast,
|
||||
},
|
||||
);
|
||||
@@ -199,43 +199,41 @@ impl ScriptHost {
|
||||
board_queue,
|
||||
errors,
|
||||
scopes,
|
||||
board: board_ref
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls `tick(dt)` on every scripted object that defines it, then drains queues.
|
||||
pub fn run_tick(&mut self, state: ScriptState, dt: f64) {
|
||||
self.run_hook_on_all(Hook::Tick, state, dt);
|
||||
pub fn run_tick(&mut self, dt: f64) {
|
||||
self.run_hook_on_all(Hook::Tick, dt);
|
||||
}
|
||||
|
||||
pub fn run_init(&mut self, state: ScriptState) {
|
||||
self.run_hook_on_all(Hook::Init, state, 0.0)
|
||||
pub fn run_init(&mut self) {
|
||||
self.run_hook_on_all(Hook::Init, 0.0)
|
||||
}
|
||||
|
||||
/// Run the given hook on every object that defines it. For hooks other than
|
||||
/// `Tick`, dt should just be 0.0
|
||||
fn run_hook_on_all(&mut self, hook: Hook, state: ScriptState, dt: f64) {
|
||||
let all_ids = state.board.borrow().all_ids();
|
||||
fn run_hook_on_all(&mut self, hook: Hook, dt: f64) {
|
||||
let all_ids = self.board.borrow().all_ids();
|
||||
let arg = match hook {
|
||||
Hook::Tick => Some(Dynamic::from(dt)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
for id in all_ids {
|
||||
self.run_hook_on_one(hook, state.clone(), id, arg.clone(), dt)
|
||||
self.run_hook_on_one(hook, id, arg.clone(), dt)
|
||||
}
|
||||
}
|
||||
|
||||
fn run_hook_on_one(&mut self, hook: Hook, state: ScriptState, id: ObjectId, arg: Option<Dynamic>, dt: f64) {
|
||||
if let Some(mut info) = ObjectInfo::from_id(id, state.board.clone()) {
|
||||
fn run_hook_on_one(&mut self, hook: Hook, id: ObjectId, arg: Option<Dynamic>, dt: f64) {
|
||||
if let Some(mut info) = ObjectInfo::from_id(id, self.board.clone()) {
|
||||
if let Some(script_key) = info.script_name.as_ref()
|
||||
&& let Some(script) = self.scripts.get(script_key)
|
||||
&& let Some(scope) = self.scopes.get_mut(&id) {
|
||||
|
||||
if script.has(hook) {
|
||||
let mut args = vec![
|
||||
Dynamic::from(info.clone()),
|
||||
Dynamic::from(state.clone())
|
||||
];
|
||||
let mut args = vec![Dynamic::from(info.clone())];
|
||||
if let Some(d) = arg { args.push(d) }
|
||||
|
||||
// Call this with opts tagging this call as our id. The write API will read
|
||||
@@ -261,8 +259,8 @@ impl ScriptHost {
|
||||
|
||||
/// 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, state: ScriptState, id: ObjectId, bumper: i64) {
|
||||
self.run_hook_on_one(Hook::Bump, state, id, Some(Dynamic::from(bumper)), 0.0);
|
||||
pub fn run_bump(&mut self, id: ObjectId, bumper: i64) {
|
||||
self.run_hook_on_one(Hook::Bump, id, Some(Dynamic::from(bumper)), 0.0);
|
||||
}
|
||||
|
||||
/// Calls `grab()` on the object with [`ObjectId`] `object_id`, if it defines the
|
||||
@@ -271,21 +269,20 @@ 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, state: ScriptState, object_id: ObjectId) {
|
||||
self.run_hook_on_one(Hook::Grab, state, object_id, None, 0.0);
|
||||
pub fn run_grab(&mut self, object_id: ObjectId) {
|
||||
self.run_hook_on_one(Hook::Grab, object_id, None, 0.0);
|
||||
}
|
||||
|
||||
/// Calls the named function on the object with [`ObjectId`] `target_id`.
|
||||
///
|
||||
/// What we pass depends on arity, in this order:
|
||||
/// - If it has arity 3, we pass `[ObjectInfo, ScriptState, SendArg]`
|
||||
/// - If it has arity 2, we pass `[ObjectInfo, ScriptState]`
|
||||
/// - If it has arity 1, we pass the arg
|
||||
/// - If it has arity 2, we pass `[ObjectInfo, arg]`
|
||||
/// - If it has arity 1, we pass the ObjectInfo alone
|
||||
/// - If it has arity 0, we pass nothing
|
||||
///
|
||||
/// In cases where the arg isn't provided but we have the arity, we pass `Dynamic::UNIT`
|
||||
pub(crate) fn run_send(&mut self, state: ScriptState, id: ObjectId, fn_name: &str, arg: SendArg) {
|
||||
if let Some(mut info) = ObjectInfo::from_id(id, state.board.clone()) {
|
||||
pub(crate) fn run_send(&mut self, id: ObjectId, fn_name: &str, arg: SendArg) {
|
||||
if let Some(mut info) = ObjectInfo::from_id(id, self.board.clone()) {
|
||||
if let Some(script_key) = info.script_name.as_ref()
|
||||
&& let Some(script) = self.scripts.get(script_key)
|
||||
&& let Some(scope) = self.scopes.get_mut(&id) {
|
||||
@@ -307,15 +304,11 @@ impl ScriptHost {
|
||||
|
||||
// Assemble the args
|
||||
let mut args = vec![];
|
||||
if arities.contains(&3) {
|
||||
if arities.contains(&2) {
|
||||
args.push(Dynamic::from(info.clone()));
|
||||
args.push(Dynamic::from(state.clone()));
|
||||
args.push(arg.into());
|
||||
} else if arities.contains(&2) {
|
||||
args.push(Dynamic::from(info.clone()));
|
||||
args.push(Dynamic::from(state.clone()));
|
||||
} else if arities.contains(&1) {
|
||||
args.push(arg.into());
|
||||
args.push(Dynamic::from(info.clone()));
|
||||
}
|
||||
|
||||
// Call this with opts tagging this call as our id. The write API will read
|
||||
@@ -614,9 +607,10 @@ fn read_coord_array(arr: &Array) -> Result<Vec<(i64, i64)>, ()> {
|
||||
/// Registers direction and color constants as a global Rhai module so they are
|
||||
/// visible to every function at any call depth, including Rhai-to-Rhai calls.
|
||||
/// (Scope-level constants are only visible to the top-level function Rust calls.)
|
||||
fn register_global_constants(engine: &mut Engine, board: BoardRef) {
|
||||
fn register_global_constants(engine: &mut Engine, board: BoardRef, player: PlayerRef) {
|
||||
let mut m = Module::new();
|
||||
m.set_var("Board", board);
|
||||
m.set_var("Board", board.clone());
|
||||
m.set_var("Player", PlayerWithPos(player.clone(), board));
|
||||
m.set_var("North", Direction::North);
|
||||
m.set_var("South", Direction::South);
|
||||
m.set_var("East", Direction::East);
|
||||
|
||||
Reference in New Issue
Block a user