Compare commits
91 Commits
md-generic
...
min-diff
| Author | SHA1 | Date | |
|---|---|---|---|
|
493cf242c6
|
|||
|
9b3a9ce437
|
|||
|
73f0a85f81
|
|||
|
332e11a627
|
|||
|
2d7f5cdc7d
|
|||
|
822f4571d2
|
|||
|
ac4c84f562
|
|||
|
3a7aaa20f8
|
|||
|
2e77366a17
|
|||
|
8a1f434a2a
|
|||
|
80d3df4659
|
|||
|
47f94fe359
|
|||
|
c4a2811627
|
|||
|
b23d4d590d
|
|||
|
cb9307bdf2
|
|||
|
ae7582704b
|
|||
|
7f0f63570e
|
|||
|
dbe96a0451
|
|||
|
291cedff3f
|
|||
|
43a2c76906
|
|||
|
7d8dbf7e82
|
|||
|
7640ea824d
|
|||
|
f3b02bba92
|
|||
|
9d04df4894
|
|||
|
f90436f0cc
|
|||
|
5e14a85d84
|
|||
|
da718e4bd2
|
|||
|
5641e9a26f
|
|||
|
7e7839f4aa
|
|||
|
6448d7cc57
|
|||
|
b8be169092
|
|||
|
9c4c14c5dc
|
|||
|
ca40e65060
|
|||
|
492e72c1bc
|
|||
|
03bf2650fd
|
|||
|
0c8cf02287
|
|||
|
af1374906b
|
|||
|
570d33a030
|
|||
|
d0c38a6e66
|
|||
|
dd7a636fa9
|
|||
|
2483abe2ad
|
|||
|
6621e369f2
|
|||
|
1b833ef6b3
|
|||
|
8a1ab4e03c
|
|||
|
069db75d3a
|
|||
|
de54bcfc36
|
|||
|
e777b89c6d
|
|||
|
d17153d17d
|
|||
|
e514c27675
|
|||
|
d1c13757e0
|
|||
|
d93e558678
|
|||
|
0048306236
|
|||
|
ee50f8dc1e
|
|||
|
e4966b037f
|
|||
|
96cdd684d1
|
|||
|
838130fec4
|
|||
|
8a3badc270
|
|||
|
4470e88d7b
|
|||
|
df7bee6cd1
|
|||
|
4fdd254f2a
|
|||
|
8a9db203fa
|
|||
|
be05fd108a
|
|||
|
6160872469
|
|||
|
2c1fa5da22
|
|||
|
6fe45f4873
|
|||
|
e1dac67aa0
|
|||
|
f9ed33073e
|
|||
|
91636747d4
|
|||
|
03b72301a3
|
|||
|
214b23f780
|
|||
|
6d98407830
|
|||
|
978659e8c6
|
|||
|
d00871f87f
|
|||
|
d2ed97fcf2
|
|||
|
ab3c693f84
|
|||
|
f0c7677a77
|
|||
|
eed0abcc2c
|
|||
|
bc5cdc7313
|
|||
|
14a5a3f964
|
|||
|
18b7bba901
|
|||
|
1770ac7292
|
|||
|
7384886512
|
|||
|
1dbde609cc
|
|||
|
e024f37843
|
|||
|
4059cfa527
|
|||
|
e4f3418bc6
|
|||
|
6ca6d5e484
|
|||
|
0668ac2def
|
|||
|
73e3181d0c
|
|||
|
19ba8f2445
|
|||
|
0495d07e26
|
908
Cargo.lock
generated
908
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ id = { version = "0.1.0", registry = "strafesnet" }
|
||||
strafesnet_common = { path = "../../lib/common", registry = "strafesnet" }
|
||||
strafesnet_session = { path = "../session", registry = "strafesnet" }
|
||||
strafesnet_settings = { path = "../settings", registry = "strafesnet" }
|
||||
wgpu = "27.0.0"
|
||||
wgpu = "28.0.0"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -616,7 +616,7 @@ impl GraphicsState{
|
||||
address_mode_w:wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter:wgpu::FilterMode::Linear,
|
||||
min_filter:wgpu::FilterMode::Linear,
|
||||
mipmap_filter:wgpu::FilterMode::Linear,
|
||||
mipmap_filter:wgpu::MipmapFilterMode::Linear,
|
||||
..Default::default()
|
||||
});
|
||||
let repeat_sampler=device.create_sampler(&wgpu::SamplerDescriptor{
|
||||
@@ -626,7 +626,7 @@ impl GraphicsState{
|
||||
address_mode_w:wgpu::AddressMode::Repeat,
|
||||
mag_filter:wgpu::FilterMode::Linear,
|
||||
min_filter:wgpu::FilterMode::Linear,
|
||||
mipmap_filter:wgpu::FilterMode::Linear,
|
||||
mipmap_filter:wgpu::MipmapFilterMode::Linear,
|
||||
anisotropy_clamp:16,
|
||||
..Default::default()
|
||||
});
|
||||
@@ -754,7 +754,7 @@ impl GraphicsState{
|
||||
&skybox_texture_bind_group_layout,
|
||||
&model_bind_group_layout,
|
||||
],
|
||||
push_constant_ranges:&[],
|
||||
immediate_size:0,
|
||||
});
|
||||
let sky_pipeline_layout=device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor{
|
||||
label:None,
|
||||
@@ -762,7 +762,7 @@ impl GraphicsState{
|
||||
&camera_bind_group_layout,
|
||||
&skybox_texture_bind_group_layout,
|
||||
],
|
||||
push_constant_ranges:&[],
|
||||
immediate_size:0,
|
||||
});
|
||||
|
||||
// Create the render pipelines
|
||||
@@ -793,7 +793,7 @@ impl GraphicsState{
|
||||
bias:wgpu::DepthBiasState::default(),
|
||||
}),
|
||||
multisample:wgpu::MultisampleState::default(),
|
||||
multiview:None,
|
||||
multiview_mask:None,
|
||||
cache:None,
|
||||
});
|
||||
let model_pipeline=device.create_render_pipeline(&wgpu::RenderPipelineDescriptor{
|
||||
@@ -828,7 +828,7 @@ impl GraphicsState{
|
||||
bias:wgpu::DepthBiasState::default(),
|
||||
}),
|
||||
multisample:wgpu::MultisampleState::default(),
|
||||
multiview:None,
|
||||
multiview_mask:None,
|
||||
cache:None,
|
||||
});
|
||||
|
||||
@@ -880,7 +880,7 @@ impl GraphicsState{
|
||||
camera_buf,
|
||||
models:Vec::new(),
|
||||
depth_view,
|
||||
staging_belt:wgpu::util::StagingBelt::new(0x100),
|
||||
staging_belt:wgpu::util::StagingBelt::new(device.clone(),0x100),
|
||||
bind_group_layouts:GraphicsBindGroupLayouts{model:model_bind_group_layout},
|
||||
samplers:GraphicsSamplers{repeat:repeat_sampler},
|
||||
temp_squid_texture_view:squid_texture_view,
|
||||
@@ -918,7 +918,6 @@ impl GraphicsState{
|
||||
&self.camera_buf,
|
||||
0,
|
||||
wgpu::BufferSize::new((camera_uniforms.len() * 4) as wgpu::BufferAddress).unwrap(),
|
||||
device,
|
||||
)
|
||||
.copy_from_slice(bytemuck::cast_slice(&camera_uniforms));
|
||||
//This code only needs to run when the uniforms change
|
||||
@@ -965,6 +964,7 @@ impl GraphicsState{
|
||||
}),
|
||||
timestamp_writes:Default::default(),
|
||||
occlusion_query_set:Default::default(),
|
||||
multiview_mask:None,
|
||||
});
|
||||
|
||||
rpass.set_bind_group(0,&self.bind_groups.camera,&[]);
|
||||
|
||||
@@ -3,6 +3,8 @@ use strafesnet_common::integer::vec3::Vector3;
|
||||
use strafesnet_common::integer::{Fixed,Planar64,Planar64Vec3};
|
||||
|
||||
use crate::model::{DirectedEdge,FEV,MeshQuery};
|
||||
// TODO: remove mesh invert
|
||||
use crate::model::{MinkowskiMesh,MinkowskiVert};
|
||||
|
||||
// This algorithm is based on Lua code
|
||||
// written by Trey Reynolds in 2021
|
||||
@@ -98,6 +100,37 @@ const fn choose_any_direction()->Planar64Vec3{
|
||||
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>(
|
||||
[v0]:Simplex<1,M::Vert>,
|
||||
mesh:&M,
|
||||
@@ -163,7 +196,7 @@ fn reduce2<M:MeshQuery>(
|
||||
// -- modify the direction to take into account a0R and b0R
|
||||
// return direction, a0, a1, b0, b1
|
||||
return Reduced{
|
||||
dir:direction.narrow_1().unwrap(),
|
||||
dir:narrow_dir3(direction),
|
||||
simplex:Simplex1_3::Simplex2([v0,v1]),
|
||||
};
|
||||
}
|
||||
@@ -229,7 +262,7 @@ fn reduce3<M:MeshQuery>(
|
||||
|
||||
// return direction, a0, a1, b0, b1, c0, c1
|
||||
return Reduced{
|
||||
dir:direction.narrow_1().unwrap(),
|
||||
dir:narrow_dir2(direction),
|
||||
simplex:Simplex1_3::Simplex3([v0,v1,v2]),
|
||||
};
|
||||
}
|
||||
@@ -263,14 +296,14 @@ fn reduce3<M:MeshQuery>(
|
||||
if direction==vec3::zero(){
|
||||
// direction = uv
|
||||
return Reduced{
|
||||
dir:uv.narrow_1().unwrap(),
|
||||
dir:narrow_dir2(uv),
|
||||
simplex:Simplex1_3::Simplex2([v0,v1]),
|
||||
};
|
||||
}
|
||||
|
||||
// return direction, a0, a1, b0, b1
|
||||
return Reduced{
|
||||
dir:direction.narrow_1().unwrap(),
|
||||
dir:narrow_dir3(direction),
|
||||
simplex:Simplex1_3::Simplex2([v0,v1]),
|
||||
};
|
||||
}
|
||||
@@ -281,7 +314,7 @@ fn reduce3<M:MeshQuery>(
|
||||
if dir==vec3::zero(){
|
||||
// direction = uv
|
||||
return Reduced{
|
||||
dir:uv.narrow_1().unwrap(),
|
||||
dir:narrow_dir2(uv),
|
||||
simplex:Simplex1_3::Simplex1([v0]),
|
||||
};
|
||||
}
|
||||
@@ -397,12 +430,12 @@ fn reduce4<M:MeshQuery>(
|
||||
// return direction, a0, a1, b0, b1, c0, c1
|
||||
if uv_w.is_negative(){
|
||||
return Reduce::Reduced(Reduced{
|
||||
dir:uv.narrow_1().unwrap(),
|
||||
dir:narrow_dir2(uv),
|
||||
simplex:Simplex1_3::Simplex3([v0,v1,v2]),
|
||||
});
|
||||
}else{
|
||||
return Reduce::Reduced(Reduced{
|
||||
dir:-uv.narrow_1().unwrap(),
|
||||
dir:narrow_dir2(-uv),
|
||||
simplex:Simplex1_3::Simplex3([v0,v1,v2]),
|
||||
});
|
||||
}
|
||||
@@ -439,12 +472,12 @@ fn reduce4<M:MeshQuery>(
|
||||
// return direction, a0, a1, b0, b1
|
||||
if uv_w.is_negative(){
|
||||
return Reduce::Reduced(Reduced{
|
||||
dir:uv.narrow_1().unwrap(),
|
||||
dir:narrow_dir2(uv),
|
||||
simplex:Simplex1_3::Simplex2([v0,v1]),
|
||||
});
|
||||
}else{
|
||||
return Reduce::Reduced(Reduced{
|
||||
dir:-uv.narrow_1().unwrap(),
|
||||
dir:narrow_dir2(-uv),
|
||||
simplex:Simplex1_3::Simplex2([v0,v1]),
|
||||
});
|
||||
}
|
||||
@@ -452,7 +485,7 @@ fn reduce4<M:MeshQuery>(
|
||||
|
||||
// return direction, a0, a1, b0, b1
|
||||
return Reduce::Reduced(Reduced{
|
||||
dir:direction.narrow_1().unwrap(),
|
||||
dir:narrow_dir3(direction),
|
||||
simplex:Simplex1_3::Simplex2([v0,v1]),
|
||||
});
|
||||
}
|
||||
@@ -464,12 +497,12 @@ fn reduce4<M:MeshQuery>(
|
||||
// direction = uvw < 0 and uv or -uv
|
||||
if uv_w.is_negative(){
|
||||
return Reduce::Reduced(Reduced{
|
||||
dir:uv.narrow_1().unwrap(),
|
||||
dir:narrow_dir2(uv),
|
||||
simplex:Simplex1_3::Simplex1([v0]),
|
||||
});
|
||||
}else{
|
||||
return Reduce::Reduced(Reduced{
|
||||
dir:-uv.narrow_1().unwrap(),
|
||||
dir:narrow_dir2(-uv),
|
||||
simplex:Simplex1_3::Simplex1([v0]),
|
||||
});
|
||||
}
|
||||
@@ -502,10 +535,10 @@ impl<Vert> Simplex2_4<Vert>{
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_point<M:MeshQuery>(mesh:&M,point:Planar64Vec3)->bool{
|
||||
pub fn contains_point(mesh:&MinkowskiMesh<'_>,point:Planar64Vec3)->bool{
|
||||
const ENABLE_FAST_FAIL:bool=true;
|
||||
// TODO: remove mesh negation
|
||||
minimum_difference::<ENABLE_FAST_FAIL,_,M>(&-mesh,point,
|
||||
minimum_difference::<ENABLE_FAST_FAIL,_,_>(&-mesh,point,
|
||||
// on_exact
|
||||
|is_intersecting,_simplex|{
|
||||
is_intersecting
|
||||
@@ -672,7 +705,7 @@ fn crawl_to_closest_ev<M:MeshQuery>(mesh:&M,simplex:Simplex<2,M::Vert>,point:Pla
|
||||
}
|
||||
|
||||
/// This function drops a vertex down to an edge or a face if the path from infinity did not cross any vertex-edge boundaries but the point is supposed to have already crossed a boundary down from a vertex
|
||||
fn crawl_to_closest_fev<M:MeshQuery>(mesh:&M,simplex:Simplex<3,M::Vert>,point:Planar64Vec3)->FEV::<M>{
|
||||
fn crawl_to_closest_fev<'a>(mesh:&MinkowskiMesh<'a>,simplex:Simplex<3,MinkowskiVert>,point:Planar64Vec3)->FEV::<MinkowskiMesh<'a>>{
|
||||
// naively start at the closest vertex
|
||||
// the closest vertex is not necessarily the one with the fewest boundary hops
|
||||
// but it doesn't matter, we will get there regardless.
|
||||
@@ -719,10 +752,10 @@ fn crawl_to_closest_fev<M:MeshQuery>(mesh:&M,simplex:Simplex<3,M::Vert>,point:Pl
|
||||
}
|
||||
}
|
||||
|
||||
pub fn closest_fev_not_inside<M:MeshQuery>(mesh:&M,point:Planar64Vec3)->Option<FEV<M>>{
|
||||
pub fn closest_fev_not_inside<'a>(mesh:&MinkowskiMesh<'a>,point:Planar64Vec3)->Option<FEV<MinkowskiMesh<'a>>>{
|
||||
const ENABLE_FAST_FAIL:bool=false;
|
||||
// TODO: remove mesh negation
|
||||
minimum_difference::<ENABLE_FAST_FAIL,_,M>(&-mesh,point,
|
||||
minimum_difference::<ENABLE_FAST_FAIL,_,_>(&-mesh,point,
|
||||
// on_exact
|
||||
|is_intersecting,simplex|{
|
||||
if is_intersecting{
|
||||
@@ -841,4 +874,40 @@ fn minimum_difference<const ENABLE_FAST_FAIL:bool,T,M:MeshQuery>(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: unit tests
|
||||
#[cfg(test)]
|
||||
mod test{
|
||||
use super::*;
|
||||
use crate::model::{PhysicsMesh,PhysicsMeshView};
|
||||
|
||||
fn mesh_contains_point(mesh:PhysicsMeshView<'_>,point:Planar64Vec3)->bool{
|
||||
const ENABLE_FAST_FAIL:bool=true;
|
||||
// TODO: remove mesh negation
|
||||
minimum_difference::<ENABLE_FAST_FAIL,_,_>(&mesh,point,
|
||||
// on_exact
|
||||
|is_intersecting,_simplex|{
|
||||
is_intersecting
|
||||
},
|
||||
// on_escape
|
||||
|_simplex|{
|
||||
// intersection is guaranteed at this point
|
||||
true
|
||||
},
|
||||
// fast_fail value
|
||||
||false
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cube_points(){
|
||||
let mesh=PhysicsMesh::unit_cube();
|
||||
let mesh_view=mesh.complete_mesh_view();
|
||||
for x in -2..=2{
|
||||
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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,17 +103,21 @@ pub trait MeshQuery{
|
||||
}
|
||||
#[derive(Debug)]
|
||||
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>,
|
||||
//verts are redundant, use edge[i].verts[0]
|
||||
//verts:Vec<VertId>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct EdgeRefs{
|
||||
faces:[SubmeshFaceId;2],//left, right
|
||||
verts:[SubmeshVertId;2],//bottom, top
|
||||
verts:[SubmeshVertId;2],//start, end
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct VertRefs{
|
||||
faces:Vec<SubmeshFaceId>,
|
||||
// edges are always directed away from the vert
|
||||
edges:Vec<SubmeshDirectedEdgeId>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
@@ -672,8 +676,14 @@ impl MinkowskiMesh<'_>{
|
||||
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)>{
|
||||
let fev=crate::minimum_difference::closest_fev_not_inside(self,relative_body.position)?;
|
||||
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
|
||||
let (lower_bound,upper_bound)=(upper_bound.map(|&t|-t),lower_bound.map(|&t|-t));
|
||||
let infinity_body=-relative_body;
|
||||
|
||||
@@ -366,7 +366,7 @@ impl_additive_operator!( Fixed, BitXor, bitxor, Self );
|
||||
// non-wide operators. The result is the same width as the inputs.
|
||||
|
||||
// This macro is not used in the default configuration.
|
||||
#[allow(unused_macros)]
|
||||
#[expect(unused_macros)]
|
||||
macro_rules! impl_multiplicative_operator_not_const_generic {
|
||||
( ($struct: ident, $trait: ident, $method: ident, $output: ty ), $width:expr ) => {
|
||||
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
|
||||
|
||||
#[allow(unused_macros)]
|
||||
#[expect(unused_macros)]
|
||||
macro_rules! impl_wide_operators{
|
||||
($lhs:expr,$rhs:expr)=>{
|
||||
impl core::ops::Mul<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{
|
||||
|
||||
@@ -13,16 +13,16 @@ authors = ["Rhys Lloyd <krakow20@gmail.com>"]
|
||||
bytemuck = "1.14.3"
|
||||
glam = "0.30.0"
|
||||
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_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" }
|
||||
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_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]
|
||||
workspace = true
|
||||
|
||||
@@ -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
|
||||
let textureless_render_group=render_config_deferred_loader.acquire_render_config_id(None);
|
||||
|
||||
let db=rbx_reflection_database::get();
|
||||
let db=rbx_reflection_database::get().unwrap();
|
||||
let basepart=&db.classes["BasePart"];
|
||||
let baseparts=dom.descendants().filter(|&instance|
|
||||
db.classes.get(instance.class.as_str()).is_some_and(|class|
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "roblox_emulator"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
edition = "2024"
|
||||
repository = "https://git.itzana.me/StrafesNET/strafe-project"
|
||||
license = "MIT OR Apache-2.0"
|
||||
@@ -15,10 +15,10 @@ run-service=[]
|
||||
glam = "0.30.0"
|
||||
mlua = { version = "0.11.3", features = ["luau"] }
|
||||
phf = { version = "0.13.1", features = ["macros"] }
|
||||
rbx_dom_weak = { version = "3.0.1-sn5", registry = "strafesnet" }
|
||||
rbx_reflection = "5.0.0"
|
||||
rbx_reflection_database = "1.0.0"
|
||||
rbx_types = "2.0.0"
|
||||
rbx_dom_weak = "4.1.0"
|
||||
rbx_reflection = "6.1.0"
|
||||
rbx_reflection_database = "2.0.2"
|
||||
rbx_types = "3.1.0"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
@@ -52,7 +52,7 @@ 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{
|
||||
let db=rbx_reflection_database::get();
|
||||
let db=rbx_reflection_database::get().unwrap();
|
||||
let Some(superclass)=db.classes.get(superclass)else{
|
||||
panic!("Invalid class");
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ impl PartialEq for EnumItem<'_>{
|
||||
pub struct Enums;
|
||||
impl Enums{
|
||||
pub fn get(&self,index:&str)->Option<EnumItems<'static>>{
|
||||
let db=rbx_reflection_database::get();
|
||||
let db=rbx_reflection_database::get().unwrap();
|
||||
db.enums.get(index).map(|ed|EnumItems{ed})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
let db=rbx_reflection_database::get();
|
||||
let db=rbx_reflection_database::get().unwrap();
|
||||
let (Some(class),Some(superclass))=(db.classes.get(class),db.classes.get(superclass))else{
|
||||
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>{
|
||||
let db=rbx_reflection_database::get();
|
||||
let db=rbx_reflection_database::get().unwrap();
|
||||
let superclass_descriptor=db.classes.get(superclass)?;
|
||||
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))
|
||||
})
|
||||
}
|
||||
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();
|
||||
let db=rbx_reflection_database::get().unwrap();
|
||||
let superclass_descriptor=db.classes.get(superclass)?;
|
||||
dom.descendants_of(instance.referent()).find(|inst|{
|
||||
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|{
|
||||
let instance=this.get(dom)?;
|
||||
//println!("__index t={} i={index:?}",instance.name);
|
||||
let db=rbx_reflection_database::get();
|
||||
let db=rbx_reflection_database::get().unwrap();
|
||||
let class=db.classes.get(instance.class.as_str()).ok_or_else(||mlua::Error::runtime("Class missing"))?;
|
||||
// Find existing property
|
||||
// Interestingly, ustr can know ahead of time if
|
||||
@@ -344,7 +344,7 @@ impl mlua::UserData for Instance{
|
||||
let index_str=&*index.to_str()?;
|
||||
dom_mut(lua,|dom|{
|
||||
let instance=this.get_mut(dom)?;
|
||||
let db=rbx_reflection_database::get();
|
||||
let db=rbx_reflection_database::get().unwrap();
|
||||
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|
|
||||
cls.properties.get(index_str)
|
||||
|
||||
@@ -13,10 +13,10 @@ futures = "0.3.31"
|
||||
image = "0.25.2"
|
||||
image_dds = "0.7.1"
|
||||
rbx_asset = { version = "0.5.0", registry = "strafesnet" }
|
||||
rbx_binary = { version = "1.0.1-sn5", registry = "strafesnet" }
|
||||
rbx_dom_weak = { version = "3.0.1-sn5", registry = "strafesnet" }
|
||||
rbx_reflection_database = "1.0.0"
|
||||
rbx_xml = { version = "1.0.1-sn5", registry = "strafesnet" }
|
||||
rbx_binary = "2.0.1"
|
||||
rbx_dom_weak = "4.1.0"
|
||||
rbx_reflection_database = "2.0.2"
|
||||
rbx_xml = "2.0.1"
|
||||
rbxassetid = { version = "0.1.0", 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" }
|
||||
|
||||
@@ -28,7 +28,7 @@ strafesnet_rbx_loader = { path = "../lib/rbx_loader", registry = "strafesnet", o
|
||||
strafesnet_session = { path = "../engine/session", registry = "strafesnet" }
|
||||
strafesnet_settings = { path = "../engine/settings", registry = "strafesnet" }
|
||||
strafesnet_snf = { path = "../lib/snf", registry = "strafesnet", optional = true }
|
||||
wgpu = "27.0.0"
|
||||
wgpu = "28.0.0"
|
||||
winit = "0.30.7"
|
||||
|
||||
[profile.dev]
|
||||
|
||||
@@ -52,7 +52,7 @@ impl<'a> SetupContextPartial2<'a>{
|
||||
let required_features=required_features();
|
||||
|
||||
//no helper function smh gotta write it myself
|
||||
let adapters=self.instance.enumerate_adapters(self.backends);
|
||||
let adapters=pollster::block_on(self.instance.enumerate_adapters(self.backends));
|
||||
|
||||
let mut chosen_adapter=None;
|
||||
let mut chosen_adapter_score=0;
|
||||
|
||||
Reference in New Issue
Block a user