Compare commits

..

81 Commits

Author SHA1 Message Date
ddfeca41e9 add failing test 2025-12-10 15:15:09 -08:00
8f580ad6ba add loop 2025-12-10 15:14:48 -08:00
68e81b31ba add test points 2025-12-10 15:09:30 -08:00
cbd6e1a608 add unit test 2025-12-10 15:06:58 -08:00
0e3cdedc05 partially implement md generic 2025-12-10 14:52:14 -08:00
97cec0e709 fix constraints epsilon
these were supposed to be 3 voxels but were on the order of 3 units
2025-12-05 10:34:21 -08:00
8e24739721 handle non-canonnical multi-edge spanning edges 2025-12-05 10:34:21 -08:00
5f2d9d34bb Meshquery::farthest_vert 2025-12-05 10:31:17 -08:00
cd43c5aabe todo 2025-12-05 10:31:17 -08:00
cf4aa8ed16 why 2025-12-05 10:31:17 -08:00
c71e5e9e20 think through simplex constraints 2025-12-04 12:03:38 -08:00
261bc5c845 refactor algorithm to use a struct 2025-12-04 11:21:08 -08:00
6f8c2692ca comments 2025-12-02 10:12:51 -08:00
3dd897b47f comment todos 2025-12-02 10:12:51 -08:00
fcc2348eb0 add unfortunate algorithm 2025-12-02 09:21:42 -08:00
8ca0c94445 remove Eq for MinkowskiFace 2025-11-27 12:15:29 -08:00
463a70c5f4 breakout 2025-11-27 12:15:29 -08:00
643b4fea37 change on_exact signature 2025-11-27 12:15:29 -08:00
1752c51b8f fail without crash 2025-11-27 12:15:29 -08:00
348769a270 no print 2025-11-27 12:15:29 -08:00
7b53d7d595 use new algorithm 2025-11-27 12:15:29 -08:00
18c73b12d8 convert to fev using dumbest algorithm possible 2025-11-27 11:52:28 -08:00
4ff62cc991 negate minkowski input to minimum_difference 2025-11-27 10:11:15 -08:00
a8d9167152 make hint_point consistent with vert 2025-11-27 10:05:13 -08:00
21f4d13ce0 rename variable 2025-11-27 10:05:13 -08:00
84e55c557a physics: derive Eq for Minkowski FEV 2025-11-26 09:45:03 -08:00
f96398cc84 remove indexing 2025-11-25 15:57:14 -08:00
9ff0736d50 put comment back in 2025-11-25 12:12:33 -08:00
c3d390dda0 use struct 2025-11-25 11:50:40 -08:00
eeb47abde1 reduce member fn 2025-11-25 11:43:58 -08:00
567354cebb split reduce 2025-11-25 11:43:47 -08:00
a787bf2ab2 deconstruct 2025-11-25 11:35:11 -08:00
623cc8d822 refactor using Simplex enum 2025-11-25 11:30:24 -08:00
6da4f3b3fb simplify perp 2025-11-25 09:49:30 -08:00
982b837143 fix algorithm 2025-11-25 09:32:25 -08:00
02b52ef748 rename 2025-11-25 09:22:46 -08:00
e32523e626 style 2025-11-25 09:15:25 -08:00
9a0c26cc97 careful relative point opti 2025-11-25 09:15:18 -08:00
45c2fdbb3f work 2025-11-25 09:12:31 -08:00
c1d3045a77 include relative point 2025-11-25 09:09:46 -08:00
f1ca5a3735 fix degenerate case 2025-11-25 09:00:23 -08:00
3fa048434b fix wrong 2025-11-25 09:00:13 -08:00
0909a62caf use min diff 2025-11-25 08:42:05 -08:00
97012940cd implement contains_point 2025-11-25 08:33:10 -08:00
b601667d6a rename variable 2025-11-25 08:32:56 -08:00
6d5c7df14a work 2025-11-25 08:15:45 -08:00
3140c0a552 reduce min dist bit width 2025-11-25 08:15:45 -08:00
f9a92b7a8d FnOnce 2025-11-24 14:34:05 -08:00
1fa6d5c031 fast fail fn 2025-11-24 14:33:57 -08:00
05954bc487 more naming things 2025-11-24 14:18:06 -08:00
e11d96a9b3 refine naming 2025-11-24 14:07:34 -08:00
5ee8a02693 names 2025-11-24 13:58:11 -08:00
efba2a8f19 stuff 2025-11-24 13:54:18 -08:00
de44e19909 switch trait to closures 2025-11-24 13:42:10 -08:00
c7e29d05d4 insane trait just to remove if statements 2025-11-24 13:28:28 -08:00
6171ceab6d refactor calculation result 2025-11-24 13:04:51 -08:00
41aeeefb5b details later 2025-11-24 13:04:51 -08:00
1473fe8fe1 remove is more clear 2025-11-24 13:04:51 -08:00
ac987a2efd remove unused 2025-11-24 13:04:51 -08:00
1050d824e6 work 2025-11-24 13:04:51 -08:00
496f838408 work 2025-11-24 13:04:51 -08:00
38a7aaa046 work 2025-11-24 13:04:51 -08:00
ce246acb43 work 2025-11-24 13:04:51 -08:00
3a7eeaee7f notes 2025-11-24 13:04:51 -08:00
9afbd0a91d zero 2025-11-24 13:04:51 -08:00
2ffa9cbe6c idea 2025-11-24 13:04:51 -08:00
8dee2140e1 eugh 2025-11-24 13:04:51 -08:00
af9f1a218e work 2025-11-24 13:04:51 -08:00
b8442274a5 work 2025-11-24 13:04:51 -08:00
72ba5bad63 work 2025-11-24 13:04:51 -08:00
d7b779170e work 2025-11-24 13:04:51 -08:00
ff28c0a311 wip paste fns 2025-11-24 13:04:51 -08:00
69f49d3dcf no hold ref 2025-11-24 13:04:51 -08:00
a91dfe07ec work 2025-11-24 13:04:51 -08:00
922f80657c work 2025-11-24 13:04:51 -08:00
f05e6b5995 work 2025-11-24 13:04:51 -08:00
e2ba15880a work 2025-11-24 13:04:51 -08:00
749ace538d work 2025-11-24 13:04:51 -08:00
6d9fc38ef1 work 2025-11-24 13:04:51 -08:00
565b53138c work 2025-11-24 13:04:51 -08:00
b0668136d6 wip 2025-11-24 13:04:51 -08:00
15 changed files with 461 additions and 589 deletions

