Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
46 changes: 0 additions & 46 deletions crates/bevy_mod_scripting_core/src/event.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -41,50 +39,6 @@ pub struct ScriptDetachedEvent(pub ScriptAttachment);
#[derive(Message, Clone, Debug)]
pub struct ScriptAssetModifiedEvent(pub AssetId<ScriptAsset>);

#[derive(Message)]
/// Wrapper around a script event making it available to read by a specific plugin only
pub struct ForPlugin<T, P: IntoScriptPluginParams>(T, PhantomData<fn(P)>);

impl<T: std::fmt::Debug, P: IntoScriptPluginParams> std::fmt::Debug for ForPlugin<T, P> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("ForPlugin").field(&self.0).finish()
}
}

impl<T, P: IntoScriptPluginParams> From<T> for ForPlugin<T, P> {
fn from(value: T) -> Self {
Self::new(value)
}
}

impl<T: Clone, P: IntoScriptPluginParams> Clone for ForPlugin<T, P> {
fn clone(&self) -> Self {
Self(self.0.clone(), self.1)
}
}

impl<T, P: IntoScriptPluginParams> ForPlugin<T, P> {
/// 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
///
Expand Down
15 changes: 4 additions & 11 deletions crates/bevy_mod_scripting_core/src/pipeline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
context::ScriptingLoader,
error::ScriptError,
event::{
ForPlugin, Recipients, ScriptAssetModifiedEvent, ScriptAttachedEvent, ScriptDetachedEvent,
Recipients, ScriptAssetModifiedEvent, ScriptAttachedEvent, ScriptDetachedEvent,
ScriptErrorEvent,
},
pipeline::hooks::{
Expand Down Expand Up @@ -136,13 +136,6 @@ impl<P: IntoScriptPluginParams> std::fmt::Debug for ScriptProcessingSchedule<P>
}
}

impl<P: IntoScriptPluginParams> ScriptLoadingPipeline<P> {
fn add_plugin_message<E: Message>(&self, app: &mut App) -> &Self {
app.add_message::<E>().add_message::<ForPlugin<E, P>>();
self
}
}

/// A trait describing things containing script handles
pub trait GetScriptHandle {
/// Retrieve the contained script handle
Expand Down Expand Up @@ -204,9 +197,9 @@ impl<T: GetScriptHandle + Message + Clone> LoadedWithHandles<'_, '_, T> {

impl<P: IntoScriptPluginParams> Plugin for ScriptLoadingPipeline<P> {
fn build(&self, app: &mut App) {
self.add_plugin_message::<ScriptAttachedEvent>(app)
.add_plugin_message::<ScriptDetachedEvent>(app)
.add_plugin_message::<ScriptAssetModifiedEvent>(app);
app.add_message::<ScriptAttachedEvent>()
.add_message::<ScriptDetachedEvent>()
.add_message::<ScriptAssetModifiedEvent>();

app.init_resource::<ActiveMachinesData>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)?,
Expand Down Expand Up @@ -523,6 +526,10 @@ pub enum ScenarioStep {
WaitForScriptAssetLoaded {
script: Handle<ScriptAsset>,
},
/// 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<ScriptAsset>,
Expand Down Expand Up @@ -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());
}
Expand Down
2 changes: 1 addition & 1 deletion scenario_file_language_server/src/scenario.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Loading