Skip to content

Commit

Permalink
Fix removal of script contexts (#81)
Browse files Browse the repository at this point in the history
* mmm

* same behaviour as for lua

* some printing

* setup an example that demonstrates the issue

* fixed the bug lol

* if a function isnt found, dont scream in the console

* Update multiple_events_rhai.rhai

* fix clippy?

* using the ScriptLoaded event

* filter so we only get entities that still have to call "on_init"

* this shows the problem

* on_test is called on 1 entity, all others are removed

* aaa

* giving script id instead of enttiy id

* Revert "giving script id instead of enttiy id"

This reverts commit ab5062a.

* that should be fixed. but funny enough, a script still somehow exists.

* Revert "Revert "giving script id instead of enttiy id""

This reverts commit 13df73f.

* this fixes the bug.

* removed "on_test"

* Update bevy_mod_scripting_core/src/systems.rs

Co-authored-by: Maksymilian Mozolewski <[email protected]>

* applied suggestions / fixed errors

---------

Co-authored-by: Maksymilian Mozolewski <[email protected]>
  • Loading branch information
zwazel and makspll authored Oct 14, 2023
1 parent 32eba12 commit a3bccba
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 23 deletions.
2 changes: 2 additions & 0 deletions assets/scripts/multiple_events_rhai.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ fn on_init(name) {

fn on_update(name, delta) {
print(`Hello World! From "${name}" in Update: ${delta}`);

world.despawn_recursive(entity);
}
15 changes: 12 additions & 3 deletions bevy_mod_scripting_core/src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,20 @@ pub fn script_remove_synchronizer<H: ScriptHost>(
mut query: RemovedComponents<ScriptCollection<H::ScriptAsset>>,
mut contexts: ResMut<ScriptContexts<H::ScriptContext>>,
) {
query.iter().for_each(|v| {
for v in query.iter() {
// we know that this entity used to have a script component
// ergo a script context must exist in ctxts, remove all scripts on the entity
contexts.remove_context(v.index());
})
let script_ids = contexts
.context_entities
.iter()
.filter_map(|(script_id, (entity, ..))| {
(entity.index() == v.index()).then_some(*script_id)
})
.collect::<Vec<_>>();
for script_id in script_ids {
contexts.remove_context(script_id);
}
}
}

/// Reloads hot-reloaded scripts, or loads missing contexts for scripts which were added but not loaded
Expand Down
50 changes: 30 additions & 20 deletions examples/rhai/multiple_events_rhai.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use bevy::{prelude::*, reflect::Reflect};
use bevy_mod_scripting_core::{
event::ScriptLoaded,
prelude::{APIProvider, PriorityEventWriter, Recipients, Script, ScriptCollection},
AddScriptApiProvider, AddScriptHost, AddScriptHostHandler, ScriptingPlugin,
};
Expand All @@ -17,7 +18,7 @@ fn main() {
.add_systems(Update, (call_init, call_update))
.add_script_host::<RhaiScriptHost<ScriptArgs>>(PostUpdate)
.add_api_provider::<RhaiScriptHost<ScriptArgs>>(Box::new(RhaiBevyAPIProvider))
.add_script_handler::<RhaiScriptHost<ScriptArgs>, 0, 1>(PostUpdate)
.add_script_handler::<RhaiScriptHost<ScriptArgs>, 0, 2>(PostUpdate)
.run();
}

Expand Down Expand Up @@ -106,28 +107,37 @@ fn call_update(

fn call_init(
mut events: PriorityEventWriter<RhaiEvent<ScriptArgs>>,
mut commands: Commands,
mut loaded_scripts: EventReader<ScriptLoaded>,
entity_query: Query<
(Entity, Option<&Name>, Option<&ScriptCollection<RhaiFile>>),
Added<NewlyAddedEntityCallInit>,
With<NewlyAddedEntityCallInit>,
>,
mut commands: Commands,
) {
entity_query.for_each(|(entity, name, scripts)| {
if scripts.is_some() {
events.send(
RhaiEvent {
hook_name: "on_init".to_owned(),
args: ScriptArgs {
delta_time: None,
entity_name: name.map(|n| n.to_string()),
},
recipients: Recipients::Entity(entity),
},
0,
);
commands.entity(entity).remove::<NewlyAddedEntityCallInit>();
} else {
commands.entity(entity).remove::<NewlyAddedEntityCallInit>();
// Call init on all entities that have a script that was just loaded, and remove the Marker component, so that Update can be called
'outer: for loaded_script in loaded_scripts.iter() {
for (entity, name, scripts) in entity_query.iter() {
if let Some(scripts) = scripts {
if scripts.scripts.iter().any(|s| s.id() == loaded_script.sid) {
events.send(
RhaiEvent {
hook_name: "on_init".to_owned(),
args: ScriptArgs {
entity_name: name.map(|n| n.to_string()),
..Default::default()
},
recipients: Recipients::ScriptID(loaded_script.sid),
},
0,
);

commands.entity(entity).remove::<NewlyAddedEntityCallInit>();
continue 'outer;
}
} else {
commands.entity(entity).remove::<NewlyAddedEntityCallInit>();
continue 'outer;
}
}
});
}
}

0 comments on commit a3bccba

Please sign in to comment.