diff --git a/src/runner/runner.rs b/src/runner/runner.rs index 0811be0..032d539 100644 --- a/src/runner/runner.rs +++ b/src/runner/runner.rs @@ -33,6 +33,7 @@ fn init(lua:&mlua::Lua)->mlua::Result<()>{ #[cfg(feature="run-service")] crate::scheduler::set_globals(lua,&globals)?; + super::script_signal::set_globals(lua,&globals)?; super::r#enum::set_globals(lua,&globals)?; super::color3::set_globals(lua,&globals)?; super::vector3::set_globals(lua,&globals)?; diff --git a/src/runner/script_signal.rs b/src/runner/script_signal.rs index ba6af7b..5197065 100644 --- a/src/runner/script_signal.rs +++ b/src/runner/script_signal.rs @@ -1,5 +1,7 @@ use std::{cell::RefCell,rc::Rc}; +use mlua::UserDataFields; + #[derive(Clone)] struct FunctionList{ functions:Vec, @@ -41,10 +43,9 @@ 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:RcFunctionList, + connections:RcFunctionList, once:RcFunctionList, wait:Rc>>, - wait_function:std::cell::OnceCell, } pub struct ScriptConnection{ connection:RcFunctionList, @@ -53,14 +54,13 @@ pub struct ScriptConnection{ impl ScriptSignal{ pub fn new()->Self{ Self{ - callbacks:RcFunctionList::new(), + connections:RcFunctionList::new(), once:RcFunctionList::new(), wait:Rc::new(RefCell::new(Vec::new())), - wait_function:std::cell::OnceCell::new(), } } pub fn fire(&self,args:&mlua::MultiValue){ - self.callbacks.fire(args); + self.connections.fire(args); //Replace the FunctionList with an empty one and drop the borrow let once=std::mem::replace(&mut *self.once.functions.borrow_mut(),FunctionList::new()); once.fire(args); @@ -73,9 +73,9 @@ impl ScriptSignal{ } } pub fn connect(&self,function:mlua::Function)->ScriptConnection{ - self.callbacks.functions.borrow_mut().functions.push(function.clone()); + self.connections.functions.borrow_mut().functions.push(function.clone()); ScriptConnection{ - connection:self.callbacks.clone(), + connection:self.connections.clone(), function, } } @@ -109,32 +109,29 @@ return function() return coroutine_yield() end"; +pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ + let coroutine_table=globals.get::("coroutine")?; + let wait_thread=lua.create_function(wait_thread)?; + + //create wait function environment + let wait_env=lua.create_table()?; + wait_env.raw_set("coroutine",coroutine_table)?; + wait_env.raw_set("wait_thread",wait_thread)?; + + //construct wait function from Lua code + let wait=lua.load(LUA_WAIT) + .set_name("wait") + .set_environment(wait_env) + .call::(())?; + + lua.register_userdata_type::(|reg|{ + reg.add_field("Wait",wait); + })?; + + Ok(()) +} + impl mlua::UserData for ScriptSignal{ - fn add_fields>(fields:&mut F){ - fields.add_field_method_get("Wait",|lua,this|{ - Ok(match this.wait_function.get(){ - Some(f)=>f.clone(), - None=>{ - let coroutine_table=lua.globals().get::("coroutine")?; - let wait_thread=lua.create_function(wait_thread)?; - - //create wait function environment - let wait_env=lua.create_table()?; - wait_env.raw_set("coroutine",coroutine_table)?; - wait_env.raw_set("wait_thread",wait_thread)?; - - //construct wait function from Lua code - let wait=lua.load(LUA_WAIT) - .set_name("wait") - .set_environment(wait_env) - .call::(())?; - - this.wait_function.set(wait.clone()).unwrap(); - wait - } - }) - }); - } fn add_methods>(methods:&mut M){ methods.add_method("Connect",|_lua,this,f:mlua::Function| Ok(this.connect(f))