strafe-client/src/scheduler.rs

106 lines
2.6 KiB
Rust
Raw Normal View History

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
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>{
2024-10-17 06:07:32 +00:00
let schedule_thread=lua.create_function(|lua,dt:mlua::Value|{
let delay=match dt{
mlua::Value::Integer(i)=>i.max(0) as u64*60,
mlua::Value::Number(f)=>{
let delay=f.max(0.0)*60.0;
match delay.classify(){
std::num::FpCategory::Nan=>Err(mlua::Error::runtime("NaN"))?,
std::num::FpCategory::Infinite=>return Ok(()),
std::num::FpCategory::Normal=>if (u64::MAX as f64)<delay{
return Ok(());
},
_=>(),
}
delay as u64
},
mlua::Value::Nil=>0,
_=>Err(mlua::Error::runtime("Expected float"))?,
};
scheduler_mut(lua,|scheduler|{
scheduler.schedule_thread(delay.max(2),lua.current_thread());
Ok(())
})
2024-10-17 00:45:41 +00:00
})?;
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(())
}