From bf91d6890effc0859c1b459bba1dc5441b399029 Mon Sep 17 00:00:00 2001 From: makspll Date: Fri, 13 May 2022 12:14:42 +0100 Subject: [PATCH 1/4] add event recipient functionality --- bevy_mod_scripting/Cargo.toml | 7 +- .../assets/scripts/event_recipients.lua | 6 + .../examples/complex_game_loop.rs | 3 +- .../examples/console_integration_lua.rs | 3 +- .../examples/console_integration_rhai.rs | 3 +- .../examples/event_recipients.rs | 123 ++++++++++++++++++ bevy_mod_scripting/src/hosts/mod.rs | 101 +++++++++++--- bevy_mod_scripting/src/hosts/rhai_host/mod.rs | 27 +++- bevy_mod_scripting/src/hosts/rlua_host/mod.rs | 29 +++-- readme.md | 2 + 10 files changed, 270 insertions(+), 34 deletions(-) create mode 100644 bevy_mod_scripting/assets/scripts/event_recipients.lua create mode 100644 bevy_mod_scripting/examples/event_recipients.rs diff --git a/bevy_mod_scripting/Cargo.toml b/bevy_mod_scripting/Cargo.toml index df85752a07..16f3ddc1f1 100644 --- a/bevy_mod_scripting/Cargo.toml +++ b/bevy_mod_scripting/Cargo.toml @@ -41,4 +41,9 @@ path = "examples/console_integration_rhai.rs" [[example]] name = "complex_game_loop" -path = "examples/complex_game_loop.rs" \ No newline at end of file +path = "examples/complex_game_loop.rs" + + +[[example]] +name = "event_recipients" +path = "examples/event_recipients.rs" \ No newline at end of file diff --git a/bevy_mod_scripting/assets/scripts/event_recipients.lua b/bevy_mod_scripting/assets/scripts/event_recipients.lua new file mode 100644 index 0000000000..69b0b1ca3c --- /dev/null +++ b/bevy_mod_scripting/assets/scripts/event_recipients.lua @@ -0,0 +1,6 @@ + + +function on_event(id) + print(string.format("on_event, script_id: %d, Handling:",script)) + print(string.format("\t-> id: %d", id)) +end \ No newline at end of file diff --git a/bevy_mod_scripting/examples/complex_game_loop.rs b/bevy_mod_scripting/examples/complex_game_loop.rs index edaffe3514..43c29affa1 100644 --- a/bevy_mod_scripting/examples/complex_game_loop.rs +++ b/bevy_mod_scripting/examples/complex_game_loop.rs @@ -3,7 +3,7 @@ use bevy_console::ConsolePlugin; use bevy_event_priority::PriorityEventWriter; use bevy_mod_scripting::{ APIProvider, AddScriptHost, AddScriptHostHandler, LuaEvent, LuaFile, RLuaScriptHost, Script, - ScriptCollection, ScriptingPlugin, + ScriptCollection, ScriptingPlugin, Recipients, }; use rand::prelude::SliceRandom; use rlua::{Lua, ToLua}; @@ -55,6 +55,7 @@ fn fire_random_event(w: &mut PriorityEventWriter>, events: &[ LuaEvent { hook_name: v.0.to_string(), args: vec![arg], + recipients: Recipients::All }, v.1, ) diff --git a/bevy_mod_scripting/examples/console_integration_lua.rs b/bevy_mod_scripting/examples/console_integration_lua.rs index 8960fc5b13..bdb5186b57 100644 --- a/bevy_mod_scripting/examples/console_integration_lua.rs +++ b/bevy_mod_scripting/examples/console_integration_lua.rs @@ -2,7 +2,7 @@ use bevy::{ecs::event::Events, prelude::*}; use bevy_console::{AddConsoleCommand, ConsoleCommand, ConsolePlugin, PrintConsoleLine}; use bevy_mod_scripting::{ events::PriorityEventWriter, APIProvider, AddScriptHost, AddScriptHostHandler, LuaEvent, - LuaFile, RLuaScriptHost, Script, ScriptCollection, ScriptingPlugin, + LuaFile, RLuaScriptHost, Script, ScriptCollection, ScriptingPlugin, Recipients, }; use rlua::{Lua, ToLua}; use std::sync::Mutex; @@ -51,6 +51,7 @@ pub fn trigger_on_update_lua(mut w: PriorityEventWriter>) { let event = LuaEvent { hook_name: "on_update".to_string(), args: Vec::default(), + recipients: Recipients::All }; w.send(event, 0); diff --git a/bevy_mod_scripting/examples/console_integration_rhai.rs b/bevy_mod_scripting/examples/console_integration_rhai.rs index 814de85141..ec6a41be49 100644 --- a/bevy_mod_scripting/examples/console_integration_rhai.rs +++ b/bevy_mod_scripting/examples/console_integration_rhai.rs @@ -2,7 +2,7 @@ use bevy::{ecs::event::Events, prelude::*}; use bevy_console::{AddConsoleCommand, ConsoleCommand, ConsolePlugin, PrintConsoleLine}; use bevy_mod_scripting::{ events::PriorityEventWriter, APIProvider, AddScriptHost, AddScriptHostHandler, RhaiAPIProvider, - RhaiContext, RhaiEvent, RhaiFile, RhaiScriptHost, Script, ScriptCollection, ScriptingPlugin, + RhaiContext, RhaiEvent, RhaiFile, RhaiScriptHost, Script, ScriptCollection, ScriptingPlugin, Recipients, }; use rhai::FuncArgs; @@ -49,6 +49,7 @@ pub fn trigger_on_update_rhai(mut w: PriorityEventWriter ToLua<'lua> for MyLuaArg { + fn to_lua(self, lua: rlua::Context<'lua>) -> rlua::Result> { + self.0.to_lua(lua) + } +} + +#[derive(Default)] +pub struct LuaAPIProvider {} + +/// the custom Lua api, world is provided via a global pointer, +/// and callbacks are defined only once at script creation +impl APIProvider for LuaAPIProvider { + type Ctx = Mutex; + fn attach_api(ctx: &mut Self::Ctx) { + // callbacks can receive any `ToLuaMulti` arguments, here '()' and + // return any `FromLuaMulti` arguments, here a `usize` + // check the Rlua documentation for more details + RLuaScriptHost::::register_api_callback( + "print", + |_ctx, msg: String| { + info!("{}", msg); + Ok(()) + }, + ctx, + ) + } +} + +static COUNTER: AtomicU32 = AtomicU32::new(0); + +/// utility for generating random events from a list +fn fire_random_event(w: &mut PriorityEventWriter>, events: &[ScriptEventData]) { + let mut rng = rand::thread_rng(); + let id = COUNTER.fetch_add(1, Relaxed); + let arg = MyLuaArg(id as usize); + let event = events + .choose(&mut rng) + .map(|v| + + LuaEvent { + hook_name: v.0.to_string(), + args: vec![arg], + recipients: v.1.clone() + } + ) + .unwrap(); + + info!( + "\t - event: {},\t recipients: {:?},\t id: {}", + event.hook_name, event.recipients, id + ); + w.send(event, 0); +} + + +fn do_update(mut w: PriorityEventWriter>) { + info!("Update, firing:"); + + let all_events = [ + ScriptEventData("on_event", Recipients::All), + ScriptEventData("on_event", Recipients::ScriptID(0)), + ScriptEventData("on_event", Recipients::ScriptID(1)), + ScriptEventData("on_event", Recipients::ScriptName("scripts/event_recipients.lua".to_owned())) + ]; + + // fire random event, for any stages + fire_random_event(&mut w, &all_events); +} + +#[derive(Clone)] +pub struct ScriptEventData(&'static str, Recipients); + + +fn load_our_scripts(server: Res, mut commands: Commands) { + // spawn two identical scripts + // id's will be 0 and 1 + let path = "scripts/event_recipients.lua"; + let handle = server.load::(path); + let scripts = (0..2).into_iter() + .map(|_| { + Script::::new::,>(path.to_string(), handle.clone()) + }) + .collect(); + + commands.spawn().insert(ScriptCollection:: { + scripts + }); +} + +fn main() -> std::io::Result<()> { + let mut app = App::new(); + + app.add_plugins(DefaultPlugins) + .add_plugin(ScriptingPlugin) + .add_plugin(ConsolePlugin) + .add_startup_system(load_our_scripts) + + // randomly fire events for either all scripts, + // the script with id 0 + // or the script with id 1 + .add_system(do_update) + .add_script_handler_stage::,_,0,0>(CoreStage::PostUpdate) + .add_script_host::, _>(CoreStage::PostUpdate); + + app.run(); + + Ok(()) +} diff --git a/bevy_mod_scripting/src/hosts/mod.rs b/bevy_mod_scripting/src/hosts/mod.rs index e624f8c187..c5fd2620c8 100644 --- a/bevy_mod_scripting/src/hosts/mod.rs +++ b/bevy_mod_scripting/src/hosts/mod.rs @@ -18,13 +18,61 @@ use std::{ sync::atomic::{AtomicU32, Ordering}, }; +/// Describes the target set of scripts this event should +/// be handled by +#[derive(Clone, Debug)] +pub enum Recipients{ + /// Send to all scripts + All, + /// Send only to scripts on the given entity + Entity(Entity), + /// Send to script with the given ID + ScriptID(u32), + // Send to script with the given name + ScriptName(String) +} + +#[derive(Debug)] +pub struct FlatScriptData<'a> { + sid: u32, + entity: Entity, + name: &'a str, +} + +impl Recipients { + /// Returns true if the given script should + pub fn is_recipient(&self, c : &FlatScriptData) -> bool{ + match self { + Recipients::All => true, + Recipients::Entity(e) => e == &c.entity, + Recipients::ScriptID(i) => i == &c.sid, + Recipients::ScriptName(n) => n == c.name, + } + } +} + +impl Default for Recipients { + fn default() -> Self { + Self::All + } +} + +pub trait ScriptEvent : Send + Sync + Clone + 'static { + + /// Retrieves the recipient scripts for this event + fn recipients(&self) -> &Recipients; +} + + + + /// A script host is the interface between your rust application /// and the scripts in some interpreted language. pub trait ScriptHost: Send + Sync + 'static { /// the type of the persistent script context, representing the execution context of the script type ScriptContext: Send + Sync + 'static; /// the type of events picked up by lua callbacks - type ScriptEvent: Send + Sync + Clone + 'static; + type ScriptEvent: ScriptEvent; /// the type of asset representing the script files for this host type ScriptAsset: CodeAsset; @@ -37,11 +85,13 @@ pub trait ScriptHost: Send + Sync + 'static { fn handle_events<'a>( world: &mut World, events: &[Self::ScriptEvent], - ctxs: impl Iterator, - ) -> Result<()>; + ctxs: impl Iterator,&'a mut Self::ScriptContext)> + ) + -> Result<()>; /// Loads and runs script instantaneously without storing any script data into the world. - /// The script receives the `world` global as normal, but `entity` is set to `u64::MAX` + /// The script receives the `world` global as normal, but `entity` is set to `u64::MAX`. + /// The script id is set to `u32::MAX`. fn run_one_shot( script: &[u8], script_name: &str, @@ -49,10 +99,15 @@ pub trait ScriptHost: Send + Sync + 'static { event: Self::ScriptEvent, ) -> Result<()> { let mut ctx = Self::load_script(script, script_name)?; - let mut entity = Entity::from_bits(u64::MAX); + let entity = Entity::from_bits(u64::MAX); let events = [event; 1]; - let ctx_iter = [(&mut entity, &mut ctx); 1].into_iter(); + let ctx_iter = [ + (FlatScriptData{ + name:script_name, + sid:u32::MAX, + entity},&mut ctx) + ; 1].into_iter(); Self::handle_events(world, &events, ctx_iter) } @@ -192,7 +247,7 @@ pub struct ScriptCollection { pub struct ScriptContexts { /// holds script contexts for all scripts given their instance ids. /// This also stores contexts which are not fully loaded hence the Option - pub context_entities: HashMap)>, + pub context_entities: HashMap, String)>, } impl Default for ScriptContexts { @@ -205,11 +260,11 @@ impl Default for ScriptContexts { impl ScriptContexts { pub fn script_owner(&self, script_id: u32) -> Option { - self.context_entities.get(&script_id).map(|(e, _c)| *e) + self.context_entities.get(&script_id).map(|(e, _c , _n)| *e) } - pub fn insert_context(&mut self, script_id: u32, entity: Entity, ctx: Option) { - self.context_entities.insert(script_id, (entity, ctx)); + pub fn insert_context(&mut self, fd: FlatScriptData, ctx: Option) { + self.context_entities.insert(fd.sid, (fd.entity,ctx ,fd.name.to_owned())); } pub fn remove_context(&mut self, script_id: u32) { @@ -286,24 +341,30 @@ impl Script { script_assets: &Res>, contexts: &mut ResMut>, ) { + let fd = FlatScriptData{ + sid: new_script.id(), + entity, + name: new_script.name() + }; + let script = match script_assets.get(&new_script.handle) { Some(s) => s, None => { // not loaded yet - contexts.insert_context(new_script.id(), entity, None); + contexts.insert_context(fd, None); return; } }; match H::load_script(script.bytes(), &new_script.name) { Ok(ctx) => { - contexts.insert_context(new_script.id(), entity, Some(ctx)); + contexts.insert_context(fd, Some(ctx)); } Err(e) => { warn! {"Error in loading script {}:\n{}", &new_script.name,e} // this script will now never execute, unless manually reloaded // but contexts are left in a valid state - contexts.insert_context(new_script.id(), entity, None) + contexts.insert_context(fd, None) } } } @@ -356,7 +417,7 @@ pub(crate) fn script_add_synchronizer( let context_ids = contexts .context_entities .iter() - .filter_map(|(sid, (e, _))| if *e == entity { Some(sid) } else { None }) + .filter_map(|(sid, (e, _, _))| if *e == entity { Some(sid) } else { None }) .cloned() .collect::>(); let script_ids = new_scripts @@ -448,8 +509,16 @@ pub(crate) fn script_event_handler v, + None => return None, + }; + + Some((FlatScriptData{ sid:*sid, entity:*entity, name },ctx)) + }); match H::handle_events(world, &events, ctx_iter) { Ok(_) => {} diff --git a/bevy_mod_scripting/src/hosts/rhai_host/mod.rs b/bevy_mod_scripting/src/hosts/rhai_host/mod.rs index a5738dc9fe..e5c1950046 100644 --- a/bevy_mod_scripting/src/hosts/rhai_host/mod.rs +++ b/bevy_mod_scripting/src/hosts/rhai_host/mod.rs @@ -1,8 +1,9 @@ pub mod assets; +pub mod api; use crate::{ script_add_synchronizer, script_hot_reload_handler, script_remove_synchronizer, APIProvider, - CachedScriptEventState, ScriptContexts, ScriptHost, + CachedScriptEventState, ScriptContexts, ScriptHost, ScriptEvent, Recipients, FlatScriptData, }; use anyhow::anyhow; use beau_collector::BeauCollector as _; @@ -11,7 +12,7 @@ use bevy_event_priority::AddPriorityEvent; use rhai::*; use std::marker::PhantomData; -pub use assets::*; +pub use {assets::*,api::*}; /// More specific APIProvider implementation allowing more control over Rhai scripts pub trait RhaiAPIProvider: APIProvider { @@ -39,8 +40,16 @@ pub struct RhaiContext { pub struct RhaiEvent { pub hook_name: String, pub args: A, + pub recipients: Recipients } +impl ScriptEvent for RhaiEvent{ + fn recipients(&self) -> &crate::Recipients { + &self.recipients + } +} + + impl> ScriptHost for RhaiScriptHost { @@ -93,13 +102,19 @@ impl( world: &mut World, events: &[Self::ScriptEvent], - ctxs: impl Iterator, + ctxs: impl Iterator,&'a mut Self::ScriptContext)>, ) -> anyhow::Result<()> { - ctxs.flat_map(|(entity, ctx)| { + ctxs.flat_map(|(fd,ctx)| { ctx.scope.set_value("world", world as *mut World as usize); - ctx.scope.set_value("entity", *entity); + ctx.scope.set_value("entity", fd.entity); + ctx.scope.set_value("script", fd.sid); + + events.iter().map(move |event| { + // check if this script should handle this event + if !event.recipients().is_recipient(&fd){ + return Ok(()) + }; - events.iter().map(|event| { ctx.engine .call_fn( &mut ctx.scope, diff --git a/bevy_mod_scripting/src/hosts/rlua_host/mod.rs b/bevy_mod_scripting/src/hosts/rlua_host/mod.rs index 149688ae59..ff59e8f826 100644 --- a/bevy_mod_scripting/src/hosts/rlua_host/mod.rs +++ b/bevy_mod_scripting/src/hosts/rlua_host/mod.rs @@ -2,7 +2,7 @@ pub mod assets; use crate::{ script_add_synchronizer, script_hot_reload_handler, script_remove_synchronizer, APIProvider, - CachedScriptEventState, ScriptContexts, ScriptHost, + CachedScriptEventState, ScriptContexts, ScriptHost, ScriptEvent, Recipients, FlatScriptData, }; use anyhow::{anyhow, Result}; use beau_collector::BeauCollector as _; @@ -26,6 +26,14 @@ impl ToLua<'lua> + Clone + Sync + Send + 'static> LuaArg for T {} pub struct LuaEvent { pub hook_name: String, pub args: Vec, + pub recipients: Recipients +} + + +impl ScriptEvent for LuaEvent{ + fn recipients(&self) -> &crate::Recipients { + &self.recipients + } } /// Rlua script host, enables Lua scripting provided by the Rlua library. @@ -135,21 +143,27 @@ impl>> ScriptHost for RLuaScriptHos fn handle_events<'a>( world: &mut World, events: &[Self::ScriptEvent], - ctxs: impl Iterator, + ctxs: impl Iterator,&'a mut Self::ScriptContext)>, ) -> anyhow::Result<()> { - ctxs.map(|(entity, ctx)| { + ctxs.map(|(fd,ctx)| { let world_ptr = world as *mut World as usize; - let lua_ctx = ctx.get_mut().unwrap(); - lua_ctx.context::<_, Result<()>>(|lua_ctx| { + ctx.get_mut().unwrap().context::<_, Result<()>>(|lua_ctx| { let globals = lua_ctx.globals(); globals.set("world", world_ptr)?; - globals.set("entity", entity.to_bits())?; + globals.set("entity", fd.entity.to_bits())?; + globals.set("script", fd.sid)?; // event order is preserved, but scripts can't rely on any temporal // guarantees when it comes to other scripts callbacks, // at least for now for event in events { + + // check if this script should handle this event + if !event.recipients().is_recipient(&fd){ + continue + } + let mut f: Function = match globals.get(event.hook_name.clone()) { Ok(f) => f, Err(_) => continue, // not subscribed to this event @@ -167,8 +181,7 @@ impl>> ScriptHost for RLuaScriptHos Ok(()) }) - }) - .bcollect() + }).bcollect() } } impl>> RLuaScriptHost { diff --git a/readme.md b/readme.md index 3f5a0bbd26..b53e737992 100644 --- a/readme.md +++ b/readme.md @@ -120,6 +120,7 @@ pub fn trigger_on_update_script_callback(mut w: PriorityEventWriter { hook_name: "on_update".to_string(), args: Vec::default(), + recipients: Recipients::All }; w.send(event,0); @@ -152,6 +153,7 @@ pub fn trigger_on_update_rhai(mut w: PriorityEventWriter Date: Fri, 13 May 2022 12:22:43 +0100 Subject: [PATCH 2/4] fixed accidental change + fmt --- .../examples/complex_game_loop.rs | 6 +- .../examples/console_integration_lua.rs | 4 +- .../examples/console_integration_rhai.rs | 7 +- .../examples/event_recipients.rs | 53 ++++++------ bevy_mod_scripting/src/hosts/mod.rs | 84 ++++++++++--------- bevy_mod_scripting/src/hosts/rhai_host/mod.rs | 18 ++-- bevy_mod_scripting/src/hosts/rlua_host/mod.rs | 19 ++--- 7 files changed, 99 insertions(+), 92 deletions(-) diff --git a/bevy_mod_scripting/examples/complex_game_loop.rs b/bevy_mod_scripting/examples/complex_game_loop.rs index 43c29affa1..dee10596bd 100644 --- a/bevy_mod_scripting/examples/complex_game_loop.rs +++ b/bevy_mod_scripting/examples/complex_game_loop.rs @@ -2,8 +2,8 @@ use bevy::{core::FixedTimestep, prelude::*}; use bevy_console::ConsolePlugin; use bevy_event_priority::PriorityEventWriter; use bevy_mod_scripting::{ - APIProvider, AddScriptHost, AddScriptHostHandler, LuaEvent, LuaFile, RLuaScriptHost, Script, - ScriptCollection, ScriptingPlugin, Recipients, + APIProvider, AddScriptHost, AddScriptHostHandler, LuaEvent, LuaFile, RLuaScriptHost, + Recipients, Script, ScriptCollection, ScriptingPlugin, }; use rand::prelude::SliceRandom; use rlua::{Lua, ToLua}; @@ -55,7 +55,7 @@ fn fire_random_event(w: &mut PriorityEventWriter>, events: &[ LuaEvent { hook_name: v.0.to_string(), args: vec![arg], - recipients: Recipients::All + recipients: Recipients::All, }, v.1, ) diff --git a/bevy_mod_scripting/examples/console_integration_lua.rs b/bevy_mod_scripting/examples/console_integration_lua.rs index bdb5186b57..888352a8c4 100644 --- a/bevy_mod_scripting/examples/console_integration_lua.rs +++ b/bevy_mod_scripting/examples/console_integration_lua.rs @@ -2,7 +2,7 @@ use bevy::{ecs::event::Events, prelude::*}; use bevy_console::{AddConsoleCommand, ConsoleCommand, ConsolePlugin, PrintConsoleLine}; use bevy_mod_scripting::{ events::PriorityEventWriter, APIProvider, AddScriptHost, AddScriptHostHandler, LuaEvent, - LuaFile, RLuaScriptHost, Script, ScriptCollection, ScriptingPlugin, Recipients, + LuaFile, RLuaScriptHost, Recipients, Script, ScriptCollection, ScriptingPlugin, }; use rlua::{Lua, ToLua}; use std::sync::Mutex; @@ -51,7 +51,7 @@ pub fn trigger_on_update_lua(mut w: PriorityEventWriter>) { let event = LuaEvent { hook_name: "on_update".to_string(), args: Vec::default(), - recipients: Recipients::All + recipients: Recipients::All, }; w.send(event, 0); diff --git a/bevy_mod_scripting/examples/console_integration_rhai.rs b/bevy_mod_scripting/examples/console_integration_rhai.rs index ec6a41be49..f3bb2e432d 100644 --- a/bevy_mod_scripting/examples/console_integration_rhai.rs +++ b/bevy_mod_scripting/examples/console_integration_rhai.rs @@ -1,8 +1,9 @@ use bevy::{ecs::event::Events, prelude::*}; use bevy_console::{AddConsoleCommand, ConsoleCommand, ConsolePlugin, PrintConsoleLine}; use bevy_mod_scripting::{ - events::PriorityEventWriter, APIProvider, AddScriptHost, AddScriptHostHandler, RhaiAPIProvider, - RhaiContext, RhaiEvent, RhaiFile, RhaiScriptHost, Script, ScriptCollection, ScriptingPlugin, Recipients, + events::PriorityEventWriter, APIProvider, AddScriptHost, AddScriptHostHandler, Recipients, + RhaiAPIProvider, RhaiContext, RhaiEvent, RhaiFile, RhaiScriptHost, Script, ScriptCollection, + ScriptingPlugin, }; use rhai::FuncArgs; @@ -49,7 +50,7 @@ pub fn trigger_on_update_rhai(mut w: PriorityEventWriter>, events: &[ let arg = MyLuaArg(id as usize); let event = events .choose(&mut rng) - .map(|v| - - LuaEvent { - hook_name: v.0.to_string(), - args: vec![arg], - recipients: v.1.clone() - } - ) + .map(|v| LuaEvent { + hook_name: v.0.to_string(), + args: vec![arg], + recipients: v.1.clone(), + }) .unwrap(); info!( @@ -67,7 +64,6 @@ fn fire_random_event(w: &mut PriorityEventWriter>, events: &[ w.send(event, 0); } - fn do_update(mut w: PriorityEventWriter>) { info!("Update, firing:"); @@ -75,7 +71,10 @@ fn do_update(mut w: PriorityEventWriter>) { ScriptEventData("on_event", Recipients::All), ScriptEventData("on_event", Recipients::ScriptID(0)), ScriptEventData("on_event", Recipients::ScriptID(1)), - ScriptEventData("on_event", Recipients::ScriptName("scripts/event_recipients.lua".to_owned())) + ScriptEventData( + "on_event", + Recipients::ScriptName("scripts/event_recipients.lua".to_owned()), + ), ]; // fire random event, for any stages @@ -85,21 +84,24 @@ fn do_update(mut w: PriorityEventWriter>) { #[derive(Clone)] pub struct ScriptEventData(&'static str, Recipients); - fn load_our_scripts(server: Res, mut commands: Commands) { // spawn two identical scripts // id's will be 0 and 1 let path = "scripts/event_recipients.lua"; let handle = server.load::(path); - let scripts = (0..2).into_iter() - .map(|_| { - Script::::new::,>(path.to_string(), handle.clone()) - }) - .collect(); - - commands.spawn().insert(ScriptCollection:: { - scripts - }); + let scripts = (0..2) + .into_iter() + .map(|_| { + Script::::new::>( + path.to_string(), + handle.clone(), + ) + }) + .collect(); + + commands + .spawn() + .insert(ScriptCollection:: { scripts }); } fn main() -> std::io::Result<()> { @@ -109,13 +111,14 @@ fn main() -> std::io::Result<()> { .add_plugin(ScriptingPlugin) .add_plugin(ConsolePlugin) .add_startup_system(load_our_scripts) - // randomly fire events for either all scripts, // the script with id 0 // or the script with id 1 .add_system(do_update) - .add_script_handler_stage::,_,0,0>(CoreStage::PostUpdate) - .add_script_host::, _>(CoreStage::PostUpdate); + .add_script_handler_stage::, _, 0, 0>( + CoreStage::PostUpdate, + ) + .add_script_host::, _>(CoreStage::PostUpdate); app.run(); diff --git a/bevy_mod_scripting/src/hosts/mod.rs b/bevy_mod_scripting/src/hosts/mod.rs index c5fd2620c8..2882bd34f3 100644 --- a/bevy_mod_scripting/src/hosts/mod.rs +++ b/bevy_mod_scripting/src/hosts/mod.rs @@ -18,18 +18,18 @@ use std::{ sync::atomic::{AtomicU32, Ordering}, }; -/// Describes the target set of scripts this event should +/// Describes the target set of scripts this event should /// be handled by #[derive(Clone, Debug)] -pub enum Recipients{ +pub enum Recipients { /// Send to all scripts All, /// Send only to scripts on the given entity Entity(Entity), - /// Send to script with the given ID + /// Send to script with the given ID ScriptID(u32), // Send to script with the given name - ScriptName(String) + ScriptName(String), } #[derive(Debug)] @@ -40,8 +40,8 @@ pub struct FlatScriptData<'a> { } impl Recipients { - /// Returns true if the given script should - pub fn is_recipient(&self, c : &FlatScriptData) -> bool{ + /// Returns true if the given script should + pub fn is_recipient(&self, c: &FlatScriptData) -> bool { match self { Recipients::All => true, Recipients::Entity(e) => e == &c.entity, @@ -57,15 +57,11 @@ impl Default for Recipients { } } -pub trait ScriptEvent : Send + Sync + Clone + 'static { - +pub trait ScriptEvent: Send + Sync + Clone + 'static { /// Retrieves the recipient scripts for this event fn recipients(&self) -> &Recipients; } - - - /// A script host is the interface between your rust application /// and the scripts in some interpreted language. pub trait ScriptHost: Send + Sync + 'static { @@ -85,9 +81,8 @@ pub trait ScriptHost: Send + Sync + 'static { fn handle_events<'a>( world: &mut World, events: &[Self::ScriptEvent], - ctxs: impl Iterator,&'a mut Self::ScriptContext)> - ) - -> Result<()>; + ctxs: impl Iterator, &'a mut Self::ScriptContext)>, + ) -> Result<()>; /// Loads and runs script instantaneously without storing any script data into the world. /// The script receives the `world` global as normal, but `entity` is set to `u64::MAX`. @@ -102,12 +97,15 @@ pub trait ScriptHost: Send + Sync + 'static { let entity = Entity::from_bits(u64::MAX); let events = [event; 1]; - let ctx_iter = [ - (FlatScriptData{ - name:script_name, - sid:u32::MAX, - entity},&mut ctx) - ; 1].into_iter(); + let ctx_iter = [( + FlatScriptData { + name: script_name, + sid: u32::MAX, + entity, + }, + &mut ctx, + ); 1] + .into_iter(); Self::handle_events(world, &events, ctx_iter) } @@ -260,11 +258,12 @@ impl Default for ScriptContexts { impl ScriptContexts { pub fn script_owner(&self, script_id: u32) -> Option { - self.context_entities.get(&script_id).map(|(e, _c , _n)| *e) + self.context_entities.get(&script_id).map(|(e, _c, _n)| *e) } pub fn insert_context(&mut self, fd: FlatScriptData, ctx: Option) { - self.context_entities.insert(fd.sid, (fd.entity,ctx ,fd.name.to_owned())); + self.context_entities + .insert(fd.sid, (fd.entity, ctx, fd.name.to_owned())); } pub fn remove_context(&mut self, script_id: u32) { @@ -341,10 +340,10 @@ impl Script { script_assets: &Res>, contexts: &mut ResMut>, ) { - let fd = FlatScriptData{ - sid: new_script.id(), - entity, - name: new_script.name() + let fd = FlatScriptData { + sid: new_script.id(), + entity, + name: new_script.name(), }; let script = match script_assets.get(&new_script.handle) { @@ -506,19 +505,26 @@ pub(crate) fn script_event_handler>| { - let ctx_iter = ctxts - .as_mut() - .context_entities - .iter_mut() - .filter_map(|(sid,(entity, o, name))| { - - let ctx = match o { - Some(v) => v, - None => return None, - }; - - Some((FlatScriptData{ sid:*sid, entity:*entity, name },ctx)) - }); + let ctx_iter = + ctxts + .as_mut() + .context_entities + .iter_mut() + .filter_map(|(sid, (entity, o, name))| { + let ctx = match o { + Some(v) => v, + None => return None, + }; + + Some(( + FlatScriptData { + sid: *sid, + entity: *entity, + name, + }, + ctx, + )) + }); match H::handle_events(world, &events, ctx_iter) { Ok(_) => {} diff --git a/bevy_mod_scripting/src/hosts/rhai_host/mod.rs b/bevy_mod_scripting/src/hosts/rhai_host/mod.rs index e5c1950046..ae63e75e05 100644 --- a/bevy_mod_scripting/src/hosts/rhai_host/mod.rs +++ b/bevy_mod_scripting/src/hosts/rhai_host/mod.rs @@ -1,9 +1,8 @@ pub mod assets; -pub mod api; use crate::{ script_add_synchronizer, script_hot_reload_handler, script_remove_synchronizer, APIProvider, - CachedScriptEventState, ScriptContexts, ScriptHost, ScriptEvent, Recipients, FlatScriptData, + CachedScriptEventState, FlatScriptData, Recipients, ScriptContexts, ScriptEvent, ScriptHost, }; use anyhow::anyhow; use beau_collector::BeauCollector as _; @@ -12,7 +11,7 @@ use bevy_event_priority::AddPriorityEvent; use rhai::*; use std::marker::PhantomData; -pub use {assets::*,api::*}; +pub use assets::*; /// More specific APIProvider implementation allowing more control over Rhai scripts pub trait RhaiAPIProvider: APIProvider { @@ -40,16 +39,15 @@ pub struct RhaiContext { pub struct RhaiEvent { pub hook_name: String, pub args: A, - pub recipients: Recipients + pub recipients: Recipients, } -impl ScriptEvent for RhaiEvent{ +impl ScriptEvent for RhaiEvent { fn recipients(&self) -> &crate::Recipients { &self.recipients } } - impl> ScriptHost for RhaiScriptHost { @@ -102,17 +100,17 @@ impl( world: &mut World, events: &[Self::ScriptEvent], - ctxs: impl Iterator,&'a mut Self::ScriptContext)>, + ctxs: impl Iterator, &'a mut Self::ScriptContext)>, ) -> anyhow::Result<()> { - ctxs.flat_map(|(fd,ctx)| { + ctxs.flat_map(|(fd, ctx)| { ctx.scope.set_value("world", world as *mut World as usize); ctx.scope.set_value("entity", fd.entity); ctx.scope.set_value("script", fd.sid); events.iter().map(move |event| { // check if this script should handle this event - if !event.recipients().is_recipient(&fd){ - return Ok(()) + if !event.recipients().is_recipient(&fd) { + return Ok(()); }; ctx.engine diff --git a/bevy_mod_scripting/src/hosts/rlua_host/mod.rs b/bevy_mod_scripting/src/hosts/rlua_host/mod.rs index ff59e8f826..dea85cd888 100644 --- a/bevy_mod_scripting/src/hosts/rlua_host/mod.rs +++ b/bevy_mod_scripting/src/hosts/rlua_host/mod.rs @@ -2,7 +2,7 @@ pub mod assets; use crate::{ script_add_synchronizer, script_hot_reload_handler, script_remove_synchronizer, APIProvider, - CachedScriptEventState, ScriptContexts, ScriptHost, ScriptEvent, Recipients, FlatScriptData, + CachedScriptEventState, FlatScriptData, Recipients, ScriptContexts, ScriptEvent, ScriptHost, }; use anyhow::{anyhow, Result}; use beau_collector::BeauCollector as _; @@ -26,11 +26,10 @@ impl ToLua<'lua> + Clone + Sync + Send + 'static> LuaArg for T {} pub struct LuaEvent { pub hook_name: String, pub args: Vec, - pub recipients: Recipients + pub recipients: Recipients, } - -impl ScriptEvent for LuaEvent{ +impl ScriptEvent for LuaEvent { fn recipients(&self) -> &crate::Recipients { &self.recipients } @@ -143,9 +142,9 @@ impl>> ScriptHost for RLuaScriptHos fn handle_events<'a>( world: &mut World, events: &[Self::ScriptEvent], - ctxs: impl Iterator,&'a mut Self::ScriptContext)>, + ctxs: impl Iterator, &'a mut Self::ScriptContext)>, ) -> anyhow::Result<()> { - ctxs.map(|(fd,ctx)| { + ctxs.map(|(fd, ctx)| { let world_ptr = world as *mut World as usize; ctx.get_mut().unwrap().context::<_, Result<()>>(|lua_ctx| { @@ -158,10 +157,9 @@ impl>> ScriptHost for RLuaScriptHos // guarantees when it comes to other scripts callbacks, // at least for now for event in events { - // check if this script should handle this event - if !event.recipients().is_recipient(&fd){ - continue + if !event.recipients().is_recipient(&fd) { + continue; } let mut f: Function = match globals.get(event.hook_name.clone()) { @@ -181,7 +179,8 @@ impl>> ScriptHost for RLuaScriptHos Ok(()) }) - }).bcollect() + }) + .bcollect() } } impl>> RLuaScriptHost { From be5bfbfe87cecd2c1bffef79f16329c612a87424 Mon Sep 17 00:00:00 2001 From: makspll Date: Fri, 13 May 2022 12:22:59 +0100 Subject: [PATCH 3/4] cargo fix --- bevy_mod_scripting/examples/event_recipients.rs | 2 +- bevy_mod_scripting/src/hosts/rhai_host/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bevy_mod_scripting/examples/event_recipients.rs b/bevy_mod_scripting/examples/event_recipients.rs index 6d8f89e4ed..b9f7572c4e 100644 --- a/bevy_mod_scripting/examples/event_recipients.rs +++ b/bevy_mod_scripting/examples/event_recipients.rs @@ -1,4 +1,4 @@ -use bevy::{core::FixedTimestep, prelude::*}; +use bevy::{prelude::*}; use bevy_console::ConsolePlugin; use bevy_event_priority::PriorityEventWriter; use bevy_mod_scripting::{ diff --git a/bevy_mod_scripting/src/hosts/rhai_host/mod.rs b/bevy_mod_scripting/src/hosts/rhai_host/mod.rs index ae63e75e05..3573767182 100644 --- a/bevy_mod_scripting/src/hosts/rhai_host/mod.rs +++ b/bevy_mod_scripting/src/hosts/rhai_host/mod.rs @@ -6,7 +6,7 @@ use crate::{ }; use anyhow::anyhow; use beau_collector::BeauCollector as _; -use bevy::prelude::{AddAsset, Entity, SystemSet, World}; +use bevy::prelude::{AddAsset, SystemSet, World}; use bevy_event_priority::AddPriorityEvent; use rhai::*; use std::marker::PhantomData; From 6f3cf2f068c5fe4b79a933545b531fc2f92814aa Mon Sep 17 00:00:00 2001 From: makspll Date: Fri, 13 May 2022 12:30:38 +0100 Subject: [PATCH 4/4] cargo fmt --- bevy_mod_scripting/examples/event_recipients.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bevy_mod_scripting/examples/event_recipients.rs b/bevy_mod_scripting/examples/event_recipients.rs index b9f7572c4e..00c3731ca7 100644 --- a/bevy_mod_scripting/examples/event_recipients.rs +++ b/bevy_mod_scripting/examples/event_recipients.rs @@ -1,4 +1,4 @@ -use bevy::{prelude::*}; +use bevy::prelude::*; use bevy_console::ConsolePlugin; use bevy_event_priority::PriorityEventWriter; use bevy_mod_scripting::{