diff --git a/src/runner/instance.rs b/src/runner/instance.rs index 8ce90b8..e0604b7 100644 --- a/src/runner/instance.rs +++ b/src/runner/instance.rs @@ -237,16 +237,27 @@ impl mlua::UserData for Instance{ let class=db.classes.get(instance.class.as_str()).ok_or(mlua::Error::runtime("Class missing"))?; //Find existing property match instance.properties.get(index_str) + .cloned() //Find default value - .or_else(||db.find_default_property(class,index_str)) + .or_else(||db.find_default_property(class,index_str).cloned()) + //Find virtual property + .or_else(||{ + SuperClassIter{ + database:db, + descriptor:Some(class), + } + .find_map(|class| + find_virtual_property(&instance.properties,class,index_str) + ) + }) { - Some(&rbx_types::Variant::Int32(val))=>return val.into_lua(lua), - Some(&rbx_types::Variant::Int64(val))=>return val.into_lua(lua), - Some(&rbx_types::Variant::Float32(val))=>return val.into_lua(lua), - Some(&rbx_types::Variant::Float64(val))=>return val.into_lua(lua), - Some(&rbx_types::Variant::Ref(val))=>return Instance::new(val).into_lua(lua), - Some(&rbx_types::Variant::CFrame(cf))=>return Into::::into(cf).into_lua(lua), - Some(&rbx_types::Variant::Vector3(v))=>return Into::::into(v).into_lua(lua), + Some(rbx_types::Variant::Int32(val))=>return val.into_lua(lua), + Some(rbx_types::Variant::Int64(val))=>return val.into_lua(lua), + Some(rbx_types::Variant::Float32(val))=>return val.into_lua(lua), + Some(rbx_types::Variant::Float64(val))=>return val.into_lua(lua), + Some(rbx_types::Variant::Ref(val))=>return Instance::new(val).into_lua(lua), + Some(rbx_types::Variant::CFrame(cf))=>return Into::::into(cf).into_lua(lua), + Some(rbx_types::Variant::Vector3(v))=>return Into::::into(v).into_lua(lua), None=>(), other=>return Err(mlua::Error::runtime(format!("Instance.__index Unsupported property type instance={} index={index_str} value={other:?}",instance.name))), } @@ -415,3 +426,42 @@ impl ClassMethods<'_>{ }) } } + +/// A virtual property pointer definition shorthand. +type VirtualPropertyFunctionPointer=fn(&rbx_types::Variant)->Option; +const fn vpp( + property:&'static str, + pointer:VirtualPropertyFunctionPointer, +)->VirtualProperty{ + VirtualProperty{ + property, + pointer, + } +} +struct VirtualProperty{ + property:&'static str,// Source property name + pointer:VirtualPropertyFunctionPointer, +} +type VPD=phf::Map<&'static str,// Class name + phf::Map<&'static str,// Virtual property name + VirtualProperty + > +>; +static VIRTUAL_PROPERTY_DATABASE:VPD=phf::phf_map!{ + "BasePart"=>phf::phf_map!{ + "Position"=>vpp("CFrame",|c:&rbx_types::Variant|{ + let c=match c{ + rbx_types::Variant::CFrame(c)=>c, + _=>return None,//fail silently and ungracefully + }; + Some(rbx_types::Variant::Vector3(c.position)) + }), + }, +}; + +fn find_virtual_property(properties:&HashMap,class:&rbx_reflection::ClassDescriptor,index:&str)->Option{ + let class_virtual_properties=VIRTUAL_PROPERTY_DATABASE.get(&class.name)?; + let vp=class_virtual_properties.get(index)?; + let variant=properties.get(vp.property)?; + (vp.pointer)(variant) +}