dotzuki_engine_script/api_registrar.rs
1//! ScriptApiRegistrar trait — enables game-agnostic JS API registration.
2//!
3//! The core engine registers generic APIs (showText, moveNpc, getFlag, warpTo, etc.)
4//! on the `game` global object. Game-specific APIs (giveMonster, startBattle, etc.)
5//! are registered by implementors of this trait via `ScriptEngine::with_api()`.
6//!
7//! DSL scene management APIs (showScene, hideScene, updateUI) are registered as
8//! core APIs during `ScriptEngine::new()`.
9
10use crate::command::ScriptCommand;
11use crate::engine::ScriptEngine;
12use boa_engine::JsArgs;
13
14/// Trait for registering game-specific JavaScript APIs.
15///
16/// Implementations add function properties to the `game` global JS object
17/// (already created by the core engine) during `ScriptEngine` initialization.
18///
19/// # Example
20///
21/// ```ignore
22/// struct MyGameApi;
23/// impl ScriptApiRegistrar for MyGameApi {
24/// fn register_api(&self, engine: &mut ScriptEngine) {
25/// engine.register_async_fn("myCommand", |args, ctx| {
26/// // ... build ScriptCommand ...
27/// });
28/// }
29/// }
30///
31/// let engine = ScriptEngine::with_api(&MyGameApi);
32/// ```
33pub trait ScriptApiRegistrar {
34 /// Register functions on the `game` JS object.
35 /// Called during `ScriptEngine` initialization, after core APIs
36 /// have been registered and the `game` global object is available.
37 fn register_api(&self, engine: &mut ScriptEngine);
38}
39
40/// Register the `game.showScene()` JS API on the given engine.
41///
42/// Callable from JS as: `await game.showScene("shop")`
43/// Produces `ScriptCommand::ShowScene { scene_name, layout_json: None }`.
44pub fn register_show_scene(engine: &mut ScriptEngine) {
45 engine.register_async_fn("showScene", |args, ctx| {
46 let scene_name = args
47 .get_or_undefined(0)
48 .to_string(ctx)?
49 .to_std_string_lossy();
50 Ok(ScriptCommand::ShowScene {
51 scene_name,
52 layout_json: None,
53 })
54 });
55}
56
57/// Register the `game.hideScene()` JS API on the given engine.
58///
59/// Callable from JS as: `await game.hideScene("shop")`
60/// Produces `ScriptCommand::HideScene { scene_name }`.
61pub fn register_hide_scene(engine: &mut ScriptEngine) {
62 engine.register_async_fn("hideScene", |args, ctx| {
63 let scene_name = args
64 .get_or_undefined(0)
65 .to_string(ctx)?
66 .to_std_string_lossy();
67 Ok(ScriptCommand::HideScene { scene_name })
68 });
69}
70
71/// Register the `game.updateUI()` JS API on the given engine.
72///
73/// Callable from JS as: `await game.updateUI("shop", { gold: 999 })`
74/// The `data` argument is serialized via `JSON.stringify` by the Boa runtime.
75/// Produces `ScriptCommand::UpdateUI { scene_name, data_json }`.
76pub fn register_update_ui(engine: &mut ScriptEngine) {
77 engine.register_async_fn("updateUI", |args, ctx| {
78 let scene_name = args
79 .get_or_undefined(0)
80 .to_string(ctx)?
81 .to_std_string_lossy();
82 let data_val = args.get_or_undefined(1);
83 let json_val = data_val.to_json(ctx)?;
84 let data_json = json_val.to_string();
85 Ok(ScriptCommand::UpdateUI {
86 scene_name,
87 data_json,
88 })
89 });
90}