builtin macro
This commit is contained in:
@@ -1,70 +1,39 @@
|
||||
//! Built-in scripts: archetypes that are really scripted objects.
|
||||
//! Tag helpers for script-backed archetypes expanded from map-file keywords.
|
||||
//!
|
||||
//! Some archetypes (currently the `pusher_*` family) have behavior that an
|
||||
//! ordinary scripted object can express exactly. Rather than special-case them in
|
||||
//! the engine, the map loader *expands* such an archetype into an [`ObjectDef`]
|
||||
//! carrying an embedded Rhai script (see [`ObjectDef::builtin_script`]) plus a
|
||||
//! `BUILTIN_<archetype>` tag. The script reads that tag for any per-instance
|
||||
//! parameter (the pusher reads it for its direction), and [`crate::map_file`]'s
|
||||
//! save path uses the same tag to collapse the object back into its archetype
|
||||
//! keyword so maps round-trip.
|
||||
//! When a [`Builtin`] archetype cell is expanded into an [`ObjectDef`] by
|
||||
//! [`Board::expand_builtin_archetypes`], the object receives a `BUILTIN_<alias>`
|
||||
//! tag (e.g. `"BUILTIN_pusher_north"`) so its Rhai script can read which specific
|
||||
//! variant it is (via `Me.has_tag("BUILTIN_pusher_north")`).
|
||||
//!
|
||||
//! This module is the single place to register a new script-backed archetype:
|
||||
//! add an arm to [`archetype_script`].
|
||||
//! The save path ([`map_file`]) uses [`archetype_from_builtin_tag`] to collapse
|
||||
//! an expanded object back into its original map-file keyword so worlds
|
||||
//! round-trip correctly.
|
||||
//!
|
||||
//! The full builtin registry — which archetypes exist, their behaviors, glyphs,
|
||||
//! and embedded scripts — lives in [`crate::archetype`] via the `builtins!` macro.
|
||||
//!
|
||||
//! [`Builtin`]: crate::archetype::Builtin
|
||||
//! [`ObjectDef`]: crate::object_def::ObjectDef
|
||||
//! [`Board::expand_builtin_archetypes`]: crate::board::Board::expand_builtin_archetypes
|
||||
//! [`map_file`]: crate::map_file
|
||||
|
||||
use crate::archetype::Archetype;
|
||||
|
||||
/// Prefix for the tag that marks an object as an expanded built-in archetype and
|
||||
/// names which archetype it came from (e.g. `"BUILTIN_pusher_east"`).
|
||||
/// names which alias it came from (e.g. `"BUILTIN_pusher_east"`).
|
||||
pub(crate) const BUILTIN_TAG_PREFIX: &str = "BUILTIN_";
|
||||
|
||||
/// The pusher behavior, embedded into the binary. Shared by every direction —
|
||||
/// direction comes from the object's tag, so all pushers share one compiled AST.
|
||||
const PUSHER: &str = include_str!("scripts/pusher.rhai");
|
||||
|
||||
/// The spinner behavior, embedded into the binary. Shared by both spin directions —
|
||||
/// direction comes from the object's tag, so all spinners share one compiled AST.
|
||||
const SPINNER: &str = include_str!("scripts/spinner.rhai");
|
||||
|
||||
/// The gem behavior, embedded into the binary: a `grab()` hook that adds a gem to
|
||||
/// the player and removes the object.
|
||||
const GEM: &str = include_str!("scripts/gem.rhai");
|
||||
|
||||
/// The tag identifying an object as the expanded form of `arch`, e.g.
|
||||
/// `"BUILTIN_pusher_east"`.
|
||||
/// Returns the `BUILTIN_<alias>` tag for `arch` — e.g. `"BUILTIN_pusher_east"`.
|
||||
///
|
||||
/// For a `Builtin` archetype, `arch.name()` returns the alias (e.g. `"pusher_east"`).
|
||||
/// For terrain archetypes (wall, crate, etc.) this is never called in practice.
|
||||
pub(crate) fn builtin_tag(arch: Archetype) -> String {
|
||||
format!("{BUILTIN_TAG_PREFIX}{}", arch.name())
|
||||
}
|
||||
|
||||
/// Recovers the archetype a `BUILTIN_*` tag came from, or `None` if `tag` is not a
|
||||
/// built-in tag naming a known archetype. Used by the save path to round-trip.
|
||||
/// Recovers the `Archetype` a `BUILTIN_*` tag came from, or `None` if `tag` is not
|
||||
/// a built-in tag naming a known archetype. Used by the save path to round-trip.
|
||||
pub(crate) fn archetype_from_builtin_tag(tag: &str) -> Option<Archetype> {
|
||||
let name = tag.strip_prefix(BUILTIN_TAG_PREFIX)?;
|
||||
Archetype::try_from(name).ok()
|
||||
}
|
||||
|
||||
/// Returns the embedded script implementing `arch` as an object, or `None` if the
|
||||
/// archetype is a plain terrain cell. The one place script-backed archetypes are
|
||||
/// declared.
|
||||
pub(crate) fn archetype_script(arch: Archetype) -> Option<&'static str> {
|
||||
match arch {
|
||||
Archetype::Pusher(_) => Some(PUSHER),
|
||||
Archetype::Spinner(_) => Some(SPINNER),
|
||||
Archetype::Gem => Some(GEM),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the synthetic `BUILTIN_*` compile-key for `arch`'s embedded script, or
|
||||
/// `None` if the archetype is a plain terrain cell. [`Board::expand_builtin_archetypes`](crate::board::Board::expand_builtin_archetypes)
|
||||
/// stores this as the expanded object's `script_name` so every instance of a
|
||||
/// script-backed archetype shares one compiled AST (the source comes from
|
||||
/// [`archetype_script`]).
|
||||
pub(crate) fn archetype_script_key(arch: Archetype) -> Option<&'static str> {
|
||||
match arch {
|
||||
Archetype::Pusher(_) => Some("BUILTIN_pusher"),
|
||||
Archetype::Spinner(_) => Some("BUILTIN_spinner"),
|
||||
Archetype::Gem => Some("BUILTIN_gem"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user