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..992ab95 --- /dev/null +++ b/src/runner/script_signal.rs @@ -0,0 +1,79 @@ +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)) + // ); + } +} +impl mlua::FromLua for ScriptSignal{ + fn from_lua(value:mlua::Value,_lua:&mlua::Lua)->Result{ + match value{ + mlua::Value::UserData(ud)=>Ok(ud.borrow::()?.clone()), + other=>Err(mlua::Error::runtime(format!("Expected {} got {:?}",stringify!(ScriptSignal),other))), + } + } +} + +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(()) + }); + } +} diff --git a/src/scheduler.rs b/src/scheduler.rs index 53170d1..b767aa1 100644 --- a/src/scheduler.rs +++ b/src/scheduler.rs @@ -2,14 +2,6 @@ pub use tick::Tick; mod tick{ #[derive(Clone,Copy,Default,Hash,PartialEq,Eq,PartialOrd,Ord)] pub struct Tick(u64); - impl Tick{ - pub const fn new(value:u64)->Self{ - Self(value) - } - pub const fn get(&self)->u64{ - self.0 - } - } impl std::ops::Add for Tick{ type Output=Self; fn add(self,rhs:u64)->Self::Output{ @@ -40,9 +32,6 @@ pub struct Scheduler{ } impl Scheduler{ - pub const fn tick(&self)->Tick{ - self.tick - } pub fn has_scheduled_threads(&self)->bool{ !self.schedule.is_empty() }