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..78a4685 100644 --- a/src/runner/runner.rs +++ b/src/runner/runner.rs @@ -62,7 +62,8 @@ impl Runner{ self.lua.set_app_data::<&'static mut rbx_dom_weak::WeakDom>(unsafe{core::mem::transmute(&mut context.dom)}); Ok(Runnable{ lua:self.lua, - _lifetime:&std::marker::PhantomData + _lifetime:&std::marker::PhantomData, + scheduler:crate::scheduler::Scheduler::default(), }) } } @@ -70,7 +71,8 @@ impl Runner{ //Runnable is the same thing but has context set, which it holds the lifetime for. pub struct Runnable<'a>{ lua:mlua::Lua, - _lifetime:&'a std::marker::PhantomData<()> + _lifetime:&'a std::marker::PhantomData<()>, + scheduler:crate::scheduler::Scheduler, } impl Runnable<'_>{ pub fn drop_context(self)->Runner{ @@ -80,10 +82,23 @@ impl Runnable<'_>{ } } pub fn run_script(&self,script:super::instance::Instance)->Result<(),Error>{ + let thread=self.make_script_thread(script)?; + thread.resume::(()).map_err(|error|Error::Lua{source:"source not available".to_owned(),error})?; + Ok(()) + } + pub fn make_script_thread(&self,script:super::instance::Instance)->Result{ 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}) + let fenv=self.lua.create_table().map_err(Error::RustLua)?; + //there's gotta be a more concise way to do this + for pair in self.lua.globals().pairs::(){ + let (k,v)=pair.map_err(Error::RustLua)?; + fenv.raw_set(k,v).map_err(Error::RustLua)?; + } + fenv.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)?; + f.set_environment(fenv).map_err(Error::RustLua)?; + let thread=self.lua.create_thread(f).map_err(Error::RustLua)?; + Ok(thread) } } diff --git a/src/scheduler.rs b/src/scheduler.rs new file mode 100644 index 0000000..ec7d737 --- /dev/null +++ b/src/scheduler.rs @@ -0,0 +1,55 @@ +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 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) + } +}