902
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@ id = { version = "0.1.0", registry = "strafesnet" }
strafesnet_common = { path = "../../lib/common", registry = "strafesnet" } strafesnet_common = { path = "../../lib/common", registry = "strafesnet" }
strafesnet_session = { path = "../session", registry = "strafesnet" } strafesnet_session = { path = "../session", registry = "strafesnet" }
strafesnet_settings = { path = "../settings", registry = "strafesnet" } strafesnet_settings = { path = "../settings", registry = "strafesnet" }
wgpu = "28.0.0" wgpu = "27.0.0"
[lints] [lints]
workspace = true workspace = true

View File

@@ -616,7 +616,7 @@ impl GraphicsState{
address_mode_w:wgpu::AddressMode::ClampToEdge, address_mode_w:wgpu::AddressMode::ClampToEdge,
mag_filter:wgpu::FilterMode::Linear, mag_filter:wgpu::FilterMode::Linear,
min_filter:wgpu::FilterMode::Linear, min_filter:wgpu::FilterMode::Linear,
mipmap_filter:wgpu::MipmapFilterMode::Linear, mipmap_filter:wgpu::FilterMode::Linear,
..Default::default() ..Default::default()
}); });
let repeat_sampler=device.create_sampler(&wgpu::SamplerDescriptor{ let repeat_sampler=device.create_sampler(&wgpu::SamplerDescriptor{
@@ -626,7 +626,7 @@ impl GraphicsState{
address_mode_w:wgpu::AddressMode::Repeat, address_mode_w:wgpu::AddressMode::Repeat,
mag_filter:wgpu::FilterMode::Linear, mag_filter:wgpu::FilterMode::Linear,
min_filter:wgpu::FilterMode::Linear, min_filter:wgpu::FilterMode::Linear,
mipmap_filter:wgpu::MipmapFilterMode::Linear, mipmap_filter:wgpu::FilterMode::Linear,
anisotropy_clamp:16, anisotropy_clamp:16,
..Default::default() ..Default::default()
}); });
@@ -754,7 +754,7 @@ impl GraphicsState{
&skybox_texture_bind_group_layout, &skybox_texture_bind_group_layout,
&model_bind_group_layout, &model_bind_group_layout,
], ],
immediate_size:0, push_constant_ranges:&[],
}); });
let sky_pipeline_layout=device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor{ let sky_pipeline_layout=device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor{
label:None, label:None,
@@ -762,7 +762,7 @@ impl GraphicsState{
&camera_bind_group_layout, &camera_bind_group_layout,
&skybox_texture_bind_group_layout, &skybox_texture_bind_group_layout,
], ],
immediate_size:0, push_constant_ranges:&[],
}); });
// Create the render pipelines // Create the render pipelines
@@ -793,7 +793,7 @@ impl GraphicsState{
bias:wgpu::DepthBiasState::default(), bias:wgpu::DepthBiasState::default(),
}), }),
multisample:wgpu::MultisampleState::default(), multisample:wgpu::MultisampleState::default(),
multiview_mask:None, multiview:None,
cache:None, cache:None,
}); });
let model_pipeline=device.create_render_pipeline(&wgpu::RenderPipelineDescriptor{ let model_pipeline=device.create_render_pipeline(&wgpu::RenderPipelineDescriptor{
@@ -828,7 +828,7 @@ impl GraphicsState{
bias:wgpu::DepthBiasState::default(), bias:wgpu::DepthBiasState::default(),
}), }),
multisample:wgpu::MultisampleState::default(), multisample:wgpu::MultisampleState::default(),
multiview_mask:None, multiview:None,
cache:None, cache:None,
}); });
@@ -880,7 +880,7 @@ impl GraphicsState{
camera_buf, camera_buf,
models:Vec::new(), models:Vec::new(),
depth_view, depth_view,
staging_belt:wgpu::util::StagingBelt::new(device.clone(),0x100), staging_belt:wgpu::util::StagingBelt::new(0x100),
bind_group_layouts:GraphicsBindGroupLayouts{model:model_bind_group_layout}, bind_group_layouts:GraphicsBindGroupLayouts{model:model_bind_group_layout},
samplers:GraphicsSamplers{repeat:repeat_sampler}, samplers:GraphicsSamplers{repeat:repeat_sampler},
temp_squid_texture_view:squid_texture_view, temp_squid_texture_view:squid_texture_view,
@@ -918,6 +918,7 @@ impl GraphicsState{
&self.camera_buf, &self.camera_buf,
0, 0,
wgpu::BufferSize::new((camera_uniforms.len() * 4) as wgpu::BufferAddress).unwrap(), wgpu::BufferSize::new((camera_uniforms.len() * 4) as wgpu::BufferAddress).unwrap(),
device,
) )
.copy_from_slice(bytemuck::cast_slice(&camera_uniforms)); .copy_from_slice(bytemuck::cast_slice(&camera_uniforms));
//This code only needs to run when the uniforms change //This code only needs to run when the uniforms change
@@ -964,7 +965,6 @@ impl GraphicsState{
}), }),
timestamp_writes:Default::default(), timestamp_writes:Default::default(),
occlusion_query_set:Default::default(), occlusion_query_set:Default::default(),
multiview_mask:None,
}); });
rpass.set_bind_group(0,&self.bind_groups.camera,&[]); rpass.set_bind_group(0,&self.bind_groups.camera,&[]);

