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 struct Services{
|
||||||
pub(crate) game:Ref,
|
pub(crate) game:Ref,
|
||||||
pub(crate) workspace:Ref,
|
pub(crate) workspace:Ref,
|
||||||
pub(crate) nil:Ref,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Services{
|
impl Services{
|
||||||
fn get_or_create_services(dom:&mut WeakDom)->Result<Services,ServicesError>{
|
fn find_services(dom:&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())
|
|
||||||
);
|
|
||||||
Ok(Services{
|
Ok(Services{
|
||||||
game,
|
workspace:*dom.root().children().iter().find(|&&r|
|
||||||
workspace,
|
dom.get_by_ref(r).is_some_and(|instance|instance.class=="Workspace")
|
||||||
nil,
|
).ok_or(ServicesError::WorkspaceNotFound)?,
|
||||||
|
game:dom.root_ref(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,8 +33,8 @@ pub struct Context{
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Context{
|
impl Context{
|
||||||
pub fn from_place(mut dom:WeakDom)->Result<Context,ServicesError>{
|
pub fn from_place(dom:WeakDom)->Result<Context,ServicesError>{
|
||||||
let services=Services::get_or_create_services(&mut dom)?;
|
let services=Services::find_services(&dom)?;
|
||||||
Ok(Self{dom,services})
|
Ok(Self{dom,services})
|
||||||
}
|
}
|
||||||
pub fn script_singleton(source:String)->(Context,crate::runner::instance::Instance){
|
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));
|
||||||
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"));
|
dom.insert(game,InstanceBuilder::new("Lighting"));
|
||||||
|
|
||||||
// the root nil instance does not have a parent
|
let services=Services{game,workspace};
|
||||||
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};
|
|
||||||
Self{dom,services}
|
Self{dom,services}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@ pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
|
|||||||
table.raw_set("new",
|
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.unwrap_or(Instance::nil());
|
let parent_ref=parent.map_or(Ref::none(),|instance|instance.referent);
|
||||||
dom_mut(lua,|dom|{
|
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}
|
Self{referent}
|
||||||
}
|
}
|
||||||
pub fn new(referent:Ref)->Option<Self>{
|
pub fn new(referent:Ref)->Option<Self>{
|
||||||
match referent=="ffffffffffffffffffffffffffffffff".parse().unwrap(){
|
referent.is_some().then_some(Self{referent})
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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_else(||mlua::Error::runtime("Instance missing"))
|
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);
|
||||||
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<()>{
|
fn set_parent(lua:&mlua::Lua,this:&mut Instance,new_parent:Option<Instance>)->mlua::Result<()>{
|
||||||
let parent=val.unwrap_or(Instance::nil());
|
let parent_ref=new_parent.map_or(Ref::none(),|instance|instance.referent);
|
||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
dom.transfer_within(this.referent,parent.referent);
|
dom.transfer_within(this.referent,parent_ref);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -171,7 +162,6 @@ impl mlua::UserData for Instance{
|
|||||||
fn clone(lua:&mlua::Lua,this:&Instance,_:())->mlua::Result<Instance>{
|
fn clone(lua:&mlua::Lua,this:&Instance,_:())->mlua::Result<Instance>{
|
||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
let instance_ref=dom.clone_within(this.referent);
|
let instance_ref=dom.clone_within(this.referent);
|
||||||
dom.transfer_within(instance_ref,Instance::nil().referent);
|
|
||||||
Ok(Instance::new_unchecked(instance_ref))
|
Ok(Instance::new_unchecked(instance_ref))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -271,7 +261,7 @@ impl mlua::UserData for Instance{
|
|||||||
methods.add_method("IsA",is_a);
|
methods.add_method("IsA",is_a);
|
||||||
methods.add_method("Destroy",|lua,this,()|
|
methods.add_method("Destroy",|lua,this,()|
|
||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
dom.transfer_within(this.referent,Instance::nil().referent);
|
dom.transfer_within(this.referent,Ref::none());
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user