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{
context:Context,
services:roblox_emulator::context::Services,
}
impl Place{
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{
context,
services,
})
}
pub fn run_scripts(&mut self){
let Place{context,services}=self;
let Place{context}=self;
let runner=roblox_emulator::runner::Runner::new().unwrap();
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{
if let Err(e)=runnable.run_script(script){
println!("runner error: {e}");
@ -72,10 +70,9 @@ impl AsRef<WeakDom> for Place{
}
impl From<Model> for Place{
fn from(model:Model)->Self{
let (context,services)=Context::from_model(model.dom);
let context=Context::from_model(model.dom);
Self{
context,
services,
}
}
}

@ -10,19 +10,34 @@ pub enum ServicesError{
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(crate)dom:WeakDom,
pub(crate)services:Services,
}
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
let context=Self{dom};
let services=context.find_services()?;
Ok((context,services))
let services=Services::get_or_create_services(&mut dom)?;
Ok(Self{dom,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")
.with_property("Source",rbx_types::Variant::String(source));
let script_ref=script.referent();
@ -30,8 +45,8 @@ impl Context{
InstanceBuilder::new("DataModel")
.with_child(script)
);
let (context,services)=Self::from_model(dom);
(context,crate::runner::instance::Instance::new(script_ref),services)
let context=Self::from_model(dom);
(context,crate::runner::instance::Instance::new(script_ref))
}
/// 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{
@ -48,15 +63,7 @@ impl Context{
self.superclass_iter("LuaSourceContainer").map(crate::runner::instance::Instance::new).collect()
}
pub fn find_services(&self)->Result<Services,ServicesError>{
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){
pub fn from_model(mut dom:WeakDom)->Context{
//snapshot root instances
let children=dom.root().children().to_owned();
@ -83,10 +90,8 @@ impl Context{
dom.transfer_within(instance,workspace);
}
(
Self{dom},
Services{game,workspace},
)
let services=Services{game,workspace};
Self{dom,services}
}
}
@ -95,8 +100,3 @@ impl AsRef<WeakDom> for Context{
&self.dom
}
}
pub struct Services{
pub(crate) game:Ref,
pub(crate) workspace:Ref,
}

@ -54,14 +54,10 @@ impl Runner{
Ok(runner)
}
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();
globals.set("game",super::instance::Instance::new(services.game)).map_err(Error::RustLua)?;
globals.set("workspace",super::instance::Instance::new(services.workspace)).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(context.services.workspace)).map_err(Error::RustLua)?;
}
//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)});