View File

@@ -100,37 +100,6 @@ const fn choose_any_direction()->Planar64Vec3{
vec3::X vec3::X
} }
fn narrow_dir2(dir:Vector3<Fixed<2,64>>)->Planar64Vec3{
if dir==vec3::zero(){
return dir.narrow_1().unwrap();
}
let x=dir.x.as_bits().unsigned_abs().bits();
let y=dir.y.as_bits().unsigned_abs().bits();
let z=dir.z.as_bits().unsigned_abs().bits();
let big=x.max(y).max(z);
const MAX_BITS:u32=64+31;
if MAX_BITS<big{
dir>>(big-MAX_BITS)
}else{
dir
}.narrow_1().unwrap()
}
fn narrow_dir3(dir:Vector3<Fixed<3,96>>)->Planar64Vec3{
if dir==vec3::zero(){
return dir.narrow_1().unwrap();
}
let x=dir.x.as_bits().unsigned_abs().bits();
let y=dir.y.as_bits().unsigned_abs().bits();
let z=dir.z.as_bits().unsigned_abs().bits();
let big=x.max(y).max(z);
const MAX_BITS:u32=96+31;
if MAX_BITS<big{
dir>>(big-MAX_BITS)
}else{
dir
}.narrow_1().unwrap()
}
fn reduce1<M:MeshQuery>( fn reduce1<M:MeshQuery>(
[v0]:Simplex<1,M::Vert>, [v0]:Simplex<1,M::Vert>,
mesh:&M, mesh:&M,
@@ -196,7 +165,7 @@ fn reduce2<M:MeshQuery>(
// -- modify the direction to take into account a0R and b0R // -- modify the direction to take into account a0R and b0R
// return direction, a0, a1, b0, b1 // return direction, a0, a1, b0, b1
return Reduced{ return Reduced{
dir:narrow_dir3(direction), dir:direction.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex2([v0,v1]), simplex:Simplex1_3::Simplex2([v0,v1]),
}; };
} }
@@ -262,7 +231,7 @@ fn reduce3<M:MeshQuery>(
// return direction, a0, a1, b0, b1, c0, c1 // return direction, a0, a1, b0, b1, c0, c1
return Reduced{ return Reduced{
dir:narrow_dir2(direction), dir:direction.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex3([v0,v1,v2]), simplex:Simplex1_3::Simplex3([v0,v1,v2]),
}; };
} }
@@ -296,14 +265,14 @@ fn reduce3<M:MeshQuery>(
if direction==vec3::zero(){ if direction==vec3::zero(){
// direction = uv // direction = uv
return Reduced{ return Reduced{
dir:narrow_dir2(uv), dir:uv.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex2([v0,v1]), simplex:Simplex1_3::Simplex2([v0,v1]),
}; };
} }
// return direction, a0, a1, b0, b1 // return direction, a0, a1, b0, b1
return Reduced{ return Reduced{
dir:narrow_dir3(direction), dir:direction.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex2([v0,v1]), simplex:Simplex1_3::Simplex2([v0,v1]),
}; };
} }
@@ -314,7 +283,7 @@ fn reduce3<M:MeshQuery>(
if dir==vec3::zero(){ if dir==vec3::zero(){
// direction = uv // direction = uv
return Reduced{ return Reduced{
dir:narrow_dir2(uv), dir:uv.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex1([v0]), simplex:Simplex1_3::Simplex1([v0]),
}; };
} }
@@ -430,12 +399,12 @@ fn reduce4<M:MeshQuery>(
// return direction, a0, a1, b0, b1, c0, c1 // return direction, a0, a1, b0, b1, c0, c1
if uv_w.is_negative(){ if uv_w.is_negative(){
return Reduce::Reduced(Reduced{ return Reduce::Reduced(Reduced{
dir:narrow_dir2(uv), dir:uv.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex3([v0,v1,v2]), simplex:Simplex1_3::Simplex3([v0,v1,v2]),
}); });
}else{ }else{
return Reduce::Reduced(Reduced{ return Reduce::Reduced(Reduced{
dir:narrow_dir2(-uv), dir:-uv.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex3([v0,v1,v2]), simplex:Simplex1_3::Simplex3([v0,v1,v2]),
}); });
} }
@@ -472,12 +441,12 @@ fn reduce4<M:MeshQuery>(
// return direction, a0, a1, b0, b1 // return direction, a0, a1, b0, b1
if uv_w.is_negative(){ if uv_w.is_negative(){
return Reduce::Reduced(Reduced{ return Reduce::Reduced(Reduced{
dir:narrow_dir2(uv), dir:uv.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex2([v0,v1]), simplex:Simplex1_3::Simplex2([v0,v1]),
}); });
}else{ }else{
return Reduce::Reduced(Reduced{ return Reduce::Reduced(Reduced{
dir:narrow_dir2(-uv), dir:-uv.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex2([v0,v1]), simplex:Simplex1_3::Simplex2([v0,v1]),
}); });
} }
@@ -485,7 +454,7 @@ fn reduce4<M:MeshQuery>(
// return direction, a0, a1, b0, b1 // return direction, a0, a1, b0, b1
return Reduce::Reduced(Reduced{ return Reduce::Reduced(Reduced{
dir:narrow_dir3(direction), dir:direction.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex2([v0,v1]), simplex:Simplex1_3::Simplex2([v0,v1]),
}); });
} }
@@ -497,12 +466,12 @@ fn reduce4<M:MeshQuery>(
// direction = uvw < 0 and uv or -uv // direction = uvw < 0 and uv or -uv
if uv_w.is_negative(){ if uv_w.is_negative(){
return Reduce::Reduced(Reduced{ return Reduce::Reduced(Reduced{
dir:narrow_dir2(uv), dir:uv.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex1([v0]), simplex:Simplex1_3::Simplex1([v0]),
}); });
}else{ }else{
return Reduce::Reduced(Reduced{ return Reduce::Reduced(Reduced{
dir:narrow_dir2(-uv), dir:-uv.narrow_1().unwrap(),
simplex:Simplex1_3::Simplex1([v0]), simplex:Simplex1_3::Simplex1([v0]),
}); });
} }
@@ -901,13 +870,6 @@ mod test{
fn test_cube_points(){ fn test_cube_points(){
let mesh=PhysicsMesh::unit_cube(); let mesh=PhysicsMesh::unit_cube();
let mesh_view=mesh.complete_mesh_view(); let mesh_view=mesh.complete_mesh_view();
for x in -2..=2{ assert!(mesh_contains_point(mesh_view,vec3::NEG_Z));
for y in -2..=2{
for z in -2..=2{
let point=vec3::int(x,y,z)>>1;
assert!(mesh_contains_point(mesh_view,point),"Mesh did not contain point {point}");
}
}
}
} }
} }

View File

@@ -103,21 +103,17 @@ pub trait MeshQuery{
} }
#[derive(Debug)] #[derive(Debug)]
struct FaceRefs{ struct FaceRefs{
// I didn't write it down, but I assume the edges are directed
// clockwise when looking towards the face normal, i.e. right hand rule.
edges:Vec<SubmeshDirectedEdgeId>, edges:Vec<SubmeshDirectedEdgeId>,
//verts are redundant, use edge[i].verts[0]
//verts:Vec<VertId>, //verts:Vec<VertId>,
} }
#[derive(Debug)] #[derive(Debug)]
struct EdgeRefs{ struct EdgeRefs{
faces:[SubmeshFaceId;2],//left, right faces:[SubmeshFaceId;2],//left, right
verts:[SubmeshVertId;2],//start, end verts:[SubmeshVertId;2],//bottom, top
} }
#[derive(Debug)] #[derive(Debug)]
struct VertRefs{ struct VertRefs{
faces:Vec<SubmeshFaceId>, faces:Vec<SubmeshFaceId>,
// edges are always directed away from the vert
edges:Vec<SubmeshDirectedEdgeId>, edges:Vec<SubmeshDirectedEdgeId>,
} }
#[derive(Debug)] #[derive(Debug)]
@@ -676,14 +672,8 @@ impl MinkowskiMesh<'_>{
fev.crawl(self,relative_body,range.start_bound(),range.end_bound()).hit() fev.crawl(self,relative_body,range.start_bound(),range.end_bound()).hit()
} }
pub fn predict_collision_out(&self,relative_body:&Body,range:impl RangeBounds<Time>)->Option<(MinkowskiFace,GigaTime)>{ pub fn predict_collision_out(&self,relative_body:&Body,range:impl RangeBounds<Time>)->Option<(MinkowskiFace,GigaTime)>{
let fev=crate::minimum_difference::closest_fev_not_inside(self,relative_body.position)?;
let (lower_bound,upper_bound)=(range.start_bound(),range.end_bound()); let (lower_bound,upper_bound)=(range.start_bound(),range.end_bound());
// TODO: handle unbounded collision using infinity fev
let time=match upper_bound{
Bound::Included(&time)=>time,
Bound::Excluded(&time)=>time,
Bound::Unbounded=>unimplemented!("unbounded collision out"),
};
let fev=crate::minimum_difference::closest_fev_not_inside(self,relative_body.extrapolated_position(time))?;
// swap and negate bounds to do a time inversion // swap and negate bounds to do a time inversion
let (lower_bound,upper_bound)=(upper_bound.map(|&t|-t),lower_bound.map(|&t|-t)); let (lower_bound,upper_bound)=(upper_bound.map(|&t|-t),lower_bound.map(|&t|-t));
let infinity_body=-relative_body; let infinity_body=-relative_body;

View File

@@ -366,7 +366,7 @@ impl_additive_operator!( Fixed, BitXor, bitxor, Self );
// non-wide operators. The result is the same width as the inputs. // non-wide operators. The result is the same width as the inputs.
// This macro is not used in the default configuration. // This macro is not used in the default configuration.
#[expect(unused_macros)] #[allow(unused_macros)]
macro_rules! impl_multiplicative_operator_not_const_generic { macro_rules! impl_multiplicative_operator_not_const_generic {
( ($struct: ident, $trait: ident, $method: ident, $output: ty ), $width:expr ) => { ( ($struct: ident, $trait: ident, $method: ident, $output: ty ), $width:expr ) => {
impl<const F:usize> core::ops::$trait for $struct<$width,F>{ impl<const F:usize> core::ops::$trait for $struct<$width,F>{
@@ -545,7 +545,7 @@ impl_shift_operator!( Fixed, Shr, shr, Self );
// wide operators. The result width is the sum of the input widths, i.e. none of the multiplication // wide operators. The result width is the sum of the input widths, i.e. none of the multiplication
#[expect(unused_macros)] #[allow(unused_macros)]
macro_rules! impl_wide_operators{ macro_rules! impl_wide_operators{
($lhs:expr,$rhs:expr)=>{ ($lhs:expr,$rhs:expr)=>{
impl core::ops::Mul<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{ impl core::ops::Mul<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{

View File

@@ -13,16 +13,16 @@ authors = ["Rhys Lloyd <krakow20@gmail.com>"]
bytemuck = "1.14.3" bytemuck = "1.14.3"
glam = "0.30.0" glam = "0.30.0"
regex = { version = "1.11.3", default-features = false } regex = { version = "1.11.3", default-features = false }
rbx_binary = { version = "1.0.1-sn5", registry = "strafesnet" }
rbx_dom_weak = { version = "3.0.1-sn5", registry = "strafesnet" }
rbx_mesh = "0.5.0" rbx_mesh = "0.5.0"
rbx_reflection = "5.0.0"
rbx_reflection_database = "1.0.0"
rbx_xml = { version = "1.0.1-sn5", registry = "strafesnet" }
rbxassetid = { version = "0.1.0", path = "../rbxassetid", registry = "strafesnet" } rbxassetid = { version = "0.1.0", path = "../rbxassetid", registry = "strafesnet" }
roblox_emulator = { version = "0.5.1", path = "../roblox_emulator", default-features = false, registry = "strafesnet" } roblox_emulator = { version = "0.5.1", path = "../roblox_emulator", default-features = false, registry = "strafesnet" }
strafesnet_common = { version = "0.7.0", path = "../common", registry = "strafesnet" } strafesnet_common = { version = "0.7.0", path = "../common", registry = "strafesnet" }
strafesnet_deferred_loader = { version = "0.5.1", path = "../deferred_loader", registry = "strafesnet" } strafesnet_deferred_loader = { version = "0.5.1", path = "../deferred_loader", registry = "strafesnet" }
rbx_binary = "2.0.1"
rbx_dom_weak = "4.1.0"
rbx_reflection = "6.1.0"
rbx_reflection_database = "2.0.2"
rbx_xml = "2.0.1"
[lints] [lints]
workspace = true workspace = true

View File

@@ -559,7 +559,7 @@ pub fn convert<'a>(
//just going to leave it like this for now instead of reworking the data structures for this whole thing //just going to leave it like this for now instead of reworking the data structures for this whole thing
let textureless_render_group=render_config_deferred_loader.acquire_render_config_id(None); let textureless_render_group=render_config_deferred_loader.acquire_render_config_id(None);
let db=rbx_reflection_database::get().unwrap(); let db=rbx_reflection_database::get();
let basepart=&db.classes["BasePart"]; let basepart=&db.classes["BasePart"];
let baseparts=dom.descendants().filter(|&instance| let baseparts=dom.descendants().filter(|&instance|
db.classes.get(instance.class.as_str()).is_some_and(|class| db.classes.get(instance.class.as_str()).is_some_and(|class|

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "roblox_emulator" name = "roblox_emulator"
version = "0.5.2" version = "0.5.1"
edition = "2024" edition = "2024"
repository = "https://git.itzana.me/StrafesNET/strafe-project" repository = "https://git.itzana.me/StrafesNET/strafe-project"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
@@ -15,10 +15,10 @@ run-service=[]
glam = "0.30.0" glam = "0.30.0"
mlua = { version = "0.11.3", features = ["luau"] } mlua = { version = "0.11.3", features = ["luau"] }
phf = { version = "0.13.1", features = ["macros"] } phf = { version = "0.13.1", features = ["macros"] }
rbx_dom_weak = "4.1.0" rbx_dom_weak = { version = "3.0.1-sn5", registry = "strafesnet" }
rbx_reflection = "6.1.0" rbx_reflection = "5.0.0"
rbx_reflection_database = "2.0.2" rbx_reflection_database = "1.0.0"
rbx_types = "3.1.0" rbx_types = "2.0.0"
[lints] [lints]
workspace = true workspace = true

View File

@@ -52,7 +52,7 @@ impl Context{
} }
/// 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<'a>(&'a self,superclass:&'a str)->impl Iterator<Item=Ref>+'a{
let db=rbx_reflection_database::get().unwrap(); let db=rbx_reflection_database::get();
let Some(superclass)=db.classes.get(superclass)else{ let Some(superclass)=db.classes.get(superclass)else{
panic!("Invalid class"); panic!("Invalid class");
}; };

View File

@@ -37,7 +37,7 @@ impl PartialEq for EnumItem<'_>{
pub struct Enums; 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().unwrap(); let db=rbx_reflection_database::get();
db.enums.get(index).map(|ed|EnumItems{ed}) db.enums.get(index).map(|ed|EnumItems{ed})
} }
} }

View File

@@ -37,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().unwrap(); 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(class),db.classes.get(superclass))else{
return false; return false;
}; };
@@ -80,14 +80,14 @@ pub fn find_first_descendant_of_class<'a>(dom:&'a WeakDom,instance:&rbx_dom_weak
} }
pub fn find_first_child_which_is_a<'a>(dom:&'a 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 WeakDom,instance:&rbx_dom_weak::Instance,superclass:&str)->Option<&'a rbx_dom_weak::Instance>{
let db=rbx_reflection_database::get().unwrap(); let db=rbx_reflection_database::get();
let superclass_descriptor=db.classes.get(superclass)?; let superclass_descriptor=db.classes.get(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.as_str()).is_some_and(|descriptor|db.has_superclass(descriptor,superclass_descriptor))
}) })
} }
pub fn find_first_descendant_which_is_a<'a>(dom:&'a 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 WeakDom,instance:&rbx_dom_weak::Instance,superclass:&str)->Option<&'a rbx_dom_weak::Instance>{
let db=rbx_reflection_database::get().unwrap(); let db=rbx_reflection_database::get();
let superclass_descriptor=db.classes.get(superclass)?; let superclass_descriptor=db.classes.get(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.as_str()).is_some_and(|descriptor|db.has_superclass(descriptor,superclass_descriptor))
@@ -282,7 +282,7 @@ impl mlua::UserData for Instance{
dom_mut(lua,|dom|{ dom_mut(lua,|dom|{
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().unwrap(); 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.as_str()).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
@@ -344,7 +344,7 @@ impl mlua::UserData for Instance{
let index_str=&*index.to_str()?; let index_str=&*index.to_str()?;
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().unwrap(); 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.as_str()).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)

View File

@@ -13,10 +13,10 @@ futures = "0.3.31"
image = "0.25.2" image = "0.25.2"
image_dds = "0.7.1" image_dds = "0.7.1"
rbx_asset = { version = "0.5.0", registry = "strafesnet" } rbx_asset = { version = "0.5.0", registry = "strafesnet" }
rbx_binary = "2.0.1" rbx_binary = { version = "1.0.1-sn5", registry = "strafesnet" }
rbx_dom_weak = "4.1.0" rbx_dom_weak = { version = "3.0.1-sn5", registry = "strafesnet" }
rbx_reflection_database = "2.0.2" rbx_reflection_database = "1.0.0"
rbx_xml = "2.0.1" rbx_xml = { version = "1.0.1-sn5", registry = "strafesnet" }
rbxassetid = { version = "0.1.0", registry = "strafesnet" } rbxassetid = { version = "0.1.0", registry = "strafesnet" }
strafesnet_bsp_loader = { version = "0.3.1", path = "../lib/bsp_loader", registry = "strafesnet" } strafesnet_bsp_loader = { version = "0.3.1", path = "../lib/bsp_loader", registry = "strafesnet" }
strafesnet_deferred_loader = { version = "0.5.1", path = "../lib/deferred_loader", registry = "strafesnet" } strafesnet_deferred_loader = { version = "0.5.1", path = "../lib/deferred_loader", registry = "strafesnet" }

View File

@@ -28,7 +28,7 @@ strafesnet_rbx_loader = { path = "../lib/rbx_loader", registry = "strafesnet", o
strafesnet_session = { path = "../engine/session", registry = "strafesnet" } strafesnet_session = { path = "../engine/session", registry = "strafesnet" }
strafesnet_settings = { path = "../engine/settings", registry = "strafesnet" } strafesnet_settings = { path = "../engine/settings", registry = "strafesnet" }
strafesnet_snf = { path = "../lib/snf", registry = "strafesnet", optional = true } strafesnet_snf = { path = "../lib/snf", registry = "strafesnet", optional = true }
wgpu = "28.0.0" wgpu = "27.0.0"
winit = "0.30.7" winit = "0.30.7"
[profile.dev] [profile.dev]

View File

@@ -52,7 +52,7 @@ impl<'a> SetupContextPartial2<'a>{
let required_features=required_features(); let required_features=required_features();
//no helper function smh gotta write it myself //no helper function smh gotta write it myself
let adapters=pollster::block_on(self.instance.enumerate_adapters(self.backends)); let adapters=self.instance.enumerate_adapters(self.backends);
let mut chosen_adapter=None; let mut chosen_adapter=None;
let mut chosen_adapter_score=0; let mut chosen_adapter_score=0;