diff --git a/src/context.rs b/src/context.rs index 4ca6f66..6f8c8f0 100644 --- a/src/context.rs +++ b/src/context.rs @@ -28,7 +28,7 @@ impl Context{ class_is_a(instance.class.as_ref(),superclass) ).map(|instance|instance.referent()) } - pub fn scripts(&self)->Vec{ - self.superclass_iter("LuaSourceContainer").map(crate::script::Script::new).collect() + pub fn scripts(&self)->Vec{ + self.superclass_iter("LuaSourceContainer").map(crate::runner::instance::Script::new).collect() } } diff --git a/src/lib.rs b/src/lib.rs index 8c34547..f93d8c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,5 @@ -pub mod script; pub mod context; - pub mod runner; -pub type Result=core::result::Result; - #[cfg(test)] mod tests; diff --git a/src/runner/instance.rs b/src/runner/instance.rs index 45484d7..ac5aa6d 100644 --- a/src/runner/instance.rs +++ b/src/runner/instance.rs @@ -17,6 +17,17 @@ fn coerce_float32(value:&mlua::Value)->Option{ } } +fn get_full_name(dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance)->String{ + let mut full_name=instance.name.clone(); + let mut pref=instance.parent(); + while let Some(parent)=dom.get_by_ref(pref){ + full_name.insert(0,'.'); + full_name.insert_str(0,parent.name.as_str()); + pref=parent.parent(); + } + full_name +} + trait Referent{ fn referent(&self)->Ref; fn get<'a>(&self,dom:&'a WeakDom)->mlua::Result<&'a rbx_dom_weak::Instance>{ @@ -27,26 +38,54 @@ trait Referent{ } } -pub struct Instance{ - referent:Ref, +macro_rules! class{ + ($class:ident)=>{ + pub struct $class{ + referent:Ref, + } + impl $class{ + pub const fn new(referent:Ref)->Self{ + Self{referent} + } + } + impl Referent for $class{ + fn referent(&self)->Ref{ + self.referent + } + } + impl<'lua> mlua::FromLua<'lua> for $class{ + fn from_lua(value:mlua::Value<'lua>,_lua:&'lua mlua::Lua)->mlua::Result{ + match value{ + mlua::Value::UserData(ud)=>ud.take(), + other=>Err(mlua::Error::runtime(format!("Expected {} got {:?}",stringify!($class),other))), + } + } + } + }; } -impl Referent for Instance{ - fn referent(&self)->Ref{ - self.referent - } +macro_rules! class_composition{ + ($class:ident,($($superclass:ident),*))=>{ + impl mlua::UserData for $class{ + fn add_fields<'lua,F:mlua::UserDataFields<'lua,Self>>(fields:&mut F){ + $( + $superclass::composition_add_fields(fields); + )* + } + fn add_methods<'lua,M:mlua::UserDataMethods<'lua,Self>>(methods:&mut M){ + $( + $superclass::composition_add_methods(methods); + )* + } + } + }; } -impl From for Instance{ - fn from(value:crate::script::Script)->Self{ - Self{referent:value.script} - } -} + +class!(Instance); +class_composition!(Instance,(Instance)); impl Instance{ - pub const fn new(referent:Ref)->Self{ - Self{referent} - } - fn add_fields<'lua,T:Referent,F:mlua::UserDataFields<'lua,T>>(fields:&mut F){ + fn composition_add_fields<'lua,T:Referent,F:mlua::UserDataFields<'lua,T>>(fields:&mut F){ fields.add_field_method_get("Parent",|lua,this|{ dom(lua,|dom|{ let instance=this.get(dom)?; @@ -74,8 +113,7 @@ impl Instance{ }) }); } - - fn add_methods<'lua,T:Referent,M:mlua::UserDataMethods<'lua,T>>(methods:&mut M){ + fn composition_add_methods<'lua,T:Referent,M:mlua::UserDataMethods<'lua,T>>(methods:&mut M){ methods.add_method("GetChildren",|lua,this,_:()| dom(lua,|dom|{ let instance=this.get(dom)?; @@ -129,33 +167,13 @@ impl Instance{ ); } } -impl mlua::UserData for Instance{ - fn add_fields<'lua,F:mlua::UserDataFields<'lua,Self>>(fields:&mut F){ - Instance::add_fields(fields); - } - fn add_methods<'lua,M:mlua::UserDataMethods<'lua,Self>>(methods:&mut M){ - Instance::add_methods(methods); - } -} -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))), - } - } -} -pub struct DataModel{ - referent:Ref, -} -impl Referent for DataModel{ - fn referent(&self)->Ref{ - self.referent - } -} +class!(DataModel); +class_composition!(DataModel,(Instance,DataModel)); impl DataModel{ - fn add_methods<'lua,T,M:mlua::UserDataMethods<'lua,T>>(methods:&mut M){ + fn composition_add_fields<'lua,T:Referent,F:mlua::UserDataFields<'lua,T>>(fields:&mut F){ + } + fn composition_add_methods<'lua,T,M:mlua::UserDataMethods<'lua,T>>(methods:&mut M){ methods.add_method("GetService",|lua,this,service:String| dom(lua,|dom|{ match service.as_str(){ @@ -166,30 +184,25 @@ impl DataModel{ ); } } -impl mlua::UserData for DataModel{ - fn add_fields<'lua,F:mlua::UserDataFields<'lua,Self>>(fields:&mut F){ - Instance::add_fields(fields); - //DataModel::add_fields(fields); - } - fn add_methods<'lua,M:mlua::UserDataMethods<'lua,Self>>(methods:&mut M){ - Instance::add_methods(methods); - DataModel::add_methods(methods); - } + +class!(Lighting); +class_composition!(Lighting,(Instance)); + +#[derive(Debug)] +pub enum GetScriptError{ + NoScript, + NoSource, } -pub struct Lighting{ - referent:Ref, -} -impl Referent for Lighting{ - fn referent(&self)->Ref{ - self.referent - } -} -impl mlua::UserData for Lighting{ - fn add_fields<'lua,F:mlua::UserDataFields<'lua,Self>>(fields:&mut F){ - Instance::add_fields(fields); - } - fn add_methods<'lua,M:mlua::UserDataMethods<'lua,Self>>(methods:&mut M){ - Instance::add_methods(methods); +class!(Script); +class_composition!(Script,(Instance)); +impl Script{ + pub fn get_name_source(&self,context:&crate::context::Context)->Result<(String,String),GetScriptError>{ + let instance=context.dom.get_by_ref(self.referent).ok_or(GetScriptError::NoScript)?; + let source=match instance.properties.get("Source").ok_or(GetScriptError::NoSource)?{ + rbx_dom_weak::types::Variant::String(s)=>s.clone(), + _=>Err(GetScriptError::NoSource)?, + }; + Ok((get_full_name(&context.dom,instance),source)) } } diff --git a/src/runner/mod.rs b/src/runner/mod.rs index a00b1cf..f27d117 100644 --- a/src/runner/mod.rs +++ b/src/runner/mod.rs @@ -2,6 +2,6 @@ mod runner; mod cframe; mod vector3; -mod instance; +pub mod instance; pub use runner::Runner; diff --git a/src/runner/runner.rs b/src/runner/runner.rs index 62a7928..d10c4ab 100644 --- a/src/runner/runner.rs +++ b/src/runner/runner.rs @@ -12,7 +12,7 @@ pub enum Error{ source:String, error:mlua::Error }, - Script(crate::script::Error), + Script(super::instance::GetScriptError), /// If the lua.remove_app_data function fails RemoveAppData, } @@ -79,9 +79,9 @@ impl Runner{ init(&runner.lua)?; Ok(runner) } - pub fn run_script(&self,script:crate::script::Script,context:&mut Context)->Result<(),Error>{ - let (name,source)=script.name_source(context).map_err(Error::Script)?; - self.lua.globals().set("script",super::instance::Instance::from(script)).map_err(|error|Error::Lua{source:source.clone(),error})?; + pub fn run_script(&self,script:super::instance::Script,context:&mut Context)->Result<(),Error>{ + let (name,source)=script.get_name_source(context).map_err(Error::Script)?; + self.lua.globals().set("script",script).map_err(|error|Error::Lua{source:source.clone(),error})?; //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)}); let r=self.lua.load(source.as_str()) diff --git a/src/script.rs b/src/script.rs deleted file mode 100644 index 8a81941..0000000 --- a/src/script.rs +++ /dev/null @@ -1,37 +0,0 @@ -use rbx_dom_weak::types::Ref; - -use crate::context::Context; - -#[derive(Debug)] -pub enum Error{ - NoScript, - NoSource, -} - -fn get_full_name(dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance)->String{ - let mut full_name=instance.name.clone(); - let mut pref=instance.parent(); - while let Some(parent)=dom.get_by_ref(pref){ - full_name.insert(0,'.'); - full_name.insert_str(0,parent.name.as_str()); - pref=parent.parent(); - } - full_name -} - -pub struct Script{ - pub(crate)script:Ref, -} -impl Script{ - pub const fn new(script:Ref)->Self{ - Self{script} - } - 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)?, - }; - Ok((get_full_name(&context.dom,instance),source)) - } -}