diff --git a/assets/tests/lifecycle/default/entity_script/loading_via_entry_and_modify/lifecycle.lua b/assets/tests/lifecycle/default/entity_script/loading_via_entry_and_modify/lifecycle.lua new file mode 100644 index 0000000000..9dff611cc1 --- /dev/null +++ b/assets/tests/lifecycle/default/entity_script/loading_via_entry_and_modify/lifecycle.lua @@ -0,0 +1,11 @@ +function on_script_loaded() + return "loaded!" +end + +function on_script_unloaded() + return "unloaded!" +end + +function on_script_reloaded(val) + return "reloaded with: " .. val +end diff --git a/assets/tests/lifecycle/default/entity_script/loading_via_entry_and_modify/scenario.bmsscenario b/assets/tests/lifecycle/default/entity_script/loading_via_entry_and_modify/scenario.bmsscenario new file mode 100644 index 0000000000..91e23e2a04 --- /dev/null +++ b/assets/tests/lifecycle/default/entity_script/loading_via_entry_and_modify/scenario.bmsscenario @@ -0,0 +1,14 @@ +// #main_script lifecycle.lua +SetCurrentLanguage language="@this_script_language" +InstallPlugin emit_responses=true +FinalizeApp + +// load script by inserting empty component and immediately modifying +SpawnEntity name="test_entity_a" +LoadScriptAs as_name="script_b", path="lifecycle.lua" +WaitForScriptAssetLoaded name="script_b" +AddScriptToEntity name="test_entity_a", script="script_b" +RunUpdateOnce +AssertCallbackSuccess attachment="EntityScript", entity="test_entity_a", label="OnScriptLoaded", script="script_b", expect_string_value="loaded!" +AssertNoCallbackResponsesEmitted +AssertContextResidents attachment="EntityScript", script="script_b", entity="test_entity_a", residents_num=1 \ No newline at end of file diff --git a/crates/bevy_mod_scripting_core/src/event.rs b/crates/bevy_mod_scripting_core/src/event.rs index d84c4eb116..73f93cb824 100644 --- a/crates/bevy_mod_scripting_core/src/event.rs +++ b/crates/bevy_mod_scripting_core/src/event.rs @@ -1,7 +1,5 @@ //! Event handlers and event types for scripting. -use std::marker::PhantomData; - use ::{bevy_ecs::entity::Entity, bevy_reflect::Reflect}; use bevy_asset::{AssetId, Handle}; use bevy_ecs::message::Message; @@ -41,50 +39,6 @@ pub struct ScriptDetachedEvent(pub ScriptAttachment); #[derive(Message, Clone, Debug)] pub struct ScriptAssetModifiedEvent(pub AssetId); -#[derive(Message)] -/// Wrapper around a script event making it available to read by a specific plugin only -pub struct ForPlugin(T, PhantomData); - -impl std::fmt::Debug for ForPlugin { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("ForPlugin").field(&self.0).finish() - } -} - -impl From for ForPlugin { - fn from(value: T) -> Self { - Self::new(value) - } -} - -impl Clone for ForPlugin { - fn clone(&self) -> Self { - Self(self.0.clone(), self.1) - } -} - -impl ForPlugin { - /// Creates a new wrapper for the specific plugin - pub fn new(message: T) -> Self { - Self(message, Default::default()) - } - - /// Retrieves the inner event - pub fn event(&self) -> &T { - &self.0 - } - - /// Retrieves the inner event mutably - pub fn event_mut(&mut self) -> &mut T { - &mut self.0 - } - - /// Unpacks the inner event - pub fn inner(self) -> T { - self.0 - } -} - /// A string which disallows common invalid characters in callback labels, /// particularly at the start of the string /// diff --git a/crates/bevy_mod_scripting_core/src/pipeline/mod.rs b/crates/bevy_mod_scripting_core/src/pipeline/mod.rs index 2efc25b56f..50e72ba877 100644 --- a/crates/bevy_mod_scripting_core/src/pipeline/mod.rs +++ b/crates/bevy_mod_scripting_core/src/pipeline/mod.rs @@ -22,7 +22,7 @@ use crate::{ context::ScriptingLoader, error::ScriptError, event::{ - ForPlugin, Recipients, ScriptAssetModifiedEvent, ScriptAttachedEvent, ScriptDetachedEvent, + Recipients, ScriptAssetModifiedEvent, ScriptAttachedEvent, ScriptDetachedEvent, ScriptErrorEvent, }, pipeline::hooks::{ @@ -136,13 +136,6 @@ impl std::fmt::Debug for ScriptProcessingSchedule

} } -impl ScriptLoadingPipeline

{ - fn add_plugin_message(&self, app: &mut App) -> &Self { - app.add_message::().add_message::>(); - self - } -} - /// A trait describing things containing script handles pub trait GetScriptHandle { /// Retrieve the contained script handle @@ -204,9 +197,9 @@ impl LoadedWithHandles<'_, '_, T> { impl Plugin for ScriptLoadingPipeline

