update rbx-dom

This commit is contained in:
2025-04-14 21:12:45 -07:00
parent cb31c847d5
commit a3d39a81d0
9 changed files with 246 additions and 176 deletions
Cargo.lock
lib
rbx_loader
roblox_emulator
map-tool

@ -13,11 +13,11 @@ authors = ["Rhys Lloyd <krakow20@gmail.com>"]
bytemuck = "1.14.3"
glam = "0.30.0"
lazy-regex = "3.1.0"
rbx_binary = { version = "0.7.4", registry = "strafesnet" }
rbx_dom_weak = { version = "2.7.0", registry = "strafesnet" }
rbx_binary = "1.0.0"
rbx_dom_weak = "3.0.0"
rbx_mesh = "0.3.1"
rbx_reflection_database = { version = "0.2.10", registry = "strafesnet" }
rbx_xml = { version = "0.13.3", registry = "strafesnet" }
rbx_reflection_database = "1.0.0"
rbx_xml = "1.0.0"
rbxassetid = { version = "0.1.0", path = "../rbxassetid", registry = "strafesnet" }
roblox_emulator = { version = "0.4.7", path = "../roblox_emulator", registry = "strafesnet" }
strafesnet_common = { version = "0.6.0", path = "../common", registry = "strafesnet" }

