Fixed three script host bugs; scriptkey

This commit is contained in:
2026-07-24 23:52:03 -05:00
parent 917f4b1bf0
commit 855b287a88
7 changed files with 127 additions and 77 deletions
+42 -12
View File
@@ -1,7 +1,8 @@
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use serde::{Deserialize, Serialize};
use crate::api::queue::ObjQueue;
use crate::{Builtin, Direction};
use crate::builtin::BUILTIN_SOURCES;
use crate::floor::{Floor, FloorBiome};
use crate::glyph::Glyph;
use crate::object_def::ObjectDef;
@@ -117,6 +118,38 @@ const fn default_as_below() -> DrawLayer {
DrawLayer::Below
}
#[derive(Hash, PartialEq, Eq, Clone, Debug, Default)]
pub enum ScriptKey {
#[default]
None,
World(String),
Builtin(&'static str),
}
impl ScriptKey {
pub fn name(&self) -> &str {
match self {
ScriptKey::None => "<none>",
ScriptKey::World(name) => name.as_str(),
ScriptKey::Builtin(name) => *name
}
}
pub fn source<'a>(&self, sources: &'a HashMap<String, String>) -> Option<&'a str> {
match self {
ScriptKey::None => None,
ScriptKey::World(name) => sources.get(name).map(String::as_str),
key @ ScriptKey::Builtin(_) => BUILTIN_SOURCES.get(key).copied(),
}
}
}
impl From<Option<String>> for ScriptKey {
fn from(s: Option<String>) -> Self {
s.map_or(Self::None, |s| Self::World(s))
}
}
/// Everything an object-or-sensor needs to have a Rhai script attached.
/// TODO clean this up some, especially the script_name-vs-builtin_script dichotomy
#[derive(Clone, Default)]
@@ -136,14 +169,13 @@ pub struct ScriptAttributes {
/// or a synthetic `BUILTIN_*` name set when a script-backed archetype is
/// expanded (see [`builtin_script`](ObjectDef::builtin_script)). `None` means
/// this object has no script yet.
pub script_name: Option<String>,
pub script_name: ScriptKey,
/// Embedded built-in script source, set when a script-backed archetype (e.g. a
/// `pusher_*` or `gem`) is expanded into an object at load time (see
/// [`crate::builtin_scripts`]). When set, this is the object's script *source*
/// (its compile-key is the synthetic `BUILTIN_*` [`script_name`](ObjectDef::script_name)
/// the same expansion assigns). Not part of the map file — it is regenerated
/// from the archetype on load.
pub builtin_script: Option<&'static str>,
/// Open-ended string labels for this object. Serialized as a TOML array;
/// not subject to any rate limit — mutations take effect immediately after
/// the frame's action queue is drained.
@@ -202,7 +234,7 @@ impl SensorSpec {
optics: self.optics,
name: self.name,
tags: self.tags.into_iter().collect(),
script_name: self.script,
script_name: self.script.into(),
..Default::default()
}
}
@@ -234,8 +266,8 @@ pub trait Hookable {
/// for an expanded built-in (so identical built-ins share one compiled AST,
/// while the source still comes from `builtin_script`). `None` if the object has
/// no script.
fn script_key(&self) -> Option<&String> {
self.scriptable().script_name.as_ref()
fn script_key(&self) -> &ScriptKey {
&self.scriptable().script_name
}
}
@@ -346,8 +378,7 @@ impl IntoTile for TileSpec {
id: *next_object_id,
glyph,
optics,
script_name: script,
builtin_script: None,
script_name: script.into(),
tags: tags.into_iter().collect(),
name,
queue: ObjQueue::new(),
@@ -365,8 +396,7 @@ impl IntoTile for TileSpec {
id: *next_object_id,
glyph: glyph.unwrap_or(builtin.default_glyph_for(variant)),
optics: builtin.optics(),
script_name: None,
builtin_script: Some(builtin.script()),
script_name: builtin.script(),
tags: HashSet::from([format!("BUILTIN_{}", variant)]),
name: None,
queue: ObjQueue::new(),
@@ -389,10 +419,10 @@ impl TileSpec {
TileSpec::Builtin { kind: "wall".to_string(), glyph: None }
}
pub fn player() -> Self {
TileSpec::Builtin { kind: "wall".to_string(), glyph: None }
TileSpec::Player
}
pub fn krate() -> Self {
TileSpec::Builtin { kind: "wall".to_string(), glyph: None }
TileSpec::Builtin { kind: "crate".to_string(), glyph: None }
}
pub fn gem() -> Self {
TileSpec::Builtin { kind: "gem".to_string(), glyph: None }