{ fn build(&self, app: &mut App) { - self.add_plugin_message::(app) - .add_plugin_message::(app) - .add_plugin_message::(app); + app.add_message::() + .add_message::() + .add_message::(); app.init_resource::(); diff --git a/crates/testing_crates/bevy_mod_scripting_test_scenario_syntax/src/parse.rs b/crates/testing_crates/bevy_mod_scripting_test_scenario_syntax/src/parse.rs index f5602b847b..53abc1dadd 100644 --- a/crates/testing_crates/bevy_mod_scripting_test_scenario_syntax/src/parse.rs +++ b/crates/testing_crates/bevy_mod_scripting_test_scenario_syntax/src/parse.rs @@ -110,6 +110,11 @@ pub enum ScenarioStepSerialized { /// the script to spawn on the entity script: String, }, + /// Spawns an entity with the given name + SpawnEntity { + /// the name to give this entity for future reference + name: String, + }, /// Pushes a script into the existing script component on an entity, or creates a new one and inserts the script AddScriptToEntity { /// the name of the entity to insert into diff --git a/crates/testing_crates/bevy_mod_scripting_test_scenario_syntax/src/schema.rs b/crates/testing_crates/bevy_mod_scripting_test_scenario_syntax/src/schema.rs index f954285fa7..7b16570571 100644 --- a/crates/testing_crates/bevy_mod_scripting_test_scenario_syntax/src/schema.rs +++ b/crates/testing_crates/bevy_mod_scripting_test_scenario_syntax/src/schema.rs @@ -159,6 +159,18 @@ fn get_schema() -> ScenarioSchema { .collect(), }, ), + ( + "SpawnEntity".into(), + StepSchema { + fields: vec![str_field( + "name", + false, + "the name to give this entity for future reference", + )] + .into_iter() + .collect(), + }, + ), ( "AttachStaticScript".into(), StepSchema { diff --git a/crates/testing_crates/script_integration_test_harness/src/scenario.rs b/crates/testing_crates/script_integration_test_harness/src/scenario.rs index fa142d5d51..cf99041aaa 100644 --- a/crates/testing_crates/script_integration_test_harness/src/scenario.rs +++ b/crates/testing_crates/script_integration_test_harness/src/scenario.rs @@ -298,6 +298,9 @@ impl Scenario { entity: name, } } + ScenarioStepSerialized::SpawnEntity { name } => { + ScenarioStep::SpawnEntity { entity: name } + } ScenarioStepSerialized::AddScriptToEntity { name, script } => { ScenarioStep::AddScriptToEntity { script: self.context.get_script_handle(&script)?, @@ -523,6 +526,10 @@ pub enum ScenarioStep { WaitForScriptAssetLoaded { script: Handle, }, + /// Spawns an entity with no components + SpawnEntity { + entity: String, + }, /// Spawns an entity with the given name and attaches the given script to it. SpawnEntityWithScript { script: Handle, @@ -829,6 +836,12 @@ impl ScenarioStep { script.display() ); } + ScenarioStep::SpawnEntity { entity: name } => { + let entity = app.world_mut().spawn_empty().id(); + context.entities.insert(name.to_string(), entity); + info!("Spawned empty entity '{entity}'"); + } + ScenarioStep::EmitScriptCallbackEvent { event } => { app.world_mut().write_message(event.clone()); } diff --git a/scenario_file_language_server/src/scenario.tmLanguage.json b/scenario_file_language_server/src/scenario.tmLanguage.json index f6e2500248..e9eee3a300 100644 --- a/scenario_file_language_server/src/scenario.tmLanguage.json +++ b/scenario_file_language_server/src/scenario.tmLanguage.json @@ -21,7 +21,7 @@ "patterns": [ { "name": "keyword.control.step.scenario", - "match": "\\b(SetCurrentLanguage|InstallPlugin|SetupHandler|FinalizeApp|LoadScriptAs|WaitForScriptAssetLoaded|SpawnEntityWithScript|RunUpdateOnce|EmitScriptCallbackEvent|AssertCallbackSuccess|AssertNoCallbackResponsesEmitted|AssertContextState|AssertContextResidents|ReloadScriptFrom|DropScriptAsset|DespawnEntity|AttachStaticScript|RemoveScriptFromEntity|AddScriptToEntity)\\b" + "match": "\\b(SetCurrentLanguage|InstallPlugin|SetupHandler|FinalizeApp|LoadScriptAs|WaitForScriptAssetLoaded|SpawnEntityWithScript|RunUpdateOnce|EmitScriptCallbackEvent|AssertCallbackSuccess|AssertNoCallbackResponsesEmitted|AssertContextState|AssertContextResidents|ReloadScriptFrom|DropScriptAsset|DespawnEntity|AttachStaticScript|RemoveScriptFromEntity|AddScriptToEntity|SpawnEntity)\\b" }, { "name": "variable.parameter.field.scenario",