Skip to content

Commit 1fb4847

Browse files
committed
fix game of life, and some other bugs
1 parent 0e0037c commit 1fb4847

File tree

10 files changed

+74
-45
lines changed

10 files changed

+74
-45
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ bevy = { workspace = true, features = [
248248
"bevy_asset",
249249
"bevy_core_pipeline",
250250
"bevy_sprite",
251+
"bevy_sprite_render",
251252
"bevy_state",
252253
"x11",
253254
"bevy_ui",

assets/scripts/game_of_life.lua

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ LifeState = world.get_type_by_name("LifeState")
22
Settings = world.get_type_by_name("Settings")
33

44
info("Lua: The game_of_life.lua script just got loaded")
5-
65
math.randomseed(os.time())
76

87
function fetch_life_state()
@@ -37,11 +36,11 @@ function on_click(x, y)
3736
local dimensions = settings.physical_grid_dimensions
3837
local screen = settings.display_grid_dimensions
3938

40-
local dimension_x = dimensions._1
41-
local dimension_y = dimensions._2
39+
local dimension_x = dimensions[1]
40+
local dimension_y = dimensions[2]
4241

43-
local screen_x = screen._1
44-
local screen_y = screen._2
42+
local screen_x = screen[1]
43+
local screen_y = screen[2]
4544

4645
local cell_width = screen_x / dimension_x
4746
local cell_height = screen_y / dimension_y
@@ -78,8 +77,8 @@ function on_update()
7877
local cells = fetch_life_state().cells
7978
local settings = world.get_resource(Settings)
8079
local dimensions = settings.physical_grid_dimensions
81-
local dimension_x = dimensions._1
82-
local dimension_y = dimensions._2
80+
local dimension_x = dimensions[1]
81+
local dimension_y = dimensions[2]
8382

8483
-- primitives are passed by value to lua, keep a hold of old state but turn 255's into 1's
8584
local prev_state = {}

assets/scripts/game_of_life.rhai

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ fn on_click(x,y) {
4040
let dimensions = settings.physical_grid_dimensions;
4141
let screen = settings.display_grid_dimensions;
4242

43-
let dimension_x = dimensions["_0"];
44-
let dimension_y = dimensions["_1"];
43+
let dimension_x = dimensions[0];
44+
let dimension_y = dimensions[1];
4545

46-
let screen_x = screen["_0"];
47-
let screen_y = screen["_1"];
46+
let screen_x = screen[0];
47+
let screen_y = screen[1];
4848

4949
let cell_width = screen_x / dimension_x;
5050
let cell_height = screen_y / dimension_y;
@@ -77,8 +77,8 @@ fn on_update() {
7777
// note that here we do not make use of RhaiProxyable and just go off pure reflection
7878
let settings = world.get_resource.call(Settings);
7979
let dimensions = settings.physical_grid_dimensions;
80-
let dimension_x = dimensions["_0"];
81-
let dimension_y = dimensions["_1"];
80+
let dimension_x = dimensions[0];
81+
let dimension_y = dimensions[1];
8282

8383
// primitives are passed by value to rhai, keep a hold of old state but turn 255's into 1's
8484
let prev_state = [];

crates/bevy_mod_scripting_core/src/commands.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,16 @@ impl<P: IntoScriptPluginParams> RunScriptCallback<P> {
6060
self
6161
}
6262

63+
fn handle_error(res: &Result<ScriptValue, ScriptError>, guard: WorldGuard) {
64+
if let Err(err) = res {
65+
send_script_errors(guard, [err]);
66+
}
67+
}
68+
6369
/// Run the command on the given context.
6470
///
6571
/// Assumes this context matches the attachment for the command.
72+
/// Does not send the error as a message, this needs to be done explicitly by the caller.
6673
pub fn run_with_context(
6774
self,
6875
guard: WorldGuard,
@@ -109,6 +116,8 @@ impl<P: IntoScriptPluginParams> RunScriptCallback<P> {
109116
}
110117

111118
/// Equivalent to [`Self::run`], but usable in the case where you already have [`ScriptContext`] and [`ScriptCallbacks`] resources available.
119+
///
120+
/// Does not send the error as a message, this needs to be done explicitly by the caller.
112121
pub fn run_with_contexts(
113122
self,
114123
guard: WorldGuard,
@@ -125,7 +134,6 @@ impl<P: IntoScriptPluginParams> RunScriptCallback<P> {
125134
)
126135
.with_script(self.attachment.script().display())
127136
.with_language(P::LANGUAGE);
128-
send_script_errors(guard, [&err]);
129137
return Err(err);
130138
}
131139
};
@@ -135,19 +143,22 @@ impl<P: IntoScriptPluginParams> RunScriptCallback<P> {
135143

136144
/// Equivalent to running the command, but also returns the result of the callback.
137145
///
138-
/// The returned errors will NOT be sent as events or printed
139-
pub fn run(self, world: &mut World) -> Result<ScriptValue, ScriptError> {
146+
/// The returned errors will NOT be sent as events or printed unless send errors is set to true
147+
pub fn run(self, world: &mut World, send_errors: bool) -> Result<ScriptValue, ScriptError> {
140148
let script_contexts = world.get_resource_or_init::<ScriptContext<P>>().clone();
141149
let script_callbacks = world.get_resource_or_init::<ScriptCallbacks<P>>().clone();
142150
let guard = WorldGuard::new_exclusive(world);
143-
self.run_with_contexts(guard, script_contexts, script_callbacks)
151+
let res = self.run_with_contexts(guard.clone(), script_contexts, script_callbacks);
152+
if send_errors && res.is_err() {
153+
Self::handle_error(&res, guard);
154+
}
155+
res
144156
}
145157
}
146158

147159
impl<P: IntoScriptPluginParams> Command for RunScriptCallback<P> {
148160
fn apply(self, world: &mut World) {
149-
// Internals handle this.
150-
let _ = self.run(world);
161+
let _ = self.run(world, true);
151162
}
152163
}
153164

crates/bevy_mod_scripting_core/src/pipeline/hooks.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ impl<P: IntoScriptPluginParams> TransitionListener<ContextAssigned<P>> for OnLoa
2323
let emit_responses = P::readonly_configuration(world_id).emit_responses;
2424
let callbacks = world.get_resource_or_init::<ScriptCallbacks<P>>().clone();
2525
let guard = WorldGuard::new_exclusive(world);
26-
26+
bevy_log::trace!(
27+
"Running on_script_loaded hook for script: {}",
28+
ctxt.attachment
29+
);
2730
RunScriptCallback::<P>::new(
2831
ctxt.attachment.clone(),
2932
OnScriptLoaded::into_callback_label(),
@@ -49,7 +52,10 @@ impl<P: IntoScriptPluginParams> TransitionListener<UnloadingInitialized<P>>
4952
let emit_responses = P::readonly_configuration(world_id).emit_responses;
5053
let callbacks = world.get_resource_or_init::<ScriptCallbacks<P>>().clone();
5154
let guard = WorldGuard::new_exclusive(world);
52-
55+
bevy_log::trace!(
56+
"Running on_script_unloaded hook for script: {}",
57+
ctxt.attachment
58+
);
5359
let v = RunScriptCallback::<P>::new(
5460
ctxt.attachment.clone(),
5561
OnScriptUnloaded::into_callback_label(),
@@ -77,6 +83,11 @@ impl<P: IntoScriptPluginParams> TransitionListener<ReloadingInitialized<P>>
7783
let callbacks = world.get_resource_or_init::<ScriptCallbacks<P>>().clone();
7884
let guard = WorldGuard::new_exclusive(world);
7985

86+
bevy_log::trace!(
87+
"Running on_script_unloaded for reload hook for script: {}",
88+
ctxt.attachment
89+
);
90+
8091
let v = RunScriptCallback::<P>::new(
8192
ctxt.attachment.clone(),
8293
OnScriptUnloaded::into_callback_label(),
@@ -106,6 +117,11 @@ impl<P: IntoScriptPluginParams> TransitionListener<ContextAssigned<P>> for OnRel
106117
return Ok(());
107118
}
108119

120+
bevy_log::trace!(
121+
"Running on_script_reloaded hook for script: {}",
122+
ctxt.attachment
123+
);
124+
109125
let unload_state = ctxt.get_first_typed::<ScriptValue>(UNLOADED_SCRIPT_STATE_KEY);
110126
let unload_state = unload_state.unwrap_or(ScriptValue::Unit);
111127

crates/bevy_mod_scripting_core/src/pipeline/machines.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ impl<P: IntoScriptPluginParams> ActiveMachines<P> {
166166
// removed
167167
}
168168
Some(Err(err)) => {
169-
_ = world.write_message(ScriptErrorEvent::new(err));
169+
_ = world
170+
.write_message(ScriptErrorEvent::new(err.with_language(P::LANGUAGE)));
170171
// removed
171172
}
172173
None => {
@@ -528,9 +529,10 @@ impl<P: IntoScriptPluginParams> MachineState<P> for ContextAssigned<P> {
528529
Ok(_) => {}
529530
Err(_) => {
530531
drop(contexts_guard);
531-
_ = world.write_message(ScriptErrorEvent::new(ScriptError::from(
532-
InteropError::str("no context policy matched"),
533-
)))
532+
_ = world.write_message(ScriptErrorEvent::new(
533+
ScriptError::from(InteropError::str("no context policy matched"))
534+
.with_language(P::LANGUAGE),
535+
))
534536
}
535537
}
536538
Box::new(ready(Ok(

crates/bevy_mod_scripting_core/src/pipeline/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use bevy_ecs::{
1212
world::World,
1313
};
1414
use bevy_log::debug;
15-
use bevy_mod_scripting_asset::ScriptAsset;
15+
use bevy_mod_scripting_asset::{Language, ScriptAsset};
1616
use bevy_mod_scripting_bindings::WorldGuard;
1717
use bevy_mod_scripting_display::DisplayProxy;
1818
use bevy_platform::collections::HashSet;
@@ -160,7 +160,7 @@ pub struct LoadedWithHandles<'w, 's, T: GetScriptHandle + Message + Clone> {
160160
assets: ResMut<'w, Assets<ScriptAsset>>,
161161
asset_server: Res<'w, AssetServer>,
162162
fresh_events: MessageReader<'w, 's, T>,
163-
loaded_with_handles: Local<'s, VecDeque<(T, StrongScriptHandle)>>,
163+
loaded_with_handles: Local<'s, VecDeque<(T, StrongScriptHandle, Language)>>,
164164
loading: Local<'s, VecDeque<T>>,
165165
}
166166

@@ -170,7 +170,7 @@ impl<T: GetScriptHandle + Message + Clone> LoadedWithHandles<'_, '_, T> {
170170
///
171171
/// This uses a [`EventReader<T>`] underneath, meaning if you don't call this method once every frame (or every other frame).
172172
/// You may miss events.
173-
pub fn get_loaded(&mut self) -> impl Iterator<Item = (T, StrongScriptHandle)> {
173+
pub fn get_loaded(&mut self) -> impl Iterator<Item = (T, StrongScriptHandle, Language)> {
174174
// first get all of the fresh_events
175175
self.loading.extend(self.fresh_events.read().cloned());
176176
// now process the loading queue
@@ -180,7 +180,8 @@ impl<T: GetScriptHandle + Message + Clone> LoadedWithHandles<'_, '_, T> {
180180
Some(LoadState::Loaded) | None => { // none in case this is added in memory and not through asset server
181181
let strong = StrongScriptHandle::from_assets(handle, &mut self.assets);
182182
if let Some(strong) = strong {
183-
self.loaded_with_handles.push_front((e.clone(), strong));
183+
let lang = strong.get(&self.assets).language.clone();
184+
self.loaded_with_handles.push_front((e.clone(), strong, lang));
184185
}
185186
false
186187
}

crates/bevy_mod_scripting_core/src/pipeline/start.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,17 @@ pub fn filter_script_attachments<P: IntoScriptPluginParams>(
8484
mut events: LoadedWithHandles<ScriptAttachedEvent>,
8585
mut filtered: MessageWriter<ForPlugin<ScriptAttachedEvent, P>>,
8686
) {
87-
let mut batch = events.get_loaded().map(|(mut a, b)| {
88-
trace!("dispatching script attachment event for: {a:?}");
89-
*a.0.script_mut() = b.0;
90-
ForPlugin::new(a)
91-
});
87+
let mut batch = events
88+
.get_loaded()
89+
.filter(|(_, _, l)| *l == P::LANGUAGE)
90+
.map(|(mut a, b, _)| {
91+
trace!(
92+
"dispatching script attachment event for: {a:?}, language: {}",
93+
P::LANGUAGE
94+
);
95+
*a.0.script_mut() = b.0;
96+
ForPlugin::new(a)
97+
});
9298

9399
if let Some(next) = batch.next() {
94100
filtered.write_batch(std::iter::once(next).chain(batch));

crates/languages/bevy_mod_scripting_lua/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ pub fn lua_handler(
355355
let out = handler
356356
.call::<LuaScriptValue>(input)
357357
.map_err(IntoInteropError::to_bms_error)?;
358+
358359
Ok(out.into())
359360
}
360361

examples/game_of_life.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use bevy_mod_scripting_bindings::AllocatorDiagnosticPlugin;
1818
use clap::Parser;
1919

2020
// CONSOLE SETUP
21-
2221
fn console_app(app: &mut App) -> &mut App {
2322
// forward logs to the console
2423
app.add_plugins((
@@ -114,7 +113,6 @@ pub enum GameOfLifeCommand {
114113
// ------------- GAME OF LIFE
115114
fn game_of_life_app(app: &mut App) -> &mut App {
116115
app.insert_resource(Time::<Fixed>::from_seconds(UPDATE_FREQUENCY.into()))
117-
// .add_plugins(BMSPlugin.set(LuaScriptingPlugin::default().enable_context_sharing()))
118116
.add_plugins(BMSPlugin)
119117
.register_type::<LifeState>()
120118
.register_type::<Settings>()
@@ -176,6 +174,7 @@ pub fn register_script_functions(app: &mut App) -> &mut App {
176174
app
177175
}
178176

177+
// drawing based on https://github.com/bevyengine/bevy/blob/main/examples/2d/cpu_draw.rs
179178
pub fn init_game_of_life_state(
180179
mut commands: Commands,
181180
mut assets: ResMut<Assets<Image>>,
@@ -194,18 +193,11 @@ pub fn init_game_of_life_state(
194193
);
195194

196195
image.sampler = ImageSampler::nearest();
196+
let handle = assets.add(image);
197197

198198
commands.spawn(Camera2d);
199199
commands
200-
.spawn(Sprite {
201-
image: assets.add(image),
202-
custom_size: Some(Vec2::new(
203-
settings.display_grid_dimensions.0 as f32,
204-
settings.display_grid_dimensions.1 as f32,
205-
)),
206-
color: Color::srgb(1.0, 0.388, 0.278), // TOMATO
207-
..Default::default()
208-
})
200+
.spawn(Sprite::from_image(handle))
209201
.insert(LifeState {
210202
cells: vec![
211203
0u8;

0 commit comments

Comments
 (0)