diff --git a/src/lib.rs b/src/lib.rs index b97eda2..669c126 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ pub mod runner; pub mod context; +pub(crate) mod scheduler; #[cfg(test)] mod tests; diff --git a/src/runner/runner.rs b/src/runner/runner.rs index f84e8b1..856c2b7 100644 --- a/src/runner/runner.rs +++ b/src/runner/runner.rs @@ -60,6 +60,7 @@ impl Runner{ } //this makes set_app_data shut up about the lifetime self.lua.set_app_data::<&'static mut rbx_dom_weak::WeakDom>(unsafe{core::mem::transmute(&mut context.dom)}); + self.lua.set_app_data::(crate::scheduler::Scheduler::default()); Ok(Runnable{ lua:self.lua, _lifetime:&std::marker::PhantomData @@ -75,15 +76,21 @@ pub struct Runnable<'a>{ impl Runnable<'_>{ pub fn drop_context(self)->Runner{ self.lua.remove_app_data::<&'static mut rbx_dom_weak::WeakDom>(); + self.lua.remove_app_data::(); Runner{ lua:self.lua, } } pub fn run_script(&self,script:super::instance::Instance)->Result<(),Error>{ let (name,source)=super::instance::get_name_source(&self.lua,script).map_err(Error::RustLua)?; - self.lua.globals().set("script",script).map_err(Error::RustLua)?; - self.lua.load(source.as_str()) - .set_name(name) - .exec().map_err(|error|Error::Lua{source,error}) + self.lua.globals().raw_set("script",script).map_err(Error::RustLua)?; + let f=self.lua.load(source.as_str()) + .set_name(name).into_function().map_err(Error::RustLua)?; + // TODO: set_environment without losing the ability to print from Lua + let thread=self.lua.create_thread(f).map_err(Error::RustLua)?; + thread.resume::(()).map_err(|error|Error::Lua{source,error})?; + // wait() is called from inside Lua and goes to a rust function that schedules the thread and then yields + // No need to schedule the thread here + Ok(()) } } diff --git a/src/scheduler.rs b/src/scheduler.rs new file mode 100644 index 0000000..f99a5c8 --- /dev/null +++ b/src/scheduler.rs @@ -0,0 +1,58 @@ +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{ + Self(self.0+rhs) + } + } + impl std::ops::Sub for Tick{ + type Output=Self; + fn sub(self,rhs:u64)->Self::Output{ + Self(self.0-rhs) + } + } + impl std::ops::AddAssign for Tick{ + fn add_assign(&mut self,rhs:u64){ + self.0+=rhs; + } + } + impl std::ops::SubAssign for Tick{ + fn sub_assign(&mut self,rhs:u64){ + self.0-=rhs; + } + } +} +#[derive(Default)] +pub struct Scheduler{ + tick:Tick, + schedule:std::collections::HashMap>, +} + +impl Scheduler{ + pub const fn tick(&self)->Tick{ + self.tick + } + pub fn has_scheduled_threads(&self)->bool{ + !self.schedule.is_empty() + } + pub fn schedule_thread(&mut self,delay:u64,thread:mlua::Thread){ + self.schedule.entry(self.tick+delay.max(1)) + .or_insert(Vec::new()) + .push(thread); + } + pub fn tick_threads(&mut self)->Option>{ + self.tick+=1; + self.schedule.remove(&self.tick) + } +}