From 2dddda685a34775ebafc34c50b8fdaf1055afabb Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 18 Sep 2024 18:47:38 -0700 Subject: [PATCH] must own (rework api) --- src/context.rs | 11 +++--- src/lib.rs | 2 +- src/runner/instance.rs | 79 ++++++++++++++++++++++++++++++++++++++++++ src/runner/mod.rs | 1 + src/runner/runner.rs | 48 +++++++++++++++++-------- src/script.rs | 34 +++++------------- 6 files changed, 130 insertions(+), 45 deletions(-) create mode 100644 src/runner/instance.rs diff --git a/src/context.rs b/src/context.rs index 47957bc..cc5f4e0 100644 --- a/src/context.rs +++ b/src/context.rs @@ -10,14 +10,17 @@ pub fn class_is_a(class:&str,superclass:&str)->bool{ ) } -pub struct Context<'a>{ - pub(crate)dom:&'a mut WeakDom, +pub struct Context{ + pub(crate)dom:WeakDom, } -impl Context<'_>{ - pub fn new(dom:&mut WeakDom)->Context<'_>{ +impl Context{ + pub fn new(dom:WeakDom)->Context{ Context{dom} } + pub fn into_inner(self)->WeakDom{ + self.dom + } /// Creates an iterator over all items of a particular class. pub fn superclass_iter<'a>(&'a self,superclass:&'a str)->impl Iterator+'a{ self.dom.descendants().filter(|&instance| diff --git a/src/lib.rs b/src/lib.rs index fb0dd5f..8c34547 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ pub mod script; pub mod context; -mod runner; +pub mod runner; pub type Result=core::result::Result; diff --git a/src/runner/instance.rs b/src/runner/instance.rs new file mode 100644 index 0000000..f8103a4 --- /dev/null +++ b/src/runner/instance.rs @@ -0,0 +1,79 @@ +use rbx_dom_weak::WeakDom; + +use super::vector3::Vector3; + +pub struct Instance{ + referent:rbx_types::Ref, +} + +impl From for Instance{ + fn from(value:crate::script::Script)->Self{ + Self{referent:value.script} + } +} + +impl Instance{ + pub const fn new(referent:rbx_types::Ref)->Self{ + Self{referent} + } + pub fn get<'a>(&'a self,dom:&'a WeakDom)->mlua::Result<&'a rbx_dom_weak::Instance>{ + dom.get_by_ref(self.referent).ok_or(mlua::Error::runtime("Instance missing")) + } + pub fn get_mut<'a>(&'a self,dom:&'a mut WeakDom)->mlua::Result<&'a mut rbx_dom_weak::Instance>{ + dom.get_by_ref_mut(self.referent).ok_or(mlua::Error::runtime("Instance missing")) + } +} + +// LMAO look at this function! +fn dom(lua:&mlua::Lua,mut f:impl FnMut(&mut WeakDom)->mlua::Result)->mlua::Result{ + f(&mut *lua.app_data_mut::().ok_or(mlua::Error::runtime("DataModel missing"))?) +} + +impl mlua::UserData for Instance{ + fn add_fields<'lua,F:mlua::UserDataFields<'lua,Self>>(fields:&mut F){ + fields.add_field_method_get("Parent",|lua,this|{ + dom(lua,|dom|{ + let instance=this.get(dom)?; + Ok(Instance::new(instance.parent())) + }) + }); + fields.add_field_method_set("Parent",|lua,this,val:Self|{ + dom(lua,|dom|{ + dom.transfer_within(this.referent,val.referent); + Ok(()) + }) + }); + } + + fn add_methods<'lua,M:mlua::UserDataMethods<'lua,Self>>(methods:&mut M){ + methods.add_meta_function(mlua::MetaMethod::NewIndex,|lua,(this,index,value):(Self,mlua::String,mlua::Value)| + dom(lua,|dom|{ + let instance=this.get_mut(dom)?; + let index_str=index.to_str()?; + let class=rbx_reflection_database::get().classes.get(instance.class.as_str()).ok_or(mlua::Error::runtime("Class missing"))?; + let property=class.default_properties.get(index_str).ok_or(mlua::Error::runtime(format!("Property '{index_str}' missing on class '{}'",class.name)))?; + match property{ + rbx_types::Variant::Vector3(_)=>{ + let typed_value:Vector3=value.as_userdata().ok_or(mlua::Error::runtime("Expected Userdata"))?.take()?; + instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Vector3(typed_value.into())); + }, + rbx_types::Variant::Float64(_)=>{ + let typed_value:f64=value.as_f64().ok_or(mlua::Error::runtime("Expected f64"))?; + instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Float64(typed_value)); + }, + _=>unimplemented!(), + } + Ok(()) + }) + ); + } +} + +impl<'lua> mlua::FromLua<'lua> for Instance{ + fn from_lua(value:mlua::prelude::LuaValue<'lua>,_lua:&'lua mlua::prelude::Lua)->mlua::prelude::LuaResult{ + match value{ + mlua::Value::UserData(ud)=>ud.take(), + other=>Err(mlua::Error::runtime(format!("Expected Instance got {:?}",other))), + } + } +} diff --git a/src/runner/mod.rs b/src/runner/mod.rs index 905b778..a00b1cf 100644 --- a/src/runner/mod.rs +++ b/src/runner/mod.rs @@ -2,5 +2,6 @@ mod runner; mod cframe; mod vector3; +mod instance; pub use runner::Runner; diff --git a/src/runner/runner.rs b/src/runner/runner.rs index 4297b71..0d68d5e 100644 --- a/src/runner/runner.rs +++ b/src/runner/runner.rs @@ -1,9 +1,28 @@ +use crate::context::Context; + use super::vector3::Vector3; use super::cframe::CFrame; pub struct Runner{ lua:mlua::Lua, } +#[derive(Debug)] +pub enum Error{ + Lua(mlua::Error), + Script(crate::script::Error), + /// If the lua.remove_app_data function fails + RemoveAppData, +} +impl Error{ + pub fn print(self){ + match self{ + Self::Lua(mlua::Error::RuntimeError(s))=>{ + println!("lua error: {s}"); + }, + other=>println!("{:?}",other), + } + } +} fn init(lua:&mlua::Lua)->mlua::Result<()>{ lua.sandbox(true)?; @@ -57,20 +76,19 @@ impl Runner{ init(&runner.lua)?; Ok(runner) } - pub fn set_script(&self,script:rbx_dom_weak::types::Ref,name:String)->mlua::Result<()>{ - //TODO: Instance type - let script_table=self.lua.create_table()?; - //script.Name - script_table.raw_set("Name",name)?; - self.lua.globals().set("script",script_table)?; - Ok(()) - } - pub fn run(&self,source:String,context:&mut crate::context::Context)->mlua::Result<()>{ - //Set up dom access here? - let script:mlua::Table<'_>=self.lua.globals().raw_get("script")?; - let name:String=script.raw_get("Name")?; - self.lua.load(source) - .set_name(name) - .exec() + pub fn run_script(&self,script:crate::script::Script,context:Context)->(Context,Result<(),Error>){ + let yoink=script.name_source(&context); + self.lua.set_app_data(context.dom); + let r=(||{ + let (name,source)=yoink.map_err(Error::Script)?; + self.lua.globals().set("script",super::instance::Instance::from(script)).map_err(Error::Lua)?; + self.lua.load(source) + .set_name(name) + .exec().map_err(Error::Lua)?; + Ok(()) + })(); + let dom=self.lua.remove_app_data() + .expect("Fatal: Lua lost the dom"); + (Context::new(dom),r) } } diff --git a/src/script.rs b/src/script.rs index f2cb1a7..8a81941 100644 --- a/src/script.rs +++ b/src/script.rs @@ -1,21 +1,12 @@ use rbx_dom_weak::types::Ref; +use crate::context::Context; + #[derive(Debug)] pub enum Error{ - Runner(mlua::Error), NoScript, NoSource, } -impl Error{ - pub fn print(self){ - match self{ - Self::Runner(mlua::Error::RuntimeError(s))=>{ - println!("lua error: {s}"); - }, - other=>println!("{:?}",other), - } - } -} fn get_full_name(dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance)->String{ let mut full_name=instance.name.clone(); @@ -29,25 +20,18 @@ fn get_full_name(dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance)->S } pub struct Script{ - script:Ref, + pub(crate)script:Ref, } impl Script{ pub const fn new(script:Ref)->Self{ Self{script} } - pub fn run(&self,context:&mut crate::context::Context)->Result<(),Error>{ - // grab source - let (source,full_name)={ - let instance=context.dom.get_by_ref(self.script).ok_or(Error::NoScript)?; - let source=match instance.properties.get("Source").ok_or(Error::NoSource)?{ - rbx_dom_weak::types::Variant::String(s)=>s.clone(), - _=>Err(Error::NoSource)?, - }; - (source,get_full_name(&context.dom,instance)) + pub fn name_source(&self,context:&Context)->Result<(String,String),Error>{ + let instance=context.dom.get_by_ref(self.script).ok_or(Error::NoScript)?; + let source=match instance.properties.get("Source").ok_or(Error::NoSource)?{ + rbx_dom_weak::types::Variant::String(s)=>s.clone(), + _=>Err(Error::NoSource)?, }; - // run it lole - let runner=crate::runner::Runner::new().map_err(Error::Runner)?; - runner.set_script(self.script,full_name).map_err(Error::Runner)?; - runner.run(source,context).map_err(Error::Runner) + Ok((get_full_name(&context.dom,instance),source)) } }