roblox_emulator: refactor nil instances
This commit is contained in:
parent
8bfc201d1f
commit
3d399635d7
lib/roblox_emulator/src
@ -13,24 +13,15 @@ pub enum ServicesError{
|
||||
pub struct Services{
|
||||
pub(crate) game:Ref,
|
||||
pub(crate) workspace:Ref,
|
||||
pub(crate) nil:Ref,
|
||||
}
|
||||
|
||||
impl Services{
|
||||
fn get_or_create_services(dom:&mut WeakDom)->Result<Services,ServicesError>{
|
||||
let game=dom.root_ref();
|
||||
// error if workspace does not exist
|
||||
let workspace=*dom.root().children().iter().find(|&&r|
|
||||
dom.get_by_ref(r).is_some_and(|instance|instance.class=="Workspace")
|
||||
).ok_or(ServicesError::WorkspaceNotFound)?;
|
||||
// the root nil instance does not have a parent
|
||||
let nil=dom.insert(Ref::none(),InstanceBuilder::new("Nil")
|
||||
.with_referent(<Ref as std::str::FromStr>::from_str("ffffffffffffffffffffffffffffffff").unwrap())
|
||||
);
|
||||
fn find_services(dom:&WeakDom)->Result<Services,ServicesError>{
|
||||
Ok(Services{
|
||||
game,
|
||||
workspace,
|
||||
nil,
|
||||
workspace:*dom.root().children().iter().find(|&&r|
|
||||
dom.get_by_ref(r).is_some_and(|instance|instance.class=="Workspace")
|
||||
).ok_or(ServicesError::WorkspaceNotFound)?,
|
||||
game:dom.root_ref(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -42,8 +33,8 @@ pub struct Context{
|
||||
}
|
||||
|
||||
impl Context{
|
||||
pub fn from_place(mut dom:WeakDom)->Result<Context,ServicesError>{
|
||||
let services=Services::get_or_create_services(&mut dom)?;
|
||||
pub fn from_place(dom:WeakDom)->Result<Context,ServicesError>{
|
||||
let services=Services::find_services(&dom)?;
|
||||
Ok(Self{dom,services})
|
||||
}
|
||||
pub fn script_singleton(source:String)->(Context,crate::runner::instance::Instance){
|
||||
@ -106,15 +97,9 @@ impl Context{
|
||||
game.properties.insert(static_ustr("workspace"),rbx_types::Variant::Ref(workspace));
|
||||
game.properties.insert(static_ustr("Workspace"),rbx_types::Variant::Ref(workspace));
|
||||
}
|
||||
|
||||
dom.insert(game,InstanceBuilder::new("Lighting"));
|
||||
|
||||
// the root nil instance does not have a parent
|
||||
let nil=dom.insert(Ref::none(),InstanceBuilder::new("Nil")
|
||||
.with_referent(<Ref as std::str::FromStr>::from_str("ffffffffffffffffffffffffffffffff").unwrap())
|
||||
);
|
||||
|
||||
let services=Services{game,workspace,nil};
|
||||
let services=Services{game,workspace};
|
||||
Self{dom,services}
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
|
||||
table.raw_set("new",
|
||||
lua.create_function(|lua,(class_name,parent):(mlua::String,Option<Instance>)|{
|
||||
let class_name_str=&*class_name.to_str()?;
|
||||
let parent=parent.unwrap_or(Instance::nil());
|
||||
let parent_ref=parent.map_or(Ref::none(),|instance|instance.referent);
|
||||
dom_mut(lua,|dom|{
|
||||
Ok(Instance::new_unchecked(dom.insert(parent.referent,InstanceBuilder::new(class_name_str))))
|
||||
Ok(Instance::new_unchecked(dom.insert(parent_ref,InstanceBuilder::new(class_name_str))))
|
||||
})
|
||||
})?
|
||||
)?;
|
||||
@ -107,16 +107,7 @@ impl Instance{
|
||||
Self{referent}
|
||||
}
|
||||
pub fn new(referent:Ref)->Option<Self>{
|
||||
match referent=="ffffffffffffffffffffffffffffffff".parse().unwrap(){
|
||||
true=>None,
|
||||
false=>Some(Self{referent})
|
||||
}
|
||||
}
|
||||
// Using a sentinel value as a ref for nil instances because global variables are hard.
|
||||
pub fn nil()->Self{
|
||||
Self{
|
||||
referent:"ffffffffffffffffffffffffffffffff".parse().unwrap()
|
||||
}
|
||||
referent.is_some().then_some(Self{referent})
|
||||
}
|
||||
pub fn get<'a>(&self,dom:&'a WeakDom)->mlua::Result<&'a rbx_dom_weak::Instance>{
|
||||
dom.get_by_ref(self.referent).ok_or_else(||mlua::Error::runtime("Instance missing"))
|
||||
@ -137,10 +128,10 @@ impl mlua::UserData for Instance{
|
||||
}
|
||||
fields.add_field_method_get("parent",get_parent);
|
||||
fields.add_field_method_get("Parent",get_parent);
|
||||
fn set_parent(lua:&mlua::Lua,this:&mut Instance,val:Option<Instance>)->mlua::Result<()>{
|
||||
let parent=val.unwrap_or(Instance::nil());
|
||||
fn set_parent(lua:&mlua::Lua,this:&mut Instance,new_parent:Option<Instance>)->mlua::Result<()>{
|
||||
let parent_ref=new_parent.map_or(Ref::none(),|instance|instance.referent);
|
||||
dom_mut(lua,|dom|{
|
||||
dom.transfer_within(this.referent,parent.referent);
|
||||
dom.transfer_within(this.referent,parent_ref);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@ -171,7 +162,6 @@ impl mlua::UserData for Instance{
|
||||
fn clone(lua:&mlua::Lua,this:&Instance,_:())->mlua::Result<Instance>{
|
||||
dom_mut(lua,|dom|{
|
||||
let instance_ref=dom.clone_within(this.referent);
|
||||
dom.transfer_within(instance_ref,Instance::nil().referent);
|
||||
Ok(Instance::new_unchecked(instance_ref))
|
||||
})
|
||||
}
|
||||
@ -271,7 +261,7 @@ impl mlua::UserData for Instance{
|
||||
methods.add_method("IsA",is_a);
|
||||
methods.add_method("Destroy",|lua,this,()|
|
||||
dom_mut(lua,|dom|{
|
||||
dom.transfer_within(this.referent,Instance::nil().referent);
|
||||
dom.transfer_within(this.referent,Ref::none());
|
||||
Ok(())
|
||||
})
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user