diff --git a/src/context.rs b/src/context.rs index 92b1424..3f2541f 100644 --- a/src/context.rs +++ b/src/context.rs @@ -47,12 +47,8 @@ impl Context{ } pub fn find_services(&self)->Option{ - Some(Services{ - workspace:*self.dom.root().children().iter().find(|&&r| - self.dom.get_by_ref(r).is_some_and(|instance|instance.class=="Workspace") - )?, - game:self.dom.root_ref(), - }) + //nil instances isn't real, it doesn't exist in real roblox places + None } pub fn convert_into_place(&mut self)->Services{ //snapshot root instances @@ -74,6 +70,15 @@ impl Context{ game.properties.insert("Workspace".to_owned(),rbx_types::Variant::Ref(workspace)); } 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( + ::from_str("ffffffffffffffffffffffffffffffff").unwrap() + ) + ); //transfer original root instances into workspace for instance in children{ @@ -83,6 +88,7 @@ impl Context{ Services{ game, workspace, + nil, } } } @@ -90,4 +96,5 @@ impl Context{ pub struct Services{ pub game:Ref, pub workspace:Ref, + pub nil:Ref, } diff --git a/src/runner/instance.rs b/src/runner/instance.rs index 11b502b..6d199cc 100644 --- a/src/runner/instance.rs +++ b/src/runner/instance.rs @@ -16,9 +16,8 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{ instance_table.raw_set("new", lua.create_function(|lua,(class_name,parent):(mlua::String,Option)|{ 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|{ - //TODO: Nil instances 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{ Self{referent} } + // Using a sentinel value as a ref for nil instances because global variables are hard. + pub fn nil()->Self{ + Self{ + referent:::from_str("ffffffffffffffffffffffffffffffff").unwrap() + } + } 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")) } @@ -124,11 +129,12 @@ impl mlua::UserData for Instance{ fields.add_field_method_get("Parent",|lua,this|{ dom_mut(lua,|dom|{ let instance=this.get(dom)?; + //TODO: return nil when parent is Nil instances Ok(Instance::new(instance.parent())) }) }); fields.add_field_method_set("Parent",|lua,this,val:Option|{ - 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.transfer_within(this.referent,parent.referent); Ok(()) @@ -218,7 +224,7 @@ impl mlua::UserData for Instance{ ); methods.add_method("Destroy",|lua,this,()| dom_mut(lua,|dom|{ - dom.destroy(this.referent); + dom.transfer_within(this.referent,Instance::nil().referent); Ok(()) }) );