diff --git a/crates/bevy_mod_scripting_core/src/bindings/script_system.rs b/crates/bevy_mod_scripting_core/src/bindings/script_system.rs index 2faa7e4cd4..e6cd8390a6 100644 --- a/crates/bevy_mod_scripting_core/src/bindings/script_system.rs +++ b/crates/bevy_mod_scripting_core/src/bindings/script_system.rs @@ -16,7 +16,6 @@ use crate::{ event::CallbackLabel, extractors::get_all_access_ids, handler::ScriptingHandler, - runtime::RuntimeContainer, script::{ScriptAttachment, ScriptContext}, }; use ::{ @@ -201,7 +200,6 @@ impl ScriptSystemBuilder { struct DynamicHandlerContext<'w, P: IntoScriptPluginParams> { script_context: &'w ScriptContext

, - runtime_container: &'w RuntimeContainer

, } #[profiling::all_functions] @@ -213,15 +211,10 @@ impl<'w, P: IntoScriptPluginParams> DynamicHandlerContext<'w, P> { pub fn init_param(world: &mut World, system: &mut FilteredAccessSet) { let mut access = FilteredAccess::::matches_nothing(); - let runtime_container_res_id = world - .resource_id::>() - .expect("RuntimeContainer resource not found"); - let script_context_res_id = world .resource_id::>() .expect("Scripts resource not found"); - access.add_resource_read(runtime_container_res_id); access.add_resource_read(script_context_res_id); system.add(access); @@ -235,9 +228,6 @@ impl<'w, P: IntoScriptPluginParams> DynamicHandlerContext<'w, P> { unsafe { Self { script_context: system.get_resource().expect("Scripts resource not found"), - runtime_container: system - .get_resource() - .expect("RuntimeContainer resource not found"), } } } @@ -257,7 +247,7 @@ impl<'w, P: IntoScriptPluginParams> DynamicHandlerContext<'w, P> { }; // call the script - let runtime = &self.runtime_container.runtime; + let runtime = P::readonly_configuration(guard.id()).runtime; let mut context = context.lock(); diff --git a/crates/bevy_mod_scripting_core/src/commands.rs b/crates/bevy_mod_scripting_core/src/commands.rs index 2ed0cf44b3..3ad3b35eb9 100644 --- a/crates/bevy_mod_scripting_core/src/commands.rs +++ b/crates/bevy_mod_scripting_core/src/commands.rs @@ -149,32 +149,19 @@ impl CreateOrUpdateScript

{ content: &[u8], context: &mut P::C, guard: WorldGuard, - handler_ctxt: &HandlerContext

, ) -> Result<(), ScriptError> { debug!("{}: reloading context {}", P::LANGUAGE, attachment); // reload context - P::reload( - attachment, - content, - context, - guard.clone(), - &handler_ctxt.runtime_container.runtime, - ) + P::reload(attachment, content, context, guard.clone()) } fn load_context( attachment: &ScriptAttachment, content: &[u8], guard: WorldGuard, - handler_ctxt: &HandlerContext

, ) -> Result { debug!("{}: loading context {}", P::LANGUAGE, attachment); - let context = P::load( - attachment, - content, - guard.clone(), - &handler_ctxt.runtime_container.runtime, - )?; + let context = P::load(attachment, content, guard.clone())?; Ok(context) } @@ -272,16 +259,10 @@ impl CreateOrUpdateScript

{ Some(context) => { let mut context = context.lock(); - Self::reload_context( - &attachment, - content, - &mut context, - guard.clone(), - handler_ctxt, - ) - .map(|_| None) + Self::reload_context(&attachment, content, &mut context, guard.clone()) + .map(|_| None) } - None => Self::load_context(&attachment, content, guard.clone(), handler_ctxt).map(Some), + None => Self::load_context(&attachment, content, guard.clone()).map(Some), }; match result_context_to_insert { diff --git a/crates/bevy_mod_scripting_core/src/config.rs b/crates/bevy_mod_scripting_core/src/config.rs index acb534a0f3..5c48a80477 100644 --- a/crates/bevy_mod_scripting_core/src/config.rs +++ b/crates/bevy_mod_scripting_core/src/config.rs @@ -14,7 +14,7 @@ use crate::{ /// Configs contained here should be /// /// *global meaning stored in thread-locals, i.e. not annoyingly global, but pretty global. -#[derive(Debug, Default)] +#[derive(Debug)] pub struct ScriptingPluginConfiguration { /// callbacks executed before a handler callback is executed every time pub pre_handling_callbacks: &'static [ContextPreHandlingInitializer

], @@ -22,6 +22,8 @@ pub struct ScriptingPluginConfiguration { pub context_initialization_callbacks: &'static [ContextInitializer

], /// Whether to emit responses from the core callbacks like `on_script_loaded`. pub emit_responses: bool, + /// The configured runtime for the plugin + pub runtime: &'static P::R, } impl Clone for ScriptingPluginConfiguration

{ diff --git a/crates/bevy_mod_scripting_core/src/context.rs b/crates/bevy_mod_scripting_core/src/context.rs index fe8278d10f..2a50e29374 100644 --- a/crates/bevy_mod_scripting_core/src/context.rs +++ b/crates/bevy_mod_scripting_core/src/context.rs @@ -50,7 +50,6 @@ pub trait ScriptingLoader { attachment: &ScriptAttachment, content: &[u8], world: WorldGuard, - runtime: &P::R, ) -> Result; /// Reloads a script context using the provided reloader function @@ -59,7 +58,6 @@ pub trait ScriptingLoader { content: &[u8], previous_context: &mut P::C, world: WorldGuard, - runtime: &P::R, ) -> Result<(), ScriptError>; } @@ -68,7 +66,6 @@ impl ScriptingLoader

for P { attachment: &ScriptAttachment, content: &[u8], world: WorldGuard, - runtime: &P::R, ) -> Result { WorldGuard::with_existing_static_guard(world.clone(), |world| { let world_id = world.id(); @@ -78,7 +75,7 @@ impl ScriptingLoader

for P { content, P::readonly_configuration(world_id).context_initialization_callbacks, P::readonly_configuration(world_id).pre_handling_callbacks, - runtime, + P::readonly_configuration(world_id).runtime, ) }) } @@ -88,7 +85,6 @@ impl ScriptingLoader

for P { content: &[u8], previous_context: &mut P::C, world: WorldGuard, - runtime: &P::R, ) -> Result<(), ScriptError> { WorldGuard::with_existing_static_guard(world, |world| { let world_id = world.id(); @@ -99,7 +95,7 @@ impl ScriptingLoader

for P { previous_context, P::readonly_configuration(world_id).context_initialization_callbacks, P::readonly_configuration(world_id).pre_handling_callbacks, - runtime, + P::readonly_configuration(world_id).runtime, ) }) } diff --git a/crates/bevy_mod_scripting_core/src/extractors.rs b/crates/bevy_mod_scripting_core/src/extractors.rs index b1aa74f329..253a7c5adc 100644 --- a/crates/bevy_mod_scripting_core/src/extractors.rs +++ b/crates/bevy_mod_scripting_core/src/extractors.rs @@ -24,7 +24,6 @@ use crate::{ error::{InteropError, ScriptError}, event::{CallbackLabel, IntoCallbackLabel}, handler::ScriptingHandler, - runtime::RuntimeContainer, script::{ScriptAttachment, ScriptContext, StaticScripts}, }; @@ -48,8 +47,6 @@ pub fn with_handler_system_state< /// Context for systems which handle events for scripts pub struct HandlerContext { - /// The runtime container - pub(crate) runtime_container: RuntimeContainer

, /// List of static scripts pub(crate) static_scripts: StaticScripts, /// Script context @@ -61,7 +58,6 @@ impl HandlerContext

{ /// Every call to this function must be paired with a call to [`Self::release`]. pub fn yoink(world: &mut World) -> Self { Self { - runtime_container: world.remove_resource().unwrap_or_default(), static_scripts: world.remove_resource().unwrap_or_default(), script_context: world.remove_resource().unwrap_or_default(), } @@ -71,24 +67,10 @@ impl HandlerContext

{ /// Only call this if you have previously yoinked the handler context from the world. pub fn release(self, world: &mut World) { // insert the handler context back into the world - world.insert_resource(self.runtime_container); world.insert_resource(self.static_scripts); world.insert_resource(self.script_context); } - /// Splits the handler context into its individual components. - /// - /// Useful if you are needing multiple resources from the handler context. - /// Otherwise the borrow checker will prevent you from borrowing the handler context mutably multiple times. - pub fn destructure(&mut self) -> (&mut RuntimeContainer

, &mut StaticScripts) { - (&mut self.runtime_container, &mut self.static_scripts) - } - - /// Get the runtime container - pub fn runtime_container(&mut self) -> &mut RuntimeContainer

{ - &mut self.runtime_container - } - /// Get the static scripts pub fn static_scripts(&mut self) -> &mut StaticScripts { &mut self.static_scripts @@ -122,7 +104,7 @@ impl HandlerContext

{ }; // call the script - let runtime = &self.runtime_container.runtime; + let runtime = P::readonly_configuration(guard.id()).runtime; let mut context = context.lock(); diff --git a/crates/bevy_mod_scripting_core/src/lib.rs b/crates/bevy_mod_scripting_core/src/lib.rs index 55956e1e79..aa51e17467 100644 --- a/crates/bevy_mod_scripting_core/src/lib.rs +++ b/crates/bevy_mod_scripting_core/src/lib.rs @@ -12,15 +12,15 @@ use asset::{ Language, ScriptAsset, ScriptAssetLoader, configure_asset_systems, configure_asset_systems_for_plugin, }; -use bevy_app::{App, Plugin, PostStartup, PostUpdate}; +use bevy_app::{App, Plugin, PostUpdate}; use bevy_asset::{AssetApp, Handle}; +use bevy_ecs::schedule::IntoScheduleConfigs; use bevy_ecs::{ reflect::{AppTypeRegistry, ReflectComponent}, resource::Resource, schedule::SystemSet, - system::{Command, In}, + system::Command, }; -use bevy_ecs::{schedule::IntoScheduleConfigs, system::IntoSystem}; use bevy_log::error; use bevy_platform::collections::HashMap; use bindings::{ @@ -30,10 +30,9 @@ use bindings::{ }; use commands::{AddStaticScript, RemoveStaticScript}; use context::{Context, ContextInitializer, ContextPreHandlingInitializer}; -use error::ScriptError; use event::{ScriptCallbackEvent, ScriptCallbackResponseEvent, ScriptEvent}; use handler::HandlerFn; -use runtime::{Runtime, RuntimeContainer, RuntimeInitializer, RuntimeSettings, initialize_runtime}; +use runtime::{Runtime, RuntimeInitializer}; use script::{ContextPolicy, ScriptComponent, ScriptContext, StaticScripts}; use std::ops::{Deref, DerefMut}; @@ -97,8 +96,8 @@ pub trait IntoScriptPluginParams: 'static + GetPluginThreadConfig { /// Bevy plugin enabling scripting within the bevy mod scripting framework pub struct ScriptingPlugin { - /// Settings for the runtime - pub runtime_settings: RuntimeSettings

, + /// Functions configuring the runtime after it is created + pub runtime_initializers: Vec>, /// The strategy used to assign contexts to scripts pub context_policy: ContextPolicy, @@ -137,7 +136,7 @@ where impl Default for ScriptingPlugin

{ fn default() -> Self { Self { - runtime_settings: Default::default(), + runtime_initializers: Default::default(), context_policy: ContextPolicy::default(), language: Default::default(), context_initializers: Default::default(), @@ -150,16 +149,20 @@ impl Default for ScriptingPlugin

{ #[profiling::all_functions] impl Plugin for ScriptingPlugin

{ fn build(&self, app: &mut App) { - app.insert_resource(self.runtime_settings.clone()) - .insert_resource::>(RuntimeContainer { - runtime: P::build_runtime(), - }); - // initialize thread local configs + + let runtime = P::build_runtime(); + for initializer in &self.runtime_initializers { + if let Err(e) = initializer(&runtime) { + error!("Error initializing runtime: {:?}. Continuing.", e); + } + } + let config = ScriptingPluginConfiguration::

{ pre_handling_callbacks: Vec::leak(self.context_pre_handling_initializers.clone()), context_initialization_callbacks: Vec::leak(self.context_initializers.clone()), emit_responses: self.emit_responses, + runtime: Box::leak(Box::new(runtime)), }; P::set_thread_config(app.world().id(), config); @@ -196,7 +199,7 @@ impl ScriptingPlugin

{ /// /// Initializers will be run after the runtime is created, but before any contexts are loaded. pub fn add_runtime_initializer(&mut self, initializer: RuntimeInitializer

) -> &mut Self { - self.runtime_settings.initializers.push(initializer); + self.runtime_initializers.push(initializer); self } } @@ -325,16 +328,6 @@ impl Plugin for BMSScriptingInfrastructurePlugin { /// Systems registered per-language fn register_script_plugin_systems(app: &mut App) { - app.add_systems( - PostStartup, - (initialize_runtime::

.pipe(|e: In>| { - if let Err(e) = e.0 { - error!("Error initializing runtime: {:?}", e); - } - })) - .in_set(ScriptingSystemSet::RuntimeInitialization), - ); - app.add_plugins(configure_asset_systems_for_plugin::

); } @@ -346,32 +339,6 @@ fn register_types(app: &mut App) { app.register_type::(); } -/// Trait for adding a runtime initializer to an app -pub trait AddRuntimeInitializer { - /// Adds a runtime initializer to the app - fn add_runtime_initializer( - &mut self, - initializer: RuntimeInitializer

, - ) -> &mut Self; -} - -impl AddRuntimeInitializer for App { - fn add_runtime_initializer( - &mut self, - initializer: RuntimeInitializer

, - ) -> &mut Self { - if !self.world_mut().contains_resource::>() { - self.world_mut().init_resource::>(); - } - self.world_mut() - .resource_mut::>() - .as_mut() - .initializers - .push(initializer); - self - } -} - /// Trait for adding static scripts to an app pub trait ManageStaticScripts { /// Registers a script id as a static script. diff --git a/crates/bevy_mod_scripting_core/src/runtime.rs b/crates/bevy_mod_scripting_core/src/runtime.rs index d2e971ffcf..24bf75e73a 100644 --- a/crates/bevy_mod_scripting_core/src/runtime.rs +++ b/crates/bevy_mod_scripting_core/src/runtime.rs @@ -1,8 +1,6 @@ //! "Runtime" here refers to the execution evironment of scripts. This might be the VM executing bytecode or the interpreter executing source code. //! The important thing is that there is only one runtime which is used to execute all scripts of a particular type or `context`. -use ::bevy_ecs::{resource::Resource, system::Res, system::ResMut}; - use crate::{IntoScriptPluginParams, error::ScriptError}; /// A trait that all script runtimes must implement. @@ -11,52 +9,3 @@ impl Runtime for T {} /// A function that initializes a runtime. pub type RuntimeInitializer

= fn(&

::R) -> Result<(), ScriptError>; - -#[derive(Resource)] -/// Resource storing settings for a scripting plugin regarding runtime initialization & configuration. -pub struct RuntimeSettings { - /// Initializers for the runtime. These are run when the runtime is initialized. - pub initializers: Vec>, -} - -impl Default for RuntimeSettings

{ - fn default() -> Self { - Self { - initializers: Default::default(), - } - } -} - -impl Clone for RuntimeSettings

{ - fn clone(&self) -> Self { - Self { - initializers: self.initializers.clone(), - } - } -} - -/// Stores a particular runtime. -#[derive(Resource)] -pub struct RuntimeContainer { - /// The runtime contained within. - pub runtime: P::R, -} - -impl Default for RuntimeContainer

{ - fn default() -> Self { - Self { - runtime: Default::default(), - } - } -} - -#[profiling::function] -pub(crate) fn initialize_runtime( - runtime: ResMut>, - settings: Res>, -) -> Result<(), ScriptError> { - for initializer in settings.initializers.iter() { - (initializer)(&runtime.runtime)?; - } - Ok(()) -} diff --git a/crates/languages/bevy_mod_scripting_lua/src/lib.rs b/crates/languages/bevy_mod_scripting_lua/src/lib.rs index 8419924bc2..5b8da7e627 100644 --- a/crates/languages/bevy_mod_scripting_lua/src/lib.rs +++ b/crates/languages/bevy_mod_scripting_lua/src/lib.rs @@ -19,7 +19,6 @@ use bevy_mod_scripting_core::{ event::CallbackLabel, make_plugin_config_static, reflection_extensions::PartialReflectExt, - runtime::RuntimeSettings, script::{ContextPolicy, ScriptAttachment}, }; use bindings::{ @@ -71,7 +70,7 @@ impl Default for LuaScriptingPlugin { fn default() -> Self { LuaScriptingPlugin { scripting_plugin: ScriptingPlugin { - runtime_settings: RuntimeSettings::default(), + runtime_initializers: Vec::default(), context_initializers: vec![ |_script_id, context| { // set the world global diff --git a/crates/languages/bevy_mod_scripting_rhai/src/lib.rs b/crates/languages/bevy_mod_scripting_rhai/src/lib.rs index 68c7786f57..266713fe21 100644 --- a/crates/languages/bevy_mod_scripting_rhai/src/lib.rs +++ b/crates/languages/bevy_mod_scripting_rhai/src/lib.rs @@ -22,7 +22,6 @@ use bevy_mod_scripting_core::{ event::CallbackLabel, make_plugin_config_static, reflection_extensions::PartialReflectExt, - runtime::RuntimeSettings, script::{ContextPolicy, DisplayProxy, ScriptAttachment}, }; use bindings::{ @@ -88,16 +87,14 @@ impl Default for RhaiScriptingPlugin { fn default() -> Self { RhaiScriptingPlugin { scripting_plugin: ScriptingPlugin { - runtime_settings: RuntimeSettings { - initializers: vec![|runtime| { - let mut engine = runtime.write(); - engine.set_max_expr_depths(999, 999); - engine.build_type::(); - engine.build_type::(); - engine.register_iterator_result::(); - Ok(()) - }], - }, + runtime_initializers: vec![|runtime| { + let mut engine = runtime.write(); + engine.set_max_expr_depths(999, 999); + engine.build_type::(); + engine.build_type::(); + engine.register_iterator_result::(); + Ok(()) + }], context_initializers: vec![ |_, context| { context.scope.set_or_push( diff --git a/crates/testing_crates/script_integration_test_harness/src/lib.rs b/crates/testing_crates/script_integration_test_harness/src/lib.rs index 78ba1ba67a..d378a67913 100644 --- a/crates/testing_crates/script_integration_test_harness/src/lib.rs +++ b/crates/testing_crates/script_integration_test_harness/src/lib.rs @@ -314,7 +314,7 @@ where let ctxt_arc = context.script_context().get(&context_key).unwrap(); let mut ctxt_locked = ctxt_arc.lock(); - let runtime = &context.runtime_container().runtime; + let runtime = P::readonly_configuration(guard.id()).runtime; let _ = WorldAccessGuard::with_existing_static_guard(guard, |guard| { // Ensure the world is available via ThreadWorldContainer