pub struct LoadedProject { /* private fields */ }Expand description
A fully loaded zero-Rust game project.
Implementations§
Source§impl LoadedProject
impl LoadedProject
Sourcepub fn load(root: &Path) -> Result<Self>
pub fn load(root: &Path) -> Result<Self>
Load the project rooted at root (the directory containing
.dotzuki-editor.json) from disk. Convenience for
load_with_files over a DiskFiles.
§Errors
Fails on a missing/unparseable manifest or any DSL diagnostic.
Examples found in repository?
76fn main() {
77 let mut args = std::env::args().skip(1);
78 let dir = args.next().expect("usage: menu_accept <project-dir> [shot-dir]");
79 let shot_dir = args.next().map(PathBuf::from);
80
81 let project = LoadedProject::load(Path::new(&dir)).expect("load project");
82 let mut game = RunnerGame::new(
83 project,
84 RunnerOptions {
85 headless: true,
86 fresh: true,
87 // Deterministic battles: always hit, 89% variance, never crit.
88 rng_script: Some(vec![50, 100, 1]),
89 ..RunnerOptions::default()
90 },
91 )
92 .expect("boot game");
93
94 dismiss(&mut game); // StartTown main
95 println!("== 1. the shop ==");
96 println!("money at boot: {} (manifest shop.startMoney)", game.money());
97
98 // Talk to the Shopkeeper at (13,10): the shop opens on the spot.
99 game.debug_place(12, 10, Direction::Right);
100 press_a(&mut game);
101 let rows = game.shop_lines().expect("shop open");
102 println!("shop shelf: {rows:?}");
103 snap(&mut game, &shot_dir, "shop");
104
105 // Buy one Potion: 100 → 80 G, inventory 3 → 4.
106 let before = game.money();
107 press_a(&mut game);
108 let rows = game.shop_lines().expect("shop still open");
109 println!(
110 "bought a Potion: money {before} → {} G; inventory {:?}",
111 game.money(),
112 game.inventory().expect("inventory materialized")
113 );
114 println!("shop note: {:?}", rows.last());
115 snap(&mut game, &shot_dir, "shop-bought");
116 assert_eq!(game.money(), 80, "20 G charged");
117 assert_eq!(game.inventory().unwrap().get("potion"), Some(&4));
118 press_a(&mut game); // dismiss the note
119
120 // B exits; the scene resumes with its follow-up line.
121 press(&mut game, GbButton::B);
122 let page = game.dialogue_text().expect("scene resumed after the shop");
123 println!("scene resumed with: {page:?}");
124 assert!(page.contains("Come again!"), "page: {page:?}");
125 dismiss(&mut game);
126
127 println!("\n== 2. the whiteout ==");
128 // Talk to the Hermit at (11,10) and lose on purpose (overwhelming Slime).
129 game.debug_place(12, 10, Direction::Left);
130 press_a(&mut game); // "Something stirs…"
131 press_a(&mut game); // → battle
132 let mut last_log: Vec<String> = Vec::new();
133 for _ in 0..120 {
134 let Some(battle) = game.battle() else { break };
135 last_log = battle.log().to_vec();
136 press_a(&mut game);
137 }
138 println!("lost battle log:");
139 for line in &last_log {
140 println!(" {line}");
141 }
142 assert_eq!(last_log.last().map(String::as_str), Some("You lost the battle…"));
143
144 // The scene's post-lose text still plays…
145 let page = game.dialogue_text().expect("post-lose text");
146 println!("post-lose text: {page:?}");
147 assert!(page.contains("no match"), "page: {page:?}");
148 press_a(&mut game); // scene finishes → whiteout
149
150 // …then the whiteout: blackout first, then the collapsed line.
151 assert!(game.whiteout_active(), "whiteout armed");
152 idle(&mut game, 10);
153 snap(&mut game, &shot_dir, "whiteout-blackout");
154 idle(&mut game, 25);
155 let page = game.dialogue_text().expect("whiteout message");
156 println!("whiteout message: {page:?}");
157 assert!(page.contains("collapsed"), "page: {page:?}");
158 snap(&mut game, &shot_dir, "whiteout-message");
159
160 // Landing it: party healed to full, back at the entry spawn, flags kept.
161 press_a(&mut game);
162 assert!(!game.whiteout_active());
163 println!("after the whiteout:");
164 println!(" map: {:?} tile: {:?}", game.current_map_id(), game.player_tile());
165 for m in game.party_state().expect("party state") {
166 println!(" {} hp {} mp {} status {:?}", m.id, m.hp, m.mp, m.status);
167 }
168 println!(" __played_main_StartTown flag kept: {}", game.flag("__played_main_StartTown"));
169 assert_eq!(game.current_map_id(), Some("StartTown"));
170 assert!(game
171 .party_state()
172 .unwrap()
173 .iter()
174 .all(|m| m.hp > 0 && m.status.is_none()));
175 snap(&mut game, &shot_dir, "whiteout-after");
176
177 println!("\nacceptance OK");
178}More examples
69fn main() {
70 let mut args = std::env::args().skip(1);
71 let dir = args.next().expect("usage: levels_accept <project-dir> [shot-dir]");
72 let shot_dir = args.next().map(PathBuf::from);
73
74 let save_file = Path::new(&dir).join(".dotzuki-save.json");
75 let project = LoadedProject::load(Path::new(&dir)).expect("load project");
76 let mut game = RunnerGame::new(
77 project,
78 RunnerOptions {
79 headless: true,
80 fresh: true,
81 write_saves: true,
82 save_file: Some(save_file.clone()),
83 // Deterministic battles: always hit, 89% variance, never crit.
84 rng_script: Some(vec![50, 100, 1]),
85 ..RunnerOptions::default()
86 },
87 )
88 .expect("boot game");
89
90 // Auto-A drives everything: dialogue pages, battle narration, and the
91 // Fight → first-skill picks. Back-to-back `startBattle` commands swap
92 // Battle→Battle INSIDE one update, so a new battle is detected by the
93 // log resetting, not just by a not-in-battle gap.
94 let mut battle_no = 0usize;
95 let mut completed = 0usize;
96 let mut last_log: Vec<String> = Vec::new();
97 let mut was_in_battle = false;
98 let mut snapped_battle = false;
99
100 for frame_no in 0..6000u32 {
101 if frame_no % 4 == 0 {
102 frame(&mut game, GbButton::A.bit_mask());
103 } else {
104 idle(&mut game, 1);
105 }
106
107 let in_battle = game.battle().is_some();
108 if in_battle {
109 let log_len = game.battle().unwrap().log().len();
110 let new_battle = !was_in_battle || log_len < last_log.len();
111 if new_battle {
112 if was_in_battle {
113 // Seamless Battle→Battle swap: close the previous one
114 // out (the party state is already harvested).
115 completed += 1;
116 println!("\nbattle {completed} log:");
117 for line in &last_log {
118 println!(" {line}");
119 }
120 print_party(&game, &format!("after battle {completed}"));
121 println!();
122 if completed == 2 {
123 break;
124 }
125 }
126 battle_no += 1;
127 let battle = game.battle().unwrap();
128 println!("battle {battle_no} starts:");
129 for c in battle.party() {
130 println!(
131 " {} level {} exp {} hp {}/{} mp {}/{} atk {}",
132 c.name, c.level, c.exp, c.hp, c.max_hp, c.mp, c.max_mp, c.attack
133 );
134 }
135 if battle_no == 2 && !snapped_battle {
136 snapped_battle = true;
137 snap(&mut game, &shot_dir, "battle2-start");
138 }
139 }
140 last_log = game.battle().unwrap().log().to_vec();
141 } else if was_in_battle {
142 completed += 1;
143 println!("\nbattle {completed} log:");
144 for line in &last_log {
145 println!(" {line}");
146 }
147 print_party(&game, &format!("after battle {completed}"));
148 println!();
149 last_log.clear();
150 if completed == 2 {
151 break;
152 }
153 }
154 was_in_battle = in_battle;
155 }
156 if completed < 2 {
157 eprintln!("harness: only {completed} battle(s) completed within the frame cap");
158 std::process::exit(1);
159 }
160
161 // Dismiss the post-battle text so the scene finishes (the save is
162 // written at that stable point).
163 for _ in 0..40 {
164 if game.dialogue_text().is_none() {
165 break;
166 }
167 press_a(&mut game);
168 }
169 assert!(game.flag("SLIMES_BEATEN"), "the scene ran to its end");
170
171 // The Party view: Lv + EXP progress on the member rows.
172 frame(&mut game, GbButton::Start.bit_mask());
173 idle(&mut game, 1);
174 press_a(&mut game); // Party
175 println!("party view:");
176 for line in game.menu_lines().expect("party view open") {
177 println!(" {line}");
178 }
179 snap(&mut game, &shot_dir, "party-view");
180 frame(&mut game, GbButton::B.bit_mask());
181 idle(&mut game, 1);
182 frame(&mut game, GbButton::B.bit_mask());
183 idle(&mut game, 1);
184
185 // Save round trip: a fresh boot resumes level/exp from the save.
186 println!("\nsave round trip ({}):", save_file.display());
187 let project = LoadedProject::load(Path::new(&dir)).expect("reload project");
188 let game = RunnerGame::new(
189 project,
190 RunnerOptions {
191 headless: true,
192 save_file: Some(save_file),
193 rng_script: Some(vec![50, 100, 1]),
194 ..RunnerOptions::default()
195 },
196 )
197 .expect("boot from save");
198 print_party(&game, "resumed from the save");
199 assert!(
200 game.party_state().is_some_and(|p| p[0].level > 1),
201 "level must survive the save round trip"
202 );
203 println!("\nacceptance OK");
204}46fn main() {
47 let mut args = std::env::args().skip(1);
48 let dir = args.next().expect("usage: battle_accept <project-dir> [shot-dir]");
49 let shot_dir = args.next().map(PathBuf::from);
50
51 let project = LoadedProject::load(Path::new(&dir)).expect("load project");
52 let mut game = RunnerGame::new(
53 project,
54 RunnerOptions {
55 headless: true,
56 fresh: true,
57 // Deterministic battles: always hit, 89% variance, never crit.
58 rng_script: Some(vec![50, 100, 1]),
59 ..RunnerOptions::default()
60 },
61 )
62 .expect("boot game");
63
64 // The agenda per battle (index = battles started so far − 1).
65 let agendas: &[&[Pick]] = &[&[Pick::Item, Pick::Party, Pick::Fight], &[Pick::Fight]];
66 let mut battles_done = 0usize;
67 let mut agenda: Vec<Pick> = Vec::new();
68 // Queued button presses; one key every other frame (a held key is not a
69 // fresh just-press, so keys alternate with idle frames).
70 let mut keys: Vec<GbButton> = Vec::new();
71 let mut last_log: Vec<String> = Vec::new();
72 let mut snapped: Vec<String> = Vec::new();
73 let mut was_in_battle_prev = false;
74
75 let mut input = InputState::new();
76 for frame in 0..6000u32 {
77 let was_in_battle = was_in_battle_prev;
78
79 // Decide this frame's input.
80 let mut mask = 0;
81 if frame % 2 == 0 {
82 if !keys.is_empty() {
83 mask = keys.remove(0).bit_mask();
84 } else if let Some(battle) = game.battle() {
85 if battle.in_menu() {
86 let items = battle.menu_items();
87 let label = if items.first().is_some_and(|i| i == "Fight") {
88 "root"
89 } else if items.iter().any(|i| i.contains('/')) {
90 "party"
91 } else {
92 "sub"
93 };
94 if let Some(dir) = &shot_dir {
95 let tag = format!("battle{}-{label}", battles_done + 1);
96 if !snapped.contains(&tag) {
97 snapped.push(tag.clone());
98 snap(&mut game, &dir.join(format!("{tag}.png")));
99 }
100 }
101 mask = match label {
102 "root" => {
103 let pick = agenda.first().copied().unwrap_or(Pick::Fight);
104 if !agenda.is_empty() {
105 agenda.remove(0);
106 }
107 match pick {
108 Pick::Fight => GbButton::A.bit_mask(),
109 Pick::Party => {
110 keys.push(GbButton::A);
111 GbButton::Down.bit_mask()
112 }
113 Pick::Item => {
114 keys.push(GbButton::Down);
115 keys.push(GbButton::A);
116 GbButton::Down.bit_mask()
117 }
118 }
119 }
120 // Submenus: confirm the entry under the cursor (the
121 // party cursor starts on the first switchable member).
122 _ => GbButton::A.bit_mask(),
123 };
124 } else if frame % 4 == 0 {
125 mask = GbButton::A.bit_mask(); // page narration
126 }
127 } else if frame % 4 == 0 {
128 mask = GbButton::A.bit_mask(); // page dialogue
129 }
130 }
131 input.set_from_bitmask(mask);
132 game.update(&input);
133 input.begin_frame();
134
135 let in_battle = game.battle().is_some();
136 // Battle-start edge: print the party it starts with (the carried-over
137 // state from battle 2 on) and load its agenda.
138 if in_battle && !was_in_battle {
139 let n = battles_done + 1;
140 let battle = game.battle().unwrap();
141 println!("battle {n} starts:");
142 for c in battle.party() {
143 let status = c.status.as_deref().unwrap_or("-");
144 println!(
145 " {} {}/{} MP {}/{} status {}",
146 c.name, c.hp, c.max_hp, c.mp, c.max_mp, status
147 );
148 }
149 println!(" inventory: {:?}", battle.inventory());
150 agenda = agendas[battles_done].to_vec();
151 }
152 if in_battle {
153 last_log = game.battle().unwrap().log().to_vec();
154 }
155 // Battle-end edge: the runner has harvested the party state.
156 if was_in_battle && !in_battle {
157 battles_done += 1;
158 println!("\nbattle {battles_done} log:");
159 for line in &last_log {
160 println!(" {line}");
161 }
162 if let Some(party) = game.party_state() {
163 println!("party state after battle {battles_done}:");
164 for m in party {
165 println!(" {} hp {} mp {} status {:?}", m.id, m.hp, m.mp, m.status);
166 }
167 }
168 if let Some(inv) = game.inventory() {
169 println!("inventory: {inv:?}");
170 }
171 println!();
172 last_log.clear();
173 if battles_done == 2 {
174 println!("both battles done — stopping");
175 break;
176 }
177 }
178 was_in_battle_prev = in_battle;
179 }
180
181 if battles_done < 2 {
182 eprintln!("harness: only {battles_done} battle(s) completed within the frame cap");
183 std::process::exit(1);
184 }
185}46fn main() {
47 let mut args = std::env::args().skip(1);
48 let dir = args
49 .next()
50 .expect("usage: encounter_accept <project-dir> [shot-dir]");
51 let shot_dir = args.next().map(PathBuf::from);
52
53 let project = LoadedProject::load(Path::new(&dir)).expect("load project");
54 let mut game = RunnerGame::new(
55 project,
56 RunnerOptions {
57 headless: true,
58 fresh: true,
59 // Deterministic battles: always hit, 89% variance, never crit.
60 rng_script: Some(vec![50, 100, 1]),
61 ..RunnerOptions::default()
62 },
63 )
64 .expect("boot game");
65 println!("money at boot: {}", game.money());
66
67 // The agenda per battle (index = battles started so far − 1): the
68 // trainer battle tries Run first (blocked), the wild battle runs.
69 // Battle 1's agenda is pre-armed: the entry scene suspends on
70 // `startBattle` during boot, so its first menu frame precedes the
71 // battle-start edge below (later battles arm on their edge — text plays
72 // between them).
73 let agendas: &[&[Pick]] = &[&[Pick::Run, Pick::Fight], &[Pick::Run]];
74 let mut battles_done = 0usize;
75 let mut agenda: Vec<Pick> = agendas[0].to_vec();
76 // Queued button presses; one key every other frame (a held key is not a
77 // fresh just-press, so keys alternate with idle frames).
78 let mut keys: Vec<GbButton> = Vec::new();
79 let mut last_log: Vec<String> = Vec::new();
80 let mut was_in_battle_prev = false;
81 let mut snapped: Vec<String> = Vec::new();
82 // Shop agenda: 0 = root (→ Sell), 1 = sell view (→ sell one), 2 = note
83 // (→ dismiss), 3 = back to root (→ B), 4 = exit (→ B), 5 = done.
84 let mut shop_step = 0usize;
85 let mut shop_done = false;
86
87 let mut input = InputState::new();
88 for frame in 0..6000u32 {
89 let was_in_battle = was_in_battle_prev;
90
91 // Decide this frame's input.
92 let mut mask = 0;
93 if frame % 2 == 0 {
94 if !keys.is_empty() {
95 mask = keys.remove(0).bit_mask();
96 } else if let Some(battle) = game.battle() {
97 if battle.in_menu() {
98 let is_root = battle.menu_items().first().is_some_and(|i| i == "Fight");
99 mask = if is_root {
100 let pick = agenda.first().copied().unwrap_or(Pick::Fight);
101 if !agenda.is_empty() {
102 agenda.remove(0);
103 }
104 match pick {
105 Pick::Fight => GbButton::A.bit_mask(),
106 Pick::Run => {
107 // Fight/Party/Item/Run → Down ×3, confirm.
108 keys.push(GbButton::Down);
109 keys.push(GbButton::Down);
110 keys.push(GbButton::A);
111 GbButton::Down.bit_mask()
112 }
113 }
114 } else {
115 GbButton::A.bit_mask() // skill submenu
116 };
117 } else if frame % 4 == 0 {
118 mask = GbButton::A.bit_mask(); // page narration
119 }
120 } else if game.shop_lines().is_some() && battles_done == 2 && !shop_done {
121 match shop_step {
122 0 => {
123 println!("shop root: {:?}", game.shop_lines().unwrap());
124 keys.push(GbButton::Down); // → Sell
125 keys.push(GbButton::A);
126 }
127 1 => {
128 println!("sell view: {:?}", game.shop_lines().unwrap());
129 keys.push(GbButton::A); // sell one Potion
130 }
131 2 => {
132 let lines = game.shop_lines().unwrap();
133 println!("sell note: {lines:?}");
134 if let Some(dir) = &shot_dir {
135 snap(&mut game, &dir.join("shop-sold.png"));
136 }
137 keys.push(GbButton::A); // dismiss the note
138 }
139 3 => keys.push(GbButton::B), // back to the root
140 _ => keys.push(GbButton::B), // exit the shop
141 }
142 shop_step += 1;
143 } else if frame % 4 == 0 {
144 mask = GbButton::A.bit_mask(); // page dialogue
145 }
146 }
147 input.set_from_bitmask(mask);
148 game.update(&input);
149 input.begin_frame();
150
151 let in_battle = game.battle().is_some();
152 // Battle-start edge: print the matchup and load its agenda.
153 if in_battle && !was_in_battle {
154 let n = battles_done + 1;
155 let battle = game.battle().unwrap();
156 println!(
157 "battle {n} starts: {} vs {} (queued {}, trainer {}, reward {})",
158 battle.player().name,
159 battle.enemy().name,
160 battle.enemies_remaining(),
161 battle.is_trainer(),
162 battle.trainer_money(),
163 );
164 if battles_done > 0 {
165 agenda = agendas[battles_done].to_vec();
166 }
167 }
168 if in_battle {
169 // Screenshot the two v2-d narration lines on their first show.
170 // Screenshot the two v2-d narration lines on their first show.
171 let line = game
172 .battle()
173 .unwrap()
174 .current_line()
175 .map(str::to_string);
176 if let (Some(dir), Some(line)) = (&shot_dir, line) {
177 let tag = match line.as_str() {
178 l if l.starts_with("Can't escape") => Some("run-blocked"),
179 l if l.starts_with("Got away") => Some("run-safe"),
180 l if l.starts_with("Got ") && l.ends_with("for winning!") => {
181 Some("trainer-money")
182 }
183 _ => None,
184 };
185 if let Some(tag) = tag {
186 if !snapped.contains(&tag.to_string()) {
187 snapped.push(tag.to_string());
188 snap(&mut game, &dir.join(format!("{tag}.png")));
189 }
190 }
191 }
192 last_log = game.battle().unwrap().log().to_vec();
193 }
194 // Battle-end edge: the runner has harvested the state.
195 if was_in_battle && !in_battle {
196 battles_done += 1;
197 println!("\nbattle {battles_done} log:");
198 for line in &last_log {
199 println!(" {line}");
200 }
201 if battles_done == 1 {
202 assert!(
203 last_log
204 .iter()
205 .any(|l| l == "Can't escape from a trainer battle!"),
206 "the trainer Run attempt must be blocked (and the turn not consumed)"
207 );
208 }
209 println!("money after battle {battles_done}: {}", game.money());
210 if let Some(party) = game.party_state() {
211 for m in party {
212 println!(
213 " {} hp {} mp {} level {} exp {}",
214 m.id, m.hp, m.mp, m.level, m.exp
215 );
216 }
217 }
218 println!();
219 last_log.clear();
220 }
221 // Shop-exit edge.
222 if shop_step >= 5 && game.shop_lines().is_none() && !shop_done {
223 shop_done = true;
224 println!("shop closed: money {}, inventory {:?}", game.money(), game.inventory());
225 }
226 // Everything done: both battles + the shop, scene finished.
227 if battles_done == 2 && shop_done && game.battle().is_none() {
228 println!("acceptance complete");
229 break;
230 }
231 was_in_battle_prev = in_battle;
232 }
233
234 // Verify the v2-d contract points and exit non-zero on any miss.
235 let money = game.money();
236 let potions = game.inventory().and_then(|inv| inv.get("potion").copied());
237 println!("final: money {money}, potions {potions:?}");
238 assert_eq!(battles_done, 2, "both battles must complete");
239 assert!(shop_done, "the shop sell must complete");
240 assert_eq!(money, 142, "100 start + 32 trainer + 10 sell (20/2)");
241 assert_eq!(potions, Some(2), "3 starting − 1 sold");
242}Sourcepub fn load_with_files(files: Arc<dyn ProjectFiles>) -> Result<Self>
pub fn load_with_files(files: Arc<dyn ProjectFiles>) -> Result<Self>
Load the project from a ProjectFiles backend.
The DSL is compiled in memory; any compiler diagnostic (unreadable
file, compile failure, route conflict) aborts the load with an error
listing every diagnostic — the same bar dotzuki check enforces.
§Errors
Fails on a missing/unparseable manifest or any DSL diagnostic.
Sourcepub fn recompile_scripts(&mut self) -> Result<()>
pub fn recompile_scripts(&mut self) -> Result<()>
Recompile every DSL directory and swap the compiled scenes in place.
On success the script registry, routing table and stem indexes are
replaced wholesale — a scene currently mid-activation keeps running
the JS it was started with; the next activation picks up the new
source. On any compiler diagnostic the old scenes are kept and an
error listing every diagnostic is returned (same bar as load).
§Errors
Fails when the recompile produces any diagnostic.
Sourcepub fn files(&self) -> &Arc<dyn ProjectFiles> ⓘ
pub fn files(&self) -> &Arc<dyn ProjectFiles> ⓘ
The project’s file backend.
Sourcepub fn data_root(&self) -> &Path
pub fn data_root(&self) -> &Path
Resolved data root (manifest dataRoot against the project root).
Sourcepub fn data_root_rel(&self) -> &str
pub fn data_root_rel(&self) -> &str
The data root as a project-relative POSIX path (VFS key prefix).
Sourcepub fn gfx_root(&self) -> Option<&Path>
pub fn gfx_root(&self) -> Option<&Path>
Resolved graphics root (manifest gfxRoot), when configured.
Sourcepub fn gfx_root_rel(&self) -> String
pub fn gfx_root_rel(&self) -> String
The graphics root as a project-relative POSIX path (the manifest’s
gfxRoot, default "gfx").
Sourcepub fn scripts(&self) -> &ScriptLoader
pub fn scripts(&self) -> &ScriptLoader
Registry of compiled scene JS, keyed by scene name.
Sourcepub fn report(&self) -> &CompileReport
pub fn report(&self) -> &CompileReport
The full DSL compile report.
Sourcepub fn routes(&self) -> &[RouteEntry]
pub fn routes(&self) -> &[RouteEntry]
Storyline routing table (map, npc/onEnter) → storyline, collected
from @trigger declarations across all scenes.
Sourcepub fn scene_name_for_stem(&self, stem: &str) -> Option<&str>
pub fn scene_name_for_stem(&self, stem: &str) -> Option<&str>
Compiled scene name for a .scene file stem (e.g. "main" →
"Main").
Sourcepub fn stem_for_scene_name(&self, name: &str) -> Option<&str>
pub fn stem_for_scene_name(&self, name: &str) -> Option<&str>
.scene file stem for a compiled scene name.
Sourcepub fn maps_dir_rel(&self) -> String
pub fn maps_dir_rel(&self) -> String
The maps directory as a project-relative POSIX path: the map
activity’s mapsDir (dataRoot-relative), default maps.
Sourcepub fn maps_dir(&self) -> PathBuf
pub fn maps_dir(&self) -> PathBuf
Directory holding the per-map subdirectories (disk form of
maps_dir_rel).
Sourcepub fn entry_map(&self) -> Result<String>
pub fn entry_map(&self) -> Result<String>
Map to spawn on: game.entryMap, or the first map directory (sorted)
under the maps dir.
§Errors
Fails when no entryMap is configured and no map directories exist.
Sourcepub fn entry_scene_name(&self) -> Result<&str>
pub fn entry_scene_name(&self) -> Result<&str>
Scene to boot into: game.entryScene (a .scene file stem) resolved
to its compiled scene name, or the first compiled scene sorted by
source path.
§Errors
Fails when entryScene names a stem that compiled to nothing, or
when the project has no scenes at all.
Sourcepub fn load_map(&self, map_id: &str) -> Result<RuntimeMap>
pub fn load_map(&self, map_id: &str) -> Result<RuntimeMap>
Load a map by id from this project’s maps dir.
Auto Trait Implementations§
impl !RefUnwindSafe for LoadedProject
impl !Send for LoadedProject
impl !Sync for LoadedProject
impl !UnwindSafe for LoadedProject
impl Freeze for LoadedProject
impl Unpin for LoadedProject
impl UnsafeUnpin for LoadedProject
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.impl<S, T> Duplex<S> for Twhere
T: FromSample<S> + ToSample<S>,
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreimpl<T> MaybeSendSync for T
Source§impl<D> OwoColorize for D
impl<D> OwoColorize for D
Source§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
Source§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
Source§fn black(&self) -> FgColorDisplay<'_, Black, Self>
fn black(&self) -> FgColorDisplay<'_, Black, Self>
Source§fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
Source§fn red(&self) -> FgColorDisplay<'_, Red, Self>
fn red(&self) -> FgColorDisplay<'_, Red, Self>
Source§fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
Source§fn green(&self) -> FgColorDisplay<'_, Green, Self>
fn green(&self) -> FgColorDisplay<'_, Green, Self>
Source§fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
Source§fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
Source§fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
Source§fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
Source§fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
Source§fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
Source§fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
Source§fn white(&self) -> FgColorDisplay<'_, White, Self>
fn white(&self) -> FgColorDisplay<'_, White, Self>
Source§fn on_white(&self) -> BgColorDisplay<'_, White, Self>
fn on_white(&self) -> BgColorDisplay<'_, White, Self>
Source§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
Source§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
Source§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
Source§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
Source§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
Source§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
Source§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
Source§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
Source§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
Source§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
Source§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
Source§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
Source§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
Source§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
Source§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
Source§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
Source§fn bold(&self) -> BoldDisplay<'_, Self>
fn bold(&self) -> BoldDisplay<'_, Self>
Source§fn dimmed(&self) -> DimDisplay<'_, Self>
fn dimmed(&self) -> DimDisplay<'_, Self>
Source§fn italic(&self) -> ItalicDisplay<'_, Self>
fn italic(&self) -> ItalicDisplay<'_, Self>
Source§fn underline(&self) -> UnderlineDisplay<'_, Self>
fn underline(&self) -> UnderlineDisplay<'_, Self>
Source§fn blink(&self) -> BlinkDisplay<'_, Self>
fn blink(&self) -> BlinkDisplay<'_, Self>
Source§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
Source§fn reversed(&self) -> ReversedDisplay<'_, Self>
fn reversed(&self) -> ReversedDisplay<'_, Self>
Source§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
Source§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg or
a color-specific method, such as OwoColorize::green, Read moreSource§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg or
a color-specific method, such as OwoColorize::on_yellow, Read moreSource§fn fg_rgb<const R: u8, const G: u8, const B: u8>(
&self,
) -> FgColorDisplay<'_, CustomColor<R, G, B>, Self>
fn fg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> FgColorDisplay<'_, CustomColor<R, G, B>, Self>
Source§fn bg_rgb<const R: u8, const G: u8, const B: u8>(
&self,
) -> BgColorDisplay<'_, CustomColor<R, G, B>, Self>
fn bg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> BgColorDisplay<'_, CustomColor<R, G, B>, Self>
Source§fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self>
fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self>
Source§fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self>
fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self>
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.