Compare commits

...

5 Commits

6 changed files with 104 additions and 19 deletions

View File

@ -47,12 +47,8 @@ impl Context{
} }
pub fn find_services(&self)->Option<Services>{ pub fn find_services(&self)->Option<Services>{
Some(Services{ //nil instances isn't real, it doesn't exist in real roblox places
workspace:*self.dom.root().children().iter().find(|&&r| None
self.dom.get_by_ref(r).is_some_and(|instance|instance.class=="Workspace")
)?,
game:self.dom.root_ref(),
})
} }
pub fn convert_into_place(&mut self)->Services{ pub fn convert_into_place(&mut self)->Services{
//snapshot root instances //snapshot root instances
@ -74,6 +70,15 @@ impl Context{
game.properties.insert("Workspace".to_owned(),rbx_types::Variant::Ref(workspace)); game.properties.insert("Workspace".to_owned(),rbx_types::Variant::Ref(workspace));
} }
self.dom.insert(game,InstanceBuilder::new("Lighting")); self.dom.insert(game,InstanceBuilder::new("Lighting"));
// Special nonexistent class that holds instances parented to nil,
// which can still be referenced by scripts.
// Using a sentinel value as a ref because global variables are hard.
let nil=self.dom.insert(
game,InstanceBuilder::new("Nil")
.with_referent(
<Ref as std::str::FromStr>::from_str("ffffffffffffffffffffffffffffffff").unwrap()
)
);
//transfer original root instances into workspace //transfer original root instances into workspace
for instance in children{ for instance in children{
@ -83,6 +88,7 @@ impl Context{
Services{ Services{
game, game,
workspace, workspace,
nil,
} }
} }
} }
@ -90,4 +96,5 @@ impl Context{
pub struct Services{ pub struct Services{
pub game:Ref, pub game:Ref,
pub workspace:Ref, pub workspace:Ref,
pub nil:Ref,
} }

View File

@ -0,0 +1,31 @@
#[derive(Clone,Copy)]
pub struct ColorSequence{}
impl ColorSequence{
pub const fn new()->Self{
Self{}
}
}
impl Into<rbx_types::ColorSequence> for ColorSequence{
fn into(self)->rbx_types::ColorSequence{
rbx_types::ColorSequence{
keypoints:Vec::new()
}
}
}
pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
let number_sequence_table=lua.create_table()?;
number_sequence_table.raw_set("new",
lua.create_function(|_,_:mlua::MultiValue|
Ok(ColorSequence::new())
)?
)?;
globals.set("ColorSequence",number_sequence_table)?;
Ok(())
}
impl mlua::UserData for ColorSequence{}
type_from_lua_userdata!(ColorSequence);

View File

