roblox_emulator: use extended instances
This commit is contained in:
parent
373bd3c88f
commit
de86ad06b6
lib/roblox_emulator/src/runner
@ -9,7 +9,6 @@ use crate::runner::vector3::Vector3;
|
|||||||
pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
|
pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
|
||||||
//class functions store
|
//class functions store
|
||||||
lua.set_app_data(ClassMethodsStore::default());
|
lua.set_app_data(ClassMethodsStore::default());
|
||||||
lua.set_app_data(InstanceValueStore::default());
|
|
||||||
|
|
||||||
let instance_table=lua.create_table()?;
|
let instance_table=lua.create_table()?;
|
||||||
|
|
||||||
@ -246,16 +245,13 @@ impl mlua::UserData for Instance{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//find or create an associated userdata object
|
//find or create an associated userdata object
|
||||||
if let Some(value)=instance_value_store_mut(lua,|ivs|{
|
let instance=this.get_mut(dom)?;
|
||||||
//TODO: walk class tree somehow
|
if let Some(value)=get_or_create_userdata(instance,lua,index_ustr)?{
|
||||||
match ivs.get_or_create_instance_values(&instance){
|
|
||||||
Some(mut instance_values)=>instance_values.get_or_create_value(lua,index_str),
|
|
||||||
None=>Ok(None)
|
|
||||||
}
|
|
||||||
})?{
|
|
||||||
return value.into_lua(lua);
|
return value.into_lua(lua);
|
||||||
}
|
}
|
||||||
|
// drop mutable borrow
|
||||||
//find a child with a matching name
|
//find a child with a matching name
|
||||||
|
let instance=this.get(dom)?;
|
||||||
find_first_child(dom,instance,index_str)
|
find_first_child(dom,instance,index_str)
|
||||||
.map(|instance|Instance::new(instance.referent()))
|
.map(|instance|Instance::new(instance.referent()))
|
||||||
.into_lua(lua)
|
.into_lua(lua)
|
||||||
@ -469,8 +465,6 @@ fn find_virtual_property(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lazy-loaded per-instance userdata values
|
// lazy-loaded per-instance userdata values
|
||||||
// This whole thing is a bad idea and a garbage collection nightmare.
|
|
||||||
// TODO: recreate rbx_dom_weak with my own instance type that owns this data.
|
|
||||||
type CreateUserData=fn(&mlua::Lua)->mlua::Result<mlua::AnyUserData>;
|
type CreateUserData=fn(&mlua::Lua)->mlua::Result<mlua::AnyUserData>;
|
||||||
type LUD=phf::Map<&'static str,// Class name
|
type LUD=phf::Map<&'static str,// Class name
|
||||||
phf::Map<&'static str,// Value name
|
phf::Map<&'static str,// Value name
|
||||||
@ -479,52 +473,19 @@ type LUD=phf::Map<&'static str,// Class name
|
|||||||
>;
|
>;
|
||||||
static LAZY_USER_DATA:LUD=phf::phf_map!{
|
static LAZY_USER_DATA:LUD=phf::phf_map!{
|
||||||
"RunService"=>phf::phf_map!{
|
"RunService"=>phf::phf_map!{
|
||||||
"RenderStepped"=>|lua|{
|
"RenderStepped"=>|lua|lua.create_any_userdata(crate::runner::script_signal::ScriptSignal::new()),
|
||||||
lua.create_any_userdata(crate::runner::script_signal::ScriptSignal::new())
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
#[derive(Default)]
|
fn get_or_create_userdata(instance:&mut rbx_dom_weak::Instance,lua:&mlua::Lua,index:rbx_dom_weak::Ustr)->mlua::Result<Option<mlua::AnyUserData>>{
|
||||||
pub struct InstanceValueStore{
|
use std::collections::hash_map::Entry;
|
||||||
values:HashMap<Ref,
|
Ok(match LAZY_USER_DATA.get(instance.class.as_str()){
|
||||||
HashMap<&'static str,
|
Some(userdata_map)=>match instance.userdata.entry(index){
|
||||||
mlua::AnyUserData
|
Entry::Occupied(entry)=>Some(entry.get().clone()),
|
||||||
>
|
Entry::Vacant(entry)=>match userdata_map.get(index.as_str()){
|
||||||
>,
|
Some(create_userdata)=>Some(entry.insert(create_userdata(lua)?).clone()),
|
||||||
}
|
None=>None,
|
||||||
pub struct InstanceValues<'a>{
|
},
|
||||||
named_values:&'static phf::Map<&'static str,CreateUserData>,
|
},
|
||||||
values:&'a mut HashMap<&'static str,mlua::AnyUserData>,
|
None=>None,
|
||||||
}
|
})
|
||||||
impl InstanceValueStore{
|
|
||||||
pub fn get_or_create_instance_values(&mut self,instance:&rbx_dom_weak::Instance)->Option<InstanceValues>{
|
|
||||||
LAZY_USER_DATA.get(instance.class.as_str())
|
|
||||||
.map(|named_values|
|
|
||||||
InstanceValues{
|
|
||||||
named_values,
|
|
||||||
values:self.values.entry(instance.referent())
|
|
||||||
.or_insert_with(||HashMap::new()),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl InstanceValues<'_>{
|
|
||||||
pub fn get_or_create_value(&mut self,lua:&mlua::Lua,index:&str)->mlua::Result<Option<mlua::AnyUserData>>{
|
|
||||||
Ok(match self.named_values.get_entry(index){
|
|
||||||
Some((&static_index_str,&function_pointer))=>Some(
|
|
||||||
match self.values.entry(static_index_str){
|
|
||||||
Entry::Occupied(entry)=>entry.get().clone(),
|
|
||||||
Entry::Vacant(entry)=>entry.insert(
|
|
||||||
function_pointer(lua)?
|
|
||||||
).clone(),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
None=>None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn instance_value_store_mut<T>(lua:&mlua::Lua,mut f:impl FnMut(&mut InstanceValueStore)->mlua::Result<T>)->mlua::Result<T>{
|
|
||||||
let mut cf=lua.app_data_mut::<InstanceValueStore>().ok_or_else(||mlua::Error::runtime("InstanceValueStore missing"))?;
|
|
||||||
f(&mut *cf)
|
|
||||||
}
|
}
|
||||||
|
@ -123,20 +123,15 @@ impl Runnable<'_>{
|
|||||||
}
|
}
|
||||||
#[cfg(feature="run-service")]
|
#[cfg(feature="run-service")]
|
||||||
pub fn run_service_step(&self)->Result<(),mlua::Error>{
|
pub fn run_service_step(&self)->Result<(),mlua::Error>{
|
||||||
let render_stepped=super::instance::instance::dom_mut(&self.lua,|dom|{
|
let render_stepped_signal=super::instance::instance::dom_mut(&self.lua,|dom|{
|
||||||
let run_service=super::instance::instance::find_first_child_of_class(dom,dom.root(),"RunService").ok_or_else(||mlua::Error::runtime("RunService missing"))?;
|
let run_service=super::instance::instance::find_first_child_of_class(dom,dom.root(),"RunService").ok_or_else(||mlua::Error::runtime("RunService missing"))?;
|
||||||
super::instance::instance::instance_value_store_mut(&self.lua,|instance_value_store|{
|
Ok(match run_service.userdata.get(&rbx_dom_weak::ustr("RenderStepped")){
|
||||||
//unwrap because I trust my find_first_child_of_class function to
|
Some(render_stepped)=>Some(render_stepped.borrow::<super::script_signal::ScriptSignal>()?.clone()),
|
||||||
let mut instance_values=instance_value_store.get_or_create_instance_values(run_service).ok_or_else(||mlua::Error::runtime("RunService InstanceValues missing"))?;
|
None=>None
|
||||||
let render_stepped=instance_values.get_or_create_value(&self.lua,"RenderStepped")?;
|
|
||||||
//let stepped=instance_values.get_or_create_value(&self.lua,"Stepped")?;
|
|
||||||
//let heartbeat=instance_values.get_or_create_value(&self.lua,"Heartbeat")?;
|
|
||||||
Ok(render_stepped)
|
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
if let Some(render_stepped)=render_stepped{
|
if let Some(render_stepped_signal)=render_stepped_signal{
|
||||||
let signal:&super::script_signal::ScriptSignal=&*render_stepped.borrow()?;
|
render_stepped_signal.fire(&mlua::MultiValue::new());
|
||||||
signal.fire(&mlua::MultiValue::new());
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user