From cb5b842276f9f147d24d4c4bde16e2e3e71d2e15 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 4 Oct 2024 18:43:11 -0700 Subject: [PATCH] fix Instance.__newindex + implement String --- src/runner/instance.rs | 56 +++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/src/runner/instance.rs b/src/runner/instance.rs index 213aa91..3e79efd 100644 --- a/src/runner/instance.rs +++ b/src/runner/instance.rs @@ -87,6 +87,24 @@ macro_rules! class_composition{ }; } +//TODO: update rbx_reflection and use dom.superclasses_iter +pub struct SuperClassIter<'a> { + database: &'a rbx_reflection::ReflectionDatabase<'a>, + descriptor: Option<&'a rbx_reflection::ClassDescriptor<'a>>, +} +impl<'a> SuperClassIter<'a> { + fn next_descriptor(&self) -> Option<&'a rbx_reflection::ClassDescriptor<'a>> { + let superclass = self.descriptor?.superclass.as_ref()?; + self.database.classes.get(superclass) + } +} +impl<'a> Iterator for SuperClassIter<'a> { + type Item = &'a rbx_reflection::ClassDescriptor<'a>; + fn next(&mut self) -> Option { + let next_descriptor = self.next_descriptor(); + std::mem::replace(&mut self.descriptor, next_descriptor) + } +} class!(Instance); class_composition!(Instance,(Instance)); @@ -183,28 +201,48 @@ impl Instance{ let index_str=index.to_str()?; let db=rbx_reflection_database::get(); let class=db.classes.get(instance.class.as_str()).ok_or(mlua::Error::runtime("Class missing"))?; - let property=db.find_default_property(class,index_str).ok_or(mlua::Error::runtime(format!("Property '{index_str}' missing on class '{}'",class.name)))?; - match property{ - rbx_types::Variant::Vector3(_)=>{ + let mut iter=SuperClassIter{ + database:db, + descriptor:Some(class), + }; + let property=iter.find_map(|cls|cls.properties.get(index_str)).ok_or(mlua::Error::runtime(format!("Property '{index_str}' missing on class '{}'",class.name)))?; + match &property.data_type{ + rbx_reflection::DataType::Value(rbx_types::VariantType::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::Float32(_)=>{ + rbx_reflection::DataType::Value(rbx_types::VariantType::Float32)=>{ let typed_value:f32=coerce_float32(&value).ok_or(mlua::Error::runtime("Expected f32"))?; instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Float32(typed_value)); }, - rbx_types::Variant::Enum(_)=>{ - let typed_value:super::r#enum::Enum=value.as_userdata().ok_or(mlua::Error::runtime("Expected Enum"))?.take()?; - instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Enum(typed_value.into())); + rbx_reflection::DataType::Enum(enum_name)=>{ + let typed_value=match &value{ + &mlua::Value::Integer(int)=>Ok(rbx_types::Enum::from_u32(int as u32)), + &mlua::Value::Number(num)=>Ok(rbx_types::Enum::from_u32(num as u32)), + mlua::Value::String(s)=>{ + let e=db.enums.get(enum_name).ok_or(mlua::Error::runtime("Database DataType Enum name does not exist"))?; + Ok(rbx_types::Enum::from_u32(*e.items.get(s.to_str()?).ok_or(mlua::Error::runtime("Invalid enum item"))?)) + }, + mlua::Value::UserData(any_user_data)=>{ + let e:super::r#enum::Enum=any_user_data.take()?; + Ok(e.into()) + }, + _=>Err(mlua::Error::runtime("Expected Enum")), + }?; + instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Enum(typed_value)); }, - rbx_types::Variant::Color3(_)=>{ + rbx_reflection::DataType::Value(rbx_types::VariantType::Color3)=>{ let typed_value:super::color3::Color3=value.as_userdata().ok_or(mlua::Error::runtime("Expected Color3"))?.take()?; instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Color3(typed_value.into())); }, - rbx_types::Variant::Bool(_)=>{ + rbx_reflection::DataType::Value(rbx_types::VariantType::Bool)=>{ let typed_value=value.as_boolean().ok_or(mlua::Error::runtime("Expected boolean"))?; instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Bool(typed_value)); }, + rbx_reflection::DataType::Value(rbx_types::VariantType::String)=>{ + let typed_value=value.as_str().ok_or(mlua::Error::runtime("Expected boolean"))?; + instance.properties.insert(index_str.to_owned(),rbx_types::Variant::String(typed_value.to_owned())); + }, other=>return Err(mlua::Error::runtime(format!("Unimplemented property type: {other:?}"))), } Ok(())