From 2ef1e9ae0cdeb98b52a6b4a053e0f36b6e8119d6 Mon Sep 17 00:00:00 2001 From: Daniel Bengl Date: Mon, 2 Feb 2026 21:01:30 +0100 Subject: [PATCH 1/7] Drop rapier3d in favour of avian3d --- Cargo.lock | 175 +++++++++++++++++------- Cargo.toml | 4 +- src/client/player/mod.rs | 5 +- src/client/player/systems/controller.rs | 18 ++- src/client/prelude.rs | 5 +- 5 files changed, 136 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 173d2d36..312a27f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -413,6 +413,44 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "avian3d" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e09c07567e520b22bd6890a055877cd584fc3fd4317e4a0ba599f4833a4b61bc" +dependencies = [ + "approx 0.5.1", + "avian_derive", + "bevy", + "bevy_heavy", + "bevy_math", + "bevy_transform_interpolation", + "bitflags 2.10.0", + "derive_more", + "disqualified", + "glam_matrix_extras", + "itertools 0.13.0", + "nalgebra", + "parry3d", + "parry3d-f64", + "slab", + "smallvec", + "thiserror 2.0.17", + "thread_local", +] + +[[package]] +name = "avian_derive" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b257f601a1535e0d4a7a7796f535e3a13de62fd422b16dff7c14d27f0d4048" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "base64" version = "0.22.1" @@ -999,8 +1037,8 @@ version = "17.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "207dee2dc66cbf55670c6c01932591c19febeaee9396d123c9c630b89237d87e" dependencies = [ + "avian3d", "bevy", - "bevy_rapier3d", ] [[package]] @@ -1094,6 +1132,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "bevy_heavy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c0651daa331c326e1460cb19ee5bf497ed2810982dafca8784db44725f5c4b" +dependencies = [ + "bevy_math", + "bevy_reflect", + "glam_matrix_extras", +] + [[package]] name = "bevy_image" version = "0.17.3" @@ -1439,19 +1488,6 @@ version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17d24d7906c7de556033168b3485de36c59049fbaef0c2c44c715a23e0329b10" -[[package]] -name = "bevy_rapier3d" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "802f869a3f9e1fecffcbc8d1c4593ded900ee90aef359ef430a49cf3964067ee" -dependencies = [ - "bevy", - "bitflags 2.10.0", - "log", - "nalgebra", - "rapier3d", -] - [[package]] name = "bevy_reflect" version = "0.17.3" @@ -1767,6 +1803,15 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "bevy_transform_interpolation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284738382605476667bbe80cf0959f4dffb61adbdb0149e22e67f4dbf97a5bc2" +dependencies = [ + "bevy", +] + [[package]] name = "bevy_ui" version = "0.17.3" @@ -3277,12 +3322,23 @@ version = "0.30.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9" dependencies = [ + "approx 0.5.1", "bytemuck", "libm", "rand 0.9.2", "serde_core", ] +[[package]] +name = "glam_matrix_extras" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb141d04d0bbebc52c325352ae0c930a6d42c77ccd02b7c591a73bd7bc1d859" +dependencies = [ + "bevy_reflect", + "glam 0.30.10", +] + [[package]] name = "glob" version = "0.3.3" @@ -4741,6 +4797,7 @@ dependencies = [ "num-derive", "num-traits", "ordered-float 5.1.0", + "rayon", "rstar", "simba", "slab", @@ -4750,6 +4807,34 @@ dependencies = [ "thiserror 2.0.17", ] +[[package]] +name = "parry3d-f64" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38fe282b81b60a2aee7f24db25ea73b3c82f6451888eeb5936b621adb87aa653" +dependencies = [ + "approx 0.5.1", + "arrayvec", + "bitflags 2.10.0", + "downcast-rs 2.0.2", + "either", + "ena", + "foldhash 0.2.0", + "hashbrown 0.16.1", + "log", + "nalgebra", + "num-derive", + "num-traits", + "ordered-float 5.1.0", + "rayon", + "rstar", + "simba", + "slab", + "smallvec", + "spade", + "thiserror 2.0.17", +] + [[package]] name = "paste" version = "1.0.15" @@ -4972,33 +5057,42 @@ dependencies = [ ] [[package]] -name = "proc-macro2" -version = "1.0.105" +name = "proc-macro-error-attr2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" dependencies = [ - "unicode-ident", + "proc-macro2", + "quote", ] [[package]] -name = "profiling" -version = "1.0.17" +name = "proc-macro-error2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ - "profiling-procmacros", + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "profiling-procmacros" -version = "1.0.17" +name = "proc-macro2" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" dependencies = [ - "quote", - "syn", + "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" + [[package]] name = "pxfm" version = "0.1.27" @@ -5122,31 +5216,6 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" -[[package]] -name = "rapier3d" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68073fdc88f6b709002767ce8deffffb05ac06824bf9f98a23e270bcea64ba9f" -dependencies = [ - "approx 0.5.1", - "arrayvec", - "bit-vec", - "bitflags 2.10.0", - "downcast-rs 2.0.2", - "log", - "nalgebra", - "num-derive", - "num-traits", - "ordered-float 5.1.0", - "parry3d", - "profiling", - "rustc-hash 2.1.1", - "simba", - "static_assertions", - "thiserror 2.0.17", - "wide", -] - [[package]] name = "raw-window-handle" version = "0.6.2" @@ -5337,6 +5406,7 @@ checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" name = "rsmc" version = "0.1.1" dependencies = [ + "avian3d", "bevy", "bevy-inspector-egui", "bevy_asset", @@ -5348,7 +5418,6 @@ dependencies = [ "bevy_fps_controller", "bevy_mesh", "bevy_mod_billboard", - "bevy_rapier3d", "bevy_renet", "bincode", "cgmath", diff --git a/Cargo.toml b/Cargo.toml index b2801226..00915a7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,8 +13,8 @@ bevy_asset = "0.17.3" bevy_camera = "0.17.3" bevy_mesh = "0.17.3" bevy_dev_tools = "0.17.3" -bevy_fps_controller = {version = "17.1.0", features = ["rapier"]} -bevy_rapier3d = {version ="0.32"} +bevy_fps_controller = {version = "17.1.0", features = ["avian"]} +avian3d = {version="0.4", features = ["debug-plugin"]} bevy_flair = "0.6.0" bevy_egui = { version = "0.38.1", features = ["immutable_ctx"]} bevy_diagnostic = "0.17.3" diff --git a/src/client/player/mod.rs b/src/client/player/mod.rs index 642042f2..a34085eb 100644 --- a/src/client/player/mod.rs +++ b/src/client/player/mod.rs @@ -4,6 +4,7 @@ pub mod resources; pub mod systems; use crate::prelude::*; +use avian3d::PhysicsPlugins; pub struct PlayerPlugin; @@ -12,9 +13,9 @@ impl Plugin for PlayerPlugin { debug!("Building PlayerPlugin"); info!("Building PlayerPlugin"); app.add_plugins(FpsControllerPlugin); - app.add_plugins(RapierPhysicsPlugin::::default()); + app.add_plugins(PhysicsPlugins::default()); #[cfg(feature = "physics_debug")] - app.add_plugins(RapierDebugRenderPlugin::default()); + app.add_plugins(PhysicsDebugPlugin::default()); app.add_message::(); app.insert_resource(player_resources::BlockSelection::new()); app.insert_resource(player_resources::PlayerSpawned(false)); diff --git a/src/client/player/systems/controller.rs b/src/client/player/systems/controller.rs index 39412044..0fbde77f 100644 --- a/src/client/player/systems/controller.rs +++ b/src/client/player/systems/controller.rs @@ -36,26 +36,24 @@ pub fn setup_controller_on_area_ready_system( let logical_entity = commands .spawn(( - Collider::capsule(Vec3::Y * 0.5, Vec3::Y * 1.5, 0.5), + Collider::cylinder(0.5, 1.5), Friction { - coefficient: 0.0, - combine_rule: CoefficientCombineRule::Min, + dynamic_coefficient: 0.0, + static_coefficient: 0.0, + combine_rule: CoefficientCombine::Min, }, Restitution { coefficient: 0.0, - combine_rule: CoefficientCombineRule::Min, + combine_rule: CoefficientCombine::Min, }, - ActiveEvents::COLLISION_EVENTS, - Velocity::zero(), + LinearVelocity::ZERO, #[cfg(feature = "lock_player")] - RigidBody::Fixed, + RigidBody::Static, #[cfg(not(feature = "lock_player"))] RigidBody::Dynamic, - Sleeping::disabled(), LockedAxes::ROTATION_LOCKED, - AdditionalMassProperties::Mass(1.0), + Mass(1.0), GravityScale(0.0), - Ccd { enabled: true }, Transform::from_translation(spawn_position), LogicalPlayer, #[cfg(not(feature = "lock_player"))] diff --git a/src/client/prelude.rs b/src/client/prelude.rs index 00d6f172..d412a522 100644 --- a/src/client/prelude.rs +++ b/src/client/prelude.rs @@ -14,12 +14,9 @@ pub use bevy::prelude::*; pub use bevy::transform::components::Transform; pub use bevy::window::*; +pub use avian3d::prelude::*; pub use bevy_fps_controller::controller::*; -pub use bevy_rapier3d::geometry::Collider; -pub use bevy_rapier3d::{dynamics::*, geometry::*}; -pub use bevy_rapier3d::{plugin::*, render::RapierDebugRenderPlugin}; - // networking crates pub use renet::{ClientId, ConnectionConfig, DefaultChannel, RenetClient}; From a1693ef819c780d76461e4d28f3775a02d6a0bef Mon Sep 17 00:00:00 2001 From: Daniel Bengl Date: Mon, 2 Feb 2026 22:18:11 +0100 Subject: [PATCH 2/7] Fix debug --- src/client/collider/systems.rs | 7 ++++--- src/client/player/systems/controller.rs | 4 +++- src/server/terrain/systems.rs | 12 +++++------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/client/collider/systems.rs b/src/client/collider/systems.rs index 1b579e9f..390347c8 100644 --- a/src/client/collider/systems.rs +++ b/src/client/collider/systems.rs @@ -19,10 +19,11 @@ pub fn setup_coliders_system(mut commands: Commands) { for z in collider_range.clone() { commands .spawn(( + RigidBody::Static, Collider::cuboid( - COLLIDER_CUBOID_WIDTH / 2.0, - COLLIDER_CUBOID_WIDTH / 2.0, - COLLIDER_CUBOID_WIDTH / 2.0, + COLLIDER_CUBOID_WIDTH, + COLLIDER_CUBOID_WIDTH, + COLLIDER_CUBOID_WIDTH, ), Transform::from_xyz(x as f32, y as f32, z as f32), )) diff --git a/src/client/player/systems/controller.rs b/src/client/player/systems/controller.rs index 0fbde77f..b418c9ec 100644 --- a/src/client/player/systems/controller.rs +++ b/src/client/player/systems/controller.rs @@ -36,7 +36,7 @@ pub fn setup_controller_on_area_ready_system( let logical_entity = commands .spawn(( - Collider::cylinder(0.5, 1.5), + Collider::cylinder(0.25, 1.5), Friction { dynamic_coefficient: 0.0, static_coefficient: 0.0, @@ -77,6 +77,8 @@ pub fn setup_controller_on_area_ready_system( crouch_height: 1.2, air_acceleration: 80.0, radius: 0.75, + experimental_step_offset: 0.1, + experimental_enable_ledge_cling: true, ..default() }, )) diff --git a/src/server/terrain/systems.rs b/src/server/terrain/systems.rs index 0fa1187d..8680e488 100644 --- a/src/server/terrain/systems.rs +++ b/src/server/terrain/systems.rs @@ -87,10 +87,9 @@ pub fn save_world_system( mut timer: ResMut, ) { if timer.is_ready() { + timer.reset(); info!("Saving world..."); - if save_world(&world_name.0, &chunk_manager, &generator).is_ok() { - timer.reset(); - } + save_world(&world_name.0, &chunk_manager, &generator); } } @@ -101,10 +100,9 @@ pub fn backup_world_system( mut timer: ResMut, ) { if timer.is_ready() { - println!("Backing up world..."); - if backup_world(&world_name.0, &chunk_manager, &generator).is_ok() { - timer.reset(); - } + timer.reset(); + info!("Backing up world..."); + backup_world(&world_name.0, &chunk_manager, &generator); } } From 57726c1ee1cd5add1819b56a6a57a33abe340805 Mon Sep 17 00:00:00 2001 From: Daniel Bengl Date: Tue, 3 Feb 2026 08:43:50 +0100 Subject: [PATCH 3/7] WIP collider levels --- src/client/collider/components.rs | 3 + src/client/collider/layers.rs | 8 ++ src/client/collider/mod.rs | 1 + src/client/collider/systems.rs | 129 +++++++++--------------- src/client/player/systems/controller.rs | 3 +- src/client/prelude.rs | 1 + 6 files changed, 63 insertions(+), 82 deletions(-) create mode 100644 src/client/collider/layers.rs diff --git a/src/client/collider/components.rs b/src/client/collider/components.rs index 880bc0cb..a798a54d 100644 --- a/src/client/collider/components.rs +++ b/src/client/collider/components.rs @@ -4,3 +4,6 @@ use crate::prelude::*; pub struct BlockCollider { pub relative_position: Vec3, } + +#[derive(Component)] +pub struct TerrainCollider; diff --git a/src/client/collider/layers.rs b/src/client/collider/layers.rs new file mode 100644 index 00000000..5dc6871a --- /dev/null +++ b/src/client/collider/layers.rs @@ -0,0 +1,8 @@ +use crate::prelude::*; + +#[derive(PhysicsLayer, Default, Clone, Copy)] +pub enum GameLayer { + #[default] + Player, + Terrain, +} diff --git a/src/client/collider/mod.rs b/src/client/collider/mod.rs index fa97ffc3..069f5a7c 100644 --- a/src/client/collider/mod.rs +++ b/src/client/collider/mod.rs @@ -1,5 +1,6 @@ pub mod components; pub mod events; +pub mod layers; pub mod systems; use crate::prelude::*; diff --git a/src/client/collider/systems.rs b/src/client/collider/systems.rs index 390347c8..32a5ea06 100644 --- a/src/client/collider/systems.rs +++ b/src/client/collider/systems.rs @@ -2,74 +2,58 @@ use terrain_util::client_block::block_properties; use crate::prelude::*; -static COLLIDER_GRID_SIZE: u32 = 4; -static COLLIDER_RESTING_POSITION: Vec3 = Vec3::MIN; -static COLLIDER_CUBOID_WIDTH: f32 = 1.0; +const COLLIDER_GRID_SIZE: i32 = 4; +const COLLIDER_HALF_SIZE: i32 = COLLIDER_GRID_SIZE / 2; pub fn setup_coliders_system(mut commands: Commands) { - let collider_range = 0..COLLIDER_GRID_SIZE; - + let empty_shapes: Vec<(Vec3, Quat, Collider)> = vec![]; commands.spawn(( - Collider::cuboid(256.0, 1.0, 256.0), - Transform::from_translation(COLLIDER_RESTING_POSITION), + collider_components::TerrainCollider, + RigidBody::Static, + Collider::compound(empty_shapes), + CollisionLayers::new(GameLayer::Terrain, [GameLayer::Player]), + Transform::default(), )); - - for x in collider_range.clone() { - for y in collider_range.clone() { - for z in collider_range.clone() { - commands - .spawn(( - RigidBody::Static, - Collider::cuboid( - COLLIDER_CUBOID_WIDTH, - COLLIDER_CUBOID_WIDTH, - COLLIDER_CUBOID_WIDTH, - ), - Transform::from_xyz(x as f32, y as f32, z as f32), - )) - .insert(collider_components::BlockCollider { - relative_position: Vec3 { - x: x as f32 - (COLLIDER_GRID_SIZE as f32) / 2.0, - y: y as f32 - (COLLIDER_GRID_SIZE as f32) / 2.0, - z: z as f32 - (COLLIDER_GRID_SIZE as f32) / 2.0, - }, - }); - } - } - } } pub fn handle_collider_update_events_system( mut collider_grid_events: MessageReader, - mut query: Query<(&mut Transform, &collider_components::BlockCollider)>, + mut query: Query<&mut Collider, With>, chunk_manager: Res, ) { for event in collider_grid_events.read() { - let event_position = Vec3::new( - event.grid_center_position[0], - event.grid_center_position[1], - event.grid_center_position[2], - ) - .floor(); - for (mut transform, collider) in query.iter_mut() { - let relative_position = collider.relative_position; - let collider_position = (event_position + relative_position).floor(); - - let block = chunk_manager.get_block(collider_position.as_ivec3()); - - match block { - Some(block) => { - if block_properties(block).has_collider { - transform.translation = collider_position + COLLIDER_CUBOID_WIDTH / 2.0; - } else { - transform.translation = COLLIDER_RESTING_POSITION; + let center = IVec3::new( + event.grid_center_position[0] as i32, + event.grid_center_position[1] as i32, + event.grid_center_position[2] as i32, + ); + + let mut shapes: Vec<(Vec3, Quat, Collider)> = Vec::with_capacity( + (COLLIDER_GRID_SIZE * COLLIDER_GRID_SIZE * COLLIDER_GRID_SIZE) as usize, + ); + + for x in -COLLIDER_HALF_SIZE..COLLIDER_HALF_SIZE { + for y in -COLLIDER_HALF_SIZE..COLLIDER_HALF_SIZE { + for z in -COLLIDER_HALF_SIZE..COLLIDER_HALF_SIZE { + let block_pos = center + IVec3::new(x, y, z); + + if let Some(block) = chunk_manager.get_block(block_pos) { + if block_properties(block).has_collider { + let position = Vec3::new( + block_pos.x as f32 + 0.5, + block_pos.y as f32 + 0.5, + block_pos.z as f32 + 0.5, + ); + shapes.push((position, Quat::IDENTITY, Collider::cuboid(0.5, 0.5, 0.5))); + } } } - None => { - transform.translation = COLLIDER_RESTING_POSITION; - } } } + + if let Ok(mut collider) = query.single_mut() { + *collider = Collider::compound(shapes); + } } } @@ -78,6 +62,7 @@ mod tests { use collider_events::ColliderUpdateEvent; use super::*; + fn setup_app() -> App { let mut app = App::new(); app.add_plugins(MinimalPlugins); @@ -93,10 +78,10 @@ mod tests { let mut colliders_query = app .world_mut() - .query::<&collider_components::BlockCollider>(); + .query::<&collider_components::TerrainCollider>(); let colliders_count = colliders_query.iter(app.world_mut()).count(); - assert_eq!(colliders_count, 4 * 4 * 4); + assert_eq!(colliders_count, 1); } #[test] @@ -107,22 +92,10 @@ mod tests { app.add_systems(Update, handle_collider_update_events_system); app.insert_resource(ChunkManager::new()); + let empty_shapes: Vec<(Vec3, Quat, Collider)> = vec![]; app.world_mut().spawn(( - Transform { - translation: Vec3 { - x: 0.0, - y: 0.0, - z: 0.0, - }, - ..Default::default() - }, - collider_components::BlockCollider { - relative_position: Vec3 { - x: 1.0, - y: 2.0, - z: 3.0, - }, - }, + collider_components::TerrainCollider, + Collider::compound(empty_shapes), )); let block = BlockId::Dirt; @@ -132,23 +105,17 @@ mod tests { resource.update_block(IVec3 { x: 6, y: 7, z: 8 }, block); app.world_mut().write_message(ColliderUpdateEvent { - grid_center_position: [5.0, 5.0, 5.0], + grid_center_position: [6.0, 7.0, 8.0], }); app.update(); let mut collider_query = app .world_mut() - .query::<(&Transform, &collider_components::BlockCollider)>(); + .query::<&Collider>(); let world_mut = app.world_mut(); - let (collider_transform, _) = collider_query.single(world_mut).unwrap(); - assert_eq!( - Vec3 { - x: 6.5, - y: 7.5, - z: 8.5 - }, - collider_transform.translation - ); + let collider = collider_query.single(world_mut).unwrap(); + + assert!(collider.shape().as_compound().is_some()); } } diff --git a/src/client/player/systems/controller.rs b/src/client/player/systems/controller.rs index b418c9ec..7bb30ed8 100644 --- a/src/client/player/systems/controller.rs +++ b/src/client/player/systems/controller.rs @@ -36,7 +36,7 @@ pub fn setup_controller_on_area_ready_system( let logical_entity = commands .spawn(( - Collider::cylinder(0.25, 1.5), + Collider::capsule(0.5, 1.0), Friction { dynamic_coefficient: 0.0, static_coefficient: 0.0, @@ -46,6 +46,7 @@ pub fn setup_controller_on_area_ready_system( coefficient: 0.0, combine_rule: CoefficientCombine::Min, }, + CollisionLayers::new(GameLayer::Player, [GameLayer::Terrain]), LinearVelocity::ZERO, #[cfg(feature = "lock_player")] RigidBody::Static, diff --git a/src/client/prelude.rs b/src/client/prelude.rs index d412a522..aa5ec394 100644 --- a/src/client/prelude.rs +++ b/src/client/prelude.rs @@ -39,6 +39,7 @@ pub use rsmc as lib; pub use crate::collider::components as collider_components; pub use crate::collider::events as collider_events; +pub use crate::collider::layers::GameLayer; pub use crate::collider::systems as collider_systems; pub use crate::networking::commands as networking_commands; From fba592cc5bfb86d67723fea29b0ab4c636378b39 Mon Sep 17 00:00:00 2001 From: Daniel Bengl Date: Wed, 4 Feb 2026 22:54:42 +0100 Subject: [PATCH 4/7] Revert "WIP collider levels" This reverts commit 57726c1ee1cd5add1819b56a6a57a33abe340805. --- src/client/collider/components.rs | 3 - src/client/collider/layers.rs | 8 -- src/client/collider/mod.rs | 1 - src/client/collider/systems.rs | 129 +++++++++++++++--------- src/client/player/systems/controller.rs | 3 +- src/client/prelude.rs | 1 - 6 files changed, 82 insertions(+), 63 deletions(-) delete mode 100644 src/client/collider/layers.rs diff --git a/src/client/collider/components.rs b/src/client/collider/components.rs index a798a54d..880bc0cb 100644 --- a/src/client/collider/components.rs +++ b/src/client/collider/components.rs @@ -4,6 +4,3 @@ use crate::prelude::*; pub struct BlockCollider { pub relative_position: Vec3, } - -#[derive(Component)] -pub struct TerrainCollider; diff --git a/src/client/collider/layers.rs b/src/client/collider/layers.rs deleted file mode 100644 index 5dc6871a..00000000 --- a/src/client/collider/layers.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::prelude::*; - -#[derive(PhysicsLayer, Default, Clone, Copy)] -pub enum GameLayer { - #[default] - Player, - Terrain, -} diff --git a/src/client/collider/mod.rs b/src/client/collider/mod.rs index 069f5a7c..fa97ffc3 100644 --- a/src/client/collider/mod.rs +++ b/src/client/collider/mod.rs @@ -1,6 +1,5 @@ pub mod components; pub mod events; -pub mod layers; pub mod systems; use crate::prelude::*; diff --git a/src/client/collider/systems.rs b/src/client/collider/systems.rs index 32a5ea06..390347c8 100644 --- a/src/client/collider/systems.rs +++ b/src/client/collider/systems.rs @@ -2,58 +2,74 @@ use terrain_util::client_block::block_properties; use crate::prelude::*; -const COLLIDER_GRID_SIZE: i32 = 4; -const COLLIDER_HALF_SIZE: i32 = COLLIDER_GRID_SIZE / 2; +static COLLIDER_GRID_SIZE: u32 = 4; +static COLLIDER_RESTING_POSITION: Vec3 = Vec3::MIN; +static COLLIDER_CUBOID_WIDTH: f32 = 1.0; pub fn setup_coliders_system(mut commands: Commands) { - let empty_shapes: Vec<(Vec3, Quat, Collider)> = vec![]; + let collider_range = 0..COLLIDER_GRID_SIZE; + commands.spawn(( - collider_components::TerrainCollider, - RigidBody::Static, - Collider::compound(empty_shapes), - CollisionLayers::new(GameLayer::Terrain, [GameLayer::Player]), - Transform::default(), + Collider::cuboid(256.0, 1.0, 256.0), + Transform::from_translation(COLLIDER_RESTING_POSITION), )); + + for x in collider_range.clone() { + for y in collider_range.clone() { + for z in collider_range.clone() { + commands + .spawn(( + RigidBody::Static, + Collider::cuboid( + COLLIDER_CUBOID_WIDTH, + COLLIDER_CUBOID_WIDTH, + COLLIDER_CUBOID_WIDTH, + ), + Transform::from_xyz(x as f32, y as f32, z as f32), + )) + .insert(collider_components::BlockCollider { + relative_position: Vec3 { + x: x as f32 - (COLLIDER_GRID_SIZE as f32) / 2.0, + y: y as f32 - (COLLIDER_GRID_SIZE as f32) / 2.0, + z: z as f32 - (COLLIDER_GRID_SIZE as f32) / 2.0, + }, + }); + } + } + } } pub fn handle_collider_update_events_system( mut collider_grid_events: MessageReader, - mut query: Query<&mut Collider, With>, + mut query: Query<(&mut Transform, &collider_components::BlockCollider)>, chunk_manager: Res, ) { for event in collider_grid_events.read() { - let center = IVec3::new( - event.grid_center_position[0] as i32, - event.grid_center_position[1] as i32, - event.grid_center_position[2] as i32, - ); - - let mut shapes: Vec<(Vec3, Quat, Collider)> = Vec::with_capacity( - (COLLIDER_GRID_SIZE * COLLIDER_GRID_SIZE * COLLIDER_GRID_SIZE) as usize, - ); - - for x in -COLLIDER_HALF_SIZE..COLLIDER_HALF_SIZE { - for y in -COLLIDER_HALF_SIZE..COLLIDER_HALF_SIZE { - for z in -COLLIDER_HALF_SIZE..COLLIDER_HALF_SIZE { - let block_pos = center + IVec3::new(x, y, z); - - if let Some(block) = chunk_manager.get_block(block_pos) { - if block_properties(block).has_collider { - let position = Vec3::new( - block_pos.x as f32 + 0.5, - block_pos.y as f32 + 0.5, - block_pos.z as f32 + 0.5, - ); - shapes.push((position, Quat::IDENTITY, Collider::cuboid(0.5, 0.5, 0.5))); - } + let event_position = Vec3::new( + event.grid_center_position[0], + event.grid_center_position[1], + event.grid_center_position[2], + ) + .floor(); + for (mut transform, collider) in query.iter_mut() { + let relative_position = collider.relative_position; + let collider_position = (event_position + relative_position).floor(); + + let block = chunk_manager.get_block(collider_position.as_ivec3()); + + match block { + Some(block) => { + if block_properties(block).has_collider { + transform.translation = collider_position + COLLIDER_CUBOID_WIDTH / 2.0; + } else { + transform.translation = COLLIDER_RESTING_POSITION; } } + None => { + transform.translation = COLLIDER_RESTING_POSITION; + } } } - - if let Ok(mut collider) = query.single_mut() { - *collider = Collider::compound(shapes); - } } } @@ -62,7 +78,6 @@ mod tests { use collider_events::ColliderUpdateEvent; use super::*; - fn setup_app() -> App { let mut app = App::new(); app.add_plugins(MinimalPlugins); @@ -78,10 +93,10 @@ mod tests { let mut colliders_query = app .world_mut() - .query::<&collider_components::TerrainCollider>(); + .query::<&collider_components::BlockCollider>(); let colliders_count = colliders_query.iter(app.world_mut()).count(); - assert_eq!(colliders_count, 1); + assert_eq!(colliders_count, 4 * 4 * 4); } #[test] @@ -92,10 +107,22 @@ mod tests { app.add_systems(Update, handle_collider_update_events_system); app.insert_resource(ChunkManager::new()); - let empty_shapes: Vec<(Vec3, Quat, Collider)> = vec![]; app.world_mut().spawn(( - collider_components::TerrainCollider, - Collider::compound(empty_shapes), + Transform { + translation: Vec3 { + x: 0.0, + y: 0.0, + z: 0.0, + }, + ..Default::default() + }, + collider_components::BlockCollider { + relative_position: Vec3 { + x: 1.0, + y: 2.0, + z: 3.0, + }, + }, )); let block = BlockId::Dirt; @@ -105,17 +132,23 @@ mod tests { resource.update_block(IVec3 { x: 6, y: 7, z: 8 }, block); app.world_mut().write_message(ColliderUpdateEvent { - grid_center_position: [6.0, 7.0, 8.0], + grid_center_position: [5.0, 5.0, 5.0], }); app.update(); let mut collider_query = app .world_mut() - .query::<&Collider>(); + .query::<(&Transform, &collider_components::BlockCollider)>(); let world_mut = app.world_mut(); - let collider = collider_query.single(world_mut).unwrap(); - - assert!(collider.shape().as_compound().is_some()); + let (collider_transform, _) = collider_query.single(world_mut).unwrap(); + assert_eq!( + Vec3 { + x: 6.5, + y: 7.5, + z: 8.5 + }, + collider_transform.translation + ); } } diff --git a/src/client/player/systems/controller.rs b/src/client/player/systems/controller.rs index 7bb30ed8..b418c9ec 100644 --- a/src/client/player/systems/controller.rs +++ b/src/client/player/systems/controller.rs @@ -36,7 +36,7 @@ pub fn setup_controller_on_area_ready_system( let logical_entity = commands .spawn(( - Collider::capsule(0.5, 1.0), + Collider::cylinder(0.25, 1.5), Friction { dynamic_coefficient: 0.0, static_coefficient: 0.0, @@ -46,7 +46,6 @@ pub fn setup_controller_on_area_ready_system( coefficient: 0.0, combine_rule: CoefficientCombine::Min, }, - CollisionLayers::new(GameLayer::Player, [GameLayer::Terrain]), LinearVelocity::ZERO, #[cfg(feature = "lock_player")] RigidBody::Static, diff --git a/src/client/prelude.rs b/src/client/prelude.rs index aa5ec394..d412a522 100644 --- a/src/client/prelude.rs +++ b/src/client/prelude.rs @@ -39,7 +39,6 @@ pub use rsmc as lib; pub use crate::collider::components as collider_components; pub use crate::collider::events as collider_events; -pub use crate::collider::layers::GameLayer; pub use crate::collider::systems as collider_systems; pub use crate::networking::commands as networking_commands; From 67592c66a2f6cb664987f8558b7b02fd7fbe19fa Mon Sep 17 00:00:00 2001 From: Daniel Bengl Date: Sat, 14 Feb 2026 08:50:19 +0100 Subject: [PATCH 5/7] Reduce fps display refresh rate --- src/client/gui/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/gui/mod.rs b/src/client/gui/mod.rs index e1158bc4..5dbea118 100644 --- a/src/client/gui/mod.rs +++ b/src/client/gui/mod.rs @@ -24,7 +24,7 @@ impl Plugin for GuiPlugin { ..default() }, text_color: Color::srgb(0.0, 1.0, 0.0), - refresh_interval: core::time::Duration::from_millis(10), + refresh_interval: core::time::Duration::from_millis(200), enabled: true, frame_time_graph_config: FrameTimeGraphConfig { enabled: true, From 0ef4362b97bd29cdc683b44afeb4b11de8ef2bdb Mon Sep 17 00:00:00 2001 From: Daniel Bengl Date: Sat, 14 Feb 2026 08:55:47 +0100 Subject: [PATCH 6/7] Improve prod optimization --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 00915a7c..fb768602 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,9 @@ opt-level = 3 [profile.release] opt-level = 3 +lto = "thin" +codegen-units = 1 +strip = true [[bin]] name = "client" From 57a87383e65e5821af98bc4581dab736be893113 Mon Sep 17 00:00:00 2001 From: Daniel Bengl Date: Sat, 14 Feb 2026 09:02:43 +0100 Subject: [PATCH 7/7] Improve error handling --- src/server/terrain/systems.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/server/terrain/systems.rs b/src/server/terrain/systems.rs index 8680e488..9e26f5c0 100644 --- a/src/server/terrain/systems.rs +++ b/src/server/terrain/systems.rs @@ -89,7 +89,10 @@ pub fn save_world_system( if timer.is_ready() { timer.reset(); info!("Saving world..."); - save_world(&world_name.0, &chunk_manager, &generator); + match save_world(&world_name.0, &chunk_manager, &generator) { + Ok(_) => info!("World has been saved!"), + Err(err) => error!("Err saving world: {err}"), + } } } @@ -102,7 +105,10 @@ pub fn backup_world_system( if timer.is_ready() { timer.reset(); info!("Backing up world..."); - backup_world(&world_name.0, &chunk_manager, &generator); + match backup_world(&world_name.0, &chunk_manager, &generator) { + Ok(_) => info!("World has been backed up!"), + Err(err) => error!("Err backing up world: {err}"), + } } }