@ -16,9 +16,8 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
instance_table.raw_set("new", instance_table.raw_set("new",
lua.create_function(|lua,(class_name,parent):(mlua::String,Option<Instance>)|{ lua.create_function(|lua,(class_name,parent):(mlua::String,Option<Instance>)|{
let class_name_str=&*class_name.to_str()?; let class_name_str=&*class_name.to_str()?;
let parent=parent.ok_or(mlua::Error::runtime("Nil Parent not yet supported"))?; let parent=parent.unwrap_or(Instance::nil());
dom_mut(lua,|dom|{ dom_mut(lua,|dom|{
//TODO: Nil instances
Ok(Instance::new(dom.insert(parent.referent,InstanceBuilder::new(class_name_str)))) Ok(Instance::new(dom.insert(parent.referent,InstanceBuilder::new(class_name_str))))
}) })
})? })?
@ -91,6 +90,12 @@ impl Instance{
pub const fn new(referent:Ref)->Self{ pub const fn new(referent:Ref)->Self{
Self{referent} Self{referent}
} }
// Using a sentinel value as a ref for nil instances because global variables are hard.
pub fn nil()->Self{
Self{
referent:<Ref as std::str::FromStr>::from_str("ffffffffffffffffffffffffffffffff").unwrap()
}
}
pub fn get<'a>(&self,dom:&'a WeakDom)->mlua::Result<&'a rbx_dom_weak::Instance>{ pub fn get<'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")) dom.get_by_ref(self.referent).ok_or(mlua::Error::runtime("Instance missing"))
} }
@ -124,11 +129,12 @@ impl mlua::UserData for Instance{
fields.add_field_method_get("Parent",|lua,this|{ fields.add_field_method_get("Parent",|lua,this|{
dom_mut(lua,|dom|{ dom_mut(lua,|dom|{
let instance=this.get(dom)?; let instance=this.get(dom)?;
//TODO: return nil when parent is Nil instances
Ok(Instance::new(instance.parent())) Ok(Instance::new(instance.parent()))
}) })
}); });
fields.add_field_method_set("Parent",|lua,this,val:Option<Instance>|{ fields.add_field_method_set("Parent",|lua,this,val:Option<Instance>|{
let parent=val.ok_or(mlua::Error::runtime("Nil Parent not yet supported"))?; let parent=val.unwrap_or(Instance::nil());
dom_mut(lua,|dom|{ dom_mut(lua,|dom|{
dom.transfer_within(this.referent,parent.referent); dom.transfer_within(this.referent,parent.referent);
Ok(()) Ok(())
@ -218,7 +224,7 @@ impl mlua::UserData for Instance{
); );
methods.add_method("Destroy",|lua,this,()| methods.add_method("Destroy",|lua,this,()|
dom_mut(lua,|dom|{ dom_mut(lua,|dom|{
dom.destroy(this.referent); dom.transfer_within(this.referent,Instance::nil().referent);
Ok(()) Ok(())
}) })
); );
@ -267,12 +273,10 @@ impl mlua::UserData for Instance{
database:db, database:db,
descriptor:Some(class), descriptor:Some(class),
}; };
iter.find_map(|class| iter.find_map(|class|{
cf.get_or_create_class_methods(&class.name) let mut class_methods=cf.get_or_create_class_methods(&class.name)?;
.and_then(|mut class_methods|
class_methods.get_or_create_function(lua,index_str).transpose() class_methods.get_or_create_function(lua,index_str).transpose()
) }).transpose()
).transpose()
})?{ })?{
return function.into_lua(lua); return function.into_lua(lua);
} }
@ -296,7 +300,7 @@ impl mlua::UserData for Instance{
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)))?; 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{ match &property.data_type{
rbx_reflection::DataType::Value(rbx_types::VariantType::Vector3)=>{ rbx_reflection::DataType::Value(rbx_types::VariantType::Vector3)=>{
let typed_value:Vector3=value.as_userdata().ok_or(mlua::Error::runtime("Expected Userdata"))?.take()?; let typed_value:Vector3=*value.as_userdata().ok_or(mlua::Error::runtime("Expected Userdata"))?.borrow()?;
instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Vector3(typed_value.into())); instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Vector3(typed_value.into()));
}, },
rbx_reflection::DataType::Value(rbx_types::VariantType::Float32)=>{ rbx_reflection::DataType::Value(rbx_types::VariantType::Float32)=>{
@ -312,7 +316,7 @@ impl mlua::UserData for Instance{
Ok(rbx_types::Enum::from_u32(*e.items.get(&*s.to_str()?).ok_or(mlua::Error::runtime("Invalid enum item"))?)) 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)=>{ mlua::Value::UserData(any_user_data)=>{
let e:super::r#enum::Enum=any_user_data.take()?; let e:super::r#enum::Enum=*any_user_data.borrow()?;
Ok(e.into()) Ok(e.into())
}, },
_=>Err(mlua::Error::runtime("Expected Enum")), _=>Err(mlua::Error::runtime("Expected Enum")),
@ -320,7 +324,7 @@ impl mlua::UserData for Instance{
instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Enum(typed_value)); instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Enum(typed_value));
}, },
rbx_reflection::DataType::Value(rbx_types::VariantType::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()?; let typed_value:super::color3::Color3=*value.as_userdata().ok_or(mlua::Error::runtime("Expected Color3"))?.borrow()?;
instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Color3(typed_value.into())); instance.properties.insert(index_str.to_owned(),rbx_types::Variant::Color3(typed_value.into()));
}, },
rbx_reflection::DataType::Value(rbx_types::VariantType::Bool)=>{ rbx_reflection::DataType::Value(rbx_types::VariantType::Bool)=>{
@ -331,6 +335,14 @@ impl mlua::UserData for Instance{
let typed_value=value.as_str().ok_or(mlua::Error::runtime("Expected boolean"))?; 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())); instance.properties.insert(index_str.to_owned(),rbx_types::Variant::String(typed_value.to_owned()));
}, },
rbx_reflection::DataType::Value(rbx_types::VariantType::NumberSequence)=>{
let typed_value:super::number_sequence::NumberSequence=*value.as_userdata().ok_or(mlua::Error::runtime("Expected NumberSequence"))?.borrow()?;
instance.properties.insert(index_str.to_owned(),rbx_types::Variant::NumberSequence(typed_value.into()));
},
rbx_reflection::DataType::Value(rbx_types::VariantType::ColorSequence)=>{
let typed_value:super::color_sequence::ColorSequence=*value.as_userdata().ok_or(mlua::Error::runtime("Expected ColorSequence"))?.borrow()?;
instance.properties.insert(index_str.to_owned(),rbx_types::Variant::ColorSequence(typed_value.into()));
},
other=>return Err(mlua::Error::runtime(format!("Unimplemented property type: {other:?}"))), other=>return Err(mlua::Error::runtime(format!("Unimplemented property type: {other:?}"))),
} }
Ok(()) Ok(())

View File

@ -7,5 +7,7 @@ mod color3;
mod cframe; mod cframe;
mod vector3; mod vector3;
pub mod instance; pub mod instance;
mod number_sequence;
mod color_sequence;
pub use runner::{Runner,Error}; pub use runner::{Runner,Error};

View File

@ -0,0 +1,31 @@
#[derive(Clone,Copy)]
pub struct NumberSequence{}
impl NumberSequence{
pub const fn new()->Self{
Self{}
}
}
impl Into<rbx_types::NumberSequence> for NumberSequence{
fn into(self)->rbx_types::NumberSequence{
rbx_types::NumberSequence{
keypoints:Vec::new()
}
}
}
pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
let number_sequence_table=lua.create_table()?;
number_sequence_table.raw_set("new",
lua.create_function(|_,_:mlua::MultiValue|
Ok(NumberSequence::new())
)?
)?;
globals.set("NumberSequence",number_sequence_table)?;
Ok(())
}
impl mlua::UserData for NumberSequence{}
type_from_lua_userdata!(NumberSequence);

View File

@ -34,6 +34,8 @@ fn init(lua:&mlua::Lua)->mlua::Result<()>{
super::vector3::set_globals(lua,&globals)?; super::vector3::set_globals(lua,&globals)?;
super::cframe::set_globals(lua,&globals)?; super::cframe::set_globals(lua,&globals)?;
super::instance::set_globals(lua,&globals)?; super::instance::set_globals(lua,&globals)?;
super::number_sequence::set_globals(lua,&globals)?;
super::color_sequence::set_globals(lua,&globals)?;
Ok(()) Ok(())
} }