Compare commits
4 Commits
a927119734
...
cb70c60e93
Author | SHA1 | Date | |
---|---|---|---|
cb70c60e93 | |||
d4b67e93dd | |||
eb66516f83 | |||
9c1807ec76 |
@ -7,6 +7,10 @@ license = "MIT OR Apache-2.0"
|
||||
description = "Run embedded Luau scripts which manipulate the DOM."
|
||||
authors = ["Rhys Lloyd <krakow20@gmail.com>"]
|
||||
|
||||
[features]
|
||||
default=["run-service"]
|
||||
run-service=[]
|
||||
|
||||
[dependencies]
|
||||
glam = "0.29.0"
|
||||
mlua = { version = "0.10.0-beta", features = ["luau"] }
|
||||
|
@ -1,5 +1,6 @@
|
||||
pub mod runner;
|
||||
pub mod context;
|
||||
#[cfg(feature="run-service")]
|
||||
pub(crate) mod scheduler;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,4 +1,6 @@
|
||||
use crate::context::Context;
|
||||
#[cfg(feature="run-service")]
|
||||
use crate::scheduler::scheduler_mut;
|
||||
|
||||
pub struct Runner{
|
||||
lua:mlua::Lua,
|
||||
@ -29,6 +31,8 @@ fn init(lua:&mlua::Lua)->mlua::Result<()>{
|
||||
//global environment
|
||||
let globals=lua.globals();
|
||||
|
||||
#[cfg(feature="run-service")]
|
||||
crate::scheduler::set_globals(lua,&globals)?;
|
||||
super::r#enum::set_globals(lua,&globals)?;
|
||||
super::color3::set_globals(lua,&globals)?;
|
||||
super::vector3::set_globals(lua,&globals)?;
|
||||
@ -60,6 +64,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)});
|
||||
#[cfg(feature="run-service")]
|
||||
self.lua.set_app_data::<crate::scheduler::Scheduler>(crate::scheduler::Scheduler::default());
|
||||
Ok(Runnable{
|
||||
lua:self.lua,
|
||||
@ -76,6 +81,7 @@ pub struct Runnable<'a>{
|
||||
impl Runnable<'_>{
|
||||
pub fn drop_context(self)->Runner{
|
||||
self.lua.remove_app_data::<&'static mut rbx_dom_weak::WeakDom>();
|
||||
#[cfg(feature="run-service")]
|
||||
self.lua.remove_app_data::<crate::scheduler::Scheduler>();
|
||||
Runner{
|
||||
lua:self.lua,
|
||||
@ -83,9 +89,35 @@ impl Runnable<'_>{
|
||||
}
|
||||
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::<mlua::MultiValue>(()).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(())
|
||||
}
|
||||
#[cfg(feature="run-service")]
|
||||
pub fn has_scheduled_threads(&self)->Result<bool,mlua::Error>{
|
||||
scheduler_mut(&self.lua,|scheduler|
|
||||
Ok(scheduler.has_scheduled_threads())
|
||||
)
|
||||
}
|
||||
#[cfg(feature="run-service")]
|
||||
pub fn game_tick(&self)->Result<(),mlua::Error>{
|
||||
if let Some(threads)=scheduler_mut(&self.lua,|scheduler|Ok(scheduler.tick_threads()))?{
|
||||
for thread in threads{
|
||||
//TODO: return dt and total run time
|
||||
let result=thread.resume::<mlua::MultiValue>((1.0/20.0,0.0))
|
||||
.map_err(|error|Error::Lua{source:"source unavailable".to_owned(),error});
|
||||
match result{
|
||||
Ok(_)=>(),
|
||||
Err(e)=>println!("game_tick Error: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -56,3 +56,44 @@ impl Scheduler{
|
||||
self.schedule.remove(&self.tick)
|
||||
}
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user