Skip to content

Commit cbf9407

Browse files
committed
feat(runtime): game crash error UI, Wave 19 stability
- Game errors now show ErrorScene with the error message instead of silent pop - ErrorScene now takes user back to Home (PopToRoot) on Enter - Added Lua timeout documentation (blocked by Luau thread-safety — IPC sandbox needed)
1 parent fc01e47 commit cbf9407

3 files changed

Lines changed: 27 additions & 11 deletions

File tree

crates/vibege-scene/src/scenes/error_scene.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,17 @@ impl Scene for ErrorScene {
2626
SceneKind::Modal
2727
}
2828

29-
fn on_create(&mut self, ctx: &mut SceneContext) -> SceneResult {
30-
info!(msg = %self.message, "ErrorScene: displayed");
31-
ctx.renderer.set_clear(0.15, 0.05, 0.05, 1.0);
32-
Ok(SceneAction::Continue)
33-
}
34-
3529
fn on_render(&mut self, ctx: &mut SceneContext) -> SceneResult {
3630
ctx.renderer
3731
.draw_rect(200.0, 180.0, 400.0, 240.0, 0.2, 0.05, 0.05, 1.0);
3832
ctx.renderer
3933
.draw_rect(200.0, 180.0, 400.0, 40.0, 0.5, 0.1, 0.1, 1.0);
4034
ctx.renderer
41-
.draw_text(220.0, 190.0, "Scene Error", 14.0, 1.0, 1.0, 1.0);
35+
.draw_text(220.0, 190.0, "Game Error", 14.0, 1.0, 1.0, 1.0);
4236
ctx.renderer.draw_text(
4337
220.0,
4438
240.0,
45-
"Something went wrong in this scene.",
39+
"Something went wrong in this game.",
4640
9.0,
4741
0.8,
4842
0.8,
@@ -55,10 +49,18 @@ impl Scene for ErrorScene {
5549
Ok(SceneAction::Continue)
5650
}
5751

52+
fn on_create(&mut self, ctx: &mut SceneContext) -> SceneResult {
53+
info!(msg = %self.message, "ErrorScene: displayed");
54+
ctx.renderer.set_clear(0.15, 0.05, 0.05, 1.0);
55+
Ok(SceneAction::Continue)
56+
}
57+
5858
fn on_update(&mut self, ctx: &mut SceneContext, _dt: f64) -> SceneResult {
5959
let inp = crate::input_helper::InputState::new(&ctx.input, &["enter"]);
6060
if inp.pressed(0) {
61-
return Ok(SceneAction::PopModal);
61+
return Ok(SceneAction::PopToRoot(Box::new(
62+
super::home_scene::HomeScene::new(),
63+
)));
6264
}
6365
Ok(SceneAction::Continue)
6466
}

crates/vibege-scene/src/scenes/game_manager.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::sync::Arc;
22
use std::sync::Mutex;
3+
use std::time::Duration;
34

45
use mlua::{Function, Lua};
56
use tracing::{info, warn};
@@ -10,6 +11,8 @@ use vibege_input::InputManager;
1011
use vibege_renderer::Renderer;
1112
use vibege_sdk::SdkState;
1213

14+
const LUA_TIMEOUT: Duration = Duration::from_millis(1000);
15+
1316
/// A live game session with its own isolated Lua VM.
1417
pub struct GameSession {
1518
lua: Lua,
@@ -94,6 +97,10 @@ impl GameSession {
9497
})
9598
}
9699

100+
/// Execute the game's update function.
101+
/// NOTE: Lua is not `Send`, so we cannot use thread-based timeouts.
102+
/// A long-running Lua script (infinite loop) will block the engine.
103+
/// This will be resolved when games run in sandboxed processes (Wave 21).
97104
pub fn update(&self, dt: f64) -> Result<(), String> {
98105
SdkState::tick(&self.sdk_state, dt);
99106
if self.has_update {
@@ -106,6 +113,8 @@ impl GameSession {
106113
Ok(())
107114
}
108115

116+
/// Execute the game's render function.
117+
/// NOTE: Same threading limitation as update().
109118
pub fn render(&self) -> Result<(), String> {
110119
if self.has_render {
111120
if let Ok(render_fn) = self.lua.globals().get::<Function>("render") {

crates/vibege-scene/src/scenes/game_scene.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::sync::{Arc, Mutex};
22

3+
use super::error_scene::ErrorScene;
34
use super::game_manager::GameSession;
45
use crate::scene::{Scene, SceneAction, SceneContext, SceneId, SceneResult};
56
use tracing::info;
@@ -106,7 +107,9 @@ impl Scene for GameScene {
106107
Ok(()) => Ok(SceneAction::Continue),
107108
Err(e) => {
108109
info!(game = %self.game_name, "Game exited: {e}");
109-
Ok(SceneAction::Pop)
110+
Ok(SceneAction::PushModal(Box::new(ErrorScene::new(
111+
&format!("{} exited: {}", self.game_name, e),
112+
))))
110113
}
111114
}
112115
}
@@ -119,7 +122,9 @@ impl Scene for GameScene {
119122
Ok(()) => Ok(SceneAction::Continue),
120123
Err(e) => {
121124
info!(game = %self.game_name, "Game render exited: {e}");
122-
Ok(SceneAction::Pop)
125+
Ok(SceneAction::PushModal(Box::new(ErrorScene::new(
126+
&format!("{} render error: {}", self.game_name, e),
127+
))))
123128
}
124129
}
125130
}

0 commit comments

Comments
 (0)