@ -1,4 +1,5 @@
use std::io::Read;
use rbx_dom_weak::ustr;
use rbxassetid::{RobloxAssetId,RobloxAssetIdParseErr};
use strafesnet_common::model::Mesh;
use strafesnet_deferred_loader::{loader::Loader,texture::Texture};
@ -171,12 +172,12 @@ impl Loader for MeshLoader{
return Err(MeshError::MissingInstance);
};
if physics_data.is_empty(){
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get("PhysicsData"){
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get(&ustr("PhysicsData")){
physics_data=data.as_ref();
}
}
if mesh_data.is_empty(){
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get("MeshData"){
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=instance.properties.get(&ustr("MeshData")){
mesh_data=data.as_ref();
}
}

@ -1,6 +1,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 strafesnet_common::aabb::Aabb;
use strafesnet_common::map;
use strafesnet_common::model;
@ -389,6 +390,18 @@ enum RobloxBasePartDescription{
Wedge(RobloxWedgeDescription),
CornerWedge(RobloxCornerWedgeDescription),
}
// TODO: initialize all ustrs in a top level struct thrown around as a reference
// struct UstrKludge{
// }
fn get_content_url(content:&rbx_dom_weak::types::Content)->Option<&str>{
match content.value(){
rbx_dom_weak::types::ContentType::Uri(uri)=>Some(uri.as_str()),
_=>None,
}
}
fn get_texture_description<'a>(
temp_objects:&mut Vec<rbx_dom_weak::types::Ref>,
render_config_deferred_loader:&mut RenderConfigDeferredLoader<&'a str>,
@ -401,69 +414,74 @@ fn get_texture_description<'a>(
temp_objects.clear();
recursive_collect_superclass(temp_objects,&dom,object,"Decal");
for &mut decal_ref in temp_objects{
if let Some(decal)=dom.get_by_ref(decal_ref){
if let (
Some(rbx_dom_weak::types::Variant::Content(content)),
let Some(decal)=dom.get_by_ref(decal_ref) else{
println!("Decal get_by_ref failed");
continue;
};
let (
Some(rbx_dom_weak::types::Variant::ContentId(content)),
Some(rbx_dom_weak::types::Variant::Enum(normalid)),
Some(rbx_dom_weak::types::Variant::Color3(decal_color3)),
Some(rbx_dom_weak::types::Variant::Float32(decal_transparency)),
) = (
decal.properties.get("Texture"),
decal.properties.get("Face"),
decal.properties.get("Color3"),
decal.properties.get("Transparency"),
) {
let render_id=render_config_deferred_loader.acquire_render_config_id(Some(content.as_ref()));
if let Ok(cube_face)=normalid.to_u32().try_into(){
let (roblox_texture_color,roblox_texture_transform)=if decal.class=="Texture"{
//generate tranform
if let (
Some(&rbx_dom_weak::types::Variant::Float32(offset_studs_u)),
Some(&rbx_dom_weak::types::Variant::Float32(offset_studs_v)),
Some(&rbx_dom_weak::types::Variant::Float32(studs_per_tile_u)),
Some(&rbx_dom_weak::types::Variant::Float32(studs_per_tile_v)),
) = (
decal.properties.get("OffsetStudsU"),
decal.properties.get("OffsetStudsV"),
decal.properties.get("StudsPerTileU"),
decal.properties.get("StudsPerTileV"),
)
{
let (size_u,size_v)=match cube_face{
CubeFace::Right=>(size.z,size.y),//right
CubeFace::Top=>(size.x,size.z),//top
CubeFace::Back=>(size.x,size.y),//back
CubeFace::Left=>(size.z,size.y),//left
CubeFace::Bottom=>(size.x,size.z),//bottom
CubeFace::Front=>(size.x,size.y),//front
};
(
glam::vec4(decal_color3.r,decal_color3.g,decal_color3.b,1.0-*decal_transparency),
RobloxTextureTransform{
offset_studs_u,
offset_studs_v,
studs_per_tile_u,
studs_per_tile_v,
size_u,
size_v,
}
)
}else{
(glam::Vec4::ONE,RobloxTextureTransform::identity())
}
}else{
(glam::Vec4::ONE,RobloxTextureTransform::identity())
};
part_texture_description[cube_face]=Some(RobloxFaceTextureDescription{
render:render_id,
color:roblox_texture_color,
transform:roblox_texture_transform,
});
}else{
println!("NormalId is invalid");
}
)=(
decal.properties.get(&ustr("Texture")),
decal.properties.get(&ustr("Face")),
decal.properties.get(&ustr("Color3")),
decal.properties.get(&ustr("Transparency")),
)else{
println!("Decal is missing a required property");
continue;
};
let texture_id=Some(content.as_str());
let render_id=render_config_deferred_loader.acquire_render_config_id(texture_id);
let Ok(cube_face)=normalid.to_u32().try_into()else{
println!("NormalId is invalid");
continue;
};
let (roblox_texture_color,roblox_texture_transform)=if decal.class=="Texture"{
//generate tranform
if let (
Some(&rbx_dom_weak::types::Variant::Float32(offset_studs_u)),
Some(&rbx_dom_weak::types::Variant::Float32(offset_studs_v)),
Some(&rbx_dom_weak::types::Variant::Float32(studs_per_tile_u)),
Some(&rbx_dom_weak::types::Variant::Float32(studs_per_tile_v)),
) = (
decal.properties.get(&ustr("OffsetStudsU")),
decal.properties.get(&ustr("OffsetStudsV")),
decal.properties.get(&ustr("StudsPerTileU")),
decal.properties.get(&ustr("StudsPerTileV")),
)
{
let (size_u,size_v)=match cube_face{
CubeFace::Right=>(size.z,size.y),//right
CubeFace::Top=>(size.x,size.z),//top
CubeFace::Back=>(size.x,size.y),//back
CubeFace::Left=>(size.z,size.y),//left
CubeFace::Bottom=>(size.x,size.z),//bottom
CubeFace::Front=>(size.x,size.y),//front
};
(
glam::vec4(decal_color3.r,decal_color3.g,decal_color3.b,1.0-*decal_transparency),
RobloxTextureTransform{
offset_studs_u,
offset_studs_v,
studs_per_tile_u,
studs_per_tile_v,
size_u,
size_v,
}
)
}else{
(glam::Vec4::ONE,RobloxTextureTransform::identity())
}
}
}else{
(glam::Vec4::ONE,RobloxTextureTransform::identity())
};
part_texture_description[cube_face]=Some(RobloxFaceTextureDescription{
render:render_id,
color:roblox_texture_color,
transform:roblox_texture_transform,
});
}
part_texture_description
}
@ -529,12 +547,12 @@ pub fn convert<'a>(
Some(rbx_dom_weak::types::Variant::Color3uint8(color3)),
Some(rbx_dom_weak::types::Variant::Bool(can_collide)),
) = (
object.properties.get("CFrame"),
object.properties.get("Size"),
object.properties.get("Velocity"),
object.properties.get("Transparency"),
object.properties.get("Color"),
object.properties.get("CanCollide"),
object.properties.get(&ustr("CFrame")),
object.properties.get(&ustr("Size")),
object.properties.get(&ustr("Velocity")),
object.properties.get(&ustr("Transparency")),
object.properties.get(&ustr("Color")),
object.properties.get(&ustr("CanCollide")),
)
{
let model_transform=planar64_affine3_from_roblox(cf,size);
@ -553,7 +571,7 @@ pub fn convert<'a>(
//TODO: also detect "CylinderMesh" etc here
let shape=match object.class.as_str(){
"Part"=>if let Some(rbx_dom_weak::types::Variant::Enum(shape))=object.properties.get("Shape"){
"Part"=>if let Some(rbx_dom_weak::types::Variant::Enum(shape))=object.properties.get(&ustr("Shape")){
Shape::Primitive(shape.to_u32().try_into().expect("Funky roblox PartType"))
}else{
panic!("Part has no Shape!");
@ -623,15 +641,19 @@ pub fn convert<'a>(
(MeshAvailability::Immediate,mesh_id)
},
Shape::MeshPart=>if let (
Some(rbx_dom_weak::types::Variant::Content(mesh_asset_id)),
Some(rbx_dom_weak::types::Variant::Content(texture_asset_id)),
Some(rbx_dom_weak::types::Variant::Content(mesh_content)),
Some(rbx_dom_weak::types::Variant::Content(texture_content)),
)=(
object.properties.get("MeshId"),
object.properties.get("TextureID"),
// mesh must exist
object.properties.get(&ustr("MeshContent")),
// texture is allowed to be none
object.properties.get(&ustr("TextureContent")),
){
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);
(
MeshAvailability::DeferredMesh(render_config_deferred_loader.acquire_render_config_id(Some(texture_asset_id.as_ref()))),
mesh_deferred_loader.acquire_mesh_id(MeshIndex::file_mesh(mesh_asset_id.as_ref())),
MeshAvailability::DeferredMesh(render_config_deferred_loader.acquire_render_config_id(texture_asset_id)),
mesh_deferred_loader.acquire_mesh_id(MeshIndex::file_mesh(mesh_asset_id)),
)
}else{
panic!("Mesh has no Mesh or Texture");
@ -640,13 +662,13 @@ pub fn convert<'a>(
let mut content="";
let mut mesh_data:&[u8]=&[];
let mut physics_data:&[u8]=&[];
if let Some(rbx_dom_weak::types::Variant::Content(asset_id))=object.properties.get("AssetId"){
if let Some(rbx_dom_weak::types::Variant::ContentId(asset_id))=object.properties.get(&ustr("AssetId")){
content=asset_id.as_ref();
}
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get("MeshData"){
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get(&ustr("MeshData")){
mesh_data=data.as_ref();
}
if let Some(rbx_dom_weak::types::Variant::BinaryString(data))=object.properties.get("PhysicsData"){
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);