wip: hash_str
This commit is contained in:
lib
rbx_loader
roblox_emulator
src
@ -21,19 +21,19 @@ pub mod data{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Model{
|
pub struct Model<'a>{
|
||||||
dom:WeakDom,
|
dom:WeakDom<'a>,
|
||||||
}
|
}
|
||||||
impl Model{
|
impl<'a> Model<'a>{
|
||||||
fn new(dom:WeakDom)->Self{
|
fn new(dom:WeakDom<'a>)->Self{
|
||||||
Self{dom}
|
Self{dom}
|
||||||
}
|
}
|
||||||
pub fn to_snf(&self,failure_mode:LoadFailureMode)->Result<strafesnet_common::map::CompleteMap,LoadError>{
|
pub fn to_snf(&self,failure_mode:LoadFailureMode)->Result<strafesnet_common::map::CompleteMap,LoadError>{
|
||||||
to_snf(self,failure_mode)
|
to_snf(self,failure_mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl AsRef<WeakDom> for Model{
|
impl<'a> AsRef<WeakDom<'a>> for Model<'a>{
|
||||||
fn as_ref(&self)->&WeakDom{
|
fn as_ref(&self)->&WeakDom<'a>{
|
||||||
&self.dom
|
&self.dom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ pub fn read<R:Read>(input:R)->Result<Model,ReadError>{
|
|||||||
let mut buf=std::io::BufReader::new(input);
|
let mut buf=std::io::BufReader::new(input);
|
||||||
let peek=std::io::BufRead::fill_buf(&mut buf).map_err(ReadError::Io)?;
|
let peek=std::io::BufRead::fill_buf(&mut buf).map_err(ReadError::Io)?;
|
||||||
match peek.get(0..8){
|
match peek.get(0..8){
|
||||||
Some(b"<roblox!")=>rbx_binary::from_reader(buf).map(Model::new).map_err(ReadError::RbxBinary),
|
Some(b"<roblox!")=>rbx_binary::from_reader_default(buf).map(Model::new).map_err(ReadError::RbxBinary),
|
||||||
Some(b"<roblox ")=>rbx_xml::from_reader_default(buf).map(Model::new).map_err(ReadError::RbxXml),
|
Some(b"<roblox ")=>rbx_xml::from_reader_default(buf).map(Model::new).map_err(ReadError::RbxXml),
|
||||||
_=>Err(ReadError::UnknownFileFormat),
|
_=>Err(ReadError::UnknownFileFormat),
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,7 @@ use strafesnet_deferred_loader::{loader::Loader,texture::Texture};
|
|||||||
use crate::data::RobloxMeshBytes;
|
use crate::data::RobloxMeshBytes;
|
||||||
use crate::rbx::RobloxPartDescription;
|
use crate::rbx::RobloxPartDescription;
|
||||||
|
|
||||||
// disallow non-static lifetimes
|
use rbx_dom_weak::hstr;
|
||||||
fn static_ustr(s:&'static str)->rbx_dom_weak::Ustr{
|
|
||||||
rbx_dom_weak::ustr(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_entire_file(path:impl AsRef<std::path::Path>)->Result<Vec<u8>,std::io::Error>{
|
fn read_entire_file(path:impl AsRef<std::path::Path>)->Result<Vec<u8>,std::io::Error>{
|
||||||
let mut file=std::fs::File::open(path)?;
|
let mut file=std::fs::File::open(path)?;
|
||||||
@ -168,7 +165,7 @@ impl Loader for MeshLoader{
|
|||||||
let RobloxAssetId(asset_id)=index.content.parse()?;
|
let RobloxAssetId(asset_id)=index.content.parse()?;
|
||||||
let file_name=format!("unions/{}",asset_id);
|
let file_name=format!("unions/{}",asset_id);
|
||||||
let data=read_entire_file(file_name)?;
|
let data=read_entire_file(file_name)?;
|
||||||
let dom=rbx_binary::from_reader(std::io::Cursor::new(data))?;
|
let dom=rbx_binary::from_reader_default(data.as_slice())?;
|
||||||
let &[referent]=dom.root().children()else{
|
let &[referent]=dom.root().children()else{
|
||||||
return Err(MeshError::OneChildPolicy);
|
return Err(MeshError::OneChildPolicy);
|
||||||
};
|
};
|
||||||
@ -176,12 +173,12 @@ impl Loader for MeshLoader{
|
|||||||
return Err(MeshError::MissingInstance);
|
return Err(MeshError::MissingInstance);
|
||||||
};
|
};
|
||||||
if physics_data.is_empty(){
|
if physics_data.is_empty(){
|
||||||
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get(&static_ustr("PhysicsData")){
|
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get(hstr!("PhysicsData")){
|
||||||
physics_data=data.as_ref();
|
physics_data=data.as_ref();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if mesh_data.is_empty(){
|
if mesh_data.is_empty(){
|
||||||
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get(&static_ustr("MeshData")){
|
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get(hstr!("MeshData")){
|
||||||
mesh_data=data.as_ref();
|
mesh_data=data.as_ref();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,16 +13,13 @@ use strafesnet_deferred_loader::deferred_loader::{RenderConfigDeferredLoader,Mes
|
|||||||
use strafesnet_deferred_loader::mesh::Meshes;
|
use strafesnet_deferred_loader::mesh::Meshes;
|
||||||
use strafesnet_deferred_loader::texture::{RenderConfigs,Texture};
|
use strafesnet_deferred_loader::texture::{RenderConfigs,Texture};
|
||||||
|
|
||||||
// disallow non-static lifetimes
|
use rbx_dom_weak::{hstr,HashStr};
|
||||||
fn static_ustr(s:&'static str)->rbx_dom_weak::Ustr{
|
|
||||||
rbx_dom_weak::ustr(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recursive_collect_superclass(
|
fn recursive_collect_superclass(
|
||||||
objects:&mut std::vec::Vec<rbx_dom_weak::types::Ref>,
|
objects:&mut std::vec::Vec<rbx_dom_weak::types::Ref>,
|
||||||
dom:&rbx_dom_weak::WeakDom,
|
dom:&rbx_dom_weak::WeakDom,
|
||||||
instance:&rbx_dom_weak::Instance,
|
instance:&rbx_dom_weak::Instance,
|
||||||
superclass:&str
|
superclass:&HashStr,
|
||||||
){
|
){
|
||||||
let instance=instance;
|
let instance=instance;
|
||||||
let db=rbx_reflection_database::get();
|
let db=rbx_reflection_database::get();
|
||||||
@ -31,7 +28,7 @@ fn recursive_collect_superclass(
|
|||||||
};
|
};
|
||||||
objects.extend(
|
objects.extend(
|
||||||
dom.descendants_of(instance.referent()).filter_map(|instance|{
|
dom.descendants_of(instance.referent()).filter_map(|instance|{
|
||||||
let class=db.classes.get(instance.class.as_str())?;
|
let class=db.classes.get(instance.class)?;
|
||||||
db.has_superclass(class,superclass).then(||instance.referent())
|
db.has_superclass(class,superclass).then(||instance.referent())
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -410,7 +407,7 @@ fn get_texture_description<'a>(
|
|||||||
//use the biggest one and cut it down later...
|
//use the biggest one and cut it down later...
|
||||||
let mut part_texture_description=RobloxPartDescription::default();
|
let mut part_texture_description=RobloxPartDescription::default();
|
||||||
temp_objects.clear();
|
temp_objects.clear();
|
||||||
recursive_collect_superclass(temp_objects,&dom,object,"Decal");
|
recursive_collect_superclass(temp_objects,&dom,object,hstr!("Decal"));
|
||||||
for &mut decal_ref in temp_objects{
|
for &mut decal_ref in temp_objects{
|
||||||
let Some(decal)=dom.get_by_ref(decal_ref) else{
|
let Some(decal)=dom.get_by_ref(decal_ref) else{
|
||||||
println!("Decal get_by_ref failed");
|
println!("Decal get_by_ref failed");
|
||||||
@ -422,10 +419,10 @@ fn get_texture_description<'a>(
|
|||||||
Some(rbx_dom_weak::types::Variant::Color3(decal_color3)),
|
Some(rbx_dom_weak::types::Variant::Color3(decal_color3)),
|
||||||
Some(rbx_dom_weak::types::Variant::Float32(decal_transparency)),
|
Some(rbx_dom_weak::types::Variant::Float32(decal_transparency)),
|
||||||
)=(
|
)=(
|
||||||
decal.properties.get(&static_ustr("TextureContent")),
|
decal.properties.get(hstr!("TextureContent")),
|
||||||
decal.properties.get(&static_ustr("Face")),
|
decal.properties.get(hstr!("Face")),
|
||||||
decal.properties.get(&static_ustr("Color3")),
|
decal.properties.get(hstr!("Color3")),
|
||||||
decal.properties.get(&static_ustr("Transparency")),
|
decal.properties.get(hstr!("Transparency")),
|
||||||
)else{
|
)else{
|
||||||
println!("Decal is missing a required property");
|
println!("Decal is missing a required property");
|
||||||
continue;
|
continue;
|
||||||
@ -447,10 +444,10 @@ fn get_texture_description<'a>(
|
|||||||
Some(&rbx_dom_weak::types::Variant::Float32(studs_per_tile_u)),
|
Some(&rbx_dom_weak::types::Variant::Float32(studs_per_tile_u)),
|
||||||
Some(&rbx_dom_weak::types::Variant::Float32(studs_per_tile_v)),
|
Some(&rbx_dom_weak::types::Variant::Float32(studs_per_tile_v)),
|
||||||
) = (
|
) = (
|
||||||
decal.properties.get(&static_ustr("OffsetStudsU")),
|
decal.properties.get(hstr!("OffsetStudsU")),
|
||||||
decal.properties.get(&static_ustr("OffsetStudsV")),
|
decal.properties.get(hstr!("OffsetStudsV")),
|
||||||
decal.properties.get(&static_ustr("StudsPerTileU")),
|
decal.properties.get(hstr!("StudsPerTileU")),
|
||||||
decal.properties.get(&static_ustr("StudsPerTileV")),
|
decal.properties.get(hstr!("StudsPerTileV")),
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let (size_u,size_v)=match cube_face{
|
let (size_u,size_v)=match cube_face{
|
||||||
@ -537,7 +534,7 @@ pub fn convert<'a>(
|
|||||||
|
|
||||||
let mut object_refs=Vec::new();
|
let mut object_refs=Vec::new();
|
||||||
let mut temp_objects=Vec::new();
|
let mut temp_objects=Vec::new();
|
||||||
recursive_collect_superclass(&mut object_refs, &dom, dom.root(),"BasePart");
|
recursive_collect_superclass(&mut object_refs, &dom, dom.root(),hstr!("BasePart"));
|
||||||
for object_ref in object_refs {
|
for object_ref in object_refs {
|
||||||
if let Some(object)=dom.get_by_ref(object_ref){
|
if let Some(object)=dom.get_by_ref(object_ref){
|
||||||
if let (
|
if let (
|
||||||
@ -548,12 +545,12 @@ pub fn convert<'a>(
|
|||||||
Some(rbx_dom_weak::types::Variant::Color3uint8(color3)),
|
Some(rbx_dom_weak::types::Variant::Color3uint8(color3)),
|
||||||
Some(rbx_dom_weak::types::Variant::Bool(can_collide)),
|
Some(rbx_dom_weak::types::Variant::Bool(can_collide)),
|
||||||
) = (
|
) = (
|
||||||
object.properties.get(&static_ustr("CFrame")),
|
object.properties.get(hstr!("CFrame")),
|
||||||
object.properties.get(&static_ustr("Size")),
|
object.properties.get(hstr!("Size")),
|
||||||
object.properties.get(&static_ustr("Velocity")),
|
object.properties.get(hstr!("Velocity")),
|
||||||
object.properties.get(&static_ustr("Transparency")),
|
object.properties.get(hstr!("Transparency")),
|
||||||
object.properties.get(&static_ustr("Color")),
|
object.properties.get(hstr!("Color")),
|
||||||
object.properties.get(&static_ustr("CanCollide")),
|
object.properties.get(hstr!("CanCollide")),
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let model_transform=planar64_affine3_from_roblox(cf,size);
|
let model_transform=planar64_affine3_from_roblox(cf,size);
|
||||||
@ -572,7 +569,7 @@ pub fn convert<'a>(
|
|||||||
|
|
||||||
//TODO: also detect "CylinderMesh" etc here
|
//TODO: also detect "CylinderMesh" etc here
|
||||||
let shape=match object.class.as_str(){
|
let shape=match object.class.as_str(){
|
||||||
"Part"=>if let Some(rbx_dom_weak::types::Variant::Enum(shape))=object.properties.get(&static_ustr("Shape")){
|
"Part"=>if let Some(rbx_dom_weak::types::Variant::Enum(shape))=object.properties.get(hstr!("Shape")){
|
||||||
Shape::Primitive(shape.to_u32().try_into().expect("Funky roblox PartType"))
|
Shape::Primitive(shape.to_u32().try_into().expect("Funky roblox PartType"))
|
||||||
}else{
|
}else{
|
||||||
panic!("Part has no Shape!");
|
panic!("Part has no Shape!");
|
||||||
@ -646,9 +643,9 @@ pub fn convert<'a>(
|
|||||||
Some(rbx_dom_weak::types::Variant::Content(texture_content)),
|
Some(rbx_dom_weak::types::Variant::Content(texture_content)),
|
||||||
)=(
|
)=(
|
||||||
// mesh must exist
|
// mesh must exist
|
||||||
object.properties.get(&static_ustr("MeshContent")),
|
object.properties.get(hstr!("MeshContent")),
|
||||||
// texture is allowed to be none
|
// texture is allowed to be none
|
||||||
object.properties.get(&static_ustr("TextureContent")),
|
object.properties.get(hstr!("TextureContent")),
|
||||||
){
|
){
|
||||||
let mesh_asset_id=get_content_url(mesh_content).expect("MeshPart Mesh is not a Uri");
|
let mesh_asset_id=get_content_url(mesh_content).expect("MeshPart Mesh is not a Uri");
|
||||||
let texture_asset_id=get_content_url(texture_content);
|
let texture_asset_id=get_content_url(texture_content);
|
||||||
@ -663,13 +660,13 @@ pub fn convert<'a>(
|
|||||||
let mut content="";
|
let mut content="";
|
||||||
let mut mesh_data:&[u8]=&[];
|
let mut mesh_data:&[u8]=&[];
|
||||||
let mut physics_data:&[u8]=&[];
|
let mut physics_data:&[u8]=&[];
|
||||||
if let Some(rbx_dom_weak::types::Variant::ContentId(asset_id))=object.properties.get(&static_ustr("AssetId")){
|
if let Some(rbx_dom_weak::types::Variant::ContentId(asset_id))=object.properties.get(hstr!("AssetId")){
|
||||||
content=asset_id.as_ref();
|
content=asset_id.as_ref();
|
||||||
}
|
}
|
||||||
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get(&static_ustr("MeshData")){
|
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get(hstr!("MeshData")){
|
||||||
mesh_data=data.as_ref();
|
mesh_data=data.as_ref();
|
||||||
}
|
}
|
||||||
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get(&static_ustr("PhysicsData")){
|
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get(hstr!("PhysicsData")){
|
||||||
physics_data=data.as_ref();
|
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,size);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::util::static_ustr;
|
use rbx_dom_weak::{hstr,types::Ref,InstanceBuilder,WeakDom,UnhashedStr};
|
||||||
use rbx_dom_weak::{types::Ref,InstanceBuilder,WeakDom};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ServicesError{
|
pub enum ServicesError{
|
||||||
@ -28,36 +27,36 @@ impl Services{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type LuaAppData=&'static mut WeakDom;
|
pub type LuaAppData=&'static mut WeakDom<'static>;
|
||||||
pub struct Context{
|
pub struct Context<'a>{
|
||||||
pub(crate)dom:WeakDom,
|
pub(crate)dom:WeakDom<'a>,
|
||||||
pub(crate)services:Services,
|
pub(crate)services:Services,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context{
|
impl<'a> Context<'a>{
|
||||||
pub fn from_place(dom:WeakDom)->Result<Context,ServicesError>{
|
pub fn from_place(dom:WeakDom<'a>)->Result<Context<'a>,ServicesError>{
|
||||||
let services=Services::find_services(&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<'a>,crate::runner::instance::Instance){
|
||||||
let script=InstanceBuilder::new("Script")
|
let script=InstanceBuilder::new(hstr!("Script"))
|
||||||
.with_property("Source",rbx_types::Variant::String(source));
|
.with_property(hstr!("Source"),rbx_types::Variant::String(source));
|
||||||
let script_ref=script.referent();
|
let script_ref=script.referent();
|
||||||
let dom=WeakDom::new(
|
let dom=WeakDom::new(
|
||||||
InstanceBuilder::new("DataModel")
|
InstanceBuilder::new(hstr!("DataModel"))
|
||||||
.with_child(script)
|
.with_child(script)
|
||||||
);
|
);
|
||||||
let context=Self::from_model(dom);
|
let context=Self::from_model(dom);
|
||||||
(context,crate::runner::instance::Instance::new_unchecked(script_ref))
|
(context,crate::runner::instance::Instance::new_unchecked(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<'b>(&'b self,superclass:&'b str)->impl Iterator<Item=Ref>+'b{
|
||||||
let db=rbx_reflection_database::get();
|
let db=rbx_reflection_database::get();
|
||||||
let Some(superclass)=db.classes.get(superclass)else{
|
let Some(superclass)=db.classes.get(UnhashedStr::from_ref(superclass))else{
|
||||||
panic!("Invalid class");
|
panic!("Invalid class");
|
||||||
};
|
};
|
||||||
self.dom.descendants().filter_map(|instance|{
|
self.dom.descendants().filter_map(|instance|{
|
||||||
let class=db.classes.get(instance.class.as_str())?;
|
let class=db.classes.get(instance.class)?;
|
||||||
db.has_superclass(class,superclass).then(||instance.referent())
|
db.has_superclass(class,superclass).then(||instance.referent())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -65,7 +64,7 @@ impl Context{
|
|||||||
self.superclass_iter("Script")
|
self.superclass_iter("Script")
|
||||||
.filter_map(|script_ref|{
|
.filter_map(|script_ref|{
|
||||||
let script=self.dom.get_by_ref(script_ref)?;
|
let script=self.dom.get_by_ref(script_ref)?;
|
||||||
if let None|Some(rbx_dom_weak::types::Variant::Bool(false))=script.properties.get(&static_ustr("Disabled")){
|
if let None|Some(rbx_dom_weak::types::Variant::Bool(false))=script.properties.get(hstr!("Disabled")){
|
||||||
return Some(crate::runner::instance::Instance::new_unchecked(script_ref));
|
return Some(crate::runner::instance::Instance::new_unchecked(script_ref));
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -73,17 +72,17 @@ impl Context{
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_model(mut dom:WeakDom)->Context{
|
pub fn from_model(mut dom:WeakDom<'a>)->Context<'a>{
|
||||||
//snapshot root instances
|
//snapshot root instances
|
||||||
let children=dom.root().children().to_owned();
|
let children=dom.root().children().to_owned();
|
||||||
|
|
||||||
//insert services
|
//insert services
|
||||||
let game=dom.root_ref();
|
let game=dom.root_ref();
|
||||||
let terrain_bldr=InstanceBuilder::new("Terrain");
|
let terrain_bldr=InstanceBuilder::new(hstr!("Terrain"));
|
||||||
let workspace=dom.insert(game,
|
let workspace=dom.insert(game,
|
||||||
InstanceBuilder::new("Workspace")
|
InstanceBuilder::new(hstr!("Workspace"))
|
||||||
//Set Workspace.Terrain property equal to Terrain
|
//Set Workspace.Terrain property equal to Terrain
|
||||||
.with_property("Terrain",terrain_bldr.referent())
|
.with_property(hstr!("Terrain"),terrain_bldr.referent())
|
||||||
.with_child(terrain_bldr)
|
.with_child(terrain_bldr)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -96,18 +95,18 @@ impl Context{
|
|||||||
//Lowercase and upper case workspace property!
|
//Lowercase and upper case workspace property!
|
||||||
let game=dom.root_mut();
|
let game=dom.root_mut();
|
||||||
// TODO: DELETE THIS!
|
// TODO: DELETE THIS!
|
||||||
game.properties.insert(static_ustr("workspace"),rbx_types::Variant::Ref(workspace));
|
game.properties.insert(hstr!("workspace"),rbx_types::Variant::Ref(workspace));
|
||||||
game.properties.insert(static_ustr("Workspace"),rbx_types::Variant::Ref(workspace));
|
game.properties.insert(hstr!("Workspace"),rbx_types::Variant::Ref(workspace));
|
||||||
}
|
}
|
||||||
dom.insert(game,InstanceBuilder::new("Lighting"));
|
dom.insert(game,InstanceBuilder::new(hstr!("Lighting")));
|
||||||
|
|
||||||
let services=Services{game,workspace};
|
let services=Services{game,workspace};
|
||||||
Self{dom,services}
|
Self{dom,services}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<WeakDom> for Context{
|
impl<'a> AsRef<WeakDom<'a>> for Context<'a>{
|
||||||
fn as_ref(&self)->&WeakDom{
|
fn as_ref(&self)->&WeakDom<'a>{
|
||||||
&self.dom
|
&self.dom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
mod util;
|
|
||||||
pub mod runner;
|
pub mod runner;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
#[cfg(feature="run-service")]
|
#[cfg(feature="run-service")]
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
|
use rbx_dom_weak::{HashStr, UnhashedStr};
|
||||||
|
|
||||||
#[derive(Clone,Copy)]
|
#[derive(Clone,Copy)]
|
||||||
pub struct EnumItem<'a>{
|
pub struct EnumItem<'a>{
|
||||||
name:Option<&'a str>,
|
name:Option<&'a HashStr>,
|
||||||
value:u32,
|
value:u32,
|
||||||
}
|
}
|
||||||
impl<'a> EnumItem<'a>{
|
impl<'a> EnumItem<'a>{
|
||||||
fn known_name((name,&value):(&'a std::borrow::Cow<'a,str>,&u32))->Self{
|
fn known_name((name,&value):(&&'a HashStr,&u32))->Self{
|
||||||
Self{name:Some(name.as_ref()),value}
|
Self{name:Some(name),value}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> From<rbx_types::Enum> for EnumItem<'a>{
|
impl<'a> From<rbx_types::Enum> for EnumItem<'a>{
|
||||||
@ -38,7 +40,7 @@ pub struct Enums;
|
|||||||
impl Enums{
|
impl Enums{
|
||||||
pub fn get(&self,index:&str)->Option<EnumItems<'static>>{
|
pub fn get(&self,index:&str)->Option<EnumItems<'static>>{
|
||||||
let db=rbx_reflection_database::get();
|
let db=rbx_reflection_database::get();
|
||||||
db.enums.get(index).map(|ed|EnumItems{ed})
|
db.enums.get(UnhashedStr::from_ref(index)).map(|ed|EnumItems{ed})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Clone,Copy)]
|
#[derive(Clone,Copy)]
|
||||||
@ -51,7 +53,7 @@ impl<'a> EnumItems<'a>{
|
|||||||
self.ed.items.iter().find(|&(_,&v)|v==value).map(EnumItem::known_name)
|
self.ed.items.iter().find(|&(_,&v)|v==value).map(EnumItem::known_name)
|
||||||
}
|
}
|
||||||
pub fn from_name(&self,name:&str)->Option<EnumItem<'a>>{
|
pub fn from_name(&self,name:&str)->Option<EnumItem<'a>>{
|
||||||
self.ed.items.get_key_value(name).map(EnumItem::known_name)
|
self.ed.items.get_key_value(UnhashedStr::from_ref(name)).map(EnumItem::known_name)
|
||||||
}
|
}
|
||||||
pub fn from_enum(&self,enum_item:EnumItem)->Option<EnumItem<'a>>{
|
pub fn from_enum(&self,enum_item:EnumItem)->Option<EnumItem<'a>>{
|
||||||
match enum_item.name{
|
match enum_item.name{
|
||||||
@ -105,7 +107,7 @@ impl mlua::UserData for EnumItems<'static>{
|
|||||||
});
|
});
|
||||||
methods.add_meta_function(mlua::MetaMethod::Index,|_,(this,val):(EnumItems,mlua::String)|{
|
methods.add_meta_function(mlua::MetaMethod::Index,|_,(this,val):(EnumItems,mlua::String)|{
|
||||||
let index=&*val.to_str()?;
|
let index=&*val.to_str()?;
|
||||||
Ok(this.ed.items.get_key_value(index).map(EnumItem::known_name))
|
Ok(this.ed.items.get_key_value(UnhashedStr::from_ref(index)).map(EnumItem::known_name))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +126,7 @@ type_from_lua_userdata!(Enums);
|
|||||||
|
|
||||||
impl mlua::UserData for EnumItem<'_>{
|
impl mlua::UserData for EnumItem<'_>{
|
||||||
fn add_fields<F:mlua::UserDataFields<Self>>(fields:&mut F){
|
fn add_fields<F:mlua::UserDataFields<Self>>(fields:&mut F){
|
||||||
fields.add_field_method_get("Name",|_,this|Ok(this.name));
|
fields.add_field_method_get("Name",|_,this|Ok(this.name.map(|s|s.as_str())));
|
||||||
fields.add_field_method_get("Value",|_,this|Ok(this.value));
|
fields.add_field_method_get("Value",|_,this|Ok(this.value));
|
||||||
}
|
}
|
||||||
fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){
|
fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){
|
||||||
|
@ -2,9 +2,8 @@ use std::collections::{hash_map::Entry,HashMap};
|
|||||||
|
|
||||||
use mlua::{FromLua,FromLuaMulti,IntoLua,IntoLuaMulti};
|
use mlua::{FromLua,FromLuaMulti,IntoLua,IntoLuaMulti};
|
||||||
use rbx_types::Ref;
|
use rbx_types::Ref;
|
||||||
use rbx_dom_weak::{Ustr,InstanceBuilder,WeakDom};
|
use rbx_dom_weak::{hstr,HashStr,UnhashedStr,InstanceBuilder,WeakDom};
|
||||||
|
|
||||||
use crate::util::static_ustr;
|
|
||||||
use crate::runner::vector3::Vector3;
|
use crate::runner::vector3::Vector3;
|
||||||
use crate::runner::number::Number;
|
use crate::runner::number::Number;
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ pub fn dom_mut<T>(lua:&mlua::Lua,mut f:impl FnMut(&mut WeakDom)->mlua::Result<T>
|
|||||||
|
|
||||||
pub fn class_is_a(class:&str,superclass:&str)->bool{
|
pub fn class_is_a(class:&str,superclass:&str)->bool{
|
||||||
let db=rbx_reflection_database::get();
|
let db=rbx_reflection_database::get();
|
||||||
let (Some(class),Some(superclass))=(db.classes.get(class),db.classes.get(superclass))else{
|
let (Some(class),Some(superclass))=(db.classes.get(UnhashedStr::from_ref(class)),db.classes.get(UnhashedStr::from_ref(superclass)))else{
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
db.has_superclass(class,superclass)
|
db.has_superclass(class,superclass)
|
||||||
@ -57,7 +56,7 @@ fn get_full_name(dom:&rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance)->S
|
|||||||
pub fn get_name_source(lua:&mlua::Lua,script:Instance)->Result<(String,String),mlua::Error>{
|
pub fn get_name_source(lua:&mlua::Lua,script:Instance)->Result<(String,String),mlua::Error>{
|
||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
let instance=script.get(dom)?;
|
let instance=script.get(dom)?;
|
||||||
let source=match instance.properties.get(&static_ustr("Source")){
|
let source=match instance.properties.get(hstr!("Source")){
|
||||||
Some(rbx_dom_weak::types::Variant::String(s))=>s.clone(),
|
Some(rbx_dom_weak::types::Variant::String(s))=>s.clone(),
|
||||||
_=>Err(mlua::Error::external("Missing script.Source"))?,
|
_=>Err(mlua::Error::external("Missing script.Source"))?,
|
||||||
};
|
};
|
||||||
@ -65,32 +64,32 @@ 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>{
|
pub fn find_first_child<'a>(dom:&'a rbx_dom_weak::WeakDom<'a>,instance:&rbx_dom_weak::Instance<'a>,name:&str)->Option<&'a rbx_dom_weak::Instance<'a>>{
|
||||||
instance.children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|inst.name==name)
|
instance.children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|inst.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>{
|
pub fn find_first_descendant<'a>(dom:&'a rbx_dom_weak::WeakDom<'a>,instance:&rbx_dom_weak::Instance<'a>,name:&str)->Option<&'a rbx_dom_weak::Instance<'a>>{
|
||||||
dom.descendants_of(instance.referent()).find(|&inst|inst.name==name)
|
dom.descendants_of(instance.referent()).find(|&inst|inst.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>{
|
pub fn find_first_child_of_class<'a>(dom:&'a rbx_dom_weak::WeakDom<'a>,instance:&rbx_dom_weak::Instance<'a>,class:&str)->Option<&'a rbx_dom_weak::Instance<'a>>{
|
||||||
instance.children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|inst.class==class)
|
instance.children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|inst.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>{
|
pub fn find_first_descendant_of_class<'a>(dom:&'a rbx_dom_weak::WeakDom<'a>,instance:&rbx_dom_weak::Instance<'a>,class:&str)->Option<&'a rbx_dom_weak::Instance<'a>>{
|
||||||
dom.descendants_of(instance.referent()).find(|&inst|inst.class==class)
|
dom.descendants_of(instance.referent()).find(|&inst|inst.class==class)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_first_child_which_is_a<'a>(dom:&'a rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,superclass:&str)->Option<&'a rbx_dom_weak::Instance>{
|
pub fn find_first_child_which_is_a<'a>(dom:&'a rbx_dom_weak::WeakDom<'a>,instance:&rbx_dom_weak::Instance<'a>,superclass:&str)->Option<&'a rbx_dom_weak::Instance<'a>>{
|
||||||
let db=rbx_reflection_database::get();
|
let db=rbx_reflection_database::get();
|
||||||
let superclass_descriptor=db.classes.get(superclass)?;
|
let superclass_descriptor=db.classes.get(UnhashedStr::from_ref(superclass))?;
|
||||||
instance.children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|{
|
instance.children().iter().filter_map(|&r|dom.get_by_ref(r)).find(|inst|{
|
||||||
db.classes.get(inst.class.as_str()).is_some_and(|descriptor|db.has_superclass(descriptor,superclass_descriptor))
|
db.classes.get(inst.class).is_some_and(|descriptor|db.has_superclass(descriptor,superclass_descriptor))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn find_first_descendant_which_is_a<'a>(dom:&'a rbx_dom_weak::WeakDom,instance:&rbx_dom_weak::Instance,superclass:&str)->Option<&'a rbx_dom_weak::Instance>{
|
pub fn find_first_descendant_which_is_a<'a>(dom:&'a rbx_dom_weak::WeakDom<'a>,instance:&rbx_dom_weak::Instance<'a>,superclass:&str)->Option<&'a rbx_dom_weak::Instance<'a>>{
|
||||||
let db=rbx_reflection_database::get();
|
let db=rbx_reflection_database::get();
|
||||||
let superclass_descriptor=db.classes.get(superclass)?;
|
let superclass_descriptor=db.classes.get(UnhashedStr::from_ref(superclass))?;
|
||||||
dom.descendants_of(instance.referent()).find(|inst|{
|
dom.descendants_of(instance.referent()).find(|inst|{
|
||||||
db.classes.get(inst.class.as_str()).is_some_and(|descriptor|db.has_superclass(descriptor,superclass_descriptor))
|
db.classes.get(inst.class).is_some_and(|descriptor|db.has_superclass(descriptor,superclass_descriptor))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,10 +104,10 @@ impl Instance{
|
|||||||
pub fn new(referent:Ref)->Option<Self>{
|
pub fn new(referent:Ref)->Option<Self>{
|
||||||
referent.is_some().then_some(Self{referent})
|
referent.is_some().then_some(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<'a>)->mlua::Result<&'a rbx_dom_weak::Instance<'a>>{
|
||||||
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"))
|
||||||
}
|
}
|
||||||
pub fn get_mut<'a>(&self,dom:&'a mut WeakDom)->mlua::Result<&'a mut rbx_dom_weak::Instance>{
|
pub fn get_mut<'a,'b>(&self,dom:&'a mut WeakDom<'b>)->mlua::Result<&'a mut rbx_dom_weak::Instance<'b>>{
|
||||||
dom.get_by_ref_mut(self.referent).ok_or_else(||mlua::Error::runtime("Instance missing"))
|
dom.get_by_ref_mut(self.referent).ok_or_else(||mlua::Error::runtime("Instance missing"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +149,7 @@ impl mlua::UserData for Instance{
|
|||||||
fields.add_field_method_get("ClassName",|lua,this|{
|
fields.add_field_method_get("ClassName",|lua,this|{
|
||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
let instance=this.get(dom)?;
|
let instance=this.get(dom)?;
|
||||||
Ok(instance.class.to_owned())
|
Ok(instance.class.as_str().to_owned())
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -283,7 +282,7 @@ impl mlua::UserData for Instance{
|
|||||||
let instance=this.get(dom)?;
|
let instance=this.get(dom)?;
|
||||||
//println!("__index t={} i={index:?}",instance.name);
|
//println!("__index t={} i={index:?}",instance.name);
|
||||||
let db=rbx_reflection_database::get();
|
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.class).ok_or_else(||mlua::Error::runtime("Class missing"))?;
|
||||||
// Find existing property
|
// Find existing property
|
||||||
// Interestingly, ustr can know ahead of time if
|
// Interestingly, ustr can know ahead of time if
|
||||||
// a property does not exist in any runtime instance
|
// a property does not exist in any runtime instance
|
||||||
@ -342,7 +341,7 @@ impl mlua::UserData for Instance{
|
|||||||
dom_mut(lua,|dom|{
|
dom_mut(lua,|dom|{
|
||||||
let instance=this.get_mut(dom)?;
|
let instance=this.get_mut(dom)?;
|
||||||
let db=rbx_reflection_database::get();
|
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.class).ok_or_else(||mlua::Error::runtime("Class missing"))?;
|
||||||
let property=db.superclasses_iter(class).find_map(|cls|
|
let property=db.superclasses_iter(class).find_map(|cls|
|
||||||
cls.properties.get(index_str)
|
cls.properties.get(index_str)
|
||||||
).ok_or_else(||
|
).ok_or_else(||
|
||||||
@ -590,7 +589,7 @@ static VIRTUAL_PROPERTY_DATABASE:VPD=phf::phf_map!{
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn find_virtual_property(
|
fn find_virtual_property(
|
||||||
properties:&rbx_dom_weak::UstrMap<rbx_types::Variant>,
|
properties:&rbx_dom_weak::HashStrMap<rbx_types::Variant>,
|
||||||
class:&rbx_reflection::ClassDescriptor,
|
class:&rbx_reflection::ClassDescriptor,
|
||||||
index:&str,
|
index:&str,
|
||||||
)->Option<rbx_types::Variant>{
|
)->Option<rbx_types::Variant>{
|
||||||
@ -641,7 +640,7 @@ static LAZY_USER_DATA:LUD=phf::phf_map!{
|
|||||||
fn get_or_create_userdata(instance:&mut rbx_dom_weak::Instance,lua:&mlua::Lua,index:&str)->mlua::Result<Option<mlua::AnyUserData>>{
|
fn get_or_create_userdata(instance:&mut rbx_dom_weak::Instance,lua:&mlua::Lua,index:&str)->mlua::Result<Option<mlua::AnyUserData>>{
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
let db=rbx_reflection_database::get();
|
let db=rbx_reflection_database::get();
|
||||||
let Some(class)=db.classes.get(instance.class.as_str())else{
|
let Some(class)=db.classes.get(instance.class)else{
|
||||||
return Ok(None)
|
return Ok(None)
|
||||||
};
|
};
|
||||||
if let Some((&static_str,create_userdata))=db.superclasses_iter(class).find_map(|superclass|
|
if let Some((&static_str,create_userdata))=db.superclasses_iter(class).find_map(|superclass|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::util::static_ustr;
|
|
||||||
#[cfg(feature="run-service")]
|
#[cfg(feature="run-service")]
|
||||||
use crate::scheduler::scheduler_mut;
|
use crate::scheduler::scheduler_mut;
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ impl Runner{
|
|||||||
init(&runner.lua).map_err(Error::RustLua)?;
|
init(&runner.lua).map_err(Error::RustLua)?;
|
||||||
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<'a>)->Result<Runnable<'a>,Error>{
|
||||||
{
|
{
|
||||||
let globals=self.lua.globals();
|
let globals=self.lua.globals();
|
||||||
globals.set("game",super::instance::Instance::new_unchecked(context.services.game)).map_err(Error::RustLua)?;
|
globals.set("game",super::instance::Instance::new_unchecked(context.services.game)).map_err(Error::RustLua)?;
|
||||||
@ -68,8 +67,7 @@ impl Runner{
|
|||||||
// SAFETY: This is not a &'static mut WeakDom,
|
// SAFETY: This is not a &'static mut WeakDom,
|
||||||
// but as long as Runnable<'a> holds the lifetime of &'a mut Context
|
// but as long as Runnable<'a> holds the lifetime of &'a mut Context
|
||||||
// it is a valid unique reference.
|
// it is a valid unique reference.
|
||||||
let ptr=&mut context.dom as *mut rbx_dom_weak::WeakDom;
|
self.lua.set_app_data::<crate::context::LuaAppData>(unsafe{core::mem::transmute(&mut context.dom)});
|
||||||
self.lua.set_app_data::<crate::context::LuaAppData>(unsafe{&mut*ptr});
|
|
||||||
#[cfg(feature="run-service")]
|
#[cfg(feature="run-service")]
|
||||||
self.lua.set_app_data::<crate::scheduler::Scheduler>(crate::scheduler::Scheduler::default());
|
self.lua.set_app_data::<crate::scheduler::Scheduler>(crate::scheduler::Scheduler::default());
|
||||||
Ok(Runnable{
|
Ok(Runnable{
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
pub fn static_ustr(s:&'static str)->rbx_dom_weak::Ustr{
|
|
||||||
rbx_dom_weak::ustr(s)
|
|
||||||
}
|
|
Reference in New Issue
Block a user