2024-10-17 02:53:58 +00:00
|
|
|
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<u64> for Tick{
|
|
|
|
type Output=Self;
|
|
|
|
fn add(self,rhs:u64)->Self::Output{
|
|
|
|
Self(self.0+rhs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl std::ops::Sub<u64> for Tick{
|
|
|
|
type Output=Self;
|
|
|
|
fn sub(self,rhs:u64)->Self::Output{
|
|
|
|
Self(self.0-rhs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl std::ops::AddAssign<u64> for Tick{
|
|
|
|
fn add_assign(&mut self,rhs:u64){
|
|
|
|
self.0+=rhs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl std::ops::SubAssign<u64> for Tick{
|
|
|
|
fn sub_assign(&mut self,rhs:u64){
|
|
|
|
self.0-=rhs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct Scheduler{
|
|
|
|
tick:Tick,
|
|
|
|
schedule:std::collections::HashMap<Tick,Vec<mlua::Thread>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
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<Vec<mlua::Thread>>{
|
|
|
|
self.tick+=1;
|
|
|
|
self.schedule.remove(&self.tick)
|
|
|
|
}
|
|
|
|
}
|
2024-10-17 00:45:41 +00:00
|
|
|
|
|
|
|
fn coerce_float64(value:&mlua::Value)->Option<f64>{
|
|
|
|
match value{
|
|
|
|
&mlua::Value::Integer(i)=>Some(i as f64),
|
|
|
|
&mlua::Value::Number(f)=>Some(f),
|
|
|
|
_=>None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn scheduler_mut<T>(lua:&mlua::Lua,mut f:impl FnMut(&mut crate::scheduler::Scheduler)->mlua::Result<T>)->mlua::Result<T>{
|
|
|
|
let mut scheduler=lua.app_data_mut::<crate::scheduler::Scheduler>().ok_or(mlua::Error::runtime("Scheduler missing"))?;
|
|
|
|
f(&mut *scheduler)
|
|
|
|
}
|
|
|
|
pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
|
|
|
|
let schedule_thread=lua.create_function(move|lua,dt:mlua::Value|{
|
|
|
|
let delay=coerce_float64(&dt).ok_or(mlua::Error::runtime("Expected float"))?.max(0.0)*60.0;
|
|
|
|
if delay<u64::MAX as f64{
|
|
|
|
scheduler_mut(lua,|scheduler|{
|
|
|
|
scheduler.schedule_thread((delay as u64).max(2),lua.current_thread());
|
|
|
|
Ok(())
|
|
|
|
}).unwrap();
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
})?;
|
|
|
|
let wait_env=lua.create_table()?;
|
|
|
|
wait_env.raw_set("coroutine",globals.get::<mlua::Table>("coroutine")?)?;
|
|
|
|
wait_env.raw_set("schedule_thread",schedule_thread)?;
|
|
|
|
let wait=lua.load("
|
|
|
|
local coroutine_yield=coroutine.yield
|
|
|
|
local schedule_thread=schedule_thread
|
|
|
|
return function(dt)
|
|
|
|
schedule_thread(dt)
|
|
|
|
return coroutine_yield()
|
|
|
|
end
|
|
|
|
")
|
|
|
|
.set_name("wait")
|
|
|
|
.set_environment(wait_env)
|
|
|
|
.call::<mlua::Function>(())?;
|
|
|
|
globals.raw_set("wait",wait)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|