diff --git a/src/runner/mod.rs b/src/runner/mod.rs index 7d716eb..a208868 100644 --- a/src/runner/mod.rs +++ b/src/runner/mod.rs @@ -7,7 +7,8 @@ mod color3; mod cframe; mod vector3; pub mod instance; -mod number_sequence; +mod script_signal; mod color_sequence; +mod number_sequence; pub use runner::{Runner,Runnable,Error}; diff --git a/src/runner/script_signal.rs b/src/runner/script_signal.rs new file mode 100644 index 0000000..f436046 --- /dev/null +++ b/src/runner/script_signal.rs @@ -0,0 +1,72 @@ +use std::{cell::RefCell,rc::Rc}; + +#[derive(Clone)] +pub struct ScriptSignal{ + // Emulate the garbage roblox api. + // ScriptConnection should not exist. + // :Disconnect should be a method on ScriptSignal, and this would be avoided entirely. + callbacks:Rc>>, +} +pub struct ScriptConnection{ + signal:ScriptSignal, + function:mlua::Function, +} +impl ScriptSignal{ + pub fn new()->Self{ + Self{ + callbacks:Rc::new(RefCell::new(Vec::new())), + } + } + // This eats the Lua error + pub fn fire(&self,args:mlua::MultiValue){ + // Make a copy of the list in case Lua attempts to modify it during the loop + let functions=self.callbacks.borrow().clone(); + for function in functions{ + //wee let's allocate for our function calls + if let Err(e)=function.call::(args.clone()){ + println!("Script Signal Error: {e}"); + } + } + } + pub fn connect(&self,function:mlua::Function)->ScriptConnection{ + self.callbacks.borrow_mut().push(function.clone()); + ScriptConnection{ + signal:self.clone(), + function, + } + } +} +impl ScriptConnection{ + pub fn position(&self)->Option{ + self.signal.callbacks.borrow().iter().position(|function|function==&self.function) + } +} + +impl mlua::UserData for ScriptSignal{ + fn add_methods>(methods:&mut M){ + methods.add_method("Connect",|_lua,this,f:mlua::Function| + Ok(this.connect(f)) + ); + // Fire is not allowed to be called from Lua + // methods.add_method("Fire",|_lua,this,args:mlua::MultiValue| + // Ok(this.fire(args)) + // ); + } +} +//type_from_lua_userdata!(ScriptSignal); + +impl mlua::UserData for ScriptConnection{ + fn add_fields>(fields:&mut F){ + fields.add_field_method_get("Connected",|_,this|{ + Ok(this.position().is_some()) + }); + } + fn add_methods>(methods:&mut M){ + methods.add_method("Disconnect",|_,this,_:()|{ + if let Some(index)=this.position(){ + this.signal.callbacks.borrow_mut().remove(index); + } + Ok(()) + }); + } +}