Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
9a50ecf12a | |||
04d7694da4 | |||
0a3825ca2d | |||
bef16f65ff |
74
Cargo.lock
generated
74
Cargo.lock
generated
@ -1409,7 +1409,7 @@ dependencies = [
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core 0.61.0",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1843,7 +1843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3098,9 +3098,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rbx_binary"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9573fee5e073d7b303f475c285197fdc8179468de66ca60ee115a58fbac99296"
|
||||
version = "1.1.0-sn3"
|
||||
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||
checksum = "f3f4cd69381a3631e117ee9542f5f8d9a2ab3b5dd8c7bdc7eb1680cc805233bc"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"log",
|
||||
@ -3115,9 +3115,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rbx_dom_weak"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04425cf6e9376e5486f4fb35906c120d1b1b45618a490318cf563fab1fa230a9"
|
||||
version = "3.1.0-sn1"
|
||||
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||
checksum = "c449e42d26c5af9d50e036219513e7a3e3bd0bc31fa32b74b82d9d4d481d74a5"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"rbx_types",
|
||||
@ -3175,9 +3175,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rbx_xml"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb623833c31cc43bbdaeb32f5e91db8ecd63fc46e438d0d268baf9e61539cf1c"
|
||||
version = "1.1.0-sn3"
|
||||
source = "sparse+https://git.itzana.me/api/packages/strafesnet/cargo/"
|
||||
checksum = "ce7d7ec62a3dc88179a61efa4827c36887a1b2bcbc258aec58de0c5149c565eb"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"base64 0.13.1",
|
||||
@ -4870,7 +4870,7 @@ dependencies = [
|
||||
"web-sys",
|
||||
"wgpu-types",
|
||||
"windows",
|
||||
"windows-core 0.58.0",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4902,7 +4902,7 @@ version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
|
||||
dependencies = [
|
||||
"windows-core 0.58.0",
|
||||
"windows-core",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
@ -4912,26 +4912,13 @@ version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
||||
dependencies = [
|
||||
"windows-implement 0.58.0",
|
||||
"windows-interface 0.58.0",
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result 0.2.0",
|
||||
"windows-strings 0.1.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
|
||||
dependencies = [
|
||||
"windows-implement 0.60.0",
|
||||
"windows-interface 0.59.1",
|
||||
"windows-link",
|
||||
"windows-result 0.3.2",
|
||||
"windows-strings 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.58.0"
|
||||
@ -4943,17 +4930,6 @@ dependencies = [
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.58.0"
|
||||
@ -4965,17 +4941,6 @@ dependencies = [
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
@ -5030,15 +4995,6 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
|
@ -13,12 +13,12 @@ authors = ["Rhys Lloyd <krakow20@gmail.com>"]
|
||||
bytemuck = "1.14.3"
|
||||
glam = "0.30.0"
|
||||
lazy-regex = "3.1.0"
|
||||
rbx_binary = "1.0.0"
|
||||
rbx_dom_weak = "3.0.0"
|
||||
rbx_binary = { version = "1.1.0-sn3", registry = "strafesnet"}
|
||||
rbx_dom_weak = { version = "3.1.0-sn1", registry = "strafesnet"}
|
||||
rbx_mesh = "0.3.1"
|
||||
rbx_reflection_database = "1.0.0"
|
||||
rbx_xml = "1.0.0"
|
||||
rbx_xml = { version = "1.1.0-sn3", registry = "strafesnet"}
|
||||
rbxassetid = { version = "0.1.0", path = "../rbxassetid", registry = "strafesnet" }
|
||||
roblox_emulator = { version = "0.4.7", path = "../roblox_emulator", registry = "strafesnet" }
|
||||
roblox_emulator = { version = "0.4.7", path = "../roblox_emulator", default-features = false, registry = "strafesnet" }
|
||||
strafesnet_common = { version = "0.6.0", path = "../common", registry = "strafesnet" }
|
||||
strafesnet_deferred_loader = { version = "0.5.0", path = "../deferred_loader", registry = "strafesnet" }
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::io::Read;
|
||||
use rbx_dom_weak::WeakDom;
|
||||
use roblox_emulator::types::WeakDom;
|
||||
use strafesnet_deferred_loader::deferred_loader::{LoadFailureMode,MeshDeferredLoader,RenderConfigDeferredLoader};
|
||||
|
||||
mod rbx;
|
||||
@ -95,8 +95,8 @@ pub fn read<R:Read>(input:R)->Result<Model,ReadError>{
|
||||
let mut buf=std::io::BufReader::new(input);
|
||||
let peek=std::io::BufRead::fill_buf(&mut buf).map_err(ReadError::Io)?;
|
||||
match &peek[0..8]{
|
||||
b"<roblox!"=>rbx_binary::from_reader(buf).map(Model::new).map_err(ReadError::RbxBinary),
|
||||
b"<roblox "=>rbx_xml::from_reader_default(buf).map(Model::new).map_err(ReadError::RbxXml),
|
||||
b"<roblox!"=>rbx_binary::from_reader_generic(buf).map(Model::new).map_err(ReadError::RbxBinary),
|
||||
b"<roblox "=>rbx_xml::from_reader_generic(buf,Default::default()).map(Model::new).map_err(ReadError::RbxXml),
|
||||
_=>Err(ReadError::UnknownFileFormat),
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use std::collections::HashMap;
|
||||
use crate::loader::MeshIndex;
|
||||
use crate::primitives::{self,CubeFace,CubeFaceDescription,WedgeFaceDescription,CornerWedgeFaceDescription,FaceDescription,Primitives};
|
||||
use rbx_dom_weak::ustr;
|
||||
use roblox_emulator::types::{WeakDom,Instance};
|
||||
use strafesnet_common::aabb::Aabb;
|
||||
use strafesnet_common::map;
|
||||
use strafesnet_common::model;
|
||||
@ -14,30 +15,23 @@ use strafesnet_deferred_loader::deferred_loader::{RenderConfigDeferredLoader,Mes
|
||||
use strafesnet_deferred_loader::mesh::Meshes;
|
||||
use strafesnet_deferred_loader::texture::{RenderConfigs,Texture};
|
||||
|
||||
fn class_is_a(class: &str, superclass: &str) -> bool {
|
||||
if class==superclass {
|
||||
return true
|
||||
}
|
||||
let class_descriptor=rbx_reflection_database::get().classes.get(class);
|
||||
if let Some(descriptor) = &class_descriptor {
|
||||
if let Some(class_super) = &descriptor.superclass {
|
||||
return class_is_a(&class_super, superclass)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
fn recursive_collect_superclass(objects: &mut std::vec::Vec<rbx_dom_weak::types::Ref>,dom: &rbx_dom_weak::WeakDom, instance: &rbx_dom_weak::Instance, superclass: &str){
|
||||
let mut stack=vec![instance];
|
||||
while let Some(item)=stack.pop(){
|
||||
for &referent in item.children(){
|
||||
if let Some(c)=dom.get_by_ref(referent){
|
||||
if class_is_a(c.class.as_str(),superclass){
|
||||
objects.push(c.referent());//copy ref
|
||||
}
|
||||
stack.push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn recursive_collect_superclass(
|
||||
objects:&mut std::vec::Vec<rbx_dom_weak::types::Ref>,
|
||||
dom:&WeakDom,
|
||||
instance:&Instance,
|
||||
superclass:&str
|
||||
){
|
||||
let instance=instance.as_ref();
|
||||
let db=rbx_reflection_database::get();
|
||||
let Some(superclass)=db.classes.get(superclass)else{
|
||||
return;
|
||||
};
|
||||
objects.extend(
|
||||
dom.descendants_of(instance.as_ref().referent()).filter_map(|instance|{
|
||||
let class=db.classes.get(instance.as_ref().class.as_str())?;
|
||||
db.has_superclass(class,superclass).then(||instance.as_ref().referent())
|
||||
})
|
||||
);
|
||||
}
|
||||
fn planar64_affine3_from_roblox(cf:&rbx_dom_weak::types::CFrame,size:&rbx_dom_weak::types::Vector3)->Planar64Affine3{
|
||||
Planar64Affine3::new(
|
||||
@ -405,19 +399,20 @@ fn get_content_url(content:&rbx_dom_weak::types::Content)->Option<&str>{
|
||||
fn get_texture_description<'a>(
|
||||
temp_objects:&mut Vec<rbx_dom_weak::types::Ref>,
|
||||
render_config_deferred_loader:&mut RenderConfigDeferredLoader<&'a str>,
|
||||
dom:&'a rbx_dom_weak::WeakDom,
|
||||
object:&rbx_dom_weak::Instance,
|
||||
dom:&'a WeakDom,
|
||||
object:&Instance,
|
||||
size:&rbx_dom_weak::types::Vector3,
|
||||
)->RobloxPartDescription{
|
||||
//use the biggest one and cut it down later...
|
||||
let mut part_texture_description=RobloxPartDescription::default();
|
||||
temp_objects.clear();
|
||||
recursive_collect_superclass(temp_objects,&dom,object,"Decal");
|
||||
recursive_collect_superclass(temp_objects,dom,object,"Decal");
|
||||
for &mut decal_ref in temp_objects{
|
||||
let Some(decal)=dom.get_by_ref(decal_ref) else{
|
||||
println!("Decal get_by_ref failed");
|
||||
continue;
|
||||
};
|
||||
let decal=decal.as_ref();
|
||||
let (
|
||||
Some(rbx_dom_weak::types::Variant::ContentId(content)),
|
||||
Some(rbx_dom_weak::types::Variant::Enum(normalid)),
|
||||
@ -521,7 +516,7 @@ struct GetAttributesArgs<'a>{
|
||||
velocity:Planar64Vec3,
|
||||
}
|
||||
pub fn convert<'a>(
|
||||
dom:&'a rbx_dom_weak::WeakDom,
|
||||
dom:&'a WeakDom,
|
||||
render_config_deferred_loader:&mut RenderConfigDeferredLoader<&'a str>,
|
||||
mesh_deferred_loader:&mut MeshDeferredLoader<MeshIndex<'a>>,
|
||||
)->PartialMap1<'a>{
|
||||
@ -536,9 +531,10 @@ pub fn convert<'a>(
|
||||
|
||||
let mut object_refs=Vec::new();
|
||||
let mut temp_objects=Vec::new();
|
||||
recursive_collect_superclass(&mut object_refs, &dom, dom.root(),"BasePart");
|
||||
for object_ref in object_refs {
|
||||
if let Some(object)=dom.get_by_ref(object_ref){
|
||||
recursive_collect_superclass(&mut object_refs,dom,dom.root(),"BasePart");
|
||||
for object_ref in object_refs{
|
||||
if let Some(object_extended)=dom.get_by_ref(object_ref){
|
||||
let object=object_extended.as_ref();
|
||||
if let (
|
||||
Some(rbx_dom_weak::types::Variant::CFrame(cf)),
|
||||
Some(rbx_dom_weak::types::Variant::Vector3(size)),
|
||||
@ -561,6 +557,7 @@ pub fn convert<'a>(
|
||||
let mut parent_ref=object.parent();
|
||||
let mut full_path=object.name.clone();
|
||||
while let Some(parent)=dom.get_by_ref(parent_ref){
|
||||
let parent=parent.as_ref();
|
||||
full_path=format!("{}.{}",parent.name,full_path);
|
||||
parent_ref=parent.parent();
|
||||
}
|
||||
@ -590,7 +587,7 @@ pub fn convert<'a>(
|
||||
let (availability,mesh_id)=match shape{
|
||||
Shape::Primitive(primitive_shape)=>{
|
||||
//TODO: TAB TAB
|
||||
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object,size);
|
||||
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object_extended,size);
|
||||
//obscure rust syntax "slice pattern"
|
||||
let RobloxPartDescription([
|
||||
f0,//Cube::Right
|
||||
@ -671,7 +668,7 @@ pub fn convert<'a>(
|
||||
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get(&ustr("PhysicsData")){
|
||||
physics_data=data.as_ref();
|
||||
}
|
||||
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object,size);
|
||||
let part_texture_description=get_texture_description(&mut temp_objects,render_config_deferred_loader,dom,object_extended,size);
|
||||
let mesh_index=MeshIndex::union(content,mesh_data,physics_data,size,part_texture_description.clone());
|
||||
let mesh_id=mesh_deferred_loader.acquire_mesh_id(mesh_index);
|
||||
(MeshAvailability::DeferredUnion(part_texture_description),mesh_id)
|
||||
|
@ -15,7 +15,7 @@ run-service=[]
|
||||
glam = "0.30.0"
|
||||
mlua = { version = "0.10.1", features = ["luau"] }
|
||||
phf = { version = "0.11.2", features = ["macros"] }
|
||||
rbx_dom_weak = "3.0.0"
|
||||
rbx_dom_weak = { version = "3.1.0-sn1", registry = "strafesnet"}
|
||||
rbx_reflection = "5.0.0"
|
||||
rbx_reflection_database = "1.0.0"
|
||||
rbx_types = "2.0.0"
|
||||
|
@ -1,4 +1,5 @@
|
||||
use rbx_dom_weak::{types::Ref,ustr,InstanceBuilder,WeakDom};
|
||||
use crate::types::WeakDom;
|
||||
use rbx_dom_weak::{types::Ref,ustr,InstanceBuilder};
|
||||
|
||||
pub fn class_is_a(class:&str,superclass:&str)->bool{
|
||||
class==superclass
|
||||
@ -19,7 +20,7 @@ impl Context{
|
||||
pub const fn new(dom:WeakDom)->Self{
|
||||
Self{dom}
|
||||
}
|
||||
pub fn script_singleton(source:String)->(Context,crate::runner::instance::Instance,Services){
|
||||
pub fn script_singleton(source:String)->(Context,crate::runner::instance::InstanceRef,Services){
|
||||
let script=InstanceBuilder::new("Script")
|
||||
.with_property("Source",rbx_types::Variant::String(source));
|
||||
let script_ref=script.referent();
|
||||
@ -28,7 +29,7 @@ impl Context{
|
||||
.with_child(script)
|
||||
));
|
||||
let services=context.convert_into_place();
|
||||
(context,crate::runner::instance::Instance::new(script_ref),services)
|
||||
(context,crate::runner::instance::InstanceRef::new(script_ref),services)
|
||||
}
|
||||
pub fn from_ref(dom:&WeakDom)->&Context{
|
||||
unsafe{&*(dom as *const WeakDom as *const Context)}
|
||||
@ -39,24 +40,24 @@ impl Context{
|
||||
/// 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{
|
||||
self.dom.descendants().filter(|&instance|
|
||||
class_is_a(instance.class.as_ref(),superclass)
|
||||
).map(|instance|instance.referent())
|
||||
class_is_a(instance.as_ref().class.as_ref(),superclass)
|
||||
).map(|instance|instance.as_ref().referent())
|
||||
}
|
||||
pub fn scripts(&self)->Vec<crate::runner::instance::Instance>{
|
||||
self.superclass_iter("LuaSourceContainer").map(crate::runner::instance::Instance::new).collect()
|
||||
pub fn scripts(&self)->Vec<crate::runner::instance::InstanceRef>{
|
||||
self.superclass_iter("LuaSourceContainer").map(crate::runner::instance::InstanceRef::new).collect()
|
||||
}
|
||||
|
||||
pub fn find_services(&self)->Option<Services>{
|
||||
Some(Services{
|
||||
workspace:*self.dom.root().children().iter().find(|&&r|
|
||||
self.dom.get_by_ref(r).is_some_and(|instance|instance.class=="Workspace")
|
||||
workspace:*self.dom.root().as_ref().children().iter().find(|&&r|
|
||||
self.dom.get_by_ref(r).is_some_and(|instance|instance.as_ref().class=="Workspace")
|
||||
)?,
|
||||
game:self.dom.root_ref(),
|
||||
})
|
||||
}
|
||||
pub fn convert_into_place(&mut self)->Services{
|
||||
//snapshot root instances
|
||||
let children=self.dom.root().children().to_owned();
|
||||
let children=self.dom.root().as_ref().children().to_owned();
|
||||
|
||||
//insert services
|
||||
let game=self.dom.root_ref();
|
||||
@ -69,7 +70,7 @@ impl Context{
|
||||
);
|
||||
{
|
||||
//Lowercase and upper case workspace property!
|
||||
let game=self.dom.root_mut();
|
||||
let game=self.dom.root_mut().as_mut();
|
||||
game.properties.insert(ustr("workspace"),rbx_types::Variant::Ref(workspace));
|
||||
game.properties.insert(ustr("Workspace"),rbx_types::Variant::Ref(workspace));
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod types;
|
||||
pub mod runner;
|
||||
pub mod context;
|
||||
#[cfg(feature="run-service")]
|
||||
|
@ -2,25 +2,25 @@ use std::collections::{hash_map::Entry,HashMap};
|
||||
|
||||
use mlua::{FromLua,FromLuaMulti,IntoLua,IntoLuaMulti};
|
||||
use rbx_types::Ref;
|
||||
use rbx_dom_weak::{ustr,Ustr,InstanceBuilder,WeakDom};
|
||||
use rbx_dom_weak::{ustr,Ustr,InstanceBuilder};
|
||||
|
||||
use crate::runner::vector3::Vector3;
|
||||
use crate::types::{WeakDom,Instance};
|
||||
|
||||
pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
|
||||
//class functions store
|
||||
lua.set_app_data(ClassMethodsStore::default());
|
||||
lua.set_app_data(InstanceValueStore::default());
|
||||
|
||||
let instance_table=lua.create_table()?;
|
||||
|
||||
//Instance.new
|
||||
instance_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<InstanceRef>)|{
|
||||
let class_name_str=&*class_name.to_str()?;
|
||||
let parent=parent.ok_or_else(||mlua::Error::runtime("Nil Parent not yet supported"))?;
|
||||
dom_mut(lua,|dom|{
|
||||
//TODO: Nil instances
|
||||
Ok(Instance::new(dom.insert(parent.referent,InstanceBuilder::new(class_name_str))))
|
||||
Ok(InstanceRef::new(dom.insert(parent.referent,InstanceBuilder::new(class_name_str))))
|
||||
})
|
||||
})?
|
||||
)?;
|
||||
@ -44,10 +44,12 @@ fn coerce_float32(value:&mlua::Value)->Option<f32>{
|
||||
}
|
||||
}
|
||||
|
||||
fn get_full_name(dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance)->String{
|
||||
fn get_full_name(dom:&WeakDom,instance:&Instance)->String{
|
||||
let instance=instance.as_ref();
|
||||
let mut full_name=instance.name.clone();
|
||||
let mut pref=instance.parent();
|
||||
while let Some(parent)=dom.get_by_ref(pref){
|
||||
let parent=parent.as_ref();
|
||||
full_name.insert(0,'.');
|
||||
full_name.insert_str(0,parent.name.as_str());
|
||||
pref=parent.parent();
|
||||
@ -55,10 +57,10 @@ fn get_full_name(dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance)->S
|
||||
full_name
|
||||
}
|
||||
//helper function for script
|
||||
pub fn get_name_source(lua:&mlua::Lua,script:Instance)->Result<(String,String),mlua::Error>{
|
||||
pub fn get_name_source(lua:&mlua::Lua,script:InstanceRef)->Result<(String,String),mlua::Error>{
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=script.get(dom)?;
|
||||
let source=match instance.properties.get(&ustr("Source")){
|
||||
let source=match instance.as_ref().properties.get(&ustr("Source")){
|
||||
Some(rbx_dom_weak::types::Variant::String(s))=>s.clone(),
|
||||
_=>Err(mlua::Error::external("Missing script.Source"))?,
|
||||
};
|
||||
@ -66,46 +68,46 @@ pub fn get_name_source(lua:&mlua::Lua,script:Instance)->Result<(String,String),m
|
||||
})
|
||||
}
|
||||
|
||||
pub fn find_first_child<'a>(dom:&'a rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,name:&str)->Option<&'a rbx_dom_weak::Instance>{
|
||||
instance.children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|inst.name==name)
|
||||
pub fn find_first_child<'a>(dom:&'a WeakDom,instance:&Instance,name:&str)->Option<&'a Instance>{
|
||||
instance.as_ref().children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|inst.as_ref().name==name)
|
||||
}
|
||||
pub fn find_first_descendant<'a>(dom:&'a rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,name:&str)->Option<&'a rbx_dom_weak::Instance>{
|
||||
dom.descendants_of(instance.referent()).find(|&inst|inst.name==name)
|
||||
pub fn find_first_descendant<'a>(dom:&'a WeakDom,instance:&Instance,name:&str)->Option<&'a Instance>{
|
||||
dom.descendants_of(instance.as_ref().referent()).find(|&inst|inst.as_ref().name==name)
|
||||
}
|
||||
|
||||
pub fn find_first_child_of_class<'a>(dom:&'a rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,class:&str)->Option<&'a rbx_dom_weak::Instance>{
|
||||
instance.children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|inst.class==class)
|
||||
pub fn find_first_child_of_class<'a>(dom:&'a WeakDom,instance:&Instance,class:&str)->Option<&'a Instance>{
|
||||
instance.as_ref().children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|inst.as_ref().class==class)
|
||||
}
|
||||
pub fn find_first_descendant_of_class<'a>(dom:&'a rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,class:&str)->Option<&'a rbx_dom_weak::Instance>{
|
||||
dom.descendants_of(instance.referent()).find(|&inst|inst.class==class)
|
||||
pub fn find_first_descendant_of_class<'a>(dom:&'a WeakDom,instance:&Instance,class:&str)->Option<&'a Instance>{
|
||||
dom.descendants_of(instance.as_ref().referent()).find(|&inst|inst.as_ref().class==class)
|
||||
}
|
||||
|
||||
#[derive(Clone,Copy)]
|
||||
pub struct Instance{
|
||||
pub struct InstanceRef{
|
||||
referent:Ref,
|
||||
}
|
||||
impl Instance{
|
||||
impl InstanceRef{
|
||||
pub const fn new(referent:Ref)->Self{
|
||||
Self{referent}
|
||||
}
|
||||
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 Instance>{
|
||||
dom.get_by_ref(self.referent).ok_or_else(||mlua::Error::runtime("Instance missing"))
|
||||
}
|
||||
pub fn get_mut<'a>(&self,dom:&'a mut WeakDom)->mlua::Result<&'a mut rbx_dom_weak::Instance>{
|
||||
pub fn get_mut<'a>(&self,dom:&'a mut WeakDom)->mlua::Result<&'a mut Instance>{
|
||||
dom.get_by_ref_mut(self.referent).ok_or_else(||mlua::Error::runtime("Instance missing"))
|
||||
}
|
||||
}
|
||||
type_from_lua_userdata!(Instance);
|
||||
type_from_lua_userdata!(InstanceRef);
|
||||
|
||||
impl mlua::UserData for Instance{
|
||||
impl mlua::UserData for InstanceRef{
|
||||
fn add_fields<F:mlua::UserDataFields<Self>>(fields:&mut F){
|
||||
fields.add_field_method_get("Parent",|lua,this|{
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get(dom)?;
|
||||
Ok(Instance::new(instance.parent()))
|
||||
let instance=this.get(dom)?.as_ref();
|
||||
Ok(InstanceRef::new(instance.parent()))
|
||||
})
|
||||
});
|
||||
fields.add_field_method_set("Parent",|lua,this,val:Option<Instance>|{
|
||||
fields.add_field_method_set("Parent",|lua,this,val:Option<InstanceRef>|{
|
||||
let parent=val.ok_or_else(||mlua::Error::runtime("Nil Parent not yet supported"))?;
|
||||
dom_mut(lua,|dom|{
|
||||
dom.transfer_within(this.referent,parent.referent);
|
||||
@ -114,13 +116,13 @@ impl mlua::UserData for Instance{
|
||||
});
|
||||
fields.add_field_method_get("Name",|lua,this|{
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get(dom)?;
|
||||
let instance=this.get(dom)?.as_ref();
|
||||
Ok(instance.name.clone())
|
||||
})
|
||||
});
|
||||
fields.add_field_method_set("Name",|lua,this,val:mlua::String|{
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get_mut(dom)?;
|
||||
let instance=this.get_mut(dom)?.as_mut();
|
||||
//Why does this need to be cloned?
|
||||
instance.name=val.to_str()?.to_owned();
|
||||
Ok(())
|
||||
@ -128,7 +130,7 @@ impl mlua::UserData for Instance{
|
||||
});
|
||||
fields.add_field_method_get("ClassName",|lua,this|{
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get(dom)?;
|
||||
let instance=this.get(dom)?.as_ref();
|
||||
Ok(instance.class.to_owned())
|
||||
})
|
||||
});
|
||||
@ -136,17 +138,17 @@ impl mlua::UserData for Instance{
|
||||
fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){
|
||||
methods.add_method("GetChildren",|lua,this,_:()|
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get(dom)?;
|
||||
let instance=this.get(dom)?.as_ref();
|
||||
let children:Vec<_>=instance
|
||||
.children()
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Instance::new)
|
||||
.map(InstanceRef::new)
|
||||
.collect();
|
||||
Ok(children)
|
||||
})
|
||||
);
|
||||
fn ffc(lua:&mlua::Lua,this:&Instance,(name,search_descendants):(mlua::String,Option<bool>))->mlua::Result<Option<Instance>>{
|
||||
fn ffc(lua:&mlua::Lua,this:&InstanceRef,(name,search_descendants):(mlua::String,Option<bool>))->mlua::Result<Option<InstanceRef>>{
|
||||
let name_str=&*name.to_str()?;
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get(dom)?;
|
||||
@ -156,7 +158,7 @@ impl mlua::UserData for Instance{
|
||||
false=>find_first_child(dom,instance,name_str),
|
||||
}
|
||||
.map(|instance|
|
||||
Instance::new(instance.referent())
|
||||
InstanceRef::new(instance.as_ref().referent())
|
||||
)
|
||||
)
|
||||
})
|
||||
@ -172,7 +174,7 @@ impl mlua::UserData for Instance{
|
||||
false=>find_first_child_of_class(dom,this.get(dom)?,class_str),
|
||||
}
|
||||
.map(|instance|
|
||||
Instance::new(instance.referent())
|
||||
InstanceRef::new(instance.as_ref().referent())
|
||||
)
|
||||
)
|
||||
})
|
||||
@ -182,7 +184,7 @@ impl mlua::UserData for Instance{
|
||||
let children:Vec<_>=dom
|
||||
.descendants_of(this.referent)
|
||||
.map(|instance|
|
||||
Instance::new(instance.referent())
|
||||
InstanceRef::new(instance.as_ref().referent())
|
||||
)
|
||||
.collect();
|
||||
Ok(children)
|
||||
@ -190,7 +192,7 @@ impl mlua::UserData for Instance{
|
||||
);
|
||||
methods.add_method("IsA",|lua,this,classname:mlua::String|
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get(dom)?;
|
||||
let instance=this.get(dom)?.as_ref();
|
||||
Ok(crate::context::class_is_a(instance.class.as_str(),&*classname.to_str()?))
|
||||
})
|
||||
);
|
||||
@ -200,39 +202,40 @@ impl mlua::UserData for Instance{
|
||||
Ok(())
|
||||
})
|
||||
);
|
||||
methods.add_meta_function(mlua::MetaMethod::ToString,|lua,this:Instance|{
|
||||
methods.add_meta_function(mlua::MetaMethod::ToString,|lua,this:InstanceRef|{
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get(dom)?;
|
||||
let instance=this.get(dom)?.as_ref();
|
||||
Ok(instance.name.clone())
|
||||
})
|
||||
});
|
||||
methods.add_meta_function(mlua::MetaMethod::Index,|lua,(this,index):(Instance,mlua::String)|{
|
||||
methods.add_meta_function(mlua::MetaMethod::Index,|lua,(this,index):(InstanceRef,mlua::String)|{
|
||||
let index_str=&*index.to_str()?;
|
||||
let index_ustr=ustr(index_str);
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get(dom)?;
|
||||
let instance_ref=instance.as_ref();
|
||||
//println!("__index t={} i={index:?}",instance.name);
|
||||
let db=rbx_reflection_database::get();
|
||||
let class=db.classes.get(instance.class.as_str()).ok_or_else(||mlua::Error::runtime("Class missing"))?;
|
||||
let class=db.classes.get(instance_ref.class.as_str()).ok_or_else(||mlua::Error::runtime("Class missing"))?;
|
||||
//Find existing property
|
||||
match instance.properties.get(&index_ustr)
|
||||
match instance_ref.properties.get(&index_ustr)
|
||||
.cloned()
|
||||
//Find default value
|
||||
.or_else(||db.find_default_property(class,index_str).cloned())
|
||||
//Find virtual property
|
||||
.or_else(||db.superclasses_iter(class).find_map(|class|
|
||||
find_virtual_property(&instance.properties,class,&index_ustr)
|
||||
find_virtual_property(&instance_ref.properties,class,&index_ustr)
|
||||
))
|
||||
{
|
||||
Some(rbx_types::Variant::Int32(val))=>return val.into_lua(lua),
|
||||
Some(rbx_types::Variant::Int64(val))=>return val.into_lua(lua),
|
||||
Some(rbx_types::Variant::Float32(val))=>return val.into_lua(lua),
|
||||
Some(rbx_types::Variant::Float64(val))=>return val.into_lua(lua),
|
||||
Some(rbx_types::Variant::Ref(val))=>return Instance::new(val).into_lua(lua),
|
||||
Some(rbx_types::Variant::Ref(val))=>return InstanceRef::new(val).into_lua(lua),
|
||||
Some(rbx_types::Variant::CFrame(cf))=>return Into::<crate::runner::cframe::CFrame>::into(cf).into_lua(lua),
|
||||
Some(rbx_types::Variant::Vector3(v))=>return Into::<crate::runner::vector3::Vector3>::into(v).into_lua(lua),
|
||||
None=>(),
|
||||
other=>return Err(mlua::Error::runtime(format!("Instance.__index Unsupported property type instance={} index={index_str} value={other:?}",instance.name))),
|
||||
other=>return Err(mlua::Error::runtime(format!("Instance.__index Unsupported property type instance={} index={index_str} value={other:?}",instance_ref.name))),
|
||||
}
|
||||
//find a function with a matching name
|
||||
if let Some(function)=class_methods_store_mut(lua,|cf|{
|
||||
@ -246,24 +249,21 @@ impl mlua::UserData for Instance{
|
||||
}
|
||||
|
||||
//find or create an associated userdata object
|
||||
if let Some(value)=instance_value_store_mut(lua,|ivs|{
|
||||
//TODO: walk class tree somehow
|
||||
match ivs.get_or_create_instance_values(&instance){
|
||||
Some(mut instance_values)=>instance_values.get_or_create_value(lua,index_str),
|
||||
None=>Ok(None)
|
||||
}
|
||||
})?{
|
||||
let instance=this.get_mut(dom)?;
|
||||
if let Some(value)=instance.get_or_create_userdata(lua,index_ustr)?{
|
||||
return value.into_lua(lua);
|
||||
}
|
||||
// drop mutable borrow
|
||||
//find a child with a matching name
|
||||
let instance=this.get(dom)?;
|
||||
find_first_child(dom,instance,index_str)
|
||||
.map(|instance|Instance::new(instance.referent()))
|
||||
.map(|instance|InstanceRef::new(instance.as_ref().referent()))
|
||||
.into_lua(lua)
|
||||
})
|
||||
});
|
||||
methods.add_meta_function(mlua::MetaMethod::NewIndex,|lua,(this,index,value):(Instance,mlua::String,mlua::Value)|{
|
||||
methods.add_meta_function(mlua::MetaMethod::NewIndex,|lua,(this,index,value):(InstanceRef,mlua::String,mlua::Value)|{
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get_mut(dom)?;
|
||||
let instance=this.get_mut(dom)?.as_mut();
|
||||
//println!("__newindex t={} i={index:?} v={value:?}",instance.name);
|
||||
let index_str=&*index.to_str()?;
|
||||
let index_ustr=ustr(index_str);
|
||||
@ -331,7 +331,7 @@ impl mlua::UserData for Instance{
|
||||
macro_rules! cf{
|
||||
($f:expr)=>{
|
||||
|lua,mut args|{
|
||||
let this=Instance::from_lua(args.pop_front().unwrap_or(mlua::Value::Nil),lua)?;
|
||||
let this=InstanceRef::from_lua(args.pop_front().unwrap_or(mlua::Value::Nil),lua)?;
|
||||
$f(lua,this,FromLuaMulti::from_lua_multi(args,lua)?)?.into_lua_multi(lua)
|
||||
}
|
||||
};
|
||||
@ -354,13 +354,13 @@ static CLASS_FUNCTION_DATABASE:CFD=phf::phf_map!{
|
||||
match service{
|
||||
"Lighting"|"RunService"=>{
|
||||
let referent=find_first_child_of_class(dom,dom.root(),service)
|
||||
.map(|instance|instance.referent())
|
||||
.map(|instance|instance.as_ref().referent())
|
||||
.unwrap_or_else(||
|
||||
dom.insert(dom.root_ref(),InstanceBuilder::new(service))
|
||||
);
|
||||
Ok(Instance::new(referent))
|
||||
Ok(InstanceRef::new(referent))
|
||||
},
|
||||
other=>Err::<Instance,_>(mlua::Error::runtime(format!("Service '{other}' not supported"))),
|
||||
other=>Err::<InstanceRef,_>(mlua::Error::runtime(format!("Service '{other}' not supported"))),
|
||||
}
|
||||
})
|
||||
}),
|
||||
@ -467,64 +467,3 @@ fn find_virtual_property(
|
||||
//Transform Source property with provided function
|
||||
(virtual_property.pointer)(variant)
|
||||
}
|
||||
|
||||
// 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 LUD=phf::Map<&'static str,// Class name
|
||||
phf::Map<&'static str,// Value name
|
||||
CreateUserData
|
||||
>
|
||||
>;
|
||||
static LAZY_USER_DATA:LUD=phf::phf_map!{
|
||||
"RunService"=>phf::phf_map!{
|
||||
"RenderStepped"=>|lua|{
|
||||
lua.create_any_userdata(crate::runner::script_signal::ScriptSignal::new())
|
||||
},
|
||||
},
|
||||
};
|
||||
#[derive(Default)]
|
||||
pub struct InstanceValueStore{
|
||||
values:HashMap<Ref,
|
||||
HashMap<&'static str,
|
||||
mlua::AnyUserData
|
||||
>
|
||||
>,
|
||||
}
|
||||
pub struct InstanceValues<'a>{
|
||||
named_values:&'static phf::Map<&'static str,CreateUserData>,
|
||||
values:&'a mut HashMap<&'static str,mlua::AnyUserData>,
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
pub mod instance;
|
||||
pub use instance::Instance;
|
||||
pub use instance::InstanceRef;
|
||||
|
@ -7,7 +7,7 @@ mod color3;
|
||||
mod cframe;
|
||||
mod vector3;
|
||||
pub mod instance;
|
||||
mod script_signal;
|
||||
pub mod script_signal;
|
||||
mod color_sequence;
|
||||
mod number_sequence;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::context::Context;
|
||||
#[cfg(feature="run-service")]
|
||||
use crate::scheduler::scheduler_mut;
|
||||
use crate::types::WeakDom;
|
||||
|
||||
pub struct Runner{
|
||||
lua:mlua::Lua,
|
||||
@ -60,11 +61,11 @@ impl Runner{
|
||||
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::InstanceRef::new(services.game)).map_err(Error::RustLua)?;
|
||||
globals.set("workspace",super::instance::InstanceRef::new(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)});
|
||||
self.lua.set_app_data::<&'static mut WeakDom>(unsafe{core::mem::transmute(&mut context.dom)});
|
||||
#[cfg(feature="run-service")]
|
||||
self.lua.set_app_data::<crate::scheduler::Scheduler>(crate::scheduler::Scheduler::default());
|
||||
Ok(Runnable{
|
||||
@ -81,14 +82,14 @@ pub struct Runnable<'a>{
|
||||
}
|
||||
impl Runnable<'_>{
|
||||
pub fn drop_context(self)->Runner{
|
||||
self.lua.remove_app_data::<&'static mut rbx_dom_weak::WeakDom>();
|
||||
self.lua.remove_app_data::<&'static mut WeakDom>();
|
||||
#[cfg(feature="run-service")]
|
||||
self.lua.remove_app_data::<crate::scheduler::Scheduler>();
|
||||
Runner{
|
||||
lua:self.lua,
|
||||
}
|
||||
}
|
||||
pub fn run_script(&self,script:super::instance::Instance)->Result<(),Error>{
|
||||
pub fn run_script(&self,script:super::instance::InstanceRef)->Result<(),Error>{
|
||||
let (name,source)=super::instance::instance::get_name_source(&self.lua,script).map_err(Error::RustLua)?;
|
||||
self.lua.globals().raw_set("script",script).map_err(Error::RustLua)?;
|
||||
let f=self.lua.load(source.as_str())
|
||||
@ -123,20 +124,15 @@ impl Runnable<'_>{
|
||||
}
|
||||
#[cfg(feature="run-service")]
|
||||
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"))?;
|
||||
super::instance::instance::instance_value_store_mut(&self.lua,|instance_value_store|{
|
||||
//unwrap because I trust my find_first_child_of_class function to
|
||||
let mut instance_values=instance_value_store.get_or_create_instance_values(run_service).ok_or_else(||mlua::Error::runtime("RunService InstanceValues missing"))?;
|
||||
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)
|
||||
Ok(match run_service.userdata.get(&rbx_dom_weak::ustr("RenderStepped")){
|
||||
Some(render_stepped)=>Some(render_stepped.borrow::<super::script_signal::ScriptSignal>()?.clone()),
|
||||
None=>None
|
||||
})
|
||||
})?;
|
||||
if let Some(render_stepped)=render_stepped{
|
||||
let signal:&super::script_signal::ScriptSignal=&*render_stepped.borrow()?;
|
||||
signal.fire(&mlua::MultiValue::new());
|
||||
if let Some(render_stepped_signal)=render_stepped_signal{
|
||||
render_stepped_signal.fire(&mlua::MultiValue::new());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
57
lib/roblox_emulator/src/types.rs
Normal file
57
lib/roblox_emulator/src/types.rs
Normal file
@ -0,0 +1,57 @@
|
||||
pub struct Instance{
|
||||
pub(crate) instance:rbx_dom_weak::Instance,
|
||||
pub(crate) userdata:rbx_dom_weak::UstrMap<mlua::AnyUserData>,
|
||||
}
|
||||
impl AsRef<rbx_dom_weak::Instance> for Instance{
|
||||
fn as_ref(&self)->&rbx_dom_weak::Instance{
|
||||
&self.instance
|
||||
}
|
||||
}
|
||||
impl AsMut<rbx_dom_weak::Instance> for Instance{
|
||||
fn as_mut(&mut self)->&mut rbx_dom_weak::Instance{
|
||||
&mut self.instance
|
||||
}
|
||||
}
|
||||
impl From<Instance> for rbx_dom_weak::Instance{
|
||||
fn from(instance:Instance)->Self{
|
||||
instance.instance
|
||||
}
|
||||
}
|
||||
impl From<rbx_dom_weak::Instance> for Instance{
|
||||
fn from(instance:rbx_dom_weak::Instance)->Self{
|
||||
Self{
|
||||
instance,
|
||||
userdata:Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type WeakDom=rbx_dom_weak::GenericWeakDom<Instance>;
|
||||
|
||||
// lazy-loaded per-instance userdata values
|
||||
type CreateUserData=fn(&mlua::Lua)->mlua::Result<mlua::AnyUserData>;
|
||||
type LUD=phf::Map<&'static str,// Class name
|
||||
phf::Map<&'static str,// Value name
|
||||
CreateUserData
|
||||
>
|
||||
>;
|
||||
static LAZY_USER_DATA:LUD=phf::phf_map!{
|
||||
"RunService"=>phf::phf_map!{
|
||||
"RenderStepped"=>|lua|lua.create_any_userdata(crate::runner::script_signal::ScriptSignal::new()),
|
||||
},
|
||||
};
|
||||
impl Instance{
|
||||
pub fn get_or_create_userdata(&mut self,lua:&mlua::Lua,index:rbx_dom_weak::Ustr)->mlua::Result<Option<mlua::AnyUserData>>{
|
||||
use std::collections::hash_map::Entry;
|
||||
Ok(match LAZY_USER_DATA.get(self.instance.class.as_str()){
|
||||
Some(userdata_map)=>match self.userdata.entry(index){
|
||||
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,
|
||||
},
|
||||
},
|
||||
None=>None,
|
||||
})
|
||||
}
|
||||
}
|
@ -14,10 +14,10 @@ image = "0.25.2"
|
||||
image_dds = "0.7.1"
|
||||
lazy-regex = "3.1.0"
|
||||
rbx_asset = { version = "0.4.4", registry = "strafesnet" }
|
||||
rbx_binary = "1.0.0"
|
||||
rbx_dom_weak = "3.0.0"
|
||||
rbx_binary = { version = "1.1.0-sn3", registry = "strafesnet"}
|
||||
rbx_dom_weak = { version = "3.1.0-sn1", registry = "strafesnet"}
|
||||
rbx_reflection_database = "1.0.0"
|
||||
rbx_xml = "1.0.0"
|
||||
rbx_xml = { version = "1.1.0-sn3", registry = "strafesnet"}
|
||||
rbxassetid = { version = "0.1.0", registry = "strafesnet" }
|
||||
strafesnet_bsp_loader = { version = "0.3.0", path = "../lib/bsp_loader", registry = "strafesnet" }
|
||||
strafesnet_deferred_loader = { version = "0.5.0", path = "../lib/deferred_loader", registry = "strafesnet" }
|
||||
|
Loading…
x
Reference in New Issue
Block a user