roblox_emulator: move services into Context

This commit is contained in:
Quaternions 2025-04-22 15:31:56 -07:00
parent 6e8da50b35
commit f0d4915fba
Signed by: Quaternions
GPG Key ID: D0DF5964F79AC131
3 changed files with 32 additions and 39 deletions
lib
rbx_loader/src
roblox_emulator/src

@ -40,21 +40,19 @@ impl AsRef<WeakDom> for Model{
pub struct Place{ pub struct Place{
context:Context, context:Context,
services:roblox_emulator::context::Services,
} }
impl Place{ impl Place{
pub fn new(dom:WeakDom)->Result<Self,roblox_emulator::context::ServicesError>{ pub fn new(dom:WeakDom)->Result<Self,roblox_emulator::context::ServicesError>{
let (context,services)=Context::from_place(dom)?; let context=Context::from_place(dom)?;
Ok(Self{ Ok(Self{
context, context,
services,
}) })
} }
pub fn run_scripts(&mut self){ pub fn run_scripts(&mut self){
let Place{context,services}=self; let Place{context}=self;
let runner=roblox_emulator::runner::Runner::new().unwrap(); let runner=roblox_emulator::runner::Runner::new().unwrap();
let scripts=context.scripts(); let scripts=context.scripts();
let runnable=runner.runnable_context_with_services(context,services).unwrap(); let runnable=runner.runnable_context(context).unwrap();
for script in scripts{ for script in scripts{
if let Err(e)=runnable.run_script(script){ if let Err(e)=runnable.run_script(script){
println!("runner error: {e}"); println!("runner error: {e}");
@ -72,10 +70,9 @@ impl AsRef<WeakDom> for Place{
} }
impl From<Model> for Place{ impl From<Model> for Place{
fn from(model:Model)->Self{ fn from(model:Model)->Self{
let (context,services)=Context::from_model(model.dom); let context=Context::from_model(model.dom);
Self{ Self{
context, context,
services,
} }
} }
} }

@ -10,19 +10,34 @@ pub enum ServicesError{
Workspace, Workspace,
} }
#[repr(transparent)] pub struct Services{
pub(crate) game:Ref,
pub(crate) workspace:Ref,
}
impl Services{
fn get_or_create_services(dom:&mut WeakDom)->Result<Services,ServicesError>{
Ok(Services{
workspace:*dom.root().children().iter().find(|&&r|
dom.get_by_ref(r).is_some_and(|instance|instance.class=="Workspace")
).ok_or(ServicesError::Workspace)?,
game:dom.root_ref(),
})
}
}
pub struct Context{ pub struct Context{
pub(crate)dom:WeakDom, pub(crate)dom:WeakDom,
pub(crate)services:Services,
} }
impl Context{ impl Context{
pub fn from_place(dom:WeakDom)->Result<(Context,Services),ServicesError>{ pub fn from_place(mut dom:WeakDom)->Result<Context,ServicesError>{
// TODO: create nil instances // TODO: create nil instances
let context=Self{dom}; let services=Services::get_or_create_services(&mut dom)?;
let services=context.find_services()?; Ok(Self{dom,services})
Ok((context,services))
} }
pub fn script_singleton(source:String)->(Context,crate::runner::instance::Instance,Services){ pub fn script_singleton(source:String)->(Context,crate::runner::instance::Instance){
let script=InstanceBuilder::new("Script") let script=InstanceBuilder::new("Script")
.with_property("Source",rbx_types::Variant::String(source)); .with_property("Source",rbx_types::Variant::String(source));
let script_ref=script.referent(); let script_ref=script.referent();
@ -30,8 +45,8 @@ impl Context{
InstanceBuilder::new("DataModel") InstanceBuilder::new("DataModel")
.with_child(script) .with_child(script)
); );
let (context,services)=Self::from_model(dom); let context=Self::from_model(dom);
(context,crate::runner::instance::Instance::new(script_ref),services) (context,crate::runner::instance::Instance::new(script_ref))
} }
/// Creates an iterator over all items of a particular class. /// Creates an iterator over all items of a particular class.
pub fn superclass_iter<'a>(&'a self,superclass:&'a str)->impl Iterator<Item=Ref>+'a{ pub fn superclass_iter<'a>(&'a self,superclass:&'a str)->impl Iterator<Item=Ref>+'a{
@ -48,15 +63,7 @@ impl Context{
self.superclass_iter("LuaSourceContainer").map(crate::runner::instance::Instance::new).collect() self.superclass_iter("LuaSourceContainer").map(crate::runner::instance::Instance::new).collect()
} }
pub fn find_services(&self)->Result<Services,ServicesError>{ pub fn from_model(mut dom:WeakDom)->Context{
Ok(Services{
workspace:*self.dom.root().children().iter().find(|&&r|
self.dom.get_by_ref(r).is_some_and(|instance|instance.class=="Workspace")
).ok_or(ServicesError::Workspace)?,
game:self.dom.root_ref(),
})
}
pub fn from_model(mut dom:WeakDom)->(Context,Services){
//snapshot root instances //snapshot root instances
let children=dom.root().children().to_owned(); let children=dom.root().children().to_owned();
@ -83,10 +90,8 @@ impl Context{
dom.transfer_within(instance,workspace); dom.transfer_within(instance,workspace);
} }
( let services=Services{game,workspace};
Self{dom}, Self{dom,services}
Services{game,workspace},
)
} }
} }
@ -95,8 +100,3 @@ impl AsRef<WeakDom> for Context{
&self.dom &self.dom
} }
} }
pub struct Services{
pub(crate) game:Ref,
pub(crate) workspace:Ref,
}

@ -54,14 +54,10 @@ impl Runner{
Ok(runner) Ok(runner)
} }
pub fn runnable_context<'a>(self,context:&'a mut Context)->Result<Runnable<'a>,Error>{ pub fn runnable_context<'a>(self,context:&'a mut Context)->Result<Runnable<'a>,Error>{
let services=context.find_services().map_err(Error::Services)?;
self.runnable_context_with_services(context,&services)
}
pub fn runnable_context_with_services<'a>(self,context:&'a mut Context,services:&crate::context::Services)->Result<Runnable<'a>,Error>{
{ {
let globals=self.lua.globals(); let globals=self.lua.globals();
globals.set("game",super::instance::Instance::new(services.game)).map_err(Error::RustLua)?; globals.set("game",super::instance::Instance::new(context.services.game)).map_err(Error::RustLua)?;
globals.set("workspace",super::instance::Instance::new(services.workspace)).map_err(Error::RustLua)?; globals.set("workspace",super::instance::Instance::new(context.services.workspace)).map_err(Error::RustLua)?;
} }
//this makes set_app_data shut up about the lifetime //this makes set_app_data shut up about the lifetime
self.lua.set_app_data::<&'static mut rbx_dom_weak::WeakDom>(unsafe{core::mem::transmute(&mut context.dom)}); self.lua.set_app_data::<&'static mut rbx_dom_weak::WeakDom>(unsafe{core::mem::transmute(&mut context.dom)});