no need for scriptstate any more
This commit is contained in:
+33
-32
@@ -13,8 +13,7 @@ pub const SAY_DURATION: f64 = 3.0;
|
||||
// Re-export ScrollLine so kiln-tui can pattern-match scroll content without
|
||||
// accessing the private `action` module directly.
|
||||
pub use crate::action::ScrollLine;
|
||||
use crate::api::state::ScriptState;
|
||||
use crate::player::Player;
|
||||
use crate::player::{Player, PlayerRef};
|
||||
|
||||
/// An active scroll overlay opened by a scripted object via `scroll()`.
|
||||
///
|
||||
@@ -72,7 +71,7 @@ pub struct GameState {
|
||||
/// per-board: it persists across board transitions, unlike the per-board
|
||||
/// position in [`Board::player`](crate::board::Board::player). Scripts mutate
|
||||
/// it via `add_gems`/`alter_health`/`set_key` and read a snapshot of it.
|
||||
pub player: Player,
|
||||
pub player: PlayerRef,
|
||||
}
|
||||
|
||||
impl GameState {
|
||||
@@ -84,11 +83,13 @@ impl GameState {
|
||||
/// Compile errors are surfaced into the log immediately.
|
||||
pub fn from_world(world: World) -> Self {
|
||||
let name = world.start.clone();
|
||||
let player = Player::new_ref();
|
||||
let host = ScriptHost::new(
|
||||
world
|
||||
.boards
|
||||
.get(&name)
|
||||
.expect("world::load guarantees start board exists"),
|
||||
.expect("world::load guarantees start board exists").clone(),
|
||||
player.clone(),
|
||||
&world.scripts,
|
||||
);
|
||||
let mut state = Self {
|
||||
@@ -99,7 +100,7 @@ impl GameState {
|
||||
speech_bubbles: Vec::new(),
|
||||
active_scroll: None,
|
||||
board_transition: None,
|
||||
player: Player::default()
|
||||
player
|
||||
};
|
||||
state.drain_errors();
|
||||
state
|
||||
@@ -163,7 +164,7 @@ impl GameState {
|
||||
/// the game is about to start — never during map deserialization, since a script
|
||||
/// may inspect the board.
|
||||
pub fn run_init(&mut self) {
|
||||
self.scripts.run_init(ScriptState::from_game_state(self));
|
||||
self.scripts.run_init();
|
||||
self.resolve();
|
||||
}
|
||||
|
||||
@@ -177,7 +178,7 @@ impl GameState {
|
||||
// this runs exactly once per player interaction with a scroll.
|
||||
self.handle_scroll();
|
||||
let secs = dt.as_secs_f64();
|
||||
self.scripts.run_tick(ScriptState::from_game_state(self), secs);
|
||||
self.scripts.run_tick(secs);
|
||||
// Expire speech bubbles before resolving new actions so a fresh say()
|
||||
// this frame isn't immediately culled.
|
||||
self.speech_bubbles.retain_mut(|b| {
|
||||
@@ -338,23 +339,22 @@ impl GameState {
|
||||
}
|
||||
// Apply the net gem change (clamped at 0, since the count is unsigned).
|
||||
if gem_delta != 0 {
|
||||
self.player.alter_gems(gem_delta);
|
||||
self.player.borrow_mut().alter_gems(gem_delta);
|
||||
}
|
||||
// Apply the net health change (clamped to [0, max_health]).
|
||||
if health_delta != 0 {
|
||||
self.player.alter_health(health_delta);
|
||||
self.player.borrow_mut().alter_health(health_delta);
|
||||
}
|
||||
for (color, present) in key_changes {
|
||||
if !self.player.keys.set_by_name(&color, present) {
|
||||
if !self.player.borrow_mut().keys.set_by_name(&color, present) {
|
||||
self.log.push(LogLine::error(format!("set_key: unknown color {color:?}")));
|
||||
}
|
||||
}
|
||||
let state = ScriptState::from_game_state(self);
|
||||
for (bumped, bumper) in bumps {
|
||||
self.scripts.run_bump(state.clone(), bumped, bumper);
|
||||
self.scripts.run_bump(bumped, bumper);
|
||||
}
|
||||
for (target, fn_name, arg) in sends {
|
||||
self.scripts.run_send(state.clone(), target, &fn_name, arg);
|
||||
self.scripts.run_send(target, &fn_name, arg);
|
||||
}
|
||||
self.drain_errors();
|
||||
}
|
||||
@@ -370,7 +370,7 @@ impl GameState {
|
||||
if let Some(scroll) = self.active_scroll.take()
|
||||
&& let Some(choice) = scroll.choice
|
||||
{
|
||||
self.scripts.run_send(ScriptState::from_game_state(self), scroll.source, &choice, SendArg::None);
|
||||
self.scripts.run_send(scroll.source, &choice, SendArg::None);
|
||||
self.drain_errors();
|
||||
}
|
||||
}
|
||||
@@ -416,7 +416,8 @@ impl GameState {
|
||||
self.board_mut().clear_all_queues();
|
||||
// Rebuild the script host for the new board's objects.
|
||||
self.scripts = ScriptHost::new(
|
||||
&self.world.boards[&self.current_board_name],
|
||||
self.world.boards[&self.current_board_name].clone(),
|
||||
self.player.clone(),
|
||||
&self.world.scripts,
|
||||
);
|
||||
// Stub hook for the front-end transition animation (1 second).
|
||||
@@ -477,13 +478,12 @@ impl GameState {
|
||||
}
|
||||
// Fire the grab hook and resolve it immediately so the grabbed thing's
|
||||
// die()/add_gems() apply now — no player+object overlap survives this call.
|
||||
let state = ScriptState::from_game_state(self);
|
||||
if let Some(id) = grabbed {
|
||||
self.scripts.run_grab(state.clone(), id);
|
||||
self.scripts.run_grab(id);
|
||||
self.resolve();
|
||||
}
|
||||
if let Some(idx) = bumped {
|
||||
self.scripts.run_bump(state, idx, -1);
|
||||
self.scripts.run_bump(idx, -1);
|
||||
self.drain_errors();
|
||||
}
|
||||
}
|
||||
@@ -539,7 +539,7 @@ mod tests {
|
||||
game.try_move(Direction::East);
|
||||
|
||||
// The gem was grabbed: gem count up, gem object gone, player on its cell.
|
||||
assert_eq!(game.player.gems, 1);
|
||||
assert_eq!(game.player.borrow().gems, 1);
|
||||
assert!(game.board().objects.is_empty());
|
||||
assert_eq!((game.board().player.x, game.board().player.y), (1, 0));
|
||||
}
|
||||
@@ -567,7 +567,7 @@ mod tests {
|
||||
game.tick(Duration::from_millis(16));
|
||||
|
||||
// No grab: the gem is untouched and the player never moved.
|
||||
assert_eq!(game.player.gems, 0);
|
||||
assert_eq!(game.player.borrow().gems, 0);
|
||||
assert!(game.board().objects.values().any(|o| o.grab));
|
||||
assert_eq!((game.board().player.x, game.board().player.y), (2, 0));
|
||||
}
|
||||
@@ -591,7 +591,7 @@ mod tests {
|
||||
// crate moves to (3,0), empty moves back to (2,0).
|
||||
let mut game = game_with_object_script(
|
||||
5,
|
||||
"fn tick(m,s,dt) { if m.queue.length == 0 { shift([[2, 0], [3, 0]]); } }",
|
||||
"fn tick(m,dt) { if m.queue.length == 0 { shift([[2, 0], [3, 0]]); } }",
|
||||
);
|
||||
game.tick(Duration::from_millis(16));
|
||||
let b = game.board();
|
||||
@@ -609,10 +609,10 @@ mod tests {
|
||||
obj.script_name = Some("s".to_string());
|
||||
let mut board = open_board(4, 1, (3, 0), vec![obj]);
|
||||
crate_at(&mut board, 2, 0);
|
||||
let src = "fn init(m,s) { \
|
||||
log(if s.board.passable(1, 0) { \"empty:yes\" } else { \"empty:no\" }); \
|
||||
log(if s.board.passable(2, 0) { \"crate:yes\" } else { \"crate:no\" }); \
|
||||
log(if s.board.passable(9, 0) { \"off:yes\" } else { \"off:no\" }); }";
|
||||
let src = "fn init(m) { \
|
||||
log(if Board.passable(1, 0) { \"empty:yes\" } else { \"empty:no\" }); \
|
||||
log(if Board.passable(2, 0) { \"crate:yes\" } else { \"crate:no\" }); \
|
||||
log(if Board.passable(9, 0) { \"off:yes\" } else { \"off:no\" }); }";
|
||||
let scripts = HashMap::from([("s".to_string(), src.to_string())]);
|
||||
let mut game = GameState::with_scripts(board, scripts);
|
||||
game.run_init();
|
||||
@@ -727,14 +727,15 @@ mod tests {
|
||||
let board = open_board(2, 1, (1, 0), vec![sobj]);
|
||||
let scripts = HashMap::from([(
|
||||
"s".to_string(),
|
||||
"fn init(m, s) { set_key(\"blue\", true); set_key(\"red\", true); }".to_string(),
|
||||
"fn init(m) { set_key(\"blue\", true); set_key(\"red\", true); }".to_string(),
|
||||
)]);
|
||||
let mut game = GameState::with_scripts(board, scripts);
|
||||
game.run_init();
|
||||
|
||||
assert!(game.player.keys.blue);
|
||||
assert!(game.player.keys.red);
|
||||
assert!(!game.player.keys.cyan); // cyan was not set by the script
|
||||
let keys = game.player.borrow().keys;
|
||||
assert!(keys.blue);
|
||||
assert!(keys.red);
|
||||
assert!(!keys.cyan); // cyan was not set by the script
|
||||
|
||||
// A second script can take a key.
|
||||
let mut sobj2 = ObjectDef::new(0, 0);
|
||||
@@ -743,12 +744,12 @@ mod tests {
|
||||
let board2 = open_board(2, 1, (1, 0), vec![sobj2]);
|
||||
let scripts2 = HashMap::from([(
|
||||
"t".to_string(),
|
||||
"fn init(m, s) { set_key(\"blue\", true); set_key(\"blue\", false); }".to_string(),
|
||||
"fn init(m) { set_key(\"blue\", true); set_key(\"blue\", false); }".to_string(),
|
||||
)]);
|
||||
let mut game2 = GameState::with_scripts(board2, scripts2);
|
||||
game2.run_init();
|
||||
|
||||
assert!(!game2.player.keys.blue);
|
||||
assert!(!game2.player.borrow().keys.blue);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -759,7 +760,7 @@ mod tests {
|
||||
let board = open_board(2, 1, (1, 0), vec![sobj]);
|
||||
let scripts = HashMap::from([(
|
||||
"s".to_string(),
|
||||
r#"fn init(m,s) { set_key("chartreuse", true); }"#.to_string(),
|
||||
r#"fn init(m) { set_key("chartreuse", true); }"#.to_string(),
|
||||
)]);
|
||||
let mut game = GameState::with_scripts(board, scripts);
|
||||
game.run_init();
|
||||
|
||||
Reference in New Issue
Block a user