From f41d6ae68612611e1baedd0e231c7f38936ec809 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Thu, 9 Apr 2026 17:00:44 +0000 Subject: [PATCH 001/106] minor name change in transparent piplien and remove todo --- .../main_passes/transparent_pass/startup.rs | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/crates/client/src/render/pipeline/main_passes/transparent_pass/startup.rs b/crates/client/src/render/pipeline/main_passes/transparent_pass/startup.rs index 4ae58049..d285cd51 100644 --- a/crates/client/src/render/pipeline/main_passes/transparent_pass/startup.rs +++ b/crates/client/src/render/pipeline/main_passes/transparent_pass/startup.rs @@ -1,6 +1,6 @@ use super::super::shared_resources::{ - CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, MAIN_DEPTH_FORMAT, - TextureArrayBindGroupLayout, + CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, TextureArrayBindGroupLayout, + MAIN_DEPTH_FORMAT, }; use crate::render::pipeline::{ gpu_resources::world_uniforms::ChunkStorageBindGroupLayout, @@ -19,13 +19,12 @@ pub struct TransparentPipelineKey { pub hdr: bool, } -// TODO: we should storethe actual layouts, NOT the descriptors #[derive(Resource)] pub struct TransparentPipeline { - pub view_layout: BindGroupLayoutDescriptor, - pub environment_layout: BindGroupLayoutDescriptor, - pub texture_layout: BindGroupLayoutDescriptor, - pub chunk_storage_layout: BindGroupLayoutDescriptor, + pub view_layout_descriptor: BindGroupLayoutDescriptor, + pub environment_layout_descriptor: BindGroupLayoutDescriptor, + pub texture_layout_descriptor: BindGroupLayoutDescriptor, + pub chunk_storage_layout_descriptor: BindGroupLayoutDescriptor, } impl FromWorld for TransparentPipeline { @@ -37,10 +36,10 @@ impl FromWorld for TransparentPipeline { let chunk_storage_layout = world.resource::(); Self { - view_layout: view_layout.descriptor.clone(), - environment_layout: environment_layout.descriptor.clone(), - texture_layout: texture_layout.descriptor.clone(), - chunk_storage_layout: chunk_storage_layout.descriptor.clone(), + view_layout_descriptor: view_layout.descriptor.clone(), + environment_layout_descriptor: environment_layout.descriptor.clone(), + texture_layout_descriptor: texture_layout.descriptor.clone(), + chunk_storage_layout_descriptor: chunk_storage_layout.descriptor.clone(), } } } @@ -58,10 +57,10 @@ impl SpecializedRenderPipeline for TransparentPipeline { RenderPipelineDescriptor { label: Some("Transparent Render Pipeline".into()), layout: vec![ - self.view_layout.clone(), - self.environment_layout.clone(), - self.texture_layout.clone(), - self.chunk_storage_layout.clone(), + self.view_layout_descriptor.clone(), + self.environment_layout_descriptor.clone(), + self.texture_layout_descriptor.clone(), + self.chunk_storage_layout_descriptor.clone(), ], push_constant_ranges: vec![], vertex: VertexState { From dc4ce2bae85b90b081067527933bd7b4561c1e5b Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Thu, 9 Apr 2026 17:33:09 +0000 Subject: [PATCH 002/106] initial protocl setup --- crates/shared/src/lib.rs | 1 + crates/shared/src/protocol/client.rs | 15 +++++++++++++++ crates/shared/src/protocol/mod.rs | 5 +++++ crates/shared/src/protocol/server.rs | 18 ++++++++++++++++++ .../simulation/chunk/components/chunk_chord.rs | 3 ++- .../input/types/simulation_action.rs | 4 +++- 6 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 crates/shared/src/protocol/client.rs create mode 100644 crates/shared/src/protocol/mod.rs create mode 100644 crates/shared/src/protocol/server.rs diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index 5b588118..a380c38a 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -1,5 +1,6 @@ pub mod load; pub mod prelude; +pub mod protocol; pub mod simulation; pub mod state; diff --git a/crates/shared/src/protocol/client.rs b/crates/shared/src/protocol/client.rs new file mode 100644 index 00000000..145833d6 --- /dev/null +++ b/crates/shared/src/protocol/client.rs @@ -0,0 +1,15 @@ +use crate::simulation::chunk::ChunkCoord; +use crate::simulation::input::types::SimulationAction; +use bevy::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum ClientMessage { + /// A discrete input action performed by the player. + Action(SimulationAction), + /// A request for the server to send voxel data for a specific chunk. + RequestChunk(ChunkCoord), + /// Updates the server on the player's current view orientation/camera state. + /// Necessary for authoritative targeting or raycasting calculations. + UpdateView { forward: Vec3 }, +} diff --git a/crates/shared/src/protocol/mod.rs b/crates/shared/src/protocol/mod.rs new file mode 100644 index 00000000..b15140c1 --- /dev/null +++ b/crates/shared/src/protocol/mod.rs @@ -0,0 +1,5 @@ +pub mod client; +pub mod server; + +pub use client::ClientMessage; +pub use server::ServerMessage; diff --git a/crates/shared/src/protocol/server.rs b/crates/shared/src/protocol/server.rs new file mode 100644 index 00000000..be03beac --- /dev/null +++ b/crates/shared/src/protocol/server.rs @@ -0,0 +1,18 @@ +use crate::simulation::chunk::ChunkCoord; +use bevy::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum ServerMessage { + /// Initial state sent to the client upon joining. + Welcome { entity_id: Entity, spawn_pos: Vec3 }, + /// Direct voxel update for a specific world position. + VoxelUpdate { position: IVec3, block_id: u16 }, + /// Bulk data for a chunk, typically compressed or encoded from ChunkVolumeData. + ChunkData { + coord: ChunkCoord, + data: Vec, // TODO: may want a more efficient encoding + }, + /// Synchronizes the authoritative game time across all clients. + SyncTime { game_time: f32, tick: u64 }, +} diff --git a/crates/shared/src/simulation/chunk/components/chunk_chord.rs b/crates/shared/src/simulation/chunk/components/chunk_chord.rs index bfd0c83a..42fd76f2 100644 --- a/crates/shared/src/simulation/chunk/components/chunk_chord.rs +++ b/crates/shared/src/simulation/chunk/components/chunk_chord.rs @@ -2,12 +2,13 @@ use crate::prelude::*; use crate::simulation::chunk::{CHUNK_DEPTH, CHUNK_HEIGHT, CHUNK_SIDE_LENGTH, CHUNK_WIDTH}; use bevy::ecs::prelude::*; use derive_more::{Deref, DerefMut}; +use serde::{Deserialize, Serialize}; use std::fmt; const BIT_SHIFT: i32 = CHUNK_SIDE_LENGTH.trailing_zeros() as i32; /// Stores the coordinate of the chunk an entity is currently in. -#[derive(Component, Clone, Deref, DerefMut, Debug)] +#[derive(Component, Serialize, Deserialize, Clone, Deref, DerefMut, Debug)] pub struct ChunkCoord { pub pos: IVec3, } diff --git a/crates/shared/src/simulation/input/types/simulation_action.rs b/crates/shared/src/simulation/input/types/simulation_action.rs index 723fe2c4..a973d815 100644 --- a/crates/shared/src/simulation/input/types/simulation_action.rs +++ b/crates/shared/src/simulation/input/types/simulation_action.rs @@ -1,5 +1,7 @@ +use serde::{Deserialize, Serialize}; + /// Defines -#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] +#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone, Copy)] pub enum SimulationAction { // Core player movement MoveForward, From ab63f64d48d0a2c10fe05ac7a615680bea2ea762 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Thu, 9 Apr 2026 17:15:43 +0000 Subject: [PATCH 003/106] separate opaque and skybox pipelines --- Cargo.toml | 1 + assets/client/shader/ui/common.wesl | 17 -- assets/client/shader/ui/main_frag.wesl | 6 - assets/client/shader/ui/main_vert.wesl | 19 -- .../world/main_passes/skybox/main_vert.wesl | 2 +- crates/client/build.rs | 4 - crates/client/src/render/mod.rs | 2 +- .../src/render/pipeline/main_passes/mod.rs | 3 + .../pipeline/main_passes/opaque_pass/mod.rs | 8 +- .../main_passes/opaque_pass/pipeline.rs | 141 +++++++++++++ .../pipeline/main_passes/opaque_pass/queue.rs | 32 +-- .../main_passes/opaque_pass/startup/mod.rs | 3 - .../opaque_pass/startup/setup_pipelines.rs | 187 ------------------ .../pipeline/main_passes/skybox_pass/mod.rs | 17 ++ .../main_passes/skybox_pass/pipeline.rs | 96 +++++++++ 15 files changed, 282 insertions(+), 256 deletions(-) delete mode 100644 assets/client/shader/ui/common.wesl delete mode 100644 assets/client/shader/ui/main_frag.wesl delete mode 100644 assets/client/shader/ui/main_vert.wesl create mode 100644 crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs delete mode 100644 crates/client/src/render/pipeline/main_passes/opaque_pass/startup/mod.rs delete mode 100644 crates/client/src/render/pipeline/main_passes/opaque_pass/startup/setup_pipelines.rs create mode 100644 crates/client/src/render/pipeline/main_passes/skybox_pass/mod.rs create mode 100644 crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs diff --git a/Cargo.toml b/Cargo.toml index 5b738dbd..44837a4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ publish = false [workspace.lints.clippy] type_complexity = "allow" +too_many_arguments = "allow" # INFO: -------------------------- # release profiles diff --git a/assets/client/shader/ui/common.wesl b/assets/client/shader/ui/common.wesl deleted file mode 100644 index 4b05d24e..00000000 --- a/assets/client/shader/ui/common.wesl +++ /dev/null @@ -1,17 +0,0 @@ -// per-view data -@group(0) @binding(0) -var ortho_projection: mat4x4; - -// per-material data -struct Material { - color: vec4, -}; -@group(1) @binding(0) -var material: Material; - -// per-object data -struct Object { - model: mat4x4, -}; -@group(2) @binding(0) -var objects: array; diff --git a/assets/client/shader/ui/main_frag.wesl b/assets/client/shader/ui/main_frag.wesl deleted file mode 100644 index f8582ba4..00000000 --- a/assets/client/shader/ui/main_frag.wesl +++ /dev/null @@ -1,6 +0,0 @@ -import package::ui::common::{material, Material}; - -@fragment -fn fs_main() -> @location(0) vec4 { - return material.color; -} \ No newline at end of file diff --git a/assets/client/shader/ui/main_vert.wesl b/assets/client/shader/ui/main_vert.wesl deleted file mode 100644 index fece7619..00000000 --- a/assets/client/shader/ui/main_vert.wesl +++ /dev/null @@ -1,19 +0,0 @@ -import package::ui::common::{ortho_projection, Object, objects, material, Material}; - -struct VertexOutput { - @builtin(position) clip_position: vec4, -}; - -@vertex -fn vs_main( - @location(0) position: vec2, - @builtin(instance_index) instance_index: u32, -) -> VertexOutput { - var out: VertexOutput; - - // scale model matrix (screen space) by the orthographic projection to get clip space - let model = objects[instance_index].model; - out.clip_position = ortho_projection * model * vec4(position, 0.0, 1.0); - - return out; -} diff --git a/assets/client/shader/world/main_passes/skybox/main_vert.wesl b/assets/client/shader/world/main_passes/skybox/main_vert.wesl index 80f14735..676de387 100644 --- a/assets/client/shader/world/main_passes/skybox/main_vert.wesl +++ b/assets/client/shader/world/main_passes/skybox/main_vert.wesl @@ -24,7 +24,7 @@ fn vs_main( let pos = vertices[in_vertex_index]; - // the full screen quad is at the maximum distance (0.0 for inverse z) + // the full screen quad is at the maximum distance (z=0.0 for inverse z) out.clip_position = vec4(pos, 0.0, 1.0); out.clip_pos_for_unproject = out.clip_position; diff --git a/crates/client/build.rs b/crates/client/build.rs index 50b17e99..7ebf223c 100644 --- a/crates/client/build.rs +++ b/crates/client/build.rs @@ -71,8 +71,4 @@ fn main() { &"package::world::shadow::main_vert".parse().unwrap(), "shadow_vert", ); - - // UI shaders - compiler.build_artifact(&"package::ui::main_vert".parse().unwrap(), "ui_vert"); - compiler.build_artifact(&"package::ui::main_frag".parse().unwrap(), "ui_frag"); } diff --git a/crates/client/src/render/mod.rs b/crates/client/src/render/mod.rs index 7a8c4530..fb481b66 100644 --- a/crates/client/src/render/mod.rs +++ b/crates/client/src/render/mod.rs @@ -19,7 +19,7 @@ use crate::render::{ RenderGraphEdgesPlugin, WorldRenderPassesPlugin, main_passes::{ bounding_box_pass::extract::WireframeToggleState, - opaque_pass::{extract::extract_opaque_meshes, startup::OpaqueRenderMode}, + opaque_pass::{extract::extract_opaque_meshes, pipeline::OpaqueRenderMode}, transparent_pass::extract::extract_transparent_meshes, }, }, diff --git a/crates/client/src/render/pipeline/main_passes/mod.rs b/crates/client/src/render/pipeline/main_passes/mod.rs index 70e81716..bf39f215 100644 --- a/crates/client/src/render/pipeline/main_passes/mod.rs +++ b/crates/client/src/render/pipeline/main_passes/mod.rs @@ -1,6 +1,7 @@ pub mod bounding_box_pass; pub mod opaque_pass; pub mod shared_resources; +pub mod skybox_pass; pub mod transparent_pass; use shared_resources::{ @@ -18,6 +19,7 @@ use crate::render::pipeline::main_passes::{ shared_resources::{ update_camera_view_buffer_system, update_environment_uniform_buffer_system, }, + skybox_pass::SkyboxRenderPassPlugin, transparent_pass::TransparentRenderPassPlugin, }; use bevy::app::{App, Plugin}; @@ -51,6 +53,7 @@ impl Plugin for PlayerCentricRenderPassPlugin { app.add_plugins(( TransparentRenderPassPlugin, OpaqueRenderPassPlugin, + SkyboxRenderPassPlugin, WireframeRenderPassPlugin, )); } diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs index b5982ff2..e18c2da4 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs +++ b/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs @@ -1,9 +1,10 @@ pub mod extract; +pub mod pipeline; pub mod prepare; pub mod queue; pub mod render; -pub mod startup; +pub use pipeline::*; pub use render::OpaquePassRenderNode; // INFO: --------------------------- @@ -17,7 +18,6 @@ use bevy::render::{ render_resource::SpecializedRenderPipelines, {Render, RenderSystems}, }; -use startup::OpaquePipelines; pub struct OpaqueRenderPassPlugin; @@ -56,7 +56,7 @@ impl Plugin for OpaqueRenderPassPlugin { // Startup // ----------------------- - app.init_resource::(); - app.init_resource::>(); + app.init_resource::(); + app.init_resource::>(); } } diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs new file mode 100644 index 00000000..b7b380f6 --- /dev/null +++ b/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs @@ -0,0 +1,141 @@ +use crate::input::systems::toggle_opaque_wireframe::OpaqueWireframeMode; +use crate::render::pipeline::{ + gpu_resources::world_uniforms::ChunkStorageBindGroupLayout, + main_passes::shared_resources::{ + CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, MAIN_DEPTH_FORMAT, + TextureArrayBindGroupLayout, + }, + shader_registry::{OPAQUE_FRAG_SHADER_HANDLE, OPAQUE_VERT_SHADER_HANDLE}, +}; +use bevy::{ + ecs::prelude::*, + render::{extract_resource::ExtractResource, render_resource::*, view::ViewTarget}, +}; +use tracing::instrument; + +/// A resource that defines the current opaque render mode +#[derive(Resource, Default, Debug, PartialEq, Eq, Hash, Clone, Copy)] +pub enum OpaqueRenderMode { + #[default] + Fill, + Wireframe, +} + +impl ExtractResource for OpaqueRenderMode { + type Source = OpaqueWireframeMode; + + fn extract_resource(source: &Self::Source) -> Self { + if source.enabled { + OpaqueRenderMode::Wireframe + } else { + OpaqueRenderMode::Fill + } + } +} + +/// A key that uniquely identifies a specialized world opaque pipeline. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct WorldOpaquePipelineKey { + pub msaa_samples: u32, + pub hdr: bool, + pub mode: OpaqueRenderMode, +} + +/// A resource that holds all the layouts and handles needed to specialize world opaque pipelines. +#[derive(Resource)] +pub struct WorldOpaquePipeline { + pub view_layout: BindGroupLayoutDescriptor, + pub environment_layout: BindGroupLayoutDescriptor, + pub texture_layout: BindGroupLayoutDescriptor, + pub chunk_storage_layout: BindGroupLayoutDescriptor, +} + +impl FromWorld for WorldOpaquePipeline { + #[instrument(skip_all)] + fn from_world(world: &mut World) -> Self { + let view_layout = world.resource::(); + let environment_layout = world.resource::(); + let texture_layout = world.resource::(); + let chunk_storage_layout = world.resource::(); + + Self { + view_layout: view_layout.descriptor.clone(), + environment_layout: environment_layout.descriptor.clone(), + texture_layout: texture_layout.descriptor.clone(), + chunk_storage_layout: chunk_storage_layout.descriptor.clone(), + } + } +} + +impl SpecializedRenderPipeline for WorldOpaquePipeline { + type Key = WorldOpaquePipelineKey; + + fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { + let format = if key.hdr { + ViewTarget::TEXTURE_FORMAT_HDR + } else { + TextureFormat::Rgba8UnormSrgb + }; + + let fragment_target = [Some(ColorTargetState { + format, + blend: Some(BlendState::REPLACE), + write_mask: ColorWrites::ALL, + })]; + + let depth_stencil = Some(DepthStencilState { + format: MAIN_DEPTH_FORMAT, + depth_write_enabled: true, + depth_compare: CompareFunction::GreaterEqual, + stencil: StencilState::default(), + bias: DepthBiasState::default(), + }); + + let polygon_mode = match key.mode { + OpaqueRenderMode::Fill => PolygonMode::Fill, + OpaqueRenderMode::Wireframe => PolygonMode::Line, + }; + + let label = match key.mode { + OpaqueRenderMode::Fill => "World Opaque Pipeline", + OpaqueRenderMode::Wireframe => "Wireframe World Opaque Pipeline", + }; + + RenderPipelineDescriptor { + label: Some(label.into()), + layout: vec![ + self.view_layout.clone(), + self.environment_layout.clone(), + self.texture_layout.clone(), + self.chunk_storage_layout.clone(), + ], + push_constant_ranges: vec![], + vertex: VertexState { + shader: OPAQUE_VERT_SHADER_HANDLE, + shader_defs: vec![], + entry_point: Some("vs_main".into()), + buffers: vec![], + }, + fragment: Some(FragmentState { + shader: OPAQUE_FRAG_SHADER_HANDLE, + shader_defs: vec![], + entry_point: Some("fs_main".into()), + targets: fragment_target.to_vec(), + }), + primitive: PrimitiveState { + topology: PrimitiveTopology::TriangleList, + front_face: FrontFace::Ccw, + polygon_mode, + cull_mode: Some(Face::Back), + ..Default::default() + }, + depth_stencil, + multisample: MultisampleState { + count: key.msaa_samples, + mask: !0, + alpha_to_coverage_enabled: false, + }, + zero_initialize_workgroup_memory: true, + } + } +} diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs index c8c3cade..c9f11c7f 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs +++ b/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs @@ -1,9 +1,8 @@ use crate::prelude::*; use crate::render::{ pipeline::main_passes::opaque_pass::extract::OpaqueRenderMeshComponent, - pipeline::main_passes::opaque_pass::startup::{ - OpaquePipelineKey, OpaquePipelines, OpaqueRenderMode, - }, + pipeline::main_passes::opaque_pass::pipeline::{OpaqueRenderMode, WorldOpaquePipeline, WorldOpaquePipelineKey}, + pipeline::main_passes::skybox_pass::{SkyboxPipeline, SkyboxPipelineKey}, types::RenderTransformComponent, }; use bevy::ecs::prelude::*; @@ -46,30 +45,35 @@ pub fn queue_opaque_system( )>, render_mode: Res, pipeline_cache: Res, - mut specialized_pipelines: ResMut>, - opaque_pipelines: Res, + mut specialized_world_pipelines: ResMut>, + world_pipelines: Res, + mut specialized_skybox_pipelines: ResMut>, + skybox_pipelines: Res, ) { for (extracted_view, msaa, mut opaque_phase) in views_query.iter_mut() { opaque_phase.items.clear(); // specialize pipelines for this view's MSAA and HDR settings - let mesh_key = OpaquePipelineKey { + let mesh_key = WorldOpaquePipelineKey { msaa_samples: msaa.samples(), hdr: extracted_view.hdr, mode: *render_mode, - is_skybox: false, }; - opaque_phase.mesh_pipeline_id = - Some(specialized_pipelines.specialize(&pipeline_cache, &opaque_pipelines, mesh_key)); + opaque_phase.mesh_pipeline_id = Some(specialized_world_pipelines.specialize( + &pipeline_cache, + &world_pipelines, + mesh_key, + )); - let skybox_key = OpaquePipelineKey { + let skybox_key = SkyboxPipelineKey { msaa_samples: msaa.samples(), hdr: extracted_view.hdr, - mode: *render_mode, - is_skybox: true, }; - opaque_phase.skybox_pipeline_id = - Some(specialized_pipelines.specialize(&pipeline_cache, &opaque_pipelines, skybox_key)); + opaque_phase.skybox_pipeline_id = Some(specialized_skybox_pipelines.specialize( + &pipeline_cache, + &skybox_pipelines, + skybox_key, + )); // collect sortable items for the render pass let camera_position = extracted_view.world_from_view.translation(); diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/startup/mod.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/startup/mod.rs deleted file mode 100644 index 4f3822ef..00000000 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/startup/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod setup_pipelines; - -pub use setup_pipelines::*; diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/startup/setup_pipelines.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/startup/setup_pipelines.rs deleted file mode 100644 index 2bd1d363..00000000 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/startup/setup_pipelines.rs +++ /dev/null @@ -1,187 +0,0 @@ -use crate::input::systems::toggle_opaque_wireframe::OpaqueWireframeMode; -use crate::render::pipeline::{ - gpu_resources::world_uniforms::ChunkStorageBindGroupLayout, - main_passes::shared_resources::{ - CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, MAIN_DEPTH_FORMAT, - TextureArrayBindGroupLayout, - }, - shader_registry::{ - OPAQUE_FRAG_SHADER_HANDLE, OPAQUE_VERT_SHADER_HANDLE, SKYBOX_FRAG_SHADER_HANDLE, - SKYBOX_VERT_SHADER_HANDLE, - }, -}; -use bevy::{ - ecs::prelude::*, - render::{extract_resource::ExtractResource, render_resource::*, view::ViewTarget}, -}; -use tracing::instrument; - -/// A resource that defines the current opaque render mode -#[derive(Resource, Default, Debug, PartialEq, Eq, Hash, Clone, Copy)] -pub enum OpaqueRenderMode { - #[default] - Fill, - Wireframe, -} - -impl ExtractResource for OpaqueRenderMode { - type Source = OpaqueWireframeMode; - - fn extract_resource(source: &Self::Source) -> Self { - if source.enabled { - OpaqueRenderMode::Wireframe - } else { - OpaqueRenderMode::Fill - } - } -} - -/// A key that uniquely identifies a specialized opaque pipeline. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub struct OpaquePipelineKey { - pub msaa_samples: u32, - pub hdr: bool, - pub mode: OpaqueRenderMode, - pub is_skybox: bool, -} - -/// A resource that holds all the layouts and handles needed to specialize opaque pipelines. -#[derive(Resource)] -pub struct OpaquePipelines { - pub view_layout: BindGroupLayoutDescriptor, - pub environment_layout: BindGroupLayoutDescriptor, - pub texture_layout: BindGroupLayoutDescriptor, - pub chunk_storage_layout: BindGroupLayoutDescriptor, -} - -impl FromWorld for OpaquePipelines { - #[instrument(skip_all)] - fn from_world(world: &mut World) -> Self { - let view_layout = world.resource::(); - let environment_layout = world.resource::(); - let texture_layout = world.resource::(); - let chunk_storage_layout = world.resource::(); - - Self { - view_layout: view_layout.descriptor.clone(), - environment_layout: environment_layout.descriptor.clone(), - texture_layout: texture_layout.descriptor.clone(), - chunk_storage_layout: chunk_storage_layout.descriptor.clone(), - } - } -} - -impl SpecializedRenderPipeline for OpaquePipelines { - type Key = OpaquePipelineKey; - - fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { - let format = if key.hdr { - ViewTarget::TEXTURE_FORMAT_HDR - } else { - TextureFormat::Rgba8UnormSrgb - }; - - let fragment_target = [Some(ColorTargetState { - format, - blend: Some(BlendState::REPLACE), - write_mask: ColorWrites::ALL, - })]; - - if key.is_skybox { - let depth_stencil = Some(DepthStencilState { - format: MAIN_DEPTH_FORMAT, - depth_write_enabled: false, - depth_compare: CompareFunction::GreaterEqual, - stencil: StencilState::default(), - bias: DepthBiasState::default(), - }); - - RenderPipelineDescriptor { - label: Some("Skybox Opaque Pipeline".into()), - layout: vec![self.view_layout.clone(), self.environment_layout.clone()], - push_constant_ranges: vec![], - vertex: VertexState { - shader: SKYBOX_VERT_SHADER_HANDLE, - shader_defs: vec![], - entry_point: Some("vs_main".into()), - buffers: vec![], - }, - fragment: Some(FragmentState { - shader: SKYBOX_FRAG_SHADER_HANDLE, - shader_defs: vec![], - entry_point: Some("fs_main".into()), - targets: fragment_target.to_vec(), - }), - primitive: PrimitiveState { - topology: PrimitiveTopology::TriangleList, - front_face: FrontFace::Ccw, - polygon_mode: PolygonMode::Fill, - cull_mode: None, - ..Default::default() - }, - depth_stencil, - multisample: MultisampleState { - count: key.msaa_samples, - mask: !0, - alpha_to_coverage_enabled: false, - }, - zero_initialize_workgroup_memory: true, - } - } else { - let depth_stencil = Some(DepthStencilState { - format: MAIN_DEPTH_FORMAT, - depth_write_enabled: true, - depth_compare: CompareFunction::GreaterEqual, - stencil: StencilState::default(), - bias: DepthBiasState::default(), - }); - - let polygon_mode = match key.mode { - OpaqueRenderMode::Fill => PolygonMode::Fill, - OpaqueRenderMode::Wireframe => PolygonMode::Line, - }; - - let label = match key.mode { - OpaqueRenderMode::Fill => "Opaque Pipeline", - OpaqueRenderMode::Wireframe => "Wireframe Opaque Pipeline", - }; - - RenderPipelineDescriptor { - label: Some(label.into()), - layout: vec![ - self.view_layout.clone(), - self.environment_layout.clone(), - self.texture_layout.clone(), - self.chunk_storage_layout.clone(), - ], - push_constant_ranges: vec![], - vertex: VertexState { - shader: OPAQUE_VERT_SHADER_HANDLE, - shader_defs: vec![], - entry_point: Some("vs_main".into()), - buffers: vec![], - }, - fragment: Some(FragmentState { - shader: OPAQUE_FRAG_SHADER_HANDLE, - shader_defs: vec![], - entry_point: Some("fs_main".into()), - targets: fragment_target.to_vec(), - }), - primitive: PrimitiveState { - topology: PrimitiveTopology::TriangleList, - front_face: FrontFace::Ccw, - polygon_mode, - cull_mode: Some(Face::Back), - ..Default::default() - }, - depth_stencil, - multisample: MultisampleState { - count: key.msaa_samples, - mask: !0, - alpha_to_coverage_enabled: false, - }, - zero_initialize_workgroup_memory: true, - } - } - } -} diff --git a/crates/client/src/render/pipeline/main_passes/skybox_pass/mod.rs b/crates/client/src/render/pipeline/main_passes/skybox_pass/mod.rs new file mode 100644 index 00000000..4ce2802d --- /dev/null +++ b/crates/client/src/render/pipeline/main_passes/skybox_pass/mod.rs @@ -0,0 +1,17 @@ +pub mod pipeline; + +pub use pipeline::*; + +use bevy::app::{App, Plugin}; +use bevy::render::render_resource::SpecializedRenderPipelines; + +pub struct SkyboxRenderPassPlugin; + +impl Plugin for SkyboxRenderPassPlugin { + fn build(&self, _app: &mut App) {} + + fn finish(&self, app: &mut App) { + app.init_resource::(); + app.init_resource::>(); + } +} diff --git a/crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs b/crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs new file mode 100644 index 00000000..a25d6d75 --- /dev/null +++ b/crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs @@ -0,0 +1,96 @@ +use crate::render::pipeline::{ + main_passes::shared_resources::{ + CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, MAIN_DEPTH_FORMAT, + }, + shader_registry::{SKYBOX_FRAG_SHADER_HANDLE, SKYBOX_VERT_SHADER_HANDLE}, +}; +use bevy::{ + ecs::prelude::*, + render::{render_resource::*, view::ViewTarget}, +}; +use tracing::instrument; + +/// A key that uniquely identifies a specialized skybox pipeline. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct SkyboxPipelineKey { + pub msaa_samples: u32, + pub hdr: bool, +} + +/// A resource that holds all the layouts and handles needed to specialize skybox pipelines. +#[derive(Resource)] +pub struct SkyboxPipeline { + pub view_layout: BindGroupLayoutDescriptor, + pub environment_layout: BindGroupLayoutDescriptor, +} + +impl FromWorld for SkyboxPipeline { + #[instrument(skip_all)] + fn from_world(world: &mut World) -> Self { + let view_layout = world.resource::(); + let environment_layout = world.resource::(); + + Self { + view_layout: view_layout.descriptor.clone(), + environment_layout: environment_layout.descriptor.clone(), + } + } +} + +impl SpecializedRenderPipeline for SkyboxPipeline { + type Key = SkyboxPipelineKey; + + fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { + let format = if key.hdr { + ViewTarget::TEXTURE_FORMAT_HDR + } else { + TextureFormat::Rgba8UnormSrgb + }; + + let fragment_target = [Some(ColorTargetState { + format, + blend: Some(BlendState::REPLACE), + write_mask: ColorWrites::ALL, + })]; + + let depth_stencil = Some(DepthStencilState { + format: MAIN_DEPTH_FORMAT, + depth_write_enabled: false, + depth_compare: CompareFunction::GreaterEqual, + stencil: StencilState::default(), + bias: DepthBiasState::default(), + }); + + RenderPipelineDescriptor { + label: Some("Skybox Pipeline".into()), + layout: vec![self.view_layout.clone(), self.environment_layout.clone()], + push_constant_ranges: vec![], + vertex: VertexState { + shader: SKYBOX_VERT_SHADER_HANDLE, + shader_defs: vec![], + entry_point: Some("vs_main".into()), + buffers: vec![], + }, + fragment: Some(FragmentState { + shader: SKYBOX_FRAG_SHADER_HANDLE, + shader_defs: vec![], + entry_point: Some("fs_main".into()), + targets: fragment_target.to_vec(), + }), + primitive: PrimitiveState { + topology: PrimitiveTopology::TriangleList, + front_face: FrontFace::Ccw, + polygon_mode: PolygonMode::Fill, + cull_mode: None, + ..Default::default() + }, + depth_stencil, + multisample: MultisampleState { + count: key.msaa_samples, + mask: !0, + alpha_to_coverage_enabled: false, + }, + zero_initialize_workgroup_memory: true, + } + } +} From 5471c6ae3d617a39cbf0be4528b1de920cecae0d Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Thu, 9 Apr 2026 18:13:25 +0000 Subject: [PATCH 004/106] draw skybox after opaque for efficiency --- .../pipeline/main_passes/opaque_pass/render.rs | 17 +++++++++-------- .../main_passes/skybox_pass/pipeline.rs | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/render.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/render.rs index 62ac3571..703a5219 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/render.rs +++ b/crates/client/src/render/pipeline/main_passes/opaque_pass/render.rs @@ -93,14 +93,6 @@ impl ViewNode for OpaquePassRenderNode { occlusion_query_set: None, }); - // INFO: ------------------------- - // skybox pipeline - // ------------------------------- - render_pass.set_pipeline(skybox_pipeline.unwrap()); - render_pass.set_bind_group(0, &view_buffer.bind_group, &[]); - render_pass.set_bind_group(1, &skybox_params.bind_group, &[]); - render_pass.draw(0..6, 0..1); - // INFO: ----------------------------------------- // mesh pipeline: iterate and draw // ----------------------------------------------- @@ -123,6 +115,15 @@ impl ViewNode for OpaquePassRenderNode { } } + // INFO: ------------------------- + // skybox pipeline + // ------------------------------- + // runs after opaque, filling in empty pixels where depth = 0.0 still + render_pass.set_pipeline(skybox_pipeline.unwrap()); + render_pass.set_bind_group(0, &view_buffer.bind_group, &[]); + render_pass.set_bind_group(1, &skybox_params.bind_group, &[]); + render_pass.draw(0..6, 0..1); + Ok(()) } } diff --git a/crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs b/crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs index a25d6d75..ce2958c8 100644 --- a/crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs +++ b/crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs @@ -56,7 +56,7 @@ impl SpecializedRenderPipeline for SkyboxPipeline { let depth_stencil = Some(DepthStencilState { format: MAIN_DEPTH_FORMAT, depth_write_enabled: false, - depth_compare: CompareFunction::GreaterEqual, + depth_compare: CompareFunction::Equal, stencil: StencilState::default(), bias: DepthBiasState::default(), }); From 5cb1d2cf9a1734972905e5f2d61e5bf386ef8273 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Thu, 9 Apr 2026 20:58:55 +0000 Subject: [PATCH 005/106] remove deprecated mesh uploads --- crates/client/src/render/data/voxel_meshes.rs | 6 +++--- .../pipeline/main_passes/opaque_pass/extract.rs | 13 +++++-------- .../render/pipeline/main_passes/opaque_pass/mod.rs | 10 ---------- .../pipeline/main_passes/opaque_pass/pipeline.rs | 8 ++++---- .../pipeline/main_passes/opaque_pass/prepare.rs | 13 ------------- .../main_passes/transparent_pass/prepare.rs | 2 +- 6 files changed, 13 insertions(+), 39 deletions(-) delete mode 100644 crates/client/src/render/pipeline/main_passes/opaque_pass/prepare.rs diff --git a/crates/client/src/render/data/voxel_meshes.rs b/crates/client/src/render/data/voxel_meshes.rs index 618d25cb..a171e467 100644 --- a/crates/client/src/render/data/voxel_meshes.rs +++ b/crates/client/src/render/data/voxel_meshes.rs @@ -18,7 +18,7 @@ pub struct RenderMeshStorageResource { #[derive(Resource, Default)] pub struct MeshesToUploadQueue { - pub queue: Vec<(AssetId, VoxelMeshAsset, Vec3)>, + pub additions: Vec<(AssetId, VoxelMeshAsset, Vec3)>, pub removals: Vec>, } @@ -51,7 +51,7 @@ pub fn extract_modified_voxel_meshes( for (mesh, transform) in opaque_meshes.iter() { if let Some(asset) = assets.get(&mesh.mesh_handle) { upload_queue - .queue + .additions .push((mesh.mesh_handle.id(), asset.clone(), transform.position)); } } @@ -59,7 +59,7 @@ pub fn extract_modified_voxel_meshes( for (mesh, transform) in transparent_meshes.iter() { if let Some(asset) = assets.get(&mesh.mesh_handle) { upload_queue - .queue + .additions .push((mesh.mesh_handle.id(), asset.clone(), transform.position)); } } diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/extract.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/extract.rs index cbc69bdd..a1463e4b 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/extract.rs +++ b/crates/client/src/render/pipeline/main_passes/opaque_pass/extract.rs @@ -1,15 +1,12 @@ use crate::render::chunk::OpaqueMeshComponent; use crate::render::chunk::VoxelMeshAsset; use crate::render::types::RenderTransformComponent; -use bevy::asset::Handle; -use bevy::ecs::prelude::*; -use bevy::render::Extract; -use bevy::render::sync_world::RenderEntity; +use bevy::{asset::Handle, ecs::prelude::*, render::sync_world::RenderEntity, render::Extract}; use shared::simulation::chunk::TransformComponent; -// INFO: -------------------------------- -// RenderWorld components -// -------------------------------------- +// INFO: ------------------------------- +// render app components +// ------------------------------------- /// A component in the render world holding the extracted mesh handle. #[derive(Component, Clone)] @@ -18,7 +15,7 @@ pub struct OpaqueRenderMeshComponent { } // INFO: ----------------------------------- -// SimWorld extraction logic +// main app extraction logic // ----------------------------------------- /// A system that extracts opaque meshes from the simulation world into the render world. diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs index e18c2da4..219c3fca 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs +++ b/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs @@ -1,6 +1,5 @@ pub mod extract; pub mod pipeline; -pub mod prepare; pub mod queue; pub mod render; @@ -23,15 +22,6 @@ pub struct OpaqueRenderPassPlugin; impl Plugin for OpaqueRenderPassPlugin { fn build(&self, app: &mut App) { - // INFO: ----------------- - // prepare - // ----------------------- - - app.add_systems( - Render, - prepare::prepare_opaque_meshes_system.in_set(RenderSystems::Prepare), - ); - // INFO: --------------- // queue // --------------------- diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs index b7b380f6..e6c41162 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs +++ b/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs @@ -1,9 +1,10 @@ use crate::input::systems::toggle_opaque_wireframe::OpaqueWireframeMode; +use crate::prelude::*; use crate::render::pipeline::{ gpu_resources::world_uniforms::ChunkStorageBindGroupLayout, main_passes::shared_resources::{ - CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, MAIN_DEPTH_FORMAT, - TextureArrayBindGroupLayout, + CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, TextureArrayBindGroupLayout, + MAIN_DEPTH_FORMAT, }, shader_registry::{OPAQUE_FRAG_SHADER_HANDLE, OPAQUE_VERT_SHADER_HANDLE}, }; @@ -11,9 +12,8 @@ use bevy::{ ecs::prelude::*, render::{extract_resource::ExtractResource, render_resource::*, view::ViewTarget}, }; -use tracing::instrument; -/// A resource that defines the current opaque render mode +/// A resource that defines the current opaque rendering polygon mode #[derive(Resource, Default, Debug, PartialEq, Eq, Hash, Clone, Copy)] pub enum OpaqueRenderMode { #[default] diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/prepare.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/prepare.rs deleted file mode 100644 index 8c72262b..00000000 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/prepare.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::prelude::*; - -/// A system that no longer needs to do anything because mesh uploads are -/// handled once per frame by the shared `MeshesToUploadQueue` in the -/// transparent pass (or any pass that runs first). -/// -/// Since the SSBO and `RenderMeshStorageResource` are shared, processing the -/// queue once is sufficient. -#[instrument(skip_all)] -pub fn prepare_opaque_meshes_system() {} - -/// Removed in favor of handling removals in the main prepare system. -pub fn delete_gpu_buffers_system() {} diff --git a/crates/client/src/render/pipeline/main_passes/transparent_pass/prepare.rs b/crates/client/src/render/pipeline/main_passes/transparent_pass/prepare.rs index bdb5f8a9..7966c819 100644 --- a/crates/client/src/render/pipeline/main_passes/transparent_pass/prepare.rs +++ b/crates/client/src/render/pipeline/main_passes/transparent_pass/prepare.rs @@ -29,7 +29,7 @@ pub fn prepare_transparent_meshes_system( } // handle uploads (Added/Modified) - for (id, mesh, world_pos) in meshes_to_upload.queue.drain(..) { + for (id, mesh, world_pos) in meshes_to_upload.additions.drain(..) { // if it already exists, free the old allocation first if let Some(old_mesh_handle) = gpu_mesh_storage.meshes.remove(&id) { chunk_memory_manager.free_chunk(*old_mesh_handle); From 1bc287d00da42cf19ab283f2df9a1a1f52978b5a Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Thu, 9 Apr 2026 21:43:55 +0000 Subject: [PATCH 006/106] add extract resource to wireframe mode --- crates/client/src/input/mod.rs | 17 +++++------ .../extra_binds/toggle_opaque_wireframe.rs | 29 ++++++++++++++----- crates/client/src/render/mod.rs | 9 +++--- .../main_passes/opaque_pass/pipeline.rs | 24 ++------------- .../pipeline/main_passes/opaque_pass/queue.rs | 3 +- .../src/simulation/block/targeted_block.rs | 2 +- 6 files changed, 39 insertions(+), 45 deletions(-) diff --git a/crates/client/src/input/mod.rs b/crates/client/src/input/mod.rs index bb7b0a44..b8485121 100644 --- a/crates/client/src/input/mod.rs +++ b/crates/client/src/input/mod.rs @@ -4,15 +4,17 @@ pub mod systems; // input module plugin // ----------------------------------- +use crate::input::systems::toggle_opaque_wireframe::OpaqueRenderMode; use crate::input::systems::{ toggle_chunk_borders::ChunkBoundsToggle, toggle_chunk_borders_system, toggle_cursor_system, - toggle_opaque_wireframe::OpaqueWireframeMode, toggle_opaque_wireframe_mode_system, + toggle_opaque_wireframe_mode_system, }; use bevy::app::{App, Plugin, PreUpdate, Update}; use bevy::ecs::{schedule::IntoScheduleConfigs, system::Res}; use shared::simulation::input::resources::{ ActionStateResource, CursorMovement, InputActionMapResource, }; +use shared::simulation::input::types::SimulationAction; use systems::processing; pub struct InputModulePlugin; @@ -42,20 +44,17 @@ impl Plugin for InputModulePlugin { app.add_systems( Update, toggle_cursor_system.run_if(|action_state: Res| { - action_state - .just_happened(shared::simulation::input::types::SimulationAction::TogglePause) + action_state.just_happened(SimulationAction::TogglePause) }), ); // toggle opaque wireframe mode - app.insert_resource(OpaqueWireframeMode::default()) + app.insert_resource(OpaqueRenderMode::default()) .add_systems( Update, toggle_opaque_wireframe_mode_system.run_if( |action_state: Res| { - action_state.just_happened( - shared::simulation::input::types::SimulationAction::ToggleOpaqueWireframeMode, - ) + action_state.just_happened(SimulationAction::ToggleOpaqueWireframeMode) }, ), ); @@ -65,9 +64,7 @@ impl Plugin for InputModulePlugin { .add_systems( Update, toggle_chunk_borders_system.run_if(|action_state: Res| { - action_state.just_happened( - shared::simulation::input::types::SimulationAction::ToggleChunkBorders, - ) + action_state.just_happened(SimulationAction::ToggleChunkBorders) }), ); } diff --git a/crates/client/src/input/systems/extra_binds/toggle_opaque_wireframe.rs b/crates/client/src/input/systems/extra_binds/toggle_opaque_wireframe.rs index bccc6469..26c9d7e5 100644 --- a/crates/client/src/input/systems/extra_binds/toggle_opaque_wireframe.rs +++ b/crates/client/src/input/systems/extra_binds/toggle_opaque_wireframe.rs @@ -1,13 +1,28 @@ use crate::prelude::*; -use bevy::ecs::{resource::Resource, system::ResMut}; +use bevy::{ + ecs::{resource::Resource, system::ResMut}, + render::extract_resource::ExtractResource, +}; -#[derive(Resource, Default)] -pub struct OpaqueWireframeMode { - pub enabled: bool, +/// A resource that defines the current opaque rendering polygon mode +#[derive(Resource, ExtractResource, Default, Debug, PartialEq, Eq, Hash, Clone, Copy)] +pub enum OpaqueRenderMode { + #[default] + Fill, + Wireframe, +} + +impl OpaqueRenderMode { + pub fn next(self) -> Self { + match self { + Self::Fill => Self::Wireframe, + Self::Wireframe => Self::Fill, + } + } } /// Toggle opaque wireframe mode on or off. -pub fn toggle_opaque_wireframe_mode_system(mut mode: ResMut) { - info!("Toggling opaque wireframe mode: {}", !mode.enabled); - mode.enabled = !mode.enabled; +pub fn toggle_opaque_wireframe_mode_system(mut mode: ResMut) { + *mode = mode.next(); + info!("Toggling opaque wireframe mode: {:?}", *mode); } diff --git a/crates/client/src/render/mod.rs b/crates/client/src/render/mod.rs index fb481b66..041d44e3 100644 --- a/crates/client/src/render/mod.rs +++ b/crates/client/src/render/mod.rs @@ -12,16 +12,17 @@ pub use data::*; // render world interface // -------------------------------------- +use crate::input::systems::toggle_opaque_wireframe::OpaqueRenderMode; use crate::prelude::*; use crate::render::{ chunk::{OpaqueMeshComponent, TransparentMeshComponent}, pipeline::{ - RenderGraphEdgesPlugin, WorldRenderPassesPlugin, main_passes::{ bounding_box_pass::extract::WireframeToggleState, - opaque_pass::{extract::extract_opaque_meshes, pipeline::OpaqueRenderMode}, + opaque_pass::extract::extract_opaque_meshes, transparent_pass::extract::extract_transparent_meshes, }, + RenderGraphEdgesPlugin, WorldRenderPassesPlugin, }, texture::BlockTextureArray, }; @@ -29,8 +30,8 @@ use bevy::{ app::{App, Plugin, SubApp}, prelude::{Add, Commands, On}, render::{ - ExtractSchedule, RenderApp, extract_resource::ExtractResourcePlugin, - sync_world::SyncToRenderWorld, + extract_resource::ExtractResourcePlugin, sync_world::SyncToRenderWorld, ExtractSchedule, + RenderApp, }, }; use shared::simulation::block::TargetedBlock; diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs index e6c41162..f50e830a 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs +++ b/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs @@ -1,4 +1,4 @@ -use crate::input::systems::toggle_opaque_wireframe::OpaqueWireframeMode; +use crate::input::systems::toggle_opaque_wireframe::OpaqueRenderMode; use crate::prelude::*; use crate::render::pipeline::{ gpu_resources::world_uniforms::ChunkStorageBindGroupLayout, @@ -10,29 +10,9 @@ use crate::render::pipeline::{ }; use bevy::{ ecs::prelude::*, - render::{extract_resource::ExtractResource, render_resource::*, view::ViewTarget}, + render::{render_resource::*, view::ViewTarget}, }; -/// A resource that defines the current opaque rendering polygon mode -#[derive(Resource, Default, Debug, PartialEq, Eq, Hash, Clone, Copy)] -pub enum OpaqueRenderMode { - #[default] - Fill, - Wireframe, -} - -impl ExtractResource for OpaqueRenderMode { - type Source = OpaqueWireframeMode; - - fn extract_resource(source: &Self::Source) -> Self { - if source.enabled { - OpaqueRenderMode::Wireframe - } else { - OpaqueRenderMode::Fill - } - } -} - /// A key that uniquely identifies a specialized world opaque pipeline. #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct WorldOpaquePipelineKey { diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs b/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs index c9f11c7f..629417cd 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs +++ b/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs @@ -1,7 +1,8 @@ +use crate::input::systems::toggle_opaque_wireframe::OpaqueRenderMode; use crate::prelude::*; use crate::render::{ pipeline::main_passes::opaque_pass::extract::OpaqueRenderMeshComponent, - pipeline::main_passes::opaque_pass::pipeline::{OpaqueRenderMode, WorldOpaquePipeline, WorldOpaquePipelineKey}, + pipeline::main_passes::opaque_pass::pipeline::{WorldOpaquePipeline, WorldOpaquePipelineKey}, pipeline::main_passes::skybox_pass::{SkyboxPipeline, SkyboxPipelineKey}, types::RenderTransformComponent, }; diff --git a/crates/shared/src/simulation/block/targeted_block.rs b/crates/shared/src/simulation/block/targeted_block.rs index c68dae09..5449f56c 100644 --- a/crates/shared/src/simulation/block/targeted_block.rs +++ b/crates/shared/src/simulation/block/targeted_block.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use bevy::ecs::prelude::*; use bevy::render::extract_resource::ExtractResource; -#[derive(Resource, Clone, Default, ExtractResource)] +#[derive(Resource, ExtractResource, Clone, Default)] pub struct TargetedBlock { pub position: Option, pub normal: Option, From 56bc784135ceb842dd3ae13df6f21079fa7717ed Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Thu, 9 Apr 2026 23:01:04 +0000 Subject: [PATCH 007/106] large refactor of render folder --- .../client/src/render/data/camera_phases.rs | 6 +- crates/client/src/render/data/voxel_meshes.rs | 11 +- crates/client/src/render/mod.rs | 21 ++- .../bounding_box}/extract.rs | 0 .../bounding_box}/gpu_resources/mod.rs | 0 .../gpu_resources/object_binding.rs | 0 .../gpu_resources/unit_cube_mesh.rs | 0 .../gpu_resources/wireframe_pipeline.rs | 13 +- .../bounding_box}/mod.rs | 4 +- .../bounding_box}/queue.rs | 2 +- .../bounding_box}/render.rs | 6 +- crates/client/src/render/passes/mod.rs | 130 ++++++++++++++++++ .../opaque_pass => passes/opaque}/extract.rs | 2 +- .../opaque_pass => passes/opaque}/mod.rs | 2 +- .../opaque_pass => passes/opaque}/pipeline.rs | 20 +-- .../opaque_pass => passes/opaque}/queue.rs | 27 ++-- .../opaque_pass => passes/opaque}/render.rs | 12 +- .../shadow}/gpu_resources/mod.rs | 0 .../shadow}/gpu_resources/shadow_pipeline.rs | 10 +- .../shadow}/gpu_resources/shadow_texture.rs | 0 .../gpu_resources/shadow_view_uniform.rs | 0 .../shadow_pass => passes/shadow}/mod.rs | 4 +- .../shadow_pass => passes/shadow}/prepare.rs | 6 +- .../shadow_pass => passes/shadow}/render.rs | 10 +- .../skybox_pass => passes/skybox}/mod.rs | 2 +- .../skybox_pass => passes/skybox}/pipeline.rs | 11 +- .../transparent}/extract.rs | 0 .../transparent}/mod.rs | 10 +- .../transparent}/prepare.rs | 4 +- .../transparent}/queue.rs | 6 +- .../transparent}/render.rs | 30 ++-- .../transparent}/startup.rs | 18 +-- .../src/render/pipeline/gpu_resources/mod.rs | 5 - .../src/render/pipeline/main_passes/mod.rs | 73 ---------- crates/client/src/render/pipeline/mod.rs | 72 ---------- .../environment_uniform.rs | 0 .../shared_resources => resources}/mod.rs | 5 +- .../tex_array_uniforms.rs | 0 .../view_uniforms.rs | 16 ++- .../world_uniforms.rs | 0 .../shader_registry.rs => shaders.rs} | 0 crates/client/src/render/types/mod.rs | 15 +- .../src/render/types/render_transform.rs | 9 ++ 43 files changed, 267 insertions(+), 295 deletions(-) rename crates/client/src/render/{pipeline/main_passes/bounding_box_pass => passes/bounding_box}/extract.rs (100%) rename crates/client/src/render/{pipeline/main_passes/bounding_box_pass => passes/bounding_box}/gpu_resources/mod.rs (100%) rename crates/client/src/render/{pipeline/main_passes/bounding_box_pass => passes/bounding_box}/gpu_resources/object_binding.rs (100%) rename crates/client/src/render/{pipeline/main_passes/bounding_box_pass => passes/bounding_box}/gpu_resources/unit_cube_mesh.rs (100%) rename crates/client/src/render/{pipeline/main_passes/bounding_box_pass => passes/bounding_box}/gpu_resources/wireframe_pipeline.rs (88%) rename crates/client/src/render/{pipeline/main_passes/bounding_box_pass => passes/bounding_box}/mod.rs (93%) rename crates/client/src/render/{pipeline/main_passes/bounding_box_pass => passes/bounding_box}/queue.rs (98%) rename crates/client/src/render/{pipeline/main_passes/bounding_box_pass => passes/bounding_box}/render.rs (95%) create mode 100644 crates/client/src/render/passes/mod.rs rename crates/client/src/render/{pipeline/main_passes/opaque_pass => passes/opaque}/extract.rs (92%) rename crates/client/src/render/{pipeline/main_passes/opaque_pass => passes/opaque}/mod.rs (95%) rename crates/client/src/render/{pipeline/main_passes/opaque_pass => passes/opaque}/pipeline.rs (89%) rename crates/client/src/render/{pipeline/main_passes/opaque_pass => passes/opaque}/queue.rs (83%) rename crates/client/src/render/{pipeline/main_passes/opaque_pass => passes/opaque}/render.rs (91%) rename crates/client/src/render/{pipeline/shadow_pass => passes/shadow}/gpu_resources/mod.rs (100%) rename crates/client/src/render/{pipeline/shadow_pass => passes/shadow}/gpu_resources/shadow_pipeline.rs (85%) rename crates/client/src/render/{pipeline/shadow_pass => passes/shadow}/gpu_resources/shadow_texture.rs (100%) rename crates/client/src/render/{pipeline/shadow_pass => passes/shadow}/gpu_resources/shadow_view_uniform.rs (100%) rename crates/client/src/render/{pipeline/shadow_pass => passes/shadow}/mod.rs (90%) rename crates/client/src/render/{pipeline/shadow_pass => passes/shadow}/prepare.rs (95%) rename crates/client/src/render/{pipeline/shadow_pass => passes/shadow}/render.rs (91%) rename crates/client/src/render/{pipeline/main_passes/skybox_pass => passes/skybox}/mod.rs (87%) rename crates/client/src/render/{pipeline/main_passes/skybox_pass => passes/skybox}/pipeline.rs (91%) rename crates/client/src/render/{pipeline/main_passes/transparent_pass => passes/transparent}/extract.rs (100%) rename crates/client/src/render/{pipeline/main_passes/transparent_pass => passes/transparent}/mod.rs (89%) rename crates/client/src/render/{pipeline/main_passes/transparent_pass => passes/transparent}/prepare.rs (93%) rename crates/client/src/render/{pipeline/main_passes/transparent_pass => passes/transparent}/queue.rs (92%) rename crates/client/src/render/{pipeline/main_passes/transparent_pass => passes/transparent}/render.rs (81%) rename crates/client/src/render/{pipeline/main_passes/transparent_pass => passes/transparent}/startup.rs (89%) delete mode 100644 crates/client/src/render/pipeline/gpu_resources/mod.rs delete mode 100644 crates/client/src/render/pipeline/main_passes/mod.rs delete mode 100644 crates/client/src/render/pipeline/mod.rs rename crates/client/src/render/{pipeline/main_passes/shared_resources => resources}/environment_uniform.rs (100%) rename crates/client/src/render/{pipeline/main_passes/shared_resources => resources}/mod.rs (78%) rename crates/client/src/render/{pipeline/main_passes/shared_resources => resources}/tex_array_uniforms.rs (100%) rename crates/client/src/render/{pipeline/main_passes/shared_resources => resources}/view_uniforms.rs (94%) rename crates/client/src/render/{pipeline/gpu_resources => resources}/world_uniforms.rs (100%) rename crates/client/src/render/{pipeline/shader_registry.rs => shaders.rs} (100%) create mode 100644 crates/client/src/render/types/render_transform.rs diff --git a/crates/client/src/render/data/camera_phases.rs b/crates/client/src/render/data/camera_phases.rs index 5d0d72ad..49447014 100644 --- a/crates/client/src/render/data/camera_phases.rs +++ b/crates/client/src/render/data/camera_phases.rs @@ -1,6 +1,6 @@ -use crate::render::pipeline::main_passes::{ - bounding_box_pass::queue::BoundingBoxPhase, opaque_pass::queue::Opaque3dRenderPhase, - transparent_pass::queue::Transparent3dRenderPhase, +use crate::render::passes::{ + bounding_box::queue::BoundingBoxPhase, opaque::queue::Opaque3dRenderPhase, + transparent::queue::Transparent3dRenderPhase, }; use bevy::prelude::*; use bevy::render::Extract; diff --git a/crates/client/src/render/data/voxel_meshes.rs b/crates/client/src/render/data/voxel_meshes.rs index a171e467..d5d4deda 100644 --- a/crates/client/src/render/data/voxel_meshes.rs +++ b/crates/client/src/render/data/voxel_meshes.rs @@ -1,5 +1,8 @@ -use crate::render::chunk::{OpaqueMeshComponent, TransparentMeshComponent, VoxelMeshAsset}; -use crate::{prelude::*, render::types::VoxelMesh}; +use crate::{ + prelude::*, + render::chunk::{OpaqueMeshComponent, TransparentMeshComponent, VoxelMeshAsset}, + render::resources::world_uniforms::VoxelMesh, +}; use bevy::{ asset::{AssetEvent, AssetId, Assets}, ecs::{ @@ -47,7 +50,7 @@ pub fn extract_modified_voxel_meshes( // output mut upload_queue: ResMut, ) { - // 1. Process mesh additions and modifications via component change detection + // process mesh additions and modifications via component change detection for (mesh, transform) in opaque_meshes.iter() { if let Some(asset) = assets.get(&mesh.mesh_handle) { upload_queue @@ -64,7 +67,7 @@ pub fn extract_modified_voxel_meshes( } } - // 2. Process events strictly for asset removals + // process events for asset removals for event in events.read() { if let AssetEvent::Removed { id } = event { upload_queue.removals.push(*id); diff --git a/crates/client/src/render/mod.rs b/crates/client/src/render/mod.rs index 041d44e3..fe2aa646 100644 --- a/crates/client/src/render/mod.rs +++ b/crates/client/src/render/mod.rs @@ -1,8 +1,10 @@ pub mod block; pub mod chunk; pub mod data; -pub mod pipeline; +pub mod passes; +pub mod resources; pub mod scheduling; +pub mod shaders; pub mod texture; pub mod types; @@ -16,13 +18,10 @@ use crate::input::systems::toggle_opaque_wireframe::OpaqueRenderMode; use crate::prelude::*; use crate::render::{ chunk::{OpaqueMeshComponent, TransparentMeshComponent}, - pipeline::{ - main_passes::{ - bounding_box_pass::extract::WireframeToggleState, - opaque_pass::extract::extract_opaque_meshes, - transparent_pass::extract::extract_transparent_meshes, - }, + passes::{ RenderGraphEdgesPlugin, WorldRenderPassesPlugin, + bounding_box::extract::WireframeToggleState, opaque::extract::extract_opaque_meshes, + transparent::extract::extract_transparent_meshes, }, texture::BlockTextureArray, }; @@ -30,18 +29,18 @@ use bevy::{ app::{App, Plugin, SubApp}, prelude::{Add, Commands, On}, render::{ - extract_resource::ExtractResourcePlugin, sync_world::SyncToRenderWorld, ExtractSchedule, - RenderApp, + ExtractSchedule, RenderApp, extract_resource::ExtractResourcePlugin, + sync_world::SyncToRenderWorld, }, }; use shared::simulation::block::TargetedBlock; -/// Plugin responsible for attaching our custom render logic to Bevy's native RenderApp +/// Plugin responsible for attaching custom render logic to Bevy's native RenderApp pub struct VantablockRenderPlugin; impl Plugin for VantablockRenderPlugin { fn build(&self, app: &mut App) { - app.add_plugins(pipeline::shader_registry::VantablockShaderPlugin); + app.add_plugins(shaders::VantablockShaderPlugin); app.add_plugins(block::BlockRenderPlugin); app.add_plugins(chunk::ChunkMeshingPlugin); diff --git a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/extract.rs b/crates/client/src/render/passes/bounding_box/extract.rs similarity index 100% rename from crates/client/src/render/pipeline/main_passes/bounding_box_pass/extract.rs rename to crates/client/src/render/passes/bounding_box/extract.rs diff --git a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/gpu_resources/mod.rs b/crates/client/src/render/passes/bounding_box/gpu_resources/mod.rs similarity index 100% rename from crates/client/src/render/pipeline/main_passes/bounding_box_pass/gpu_resources/mod.rs rename to crates/client/src/render/passes/bounding_box/gpu_resources/mod.rs diff --git a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/gpu_resources/object_binding.rs b/crates/client/src/render/passes/bounding_box/gpu_resources/object_binding.rs similarity index 100% rename from crates/client/src/render/pipeline/main_passes/bounding_box_pass/gpu_resources/object_binding.rs rename to crates/client/src/render/passes/bounding_box/gpu_resources/object_binding.rs diff --git a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/gpu_resources/unit_cube_mesh.rs b/crates/client/src/render/passes/bounding_box/gpu_resources/unit_cube_mesh.rs similarity index 100% rename from crates/client/src/render/pipeline/main_passes/bounding_box_pass/gpu_resources/unit_cube_mesh.rs rename to crates/client/src/render/passes/bounding_box/gpu_resources/unit_cube_mesh.rs diff --git a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/gpu_resources/wireframe_pipeline.rs b/crates/client/src/render/passes/bounding_box/gpu_resources/wireframe_pipeline.rs similarity index 88% rename from crates/client/src/render/pipeline/main_passes/bounding_box_pass/gpu_resources/wireframe_pipeline.rs rename to crates/client/src/render/passes/bounding_box/gpu_resources/wireframe_pipeline.rs index 4e78beda..ce7cb671 100644 --- a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/gpu_resources/wireframe_pipeline.rs +++ b/crates/client/src/render/passes/bounding_box/gpu_resources/wireframe_pipeline.rs @@ -1,11 +1,8 @@ -use crate::render::pipeline::main_passes::bounding_box_pass::WireframeObjectBindGroupLayout; -use crate::render::pipeline::main_passes::shared_resources::{ - CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, MAIN_DEPTH_FORMAT, -}; -use crate::render::pipeline::shader_registry::{ - WIREFRAME_FRAG_SHADER_HANDLE, WIREFRAME_VERT_SHADER_HANDLE, -}; +use crate::render::passes::bounding_box::WireframeObjectBindGroupLayout; +use crate::render::resources::{CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout}; +use crate::render::shaders::{WIREFRAME_FRAG_SHADER_HANDLE, WIREFRAME_VERT_SHADER_HANDLE}; use crate::render::types::WireframeVertex; +use bevy::core_pipeline::core_3d; use bevy::ecs::prelude::*; use bevy::render::render_resource::*; use bevy::render::view::ViewTarget; @@ -73,7 +70,7 @@ impl SpecializedRenderPipeline for WireframePipeline { })], }), depth_stencil: Some(DepthStencilState { - format: MAIN_DEPTH_FORMAT, + format: core_3d::CORE_3D_DEPTH_FORMAT, depth_write_enabled: false, depth_compare: CompareFunction::GreaterEqual, stencil: StencilState::default(), diff --git a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/mod.rs b/crates/client/src/render/passes/bounding_box/mod.rs similarity index 93% rename from crates/client/src/render/pipeline/main_passes/bounding_box_pass/mod.rs rename to crates/client/src/render/passes/bounding_box/mod.rs index 1c02ce27..a9ae28d0 100644 --- a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/mod.rs +++ b/crates/client/src/render/passes/bounding_box/mod.rs @@ -9,9 +9,7 @@ pub use render::BoundingBoxNode; // plugin definition // --------------------------------- -use crate::{ - VantablockNode, render::pipeline::main_passes::bounding_box_pass::queue::queue_wireframe_system, -}; +use crate::{VantablockNode, render::passes::bounding_box::queue::queue_wireframe_system}; use bevy::core_pipeline::core_3d; use bevy::prelude::{App, IntoScheduleConfigs, Plugin}; use bevy::render::{ diff --git a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/queue.rs b/crates/client/src/render/passes/bounding_box/queue.rs similarity index 98% rename from crates/client/src/render/pipeline/main_passes/bounding_box_pass/queue.rs rename to crates/client/src/render/passes/bounding_box/queue.rs index 575a2257..24a44ed4 100644 --- a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/queue.rs +++ b/crates/client/src/render/passes/bounding_box/queue.rs @@ -1,7 +1,7 @@ use crate::{ prelude::*, render::{ - pipeline::main_passes::bounding_box_pass::{ + passes::bounding_box::{ extract::WireframeToggleState, gpu_resources::{ WireframeObjectBuffer, WireframeObjectData, diff --git a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/render.rs b/crates/client/src/render/passes/bounding_box/render.rs similarity index 95% rename from crates/client/src/render/pipeline/main_passes/bounding_box_pass/render.rs rename to crates/client/src/render/passes/bounding_box/render.rs index c365042d..d4b9a0aa 100644 --- a/crates/client/src/render/pipeline/main_passes/bounding_box_pass/render.rs +++ b/crates/client/src/render/passes/bounding_box/render.rs @@ -1,8 +1,8 @@ use super::gpu_resources::{UnitCubeMesh, WireframeObjectBuffer}; use crate::prelude::*; -use crate::render::pipeline::main_passes::{ - bounding_box_pass::queue::BoundingBoxPhase, - shared_resources::{CentralCameraViewUniform, EnvironmentUniforms}, +use crate::render::{ + passes::bounding_box::queue::BoundingBoxPhase, + resources::{CentralCameraViewUniform, EnvironmentUniforms}, }; use bevy::ecs::prelude::*; use bevy::ecs::query::QueryItem; diff --git a/crates/client/src/render/passes/mod.rs b/crates/client/src/render/passes/mod.rs new file mode 100644 index 00000000..b32d9f39 --- /dev/null +++ b/crates/client/src/render/passes/mod.rs @@ -0,0 +1,130 @@ +pub mod bounding_box; +pub mod opaque; +pub mod shadow; +pub mod skybox; +pub mod transparent; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +use crate::{ + VantablockNode, + render::{ + passes::{ + bounding_box::WireframeRenderPassPlugin, opaque::OpaqueRenderPassPlugin, + shadow::ShadowRenderPassPlugin, skybox::SkyboxRenderPassPlugin, + transparent::TransparentRenderPassPlugin, + }, + resources::{ + CentralCameraViewBindGroupLayout, CentralCameraViewUniform, EnvironmentBindGroupLayout, + EnvironmentUniforms, TextureArrayBindGroupLayout, prepare_texture_array_system, + update_camera_view_buffer_system, update_environment_uniform_buffer_system, + world_uniforms::{ChunkStorageBindGroupLayout, ChunkStorageManager}, + }, + }, +}; +use bevy::prelude::IntoScheduleConfigs; +use bevy::{ + app::{App, Plugin}, + render::{Render, RenderSystems, render_graph::RenderGraphExt}, +}; + +/// A plugin that sets up all the necessary resources and render +/// passes used in the rendering pipeline. +pub struct WorldRenderPassesPlugin; + +impl Plugin for WorldRenderPassesPlugin { + fn build(&self, app: &mut App) { + // renderpass plugins + app.add_plugins((ShadowRenderPassPlugin, PlayerCentricRenderPassPlugin)); + } + + fn finish(&self, app: &mut App) { + // shared world uniform resources + app.init_resource::(); + app.init_resource::(); + } +} + +/// A plugin responsible ONLY for wiring the edges between nodes in the render graph. +/// This must be added AFTER all pass plugins to ensure all nodes exist. +pub struct RenderGraphEdgesPlugin; + +impl Plugin for RenderGraphEdgesPlugin { + fn build(&self, app: &mut App) { + app.add_render_graph_edges( + bevy::core_pipeline::core_3d::graph::Core3d, + ( + bevy::core_pipeline::core_3d::graph::Node3d::StartMainPass, + VantablockNode::ShadowPass, + bevy::core_pipeline::core_3d::graph::Node3d::MainOpaquePass, + ), + ); + + app.add_render_graph_edges( + bevy::core_pipeline::core_3d::graph::Core3d, + ( + bevy::core_pipeline::core_3d::graph::Node3d::MainOpaquePass, + VantablockNode::OpaquePass, + VantablockNode::TransparentPass, + bevy::core_pipeline::core_3d::graph::Node3d::MainTransparentPass, + ), + ); + + app.add_render_graph_edges( + bevy::core_pipeline::core_3d::graph::Core3d, + ( + bevy::core_pipeline::core_3d::graph::Node3d::MainTransparentPass, + VantablockNode::BoundingBoxPass, + bevy::core_pipeline::core_3d::graph::Node3d::EndMainPass, + ), + ); + } +} + +/// A plugin that sets up all the necessary resources and render +/// passes used in the rendering pipeline. +pub struct PlayerCentricRenderPassPlugin; + +impl Plugin for PlayerCentricRenderPassPlugin { + fn build(&self, app: &mut App) { + // INFO: ----------------------------------------- + // prepare (also shared resources) + // ----------------------------------------------- + + app.add_systems( + Render, + ( + update_camera_view_buffer_system, + update_environment_uniform_buffer_system, + prepare_texture_array_system, + ) + .in_set(RenderSystems::Prepare), + ); + + // INFO: -------------------------------------- + // subplugins for render passes + // -------------------------------------------- + + app.add_plugins(( + TransparentRenderPassPlugin, + OpaqueRenderPassPlugin, + SkyboxRenderPassPlugin, + WireframeRenderPassPlugin, + )); + } + + fn finish(&self, app: &mut App) { + // INFO: ---------------------------------------------------- + // startup (shared resources for main passes) + // ---------------------------------------------------------- + + app.init_resource::(); + app.init_resource::(); + app.init_resource::(); + app.init_resource::(); + + app.init_resource::(); + } +} diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/extract.rs b/crates/client/src/render/passes/opaque/extract.rs similarity index 92% rename from crates/client/src/render/pipeline/main_passes/opaque_pass/extract.rs rename to crates/client/src/render/passes/opaque/extract.rs index a1463e4b..06b02dbf 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/extract.rs +++ b/crates/client/src/render/passes/opaque/extract.rs @@ -1,7 +1,7 @@ use crate::render::chunk::OpaqueMeshComponent; use crate::render::chunk::VoxelMeshAsset; use crate::render::types::RenderTransformComponent; -use bevy::{asset::Handle, ecs::prelude::*, render::sync_world::RenderEntity, render::Extract}; +use bevy::{asset::Handle, ecs::prelude::*, render::Extract, render::sync_world::RenderEntity}; use shared::simulation::chunk::TransformComponent; // INFO: ------------------------------- diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs b/crates/client/src/render/passes/opaque/mod.rs similarity index 95% rename from crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs rename to crates/client/src/render/passes/opaque/mod.rs index 219c3fca..edad39ea 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/mod.rs +++ b/crates/client/src/render/passes/opaque/mod.rs @@ -3,7 +3,6 @@ pub mod pipeline; pub mod queue; pub mod render; -pub use pipeline::*; pub use render::OpaquePassRenderNode; // INFO: --------------------------- @@ -11,6 +10,7 @@ pub use render::OpaquePassRenderNode; // --------------------------------- use crate::VantablockNode; +use crate::render::passes::opaque::pipeline::WorldOpaquePipeline; use bevy::prelude::{App, IntoScheduleConfigs, Plugin}; use bevy::render::{ render_graph::{RenderGraphExt, ViewNodeRunner}, diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs b/crates/client/src/render/passes/opaque/pipeline.rs similarity index 89% rename from crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs rename to crates/client/src/render/passes/opaque/pipeline.rs index f50e830a..6314c6bd 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/pipeline.rs +++ b/crates/client/src/render/passes/opaque/pipeline.rs @@ -1,14 +1,16 @@ -use crate::input::systems::toggle_opaque_wireframe::OpaqueRenderMode; -use crate::prelude::*; -use crate::render::pipeline::{ - gpu_resources::world_uniforms::ChunkStorageBindGroupLayout, - main_passes::shared_resources::{ - CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, TextureArrayBindGroupLayout, - MAIN_DEPTH_FORMAT, +use crate::{ + input::systems::toggle_opaque_wireframe::OpaqueRenderMode, + prelude::*, + render::{ + resources::{ + CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, + TextureArrayBindGroupLayout, world_uniforms::ChunkStorageBindGroupLayout, + }, + shaders::{OPAQUE_FRAG_SHADER_HANDLE, OPAQUE_VERT_SHADER_HANDLE}, }, - shader_registry::{OPAQUE_FRAG_SHADER_HANDLE, OPAQUE_VERT_SHADER_HANDLE}, }; use bevy::{ + core_pipeline::core_3d::{self}, ecs::prelude::*, render::{render_resource::*, view::ViewTarget}, }; @@ -64,7 +66,7 @@ impl SpecializedRenderPipeline for WorldOpaquePipeline { })]; let depth_stencil = Some(DepthStencilState { - format: MAIN_DEPTH_FORMAT, + format: core_3d::CORE_3D_DEPTH_FORMAT, depth_write_enabled: true, depth_compare: CompareFunction::GreaterEqual, stencil: StencilState::default(), diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs b/crates/client/src/render/passes/opaque/queue.rs similarity index 83% rename from crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs rename to crates/client/src/render/passes/opaque/queue.rs index 629417cd..13436ce7 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/queue.rs +++ b/crates/client/src/render/passes/opaque/queue.rs @@ -1,16 +1,18 @@ -use crate::input::systems::toggle_opaque_wireframe::OpaqueRenderMode; -use crate::prelude::*; -use crate::render::{ - pipeline::main_passes::opaque_pass::extract::OpaqueRenderMeshComponent, - pipeline::main_passes::opaque_pass::pipeline::{WorldOpaquePipeline, WorldOpaquePipelineKey}, - pipeline::main_passes::skybox_pass::{SkyboxPipeline, SkyboxPipelineKey}, - types::RenderTransformComponent, +use crate::{ + input::systems::toggle_opaque_wireframe::OpaqueRenderMode, + prelude::*, + render::{ + passes::opaque::extract::OpaqueRenderMeshComponent, + passes::opaque::pipeline::{WorldOpaquePipeline, WorldOpaquePipelineKey}, + passes::skybox::{SkyboxPipeline, SkyboxPipelineKey}, + types::RenderTransformComponent, + }, }; -use bevy::ecs::prelude::*; -use bevy::render::render_resource::{ - CachedRenderPipelineId, PipelineCache, SpecializedRenderPipelines, +use bevy::{ + ecs::prelude::*, + render::render_resource::{CachedRenderPipelineId, PipelineCache, SpecializedRenderPipelines}, + render::view::{ExtractedView, Msaa}, }; -use bevy::render::view::{ExtractedView, Msaa}; #[derive(Debug)] pub struct PhaseItem { @@ -81,8 +83,7 @@ pub fn queue_opaque_system( let mut sortable_items: Vec = Vec::with_capacity(meshes_query.iter().len()); for (entity, _mesh, transform) in meshes_query.iter() { - // TODO: Frustum culling here - + // TODO: frustum culling let object_position = transform.transform.w_axis.truncate(); let distance_from_camera = (object_position - camera_position).length_squared(); diff --git a/crates/client/src/render/pipeline/main_passes/opaque_pass/render.rs b/crates/client/src/render/passes/opaque/render.rs similarity index 91% rename from crates/client/src/render/pipeline/main_passes/opaque_pass/render.rs rename to crates/client/src/render/passes/opaque/render.rs index 703a5219..8eb7d4a9 100644 --- a/crates/client/src/render/pipeline/main_passes/opaque_pass/render.rs +++ b/crates/client/src/render/passes/opaque/render.rs @@ -1,12 +1,10 @@ use crate::prelude::*; -use crate::render::pipeline::gpu_resources::world_uniforms::ChunkStorageManager; -use crate::render::pipeline::main_passes::shared_resources::TextureArrayUniforms; +use crate::render::resources::TextureArrayUniforms; +use crate::render::resources::world_uniforms::ChunkStorageManager; use crate::render::{ data::RenderMeshStorageResource, - pipeline::main_passes::{ - opaque_pass::{extract::OpaqueRenderMeshComponent, queue::Opaque3dRenderPhase}, - shared_resources::{CentralCameraViewUniform, EnvironmentUniforms}, - }, + passes::opaque::{extract::OpaqueRenderMeshComponent, queue::Opaque3dRenderPhase}, + resources::{CentralCameraViewUniform, EnvironmentUniforms}, }; use bevy::ecs::prelude::*; use bevy::ecs::query::QueryItem; @@ -28,7 +26,7 @@ impl ViewNode for OpaquePassRenderNode { &'static ViewDepthTexture, ); - #[instrument(skip_all, name = "opaque_pass_render_node")] + #[instrument(skip_all, name = "opaque_render_node")] fn run( &self, _graph: &mut RenderGraphContext, diff --git a/crates/client/src/render/pipeline/shadow_pass/gpu_resources/mod.rs b/crates/client/src/render/passes/shadow/gpu_resources/mod.rs similarity index 100% rename from crates/client/src/render/pipeline/shadow_pass/gpu_resources/mod.rs rename to crates/client/src/render/passes/shadow/gpu_resources/mod.rs diff --git a/crates/client/src/render/pipeline/shadow_pass/gpu_resources/shadow_pipeline.rs b/crates/client/src/render/passes/shadow/gpu_resources/shadow_pipeline.rs similarity index 85% rename from crates/client/src/render/pipeline/shadow_pass/gpu_resources/shadow_pipeline.rs rename to crates/client/src/render/passes/shadow/gpu_resources/shadow_pipeline.rs index e3f5b4df..e391aa94 100644 --- a/crates/client/src/render/pipeline/shadow_pass/gpu_resources/shadow_pipeline.rs +++ b/crates/client/src/render/passes/shadow/gpu_resources/shadow_pipeline.rs @@ -1,7 +1,7 @@ use super::shadow_view_uniform::ShadowViewBindGroupLayout; -use crate::render::pipeline::gpu_resources::world_uniforms::ChunkStorageBindGroupLayout; -use crate::render::pipeline::shader_registry::SHADOW_VERT_SHADER_HANDLE; -use crate::render::pipeline::shadow_pass::gpu_resources::SHADOW_DEPTH_FORMAT; +use crate::render::passes::shadow::gpu_resources::SHADOW_DEPTH_FORMAT; +use crate::render::resources::world_uniforms::ChunkStorageBindGroupLayout; +use crate::render::shaders::SHADOW_VERT_SHADER_HANDLE; use bevy::ecs::prelude::*; use bevy::mesh::PrimitiveTopology; use bevy::render::render_resource::{ @@ -21,7 +21,7 @@ impl FromWorld for ShadowPassPipeline { let view_layout = world.resource::(); let chunk_layout = world.resource::(); - let shadow_pass_depth_stencil = Some(DepthStencilState { + let shadow_depth_stencil = Some(DepthStencilState { format: SHADOW_DEPTH_FORMAT, depth_write_enabled: true, depth_compare: CompareFunction::Less, @@ -50,7 +50,7 @@ impl FromWorld for ShadowPassPipeline { cull_mode: Some(Face::Front), ..Default::default() }, - depth_stencil: shadow_pass_depth_stencil, + depth_stencil: shadow_depth_stencil, multisample: MultisampleState::default(), zero_initialize_workgroup_memory: true, }; diff --git a/crates/client/src/render/pipeline/shadow_pass/gpu_resources/shadow_texture.rs b/crates/client/src/render/passes/shadow/gpu_resources/shadow_texture.rs similarity index 100% rename from crates/client/src/render/pipeline/shadow_pass/gpu_resources/shadow_texture.rs rename to crates/client/src/render/passes/shadow/gpu_resources/shadow_texture.rs diff --git a/crates/client/src/render/pipeline/shadow_pass/gpu_resources/shadow_view_uniform.rs b/crates/client/src/render/passes/shadow/gpu_resources/shadow_view_uniform.rs similarity index 100% rename from crates/client/src/render/pipeline/shadow_pass/gpu_resources/shadow_view_uniform.rs rename to crates/client/src/render/passes/shadow/gpu_resources/shadow_view_uniform.rs diff --git a/crates/client/src/render/pipeline/shadow_pass/mod.rs b/crates/client/src/render/passes/shadow/mod.rs similarity index 90% rename from crates/client/src/render/pipeline/shadow_pass/mod.rs rename to crates/client/src/render/passes/shadow/mod.rs index ee84d78c..596c1769 100644 --- a/crates/client/src/render/pipeline/shadow_pass/mod.rs +++ b/crates/client/src/render/passes/shadow/mod.rs @@ -6,8 +6,8 @@ pub mod render; // plugin definition // --------------------------------- -use crate::render::pipeline::shadow_pass::prepare::update_shadow_view_buffer_system; -use crate::render::pipeline::shadow_pass::render::ShadowRenderPassNode; +use crate::render::passes::shadow::prepare::update_shadow_view_buffer_system; +use crate::render::passes::shadow::render::ShadowRenderPassNode; use crate::render::scheduling::VantablockNode; use bevy::app::{App, Plugin}; use bevy::prelude::IntoScheduleConfigs; diff --git a/crates/client/src/render/pipeline/shadow_pass/prepare.rs b/crates/client/src/render/passes/shadow/prepare.rs similarity index 95% rename from crates/client/src/render/pipeline/shadow_pass/prepare.rs rename to crates/client/src/render/passes/shadow/prepare.rs index 0d19d4cb..ec293d9e 100644 --- a/crates/client/src/render/pipeline/shadow_pass/prepare.rs +++ b/crates/client/src/render/passes/shadow/prepare.rs @@ -1,9 +1,9 @@ use crate::player::CAMERA_NEAR_PLANE; use crate::prelude::*; use crate::render::data::ExtractedSun; -use crate::render::pipeline::main_passes::opaque_pass::queue::Opaque3dRenderPhase; -use crate::render::pipeline::shadow_pass::gpu_resources::SHADOW_MAP_RESOLUTION; -use crate::render::pipeline::shadow_pass::gpu_resources::{ShadowViewBuffer, ShadowViewData}; +use crate::render::passes::opaque::queue::Opaque3dRenderPhase; +use crate::render::passes::shadow::gpu_resources::SHADOW_MAP_RESOLUTION; +use crate::render::passes::shadow::gpu_resources::{ShadowViewBuffer, ShadowViewData}; use bevy::ecs::prelude::*; use bevy::math::Vec4Swizzles; use bevy::render::renderer::RenderQueue; diff --git a/crates/client/src/render/pipeline/shadow_pass/render.rs b/crates/client/src/render/passes/shadow/render.rs similarity index 91% rename from crates/client/src/render/pipeline/shadow_pass/render.rs rename to crates/client/src/render/passes/shadow/render.rs index 71c9a56a..afc07042 100644 --- a/crates/client/src/render/pipeline/shadow_pass/render.rs +++ b/crates/client/src/render/passes/shadow/render.rs @@ -1,11 +1,9 @@ use crate::prelude::*; -use crate::render::pipeline::gpu_resources::world_uniforms::ChunkStorageManager; +use crate::render::resources::world_uniforms::ChunkStorageManager; use crate::render::{ data::RenderMeshStorageResource, - pipeline::main_passes::opaque_pass::{ - extract::OpaqueRenderMeshComponent, queue::Opaque3dRenderPhase, - }, - pipeline::shadow_pass::gpu_resources::{ + passes::opaque::{extract::OpaqueRenderMeshComponent, queue::Opaque3dRenderPhase}, + passes::shadow::gpu_resources::{ ShadowDepthTextureResource, ShadowPassPipeline, ShadowViewBuffer, }, }; @@ -24,7 +22,7 @@ pub struct ShadowRenderPassNode; impl ViewNode for ShadowRenderPassNode { type ViewQuery = &'static Opaque3dRenderPhase; - #[instrument(skip_all, name = "shadow_pass_render_node")] + #[instrument(skip_all, name = "shadow_render_node")] fn run( &self, _graph: &mut RenderGraphContext, diff --git a/crates/client/src/render/pipeline/main_passes/skybox_pass/mod.rs b/crates/client/src/render/passes/skybox/mod.rs similarity index 87% rename from crates/client/src/render/pipeline/main_passes/skybox_pass/mod.rs rename to crates/client/src/render/passes/skybox/mod.rs index 4ce2802d..b05808d4 100644 --- a/crates/client/src/render/pipeline/main_passes/skybox_pass/mod.rs +++ b/crates/client/src/render/passes/skybox/mod.rs @@ -1,6 +1,6 @@ pub mod pipeline; -pub use pipeline::*; +pub use pipeline::{SkyboxPipeline, SkyboxPipelineKey}; use bevy::app::{App, Plugin}; use bevy::render::render_resource::SpecializedRenderPipelines; diff --git a/crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs b/crates/client/src/render/passes/skybox/pipeline.rs similarity index 91% rename from crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs rename to crates/client/src/render/passes/skybox/pipeline.rs index ce2958c8..70827832 100644 --- a/crates/client/src/render/pipeline/main_passes/skybox_pass/pipeline.rs +++ b/crates/client/src/render/passes/skybox/pipeline.rs @@ -1,10 +1,7 @@ -use crate::render::pipeline::{ - main_passes::shared_resources::{ - CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, MAIN_DEPTH_FORMAT, - }, - shader_registry::{SKYBOX_FRAG_SHADER_HANDLE, SKYBOX_VERT_SHADER_HANDLE}, -}; +use crate::render::resources::{CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout}; +use crate::render::shaders::{SKYBOX_FRAG_SHADER_HANDLE, SKYBOX_VERT_SHADER_HANDLE}; use bevy::{ + core_pipeline::core_3d, ecs::prelude::*, render::{render_resource::*, view::ViewTarget}, }; @@ -54,7 +51,7 @@ impl SpecializedRenderPipeline for SkyboxPipeline { })]; let depth_stencil = Some(DepthStencilState { - format: MAIN_DEPTH_FORMAT, + format: core_3d::CORE_3D_DEPTH_FORMAT, depth_write_enabled: false, depth_compare: CompareFunction::Equal, stencil: StencilState::default(), diff --git a/crates/client/src/render/pipeline/main_passes/transparent_pass/extract.rs b/crates/client/src/render/passes/transparent/extract.rs similarity index 100% rename from crates/client/src/render/pipeline/main_passes/transparent_pass/extract.rs rename to crates/client/src/render/passes/transparent/extract.rs diff --git a/crates/client/src/render/pipeline/main_passes/transparent_pass/mod.rs b/crates/client/src/render/passes/transparent/mod.rs similarity index 89% rename from crates/client/src/render/pipeline/main_passes/transparent_pass/mod.rs rename to crates/client/src/render/passes/transparent/mod.rs index 300533df..6aaaf5b7 100644 --- a/crates/client/src/render/pipeline/main_passes/transparent_pass/mod.rs +++ b/crates/client/src/render/passes/transparent/mod.rs @@ -13,16 +13,18 @@ use startup::TransparentPipeline; use crate::{ VantablockNode, - render::pipeline::main_passes::transparent_pass::{ + render::passes::transparent::{ prepare::prepare_transparent_meshes_system, queue::queue_and_prepare_transparent_system, }, }; use bevy::prelude::IntoScheduleConfigs; use bevy::{ app::{App, Plugin}, - render::render_graph::{RenderGraphExt, ViewNodeRunner}, - render::render_resource::SpecializedRenderPipelines, - render::{Render, RenderSystems}, + render::{ + Render, RenderSystems, + render_graph::{RenderGraphExt, ViewNodeRunner}, + render_resource::SpecializedRenderPipelines, + }, }; pub struct TransparentRenderPassPlugin; diff --git a/crates/client/src/render/pipeline/main_passes/transparent_pass/prepare.rs b/crates/client/src/render/passes/transparent/prepare.rs similarity index 93% rename from crates/client/src/render/pipeline/main_passes/transparent_pass/prepare.rs rename to crates/client/src/render/passes/transparent/prepare.rs index 7966c819..9021983e 100644 --- a/crates/client/src/render/pipeline/main_passes/transparent_pass/prepare.rs +++ b/crates/client/src/render/passes/transparent/prepare.rs @@ -1,6 +1,4 @@ -use crate::render::pipeline::gpu_resources::world_uniforms::{ - ChunkStorageBindGroupLayout, ChunkStorageManager, -}; +use crate::render::resources::world_uniforms::{ChunkStorageBindGroupLayout, ChunkStorageManager}; use crate::{ prelude::*, render::data::{MeshesToUploadQueue, RenderMeshStorageResource}, diff --git a/crates/client/src/render/pipeline/main_passes/transparent_pass/queue.rs b/crates/client/src/render/passes/transparent/queue.rs similarity index 92% rename from crates/client/src/render/pipeline/main_passes/transparent_pass/queue.rs rename to crates/client/src/render/passes/transparent/queue.rs index e9844c7e..789e13ad 100644 --- a/crates/client/src/render/pipeline/main_passes/transparent_pass/queue.rs +++ b/crates/client/src/render/passes/transparent/queue.rs @@ -1,8 +1,6 @@ use crate::prelude::*; -use crate::render::pipeline::main_passes::transparent_pass::extract::TransparentRenderMeshComponent; -use crate::render::pipeline::main_passes::transparent_pass::startup::{ - TransparentPipeline, TransparentPipelineKey, -}; +use crate::render::passes::transparent::extract::TransparentRenderMeshComponent; +use crate::render::passes::transparent::startup::{TransparentPipeline, TransparentPipelineKey}; use crate::render::types::RenderTransformComponent; use bevy::ecs::prelude::*; use bevy::render::render_resource::{ diff --git a/crates/client/src/render/pipeline/main_passes/transparent_pass/render.rs b/crates/client/src/render/passes/transparent/render.rs similarity index 81% rename from crates/client/src/render/pipeline/main_passes/transparent_pass/render.rs rename to crates/client/src/render/passes/transparent/render.rs index 6a8d4819..536fb5c6 100644 --- a/crates/client/src/render/pipeline/main_passes/transparent_pass/render.rs +++ b/crates/client/src/render/passes/transparent/render.rs @@ -1,24 +1,24 @@ use crate::prelude::*; -use crate::render::pipeline::gpu_resources::world_uniforms::ChunkStorageManager; -use crate::render::pipeline::main_passes::shared_resources::TextureArrayUniforms; use crate::render::{ data::RenderMeshStorageResource, - pipeline::main_passes::{ - shared_resources::{CentralCameraViewUniform, EnvironmentUniforms}, - transparent_pass::{ - extract::TransparentRenderMeshComponent, queue::Transparent3dRenderPhase, - }, + passes::transparent::{ + extract::TransparentRenderMeshComponent, queue::Transparent3dRenderPhase, }, + resources::TextureArrayUniforms, + resources::world_uniforms::ChunkStorageManager, + resources::{CentralCameraViewUniform, EnvironmentUniforms}, }; -use bevy::ecs::prelude::*; use bevy::ecs::query::QueryItem; -use bevy::render::render_graph::{NodeRunError, RenderGraphContext, ViewNode}; -use bevy::render::render_resource::{ - LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, RenderPassDescriptor, - StoreOp, +use bevy::{ + ecs::prelude::*, + render::render_graph::{NodeRunError, RenderGraphContext, ViewNode}, + render::render_resource::{ + LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, RenderPassDescriptor, + StoreOp, + }, + render::renderer::RenderContext, + render::view::{ViewDepthTexture, ViewTarget}, }; -use bevy::render::renderer::RenderContext; -use bevy::render::view::{ViewDepthTexture, ViewTarget}; #[derive(Default)] pub struct TransparentPassRenderNode; @@ -30,7 +30,7 @@ impl ViewNode for TransparentPassRenderNode { &'static ViewDepthTexture, ); - #[instrument(skip_all, name = "transparent_pass_render_node")] + #[instrument(skip_all, name = "transparent_render_node")] fn run( &self, _graph: &mut RenderGraphContext, diff --git a/crates/client/src/render/pipeline/main_passes/transparent_pass/startup.rs b/crates/client/src/render/passes/transparent/startup.rs similarity index 89% rename from crates/client/src/render/pipeline/main_passes/transparent_pass/startup.rs rename to crates/client/src/render/passes/transparent/startup.rs index d285cd51..86ec6c71 100644 --- a/crates/client/src/render/pipeline/main_passes/transparent_pass/startup.rs +++ b/crates/client/src/render/passes/transparent/startup.rs @@ -1,12 +1,14 @@ -use super::super::shared_resources::{ - CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, TextureArrayBindGroupLayout, - MAIN_DEPTH_FORMAT, +use crate::render::{ + resources::world_uniforms::ChunkStorageBindGroupLayout, + resources::{ + CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, TextureArrayBindGroupLayout, + }, + shaders::{TRANSPARENT_FRAG_SHADER_HANDLE, TRANSPARENT_VERT_SHADER_HANDLE}, }; -use crate::render::pipeline::{ - gpu_resources::world_uniforms::ChunkStorageBindGroupLayout, - shader_registry::{TRANSPARENT_FRAG_SHADER_HANDLE, TRANSPARENT_VERT_SHADER_HANDLE}, +use bevy::{ + core_pipeline::core_3d, + prelude::{FromWorld, Resource, World}, }; -use bevy::prelude::{FromWorld, Resource, World}; use bevy::{render::render_resource::*, render::view::ViewTarget}; // INFO: ------------------- @@ -80,7 +82,7 @@ impl SpecializedRenderPipeline for TransparentPipeline { })], }), depth_stencil: Some(DepthStencilState { - format: MAIN_DEPTH_FORMAT, + format: core_3d::CORE_3D_DEPTH_FORMAT, depth_write_enabled: false, // transparent objects don't write depth depth_compare: CompareFunction::GreaterEqual, stencil: StencilState::default(), diff --git a/crates/client/src/render/pipeline/gpu_resources/mod.rs b/crates/client/src/render/pipeline/gpu_resources/mod.rs deleted file mode 100644 index 0d344447..00000000 --- a/crates/client/src/render/pipeline/gpu_resources/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod world_uniforms; - -pub use world_uniforms::{ - ChunkRenderData, ChunkStorageBindGroupLayout, ChunkStorageManager, VoxelMesh, -}; diff --git a/crates/client/src/render/pipeline/main_passes/mod.rs b/crates/client/src/render/pipeline/main_passes/mod.rs deleted file mode 100644 index bf39f215..00000000 --- a/crates/client/src/render/pipeline/main_passes/mod.rs +++ /dev/null @@ -1,73 +0,0 @@ -pub mod bounding_box_pass; -pub mod opaque_pass; -pub mod shared_resources; -pub mod skybox_pass; -pub mod transparent_pass; - -use shared_resources::{ - CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, TextureArrayBindGroupLayout, -}; -pub use shared_resources::{CentralCameraViewUniform, EnvironmentUniforms, MAIN_DEPTH_FORMAT}; - -// INFO: --------------------------- -// plugin definition -// --------------------------------- - -use crate::render::pipeline::main_passes::{ - bounding_box_pass::WireframeRenderPassPlugin, - opaque_pass::OpaqueRenderPassPlugin, - shared_resources::{ - update_camera_view_buffer_system, update_environment_uniform_buffer_system, - }, - skybox_pass::SkyboxRenderPassPlugin, - transparent_pass::TransparentRenderPassPlugin, -}; -use bevy::app::{App, Plugin}; -use bevy::prelude::IntoScheduleConfigs; -use bevy::render::{Render, RenderSystems}; - -/// A plugin that sets up all the necessary resources and render -/// passes used in the rendering pipeline. -pub struct PlayerCentricRenderPassPlugin; - -impl Plugin for PlayerCentricRenderPassPlugin { - fn build(&self, app: &mut App) { - // INFO: ----------------------------------------- - // prepare (also shared resources) - // ----------------------------------------------- - - app.add_systems( - Render, - ( - update_camera_view_buffer_system, - update_environment_uniform_buffer_system, - shared_resources::prepare_texture_array_system, - ) - .in_set(RenderSystems::Prepare), - ); - - // INFO: -------------------------------------- - // subplugins for render passes - // -------------------------------------------- - - app.add_plugins(( - TransparentRenderPassPlugin, - OpaqueRenderPassPlugin, - SkyboxRenderPassPlugin, - WireframeRenderPassPlugin, - )); - } - - fn finish(&self, app: &mut App) { - // INFO: ---------------------------------------------------- - // startup (shared resources for main passes) - // ---------------------------------------------------------- - - app.init_resource::(); - app.init_resource::(); - app.init_resource::(); - app.init_resource::(); - - app.init_resource::(); - } -} diff --git a/crates/client/src/render/pipeline/mod.rs b/crates/client/src/render/pipeline/mod.rs deleted file mode 100644 index 608eaf54..00000000 --- a/crates/client/src/render/pipeline/mod.rs +++ /dev/null @@ -1,72 +0,0 @@ -pub mod gpu_resources; -pub mod main_passes; -pub mod shader_registry; -pub mod shadow_pass; - -pub use gpu_resources::*; -pub use main_passes::*; -pub use shader_registry::*; -pub use shadow_pass::*; - -// INFO: --------------------------- -// plugin definition -// --------------------------------- - -use crate::VantablockNode; -use bevy::{ - app::{App, Plugin}, - render::render_graph::RenderGraphExt, -}; - -/// A plugin that sets up all the necessary resources and render -/// passes used in the rendering pipeline. -pub struct WorldRenderPassesPlugin; - -impl Plugin for WorldRenderPassesPlugin { - fn build(&self, app: &mut App) { - // renderpass plugins - app.add_plugins((ShadowRenderPassPlugin, PlayerCentricRenderPassPlugin)); - } - - fn finish(&self, app: &mut App) { - // shared world uniform resources - app.init_resource::(); - app.init_resource::(); - } -} - -/// A plugin responsible ONLY for wiring the edges between nodes in the render graph. -/// This must be added AFTER all pass plugins to ensure all nodes exist. -pub struct RenderGraphEdgesPlugin; - -impl Plugin for RenderGraphEdgesPlugin { - fn build(&self, app: &mut App) { - app.add_render_graph_edges( - bevy::core_pipeline::core_3d::graph::Core3d, - ( - bevy::core_pipeline::core_3d::graph::Node3d::StartMainPass, - VantablockNode::ShadowPass, - bevy::core_pipeline::core_3d::graph::Node3d::MainOpaquePass, - ), - ); - - app.add_render_graph_edges( - bevy::core_pipeline::core_3d::graph::Core3d, - ( - bevy::core_pipeline::core_3d::graph::Node3d::MainOpaquePass, - VantablockNode::OpaquePass, - VantablockNode::TransparentPass, - bevy::core_pipeline::core_3d::graph::Node3d::MainTransparentPass, - ), - ); - - app.add_render_graph_edges( - bevy::core_pipeline::core_3d::graph::Core3d, - ( - bevy::core_pipeline::core_3d::graph::Node3d::MainTransparentPass, - VantablockNode::BoundingBoxPass, - bevy::core_pipeline::core_3d::graph::Node3d::EndMainPass, - ), - ); - } -} diff --git a/crates/client/src/render/pipeline/main_passes/shared_resources/environment_uniform.rs b/crates/client/src/render/resources/environment_uniform.rs similarity index 100% rename from crates/client/src/render/pipeline/main_passes/shared_resources/environment_uniform.rs rename to crates/client/src/render/resources/environment_uniform.rs diff --git a/crates/client/src/render/pipeline/main_passes/shared_resources/mod.rs b/crates/client/src/render/resources/mod.rs similarity index 78% rename from crates/client/src/render/pipeline/main_passes/shared_resources/mod.rs rename to crates/client/src/render/resources/mod.rs index a9fa1a40..b75cbb8f 100644 --- a/crates/client/src/render/pipeline/main_passes/shared_resources/mod.rs +++ b/crates/client/src/render/resources/mod.rs @@ -1,10 +1,7 @@ pub mod environment_uniform; pub mod tex_array_uniforms; pub mod view_uniforms; - -use bevy::render::render_resource::TextureFormat; - -pub const MAIN_DEPTH_FORMAT: TextureFormat = TextureFormat::Depth32Float; +pub mod world_uniforms; pub use environment_uniform::{ EnvironmentBindGroupLayout, EnvironmentUniforms, update_environment_uniform_buffer_system, diff --git a/crates/client/src/render/pipeline/main_passes/shared_resources/tex_array_uniforms.rs b/crates/client/src/render/resources/tex_array_uniforms.rs similarity index 100% rename from crates/client/src/render/pipeline/main_passes/shared_resources/tex_array_uniforms.rs rename to crates/client/src/render/resources/tex_array_uniforms.rs diff --git a/crates/client/src/render/pipeline/main_passes/shared_resources/view_uniforms.rs b/crates/client/src/render/resources/view_uniforms.rs similarity index 94% rename from crates/client/src/render/pipeline/main_passes/shared_resources/view_uniforms.rs rename to crates/client/src/render/resources/view_uniforms.rs index 3b24400e..8306c8ec 100644 --- a/crates/client/src/render/pipeline/main_passes/shared_resources/view_uniforms.rs +++ b/crates/client/src/render/resources/view_uniforms.rs @@ -1,14 +1,16 @@ use crate::prelude::*; -use crate::render::pipeline::main_passes::opaque_pass::queue::Opaque3dRenderPhase; -use crate::render::pipeline::shadow_pass::gpu_resources::{ - ShadowDepthTextureResource, ShadowViewBuffer, +use crate::render::passes::{ + opaque::queue::Opaque3dRenderPhase, + shadow::gpu_resources::{ShadowDepthTextureResource, ShadowViewBuffer}, }; use bevy::ecs::prelude::*; -use bevy::render::render_resource::{ - BindGroup, BindGroupEntry, BindingResource, Buffer, BufferDescriptor, BufferUsages, +use bevy::render::{ + render_resource::{ + BindGroup, BindGroupEntry, BindingResource, Buffer, BufferDescriptor, BufferUsages, + }, + renderer::{RenderDevice, RenderQueue}, + view::ExtractedView, }; -use bevy::render::renderer::{RenderDevice, RenderQueue}; -use bevy::render::view::ExtractedView; use bytemuck::{Pod, Zeroable}; use shared::simulation::chunk::{CHUNK_SIDE_LENGTH, RENDER_DISTANCE}; diff --git a/crates/client/src/render/pipeline/gpu_resources/world_uniforms.rs b/crates/client/src/render/resources/world_uniforms.rs similarity index 100% rename from crates/client/src/render/pipeline/gpu_resources/world_uniforms.rs rename to crates/client/src/render/resources/world_uniforms.rs diff --git a/crates/client/src/render/pipeline/shader_registry.rs b/crates/client/src/render/shaders.rs similarity index 100% rename from crates/client/src/render/pipeline/shader_registry.rs rename to crates/client/src/render/shaders.rs diff --git a/crates/client/src/render/types/mod.rs b/crates/client/src/render/types/mod.rs index a55ea1cc..03f12531 100644 --- a/crates/client/src/render/types/mod.rs +++ b/crates/client/src/render/types/mod.rs @@ -1,14 +1,5 @@ -mod wireframe_vertex; +pub mod render_transform; +pub mod wireframe_vertex; -pub use crate::render::chunk::meshing::packed_face::PackedFace; -pub use crate::render::pipeline::VoxelMesh; +pub use render_transform::RenderTransformComponent; pub use wireframe_vertex::WireframeVertex; - -use bevy::ecs::component::Component; -use bevy::math::Mat4; - -/// A component representing a transform on a mesh in the render world. -#[derive(Component, Clone)] -pub struct RenderTransformComponent { - pub transform: Mat4, -} diff --git a/crates/client/src/render/types/render_transform.rs b/crates/client/src/render/types/render_transform.rs new file mode 100644 index 00000000..4d4086ad --- /dev/null +++ b/crates/client/src/render/types/render_transform.rs @@ -0,0 +1,9 @@ +use bevy::ecs::component::Component; +use bevy::math::Mat4; + +/// A component representing a transform on a mesh in the render world. +// TODO: bevy likely has a builtin +#[derive(Component, Clone)] +pub struct RenderTransformComponent { + pub transform: Mat4, +} From f24b4283a07b05b7fbb9e170343d10fed7af1f4b Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Thu, 9 Apr 2026 23:47:01 +0000 Subject: [PATCH 008/106] specialize chunk bounds extraction --- .../extra_binds/toggle_chunk_borders.rs | 7 ++++-- crates/client/src/render/mod.rs | 10 +++----- .../src/render/passes/bounding_box/extract.rs | 18 ------------- .../src/render/passes/bounding_box/mod.rs | 25 ++++++++----------- .../src/render/passes/bounding_box/queue.rs | 12 ++++----- 5 files changed, 24 insertions(+), 48 deletions(-) delete mode 100644 crates/client/src/render/passes/bounding_box/extract.rs diff --git a/crates/client/src/input/systems/extra_binds/toggle_chunk_borders.rs b/crates/client/src/input/systems/extra_binds/toggle_chunk_borders.rs index 15c33ec9..0f36cffb 100644 --- a/crates/client/src/input/systems/extra_binds/toggle_chunk_borders.rs +++ b/crates/client/src/input/systems/extra_binds/toggle_chunk_borders.rs @@ -1,7 +1,10 @@ use crate::prelude::*; -use bevy::ecs::{resource::Resource, system::ResMut}; +use bevy::{ + ecs::{resource::Resource, system::ResMut}, + render::extract_resource::ExtractResource, +}; -#[derive(Resource, Default)] +#[derive(Resource, ExtractResource, Default, Clone)] pub struct ChunkBoundsToggle { pub enabled: bool, } diff --git a/crates/client/src/render/mod.rs b/crates/client/src/render/mod.rs index fe2aa646..c07f7d05 100644 --- a/crates/client/src/render/mod.rs +++ b/crates/client/src/render/mod.rs @@ -14,13 +14,13 @@ pub use data::*; // render world interface // -------------------------------------- +use crate::input::systems::toggle_chunk_borders::ChunkBoundsToggle; use crate::input::systems::toggle_opaque_wireframe::OpaqueRenderMode; use crate::prelude::*; use crate::render::{ chunk::{OpaqueMeshComponent, TransparentMeshComponent}, passes::{ - RenderGraphEdgesPlugin, WorldRenderPassesPlugin, - bounding_box::extract::WireframeToggleState, opaque::extract::extract_opaque_meshes, + RenderGraphEdgesPlugin, WorldRenderPassesPlugin, opaque::extract::extract_opaque_meshes, transparent::extract::extract_transparent_meshes, }, texture::BlockTextureArray, @@ -51,11 +51,8 @@ impl Plugin for VantablockRenderPlugin { ExtractResourcePlugin::::default(), ExtractResourcePlugin::::default(), ExtractResourcePlugin::::default(), - )); - - app.add_plugins(( - ExtractResourcePlugin::::default(), ExtractResourcePlugin::::default(), + ExtractResourcePlugin::::default(), )); // INFO: ------------------------------------ @@ -94,6 +91,7 @@ impl Plugin for VantablockRenderPlugin { pub fn pre_setup_render_sub_app(sub_app: &mut SubApp) { // resources for rendering sub_app + .init_resource::() .init_resource::() .init_resource::() .init_resource::(); diff --git a/crates/client/src/render/passes/bounding_box/extract.rs b/crates/client/src/render/passes/bounding_box/extract.rs deleted file mode 100644 index 0fb208ca..00000000 --- a/crates/client/src/render/passes/bounding_box/extract.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::input::systems::toggle_chunk_borders::ChunkBoundsToggle; -use bevy::ecs::resource::Resource; -use bevy::render::extract_resource::ExtractResource; - -#[derive(Resource, Debug, PartialEq, Eq, Clone)] -pub struct WireframeToggleState { - pub enabled: bool, -} - -impl ExtractResource for WireframeToggleState { - type Source = ChunkBoundsToggle; - - fn extract_resource(source: &Self::Source) -> Self { - Self { - enabled: source.enabled, - } - } -} diff --git a/crates/client/src/render/passes/bounding_box/mod.rs b/crates/client/src/render/passes/bounding_box/mod.rs index a9ae28d0..b523cea3 100644 --- a/crates/client/src/render/passes/bounding_box/mod.rs +++ b/crates/client/src/render/passes/bounding_box/mod.rs @@ -1,4 +1,3 @@ -pub mod extract; pub mod gpu_resources; pub mod queue; pub mod render; @@ -10,12 +9,14 @@ pub use render::BoundingBoxNode; // --------------------------------- use crate::{VantablockNode, render::passes::bounding_box::queue::queue_wireframe_system}; -use bevy::core_pipeline::core_3d; -use bevy::prelude::{App, IntoScheduleConfigs, Plugin}; -use bevy::render::{ - render_graph::{RenderGraphExt, ViewNodeRunner}, - render_resource::SpecializedRenderPipelines, - {Render, RenderSystems}, +use bevy::{ + core_pipeline::core_3d, + prelude::{App, IntoScheduleConfigs, Plugin}, + render::{ + render_graph::{RenderGraphExt, ViewNodeRunner}, + render_resource::SpecializedRenderPipelines, + {Render, RenderSystems}, + }, }; use gpu_resources::{ UnitCubeMesh, WireframeObjectBuffer, WireframePipeline, @@ -26,16 +27,10 @@ pub struct WireframeRenderPassPlugin; impl Plugin for WireframeRenderPassPlugin { fn build(&self, app: &mut App) { - // INFO: --------------- - // queue - // --------------------- - + // queue app.add_systems(Render, queue_wireframe_system.in_set(RenderSystems::Queue)); - // INFO: ---------------------------------- - // render graph integration - // ---------------------------------------- - + // render graph node app.add_render_graph_node::>( core_3d::graph::Core3d, VantablockNode::BoundingBoxPass, diff --git a/crates/client/src/render/passes/bounding_box/queue.rs b/crates/client/src/render/passes/bounding_box/queue.rs index 24a44ed4..842582b2 100644 --- a/crates/client/src/render/passes/bounding_box/queue.rs +++ b/crates/client/src/render/passes/bounding_box/queue.rs @@ -1,12 +1,10 @@ use crate::{ + input::systems::toggle_chunk_borders::ChunkBoundsToggle, prelude::*, render::{ - passes::bounding_box::{ - extract::WireframeToggleState, - gpu_resources::{ - WireframeObjectBuffer, WireframeObjectData, - object_binding::WireframeObjectBindGroupLayout, wireframe_pipeline::*, - }, + passes::bounding_box::gpu_resources::{ + WireframeObjectBuffer, WireframeObjectData, + object_binding::WireframeObjectBindGroupLayout, wireframe_pipeline::*, }, types::RenderTransformComponent, }, @@ -40,7 +38,7 @@ pub fn queue_wireframe_system( device: Res, object_layout: Res, chunk_query: Query<&RenderTransformComponent>, - active_bounds: Res, + active_bounds: Res, targeted_block: Res, pipeline_cache: Res, mut specialized_pipelines: ResMut>, From 4c2549bad8a46f2092b962f9904b603b1b101f91 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 00:42:24 +0000 Subject: [PATCH 009/106] renaming oapque pipelins and minor refactor --- crates/client/src/render/passes/mod.rs | 16 ++++------ .../passes/opaque/{ => mesh}/extract.rs | 0 .../src/render/passes/opaque/mesh/mod.rs | 3 ++ .../passes/opaque/{ => mesh}/pipeline.rs | 14 ++++---- .../render/passes/opaque/{ => mesh}/queue.rs | 20 ++++++------ crates/client/src/render/passes/opaque/mod.rs | 32 +++++++++++-------- .../client/src/render/passes/opaque/render.rs | 27 +++++++++------- .../{skybox/pipeline.rs => opaque/skybox.rs} | 10 +++--- crates/client/src/render/passes/skybox/mod.rs | 17 ---------- 9 files changed, 68 insertions(+), 71 deletions(-) rename crates/client/src/render/passes/opaque/{ => mesh}/extract.rs (100%) create mode 100644 crates/client/src/render/passes/opaque/mesh/mod.rs rename crates/client/src/render/passes/opaque/{ => mesh}/pipeline.rs (91%) rename crates/client/src/render/passes/opaque/{ => mesh}/queue.rs (87%) rename crates/client/src/render/passes/{skybox/pipeline.rs => opaque/skybox.rs} (93%) delete mode 100644 crates/client/src/render/passes/skybox/mod.rs diff --git a/crates/client/src/render/passes/mod.rs b/crates/client/src/render/passes/mod.rs index b32d9f39..67c682f9 100644 --- a/crates/client/src/render/passes/mod.rs +++ b/crates/client/src/render/passes/mod.rs @@ -1,7 +1,6 @@ pub mod bounding_box; pub mod opaque; pub mod shadow; -pub mod skybox; pub mod transparent; // INFO: --------------------------- @@ -9,25 +8,25 @@ pub mod transparent; // --------------------------------- use crate::{ - VantablockNode, render::{ passes::{ bounding_box::WireframeRenderPassPlugin, opaque::OpaqueRenderPassPlugin, - shadow::ShadowRenderPassPlugin, skybox::SkyboxRenderPassPlugin, - transparent::TransparentRenderPassPlugin, + shadow::ShadowRenderPassPlugin, transparent::TransparentRenderPassPlugin, }, resources::{ - CentralCameraViewBindGroupLayout, CentralCameraViewUniform, EnvironmentBindGroupLayout, - EnvironmentUniforms, TextureArrayBindGroupLayout, prepare_texture_array_system, - update_camera_view_buffer_system, update_environment_uniform_buffer_system, + prepare_texture_array_system, update_camera_view_buffer_system, + update_environment_uniform_buffer_system, world_uniforms::{ChunkStorageBindGroupLayout, ChunkStorageManager}, + CentralCameraViewBindGroupLayout, CentralCameraViewUniform, EnvironmentBindGroupLayout, + EnvironmentUniforms, TextureArrayBindGroupLayout, }, }, + VantablockNode, }; use bevy::prelude::IntoScheduleConfigs; use bevy::{ app::{App, Plugin}, - render::{Render, RenderSystems, render_graph::RenderGraphExt}, + render::{render_graph::RenderGraphExt, Render, RenderSystems}, }; /// A plugin that sets up all the necessary resources and render @@ -110,7 +109,6 @@ impl Plugin for PlayerCentricRenderPassPlugin { app.add_plugins(( TransparentRenderPassPlugin, OpaqueRenderPassPlugin, - SkyboxRenderPassPlugin, WireframeRenderPassPlugin, )); } diff --git a/crates/client/src/render/passes/opaque/extract.rs b/crates/client/src/render/passes/opaque/mesh/extract.rs similarity index 100% rename from crates/client/src/render/passes/opaque/extract.rs rename to crates/client/src/render/passes/opaque/mesh/extract.rs diff --git a/crates/client/src/render/passes/opaque/mesh/mod.rs b/crates/client/src/render/passes/opaque/mesh/mod.rs new file mode 100644 index 00000000..df4cec93 --- /dev/null +++ b/crates/client/src/render/passes/opaque/mesh/mod.rs @@ -0,0 +1,3 @@ +pub mod extract; +pub mod pipeline; +pub mod queue; diff --git a/crates/client/src/render/passes/opaque/pipeline.rs b/crates/client/src/render/passes/opaque/mesh/pipeline.rs similarity index 91% rename from crates/client/src/render/passes/opaque/pipeline.rs rename to crates/client/src/render/passes/opaque/mesh/pipeline.rs index 6314c6bd..6770d0b6 100644 --- a/crates/client/src/render/passes/opaque/pipeline.rs +++ b/crates/client/src/render/passes/opaque/mesh/pipeline.rs @@ -3,8 +3,8 @@ use crate::{ prelude::*, render::{ resources::{ - CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, - TextureArrayBindGroupLayout, world_uniforms::ChunkStorageBindGroupLayout, + world_uniforms::ChunkStorageBindGroupLayout, CentralCameraViewBindGroupLayout, + EnvironmentBindGroupLayout, TextureArrayBindGroupLayout, }, shaders::{OPAQUE_FRAG_SHADER_HANDLE, OPAQUE_VERT_SHADER_HANDLE}, }, @@ -17,7 +17,7 @@ use bevy::{ /// A key that uniquely identifies a specialized world opaque pipeline. #[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub struct WorldOpaquePipelineKey { +pub struct Opaque3dPipelineKey { pub msaa_samples: u32, pub hdr: bool, pub mode: OpaqueRenderMode, @@ -25,14 +25,14 @@ pub struct WorldOpaquePipelineKey { /// A resource that holds all the layouts and handles needed to specialize world opaque pipelines. #[derive(Resource)] -pub struct WorldOpaquePipeline { +pub struct Opaque3dPipeline { pub view_layout: BindGroupLayoutDescriptor, pub environment_layout: BindGroupLayoutDescriptor, pub texture_layout: BindGroupLayoutDescriptor, pub chunk_storage_layout: BindGroupLayoutDescriptor, } -impl FromWorld for WorldOpaquePipeline { +impl FromWorld for Opaque3dPipeline { #[instrument(skip_all)] fn from_world(world: &mut World) -> Self { let view_layout = world.resource::(); @@ -49,8 +49,8 @@ impl FromWorld for WorldOpaquePipeline { } } -impl SpecializedRenderPipeline for WorldOpaquePipeline { - type Key = WorldOpaquePipelineKey; +impl SpecializedRenderPipeline for Opaque3dPipeline { + type Key = Opaque3dPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { let format = if key.hdr { diff --git a/crates/client/src/render/passes/opaque/queue.rs b/crates/client/src/render/passes/opaque/mesh/queue.rs similarity index 87% rename from crates/client/src/render/passes/opaque/queue.rs rename to crates/client/src/render/passes/opaque/mesh/queue.rs index 13436ce7..41354e9d 100644 --- a/crates/client/src/render/passes/opaque/queue.rs +++ b/crates/client/src/render/passes/opaque/mesh/queue.rs @@ -2,9 +2,11 @@ use crate::{ input::systems::toggle_opaque_wireframe::OpaqueRenderMode, prelude::*, render::{ - passes::opaque::extract::OpaqueRenderMeshComponent, - passes::opaque::pipeline::{WorldOpaquePipeline, WorldOpaquePipelineKey}, - passes::skybox::{SkyboxPipeline, SkyboxPipelineKey}, + passes::opaque::{ + extract::OpaqueRenderMeshComponent, + pipeline::{Opaque3dPipeline, Opaque3dPipelineKey}, + skybox::{OpaqueSkyboxPipeline, OpaqueSkyboxPipelineKey}, + }, types::RenderTransformComponent, }, }; @@ -48,16 +50,16 @@ pub fn queue_opaque_system( )>, render_mode: Res, pipeline_cache: Res, - mut specialized_world_pipelines: ResMut>, - world_pipelines: Res, - mut specialized_skybox_pipelines: ResMut>, - skybox_pipelines: Res, + mut specialized_world_pipelines: ResMut>, + world_pipelines: Res, + mut specialized_skybox_pipelines: ResMut>, + skybox_pipelines: Res, ) { for (extracted_view, msaa, mut opaque_phase) in views_query.iter_mut() { opaque_phase.items.clear(); // specialize pipelines for this view's MSAA and HDR settings - let mesh_key = WorldOpaquePipelineKey { + let mesh_key = Opaque3dPipelineKey { msaa_samples: msaa.samples(), hdr: extracted_view.hdr, mode: *render_mode, @@ -68,7 +70,7 @@ pub fn queue_opaque_system( mesh_key, )); - let skybox_key = SkyboxPipelineKey { + let skybox_key = OpaqueSkyboxPipelineKey { msaa_samples: msaa.samples(), hdr: extracted_view.hdr, }; diff --git a/crates/client/src/render/passes/opaque/mod.rs b/crates/client/src/render/passes/opaque/mod.rs index edad39ea..7506c3f8 100644 --- a/crates/client/src/render/passes/opaque/mod.rs +++ b/crates/client/src/render/passes/opaque/mod.rs @@ -1,21 +1,25 @@ -pub mod extract; -pub mod pipeline; -pub mod queue; +pub mod mesh; pub mod render; +pub mod skybox; +pub use mesh::*; pub use render::OpaquePassRenderNode; // INFO: --------------------------- // plugin definition // --------------------------------- -use crate::VantablockNode; -use crate::render::passes::opaque::pipeline::WorldOpaquePipeline; -use bevy::prelude::{App, IntoScheduleConfigs, Plugin}; -use bevy::render::{ - render_graph::{RenderGraphExt, ViewNodeRunner}, - render_resource::SpecializedRenderPipelines, - {Render, RenderSystems}, +use crate::{ + render::passes::opaque::{mesh::pipeline::Opaque3dPipeline, skybox::OpaqueSkyboxPipeline}, + VantablockNode, +}; +use bevy::{ + prelude::{App, IntoScheduleConfigs, Plugin}, + render::{ + render_graph::{RenderGraphExt, ViewNodeRunner}, + render_resource::SpecializedRenderPipelines, + {Render, RenderSystems}, + }, }; pub struct OpaqueRenderPassPlugin; @@ -43,10 +47,12 @@ impl Plugin for OpaqueRenderPassPlugin { fn finish(&self, app: &mut App) { // INFO: ----------------- - // Startup + // startup // ----------------------- - app.init_resource::(); - app.init_resource::>(); + app.init_resource::(); + app.init_resource::>(); + app.init_resource::(); + app.init_resource::>(); } } diff --git a/crates/client/src/render/passes/opaque/render.rs b/crates/client/src/render/passes/opaque/render.rs index 8eb7d4a9..10714fa7 100644 --- a/crates/client/src/render/passes/opaque/render.rs +++ b/crates/client/src/render/passes/opaque/render.rs @@ -1,20 +1,25 @@ use crate::prelude::*; -use crate::render::resources::TextureArrayUniforms; -use crate::render::resources::world_uniforms::ChunkStorageManager; use crate::render::{ data::RenderMeshStorageResource, passes::opaque::{extract::OpaqueRenderMeshComponent, queue::Opaque3dRenderPhase}, - resources::{CentralCameraViewUniform, EnvironmentUniforms}, + resources::{ + world_uniforms::ChunkStorageManager, CentralCameraViewUniform, EnvironmentUniforms, + TextureArrayUniforms, + }, }; -use bevy::ecs::prelude::*; -use bevy::ecs::query::QueryItem; -use bevy::render::render_graph::{NodeRunError, RenderGraphContext, ViewNode}; -use bevy::render::render_resource::{ - LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, RenderPassDescriptor, - StoreOp, +use bevy::{ + ecs::prelude::*, + ecs::query::QueryItem, + render::{ + render_graph::{NodeRunError, RenderGraphContext, ViewNode}, + render_resource::{ + LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, + RenderPassDescriptor, StoreOp, + }, + renderer::RenderContext, + view::{ViewDepthTexture, ViewTarget}, + }, }; -use bevy::render::renderer::RenderContext; -use bevy::render::view::{ViewDepthTexture, ViewTarget}; #[derive(Default)] pub struct OpaquePassRenderNode; diff --git a/crates/client/src/render/passes/skybox/pipeline.rs b/crates/client/src/render/passes/opaque/skybox.rs similarity index 93% rename from crates/client/src/render/passes/skybox/pipeline.rs rename to crates/client/src/render/passes/opaque/skybox.rs index 70827832..f36a7ae8 100644 --- a/crates/client/src/render/passes/skybox/pipeline.rs +++ b/crates/client/src/render/passes/opaque/skybox.rs @@ -9,19 +9,19 @@ use tracing::instrument; /// A key that uniquely identifies a specialized skybox pipeline. #[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub struct SkyboxPipelineKey { +pub struct OpaqueSkyboxPipelineKey { pub msaa_samples: u32, pub hdr: bool, } /// A resource that holds all the layouts and handles needed to specialize skybox pipelines. #[derive(Resource)] -pub struct SkyboxPipeline { +pub struct OpaqueSkyboxPipeline { pub view_layout: BindGroupLayoutDescriptor, pub environment_layout: BindGroupLayoutDescriptor, } -impl FromWorld for SkyboxPipeline { +impl FromWorld for OpaqueSkyboxPipeline { #[instrument(skip_all)] fn from_world(world: &mut World) -> Self { let view_layout = world.resource::(); @@ -34,8 +34,8 @@ impl FromWorld for SkyboxPipeline { } } -impl SpecializedRenderPipeline for SkyboxPipeline { - type Key = SkyboxPipelineKey; +impl SpecializedRenderPipeline for OpaqueSkyboxPipeline { + type Key = OpaqueSkyboxPipelineKey; fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor { let format = if key.hdr { diff --git a/crates/client/src/render/passes/skybox/mod.rs b/crates/client/src/render/passes/skybox/mod.rs deleted file mode 100644 index b05808d4..00000000 --- a/crates/client/src/render/passes/skybox/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -pub mod pipeline; - -pub use pipeline::{SkyboxPipeline, SkyboxPipelineKey}; - -use bevy::app::{App, Plugin}; -use bevy::render::render_resource::SpecializedRenderPipelines; - -pub struct SkyboxRenderPassPlugin; - -impl Plugin for SkyboxRenderPassPlugin { - fn build(&self, _app: &mut App) {} - - fn finish(&self, app: &mut App) { - app.init_resource::(); - app.init_resource::>(); - } -} From a55a01da9d4056d9f1c5c91d67cf8a54c6d26bdd Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 01:03:35 +0000 Subject: [PATCH 010/106] moving extract resources to live by their resource init --- crates/client/src/input/mod.rs | 2 ++ crates/client/src/render/mod.rs | 9 ++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/client/src/input/mod.rs b/crates/client/src/input/mod.rs index b8485121..938876e9 100644 --- a/crates/client/src/input/mod.rs +++ b/crates/client/src/input/mod.rs @@ -11,6 +11,7 @@ use crate::input::systems::{ }; use bevy::app::{App, Plugin, PreUpdate, Update}; use bevy::ecs::{schedule::IntoScheduleConfigs, system::Res}; +use bevy::render::extract_resource::ExtractResourcePlugin; use shared::simulation::input::resources::{ ActionStateResource, CursorMovement, InputActionMapResource, }; @@ -61,6 +62,7 @@ impl Plugin for InputModulePlugin { // toggle chunk borders app.insert_resource(ChunkBoundsToggle::default()) + .add_plugins(ExtractResourcePlugin::::default()) .add_systems( Update, toggle_chunk_borders_system.run_if(|action_state: Res| { diff --git a/crates/client/src/render/mod.rs b/crates/client/src/render/mod.rs index c07f7d05..6f109ca4 100644 --- a/crates/client/src/render/mod.rs +++ b/crates/client/src/render/mod.rs @@ -20,8 +20,8 @@ use crate::prelude::*; use crate::render::{ chunk::{OpaqueMeshComponent, TransparentMeshComponent}, passes::{ - RenderGraphEdgesPlugin, WorldRenderPassesPlugin, opaque::extract::extract_opaque_meshes, - transparent::extract::extract_transparent_meshes, + opaque::extract::extract_opaque_meshes, transparent::extract::extract_transparent_meshes, + RenderGraphEdgesPlugin, WorldRenderPassesPlugin, }, texture::BlockTextureArray, }; @@ -29,8 +29,8 @@ use bevy::{ app::{App, Plugin, SubApp}, prelude::{Add, Commands, On}, render::{ - ExtractSchedule, RenderApp, extract_resource::ExtractResourcePlugin, - sync_world::SyncToRenderWorld, + extract_resource::ExtractResourcePlugin, sync_world::SyncToRenderWorld, ExtractSchedule, + RenderApp, }, }; use shared::simulation::block::TargetedBlock; @@ -52,7 +52,6 @@ impl Plugin for VantablockRenderPlugin { ExtractResourcePlugin::::default(), ExtractResourcePlugin::::default(), ExtractResourcePlugin::::default(), - ExtractResourcePlugin::::default(), )); // INFO: ------------------------------------ From 0f2aa5635bd98ef7a6f44d1098c3898e1a08d5dd Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 01:35:48 +0000 Subject: [PATCH 011/106] add lightyear workspace dep --- Cargo.lock | 2656 ++++++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + crates/client/Cargo.toml | 1 + crates/server/Cargo.toml | 1 + crates/shared/Cargo.toml | 1 + 5 files changed, 2525 insertions(+), 135 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 065794bb..5164ea6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,10 @@ name = "accesskit" version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf203f9d3bd8f29f98833d1fbef628df18f759248a547e7e01cfbf63cda36a99" +dependencies = [ + "enumn", + "serde", +] [[package]] name = "accesskit_consumer" @@ -81,6 +85,109 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aeronet_io" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d50ca460ea143f90a3c1ecf36709b9cbb49752d5ddfbf2d67623b465fbfb81" +dependencies = [ + "anyhow", + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bytes", + "derive_more", + "log", +] + +[[package]] +name = "aeronet_steam" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c9fea14c3de9d1f8c4cb7bdd8be3e304ae4a45be9f3a8c02008b033165df976" +dependencies = [ + "aeronet_io", + "anyhow", + "bevy_app", + "bevy_ecs", + "bevy_platform", + "blocking", + "bytes", + "derive_more", + "oneshot", + "steamworks", + "sync_wrapper", + "tracing", +] + +[[package]] +name = "aeronet_websocket" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab40ded6412a153f6e189620251f44cb74dc43a218eddea9f4fe4ba55a72e763" +dependencies = [ + "aeronet_io", + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bytes", + "cfg-if", + "derive_more", + "futures", + "js-sys", + "rcgen", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", + "tokio-tungstenite", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "aeronet_webtransport" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4243f8320cca7bf4ce0e1e41aea4553007279685e181e3d566325260a49822" +dependencies = [ + "aeronet_io", + "base64", + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bytes", + "cfg-if", + "derive_more", + "futures", + "gloo-timers", + "js-sys", + "spki", + "tokio", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "wtransport", + "x509-cert", + "xwt-core", + "xwt-web", + "xwt-wtransport", +] + [[package]] name = "ahash" version = "0.8.12" @@ -103,6 +210,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "alsa" version = "0.9.1" @@ -239,6 +352,45 @@ dependencies = [ "libloading", ] +[[package]] +name = "asn1-rs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "assert_type_match" version = "0.1.1" @@ -362,12 +514,103 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "avian2d" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "060ae40aced85ed01296f556ed1909fcafe81a5e5059889bed126339ccd55b43" +dependencies = [ + "approx", + "arrayvec", + "avian_derive", + "bevy", + "bevy_heavy", + "bevy_math", + "bevy_transform_interpolation", + "bitflags 2.11.0", + "derive_more", + "disqualified", + "glam_matrix_extras", + "itertools 0.13.0", + "slab", + "smallvec", + "thiserror 2.0.18", +] + +[[package]] +name = "avian3d" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b82608b43397affac139547dfa9beb3208034c53e1a3cfe5d4079db1af362104" +dependencies = [ + "approx", + "avian_derive", + "bevy", + "bevy_heavy", + "bevy_math", + "bevy_transform_interpolation", + "bitflags 2.11.0", + "derive_more", + "disqualified", + "glam_matrix_extras", + "itertools 0.13.0", + "slab", + "smallvec", + "thiserror 2.0.18", +] + +[[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 = "aws-lc-rs" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a25cf98105baa966497416dbd42565ce3a8cf8dbfd59803ec9ad46f3126399" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "az" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7" + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "beef" version = "0.5.2" @@ -394,6 +637,7 @@ dependencies = [ "bevy_derive", "bevy_ecs", "bevy_reflect", + "serde", ] [[package]] @@ -748,6 +992,32 @@ dependencies = [ "encase_derive_impl", ] +[[package]] +name = "bevy_enhanced_input" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e4981e85546349e7ccce7e68aaf9c36e6eed556f7f29087dee184ee7941fb9" +dependencies = [ + "bevy", + "bevy_enhanced_input_macros", + "bitflags 2.11.0", + "log", + "serde", + "smallvec", + "variadics_please", +] + +[[package]] +name = "bevy_enhanced_input_macros" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4680cc23f335f1b768caf91a94b1aa1d786149788644043fe8d49e5708b5cbcc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bevy_feathers" version = "0.18.1" @@ -886,6 +1156,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "bevy_heavy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc496d1d43b890896cf561d8ce3dcf7b7b8e4c03c4e837a49a83a530abccbc5e" +dependencies = [ + "bevy_math", + "bevy_reflect", + "glam_matrix_extras", +] + [[package]] name = "bevy_image" version = "0.18.1" @@ -928,6 +1209,7 @@ dependencies = [ "bevy_reflect", "derive_more", "log", + "serde", "smol_str", "thiserror 2.0.18", ] @@ -1093,6 +1375,7 @@ dependencies = [ "bytemuck", "derive_more", "hexasphere", + "serde", "thiserror 2.0.18", "tracing", "wgpu-types", @@ -1524,6 +1807,15 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "bevy_transform_interpolation" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88545c8b0fa8f3502b9a439c71fa6b596ee9e808bfb16f27a51c8c6f7405a657" +dependencies = [ + "bevy", +] + [[package]] name = "bevy_ui" version = "0.18.1" @@ -1551,6 +1843,7 @@ dependencies = [ "bevy_utils", "bevy_window", "derive_more", + "serde", "smallvec", "taffy", "thiserror 2.0.18", @@ -1673,6 +1966,16 @@ dependencies = [ "winit", ] +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "serde", + "unty", +] + [[package]] name = "bindgen" version = "0.72.1" @@ -1825,6 +2128,10 @@ name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "portable-atomic", + "serde", +] [[package]] name = "calloop" @@ -1897,6 +2204,43 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures 0.2.17", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link 0.2.1", +] + [[package]] name = "ciborium" version = "0.2.2" @@ -1924,6 +2268,17 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + [[package]] name = "clang-sys" version = "1.8.1" @@ -1960,6 +2315,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "codespan-reporting" version = "0.12.0" @@ -2007,6 +2371,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "const_panic" version = "0.2.15" @@ -2321,6 +2691,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] @@ -2342,17 +2713,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" [[package]] -name = "dasp_sample" -version = "0.11.0" +name = "dashmap" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - -[[package]] +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + +[[package]] name = "data-encoding" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "der_derive", + "flagset", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "deranged" version = "0.5.8" @@ -2434,6 +2857,17 @@ dependencies = [ "objc2 0.6.4", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "disqualified" version = "1.0.0" @@ -2476,6 +2910,30 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "dyn-eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2d035d21af5cde1a6f5c7b444a5bf963520a9f142e5d06931178433d7d5388" + +[[package]] +name = "dyn-hash" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fdab65db9274e0168143841eb8f864a0a21f8b1b8d2ba6812bbe6024346e99e" + [[package]] name = "either" version = "1.15.0" @@ -2522,6 +2980,35 @@ dependencies = [ "syn", ] +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "enumn" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -2609,12 +3096,31 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "fixed" +version = "1.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c566da967934c6c7ee0458a9773de9b2a685bd2ce26a3b28ddfc740e640182f5" +dependencies = [ + "az", + "bytemuck", + "half", + "serde", + "typenum", +] + [[package]] name = "fixedbitset" version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" +[[package]] +name = "flagset" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" + [[package]] name = "flate2" version = "1.1.9" @@ -2711,6 +3217,21 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -2720,6 +3241,21 @@ dependencies = [ "libc", ] +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.32" @@ -2727,6 +3263,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -2735,6 +3272,17 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.32" @@ -2765,21 +3313,37 @@ dependencies = [ "syn", ] +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + [[package]] name = "futures-task" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ + "futures-channel", "futures-core", + "futures-io", "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "slab", ] @@ -2826,8 +3390,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -2837,9 +3403,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 5.3.0", "wasip2", + "wasm-bindgen", ] [[package]] @@ -2906,6 +3474,7 @@ version = "0.30.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19fc433e8437a212d1b6f1e68c7824af3aed907da60afa994e7f542d18d12aa9" dependencies = [ + "approx", "bytemuck", "encase", "libm", @@ -2913,12 +3482,34 @@ dependencies = [ "serde_core", ] +[[package]] +name = "glam_matrix_extras" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4664468a60479272b880a8bfc00ad2915229b93d2b2d585556fb33f9ba80e72" +dependencies = [ + "bevy_reflect", + "glam", +] + [[package]] name = "glob" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "glow" version = "0.16.0" @@ -2976,6 +3567,29 @@ dependencies = [ "gl_generator", ] +[[package]] +name = "governor" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9efcab3c1958580ff1f25a2a41be1668f7603d849bb63af523b208a3cc1223b8" +dependencies = [ + "cfg-if", + "dashmap", + "futures-sink", + "futures-timer", + "futures-util", + "getrandom 0.3.4", + "hashbrown 0.16.1", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand 0.9.2", + "smallvec", + "spinning_top", + "web-time", +] + [[package]] name = "gpu-alloc" version = "0.6.0" @@ -3077,6 +3691,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hashbrown" version = "0.15.5" @@ -3092,6 +3712,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ + "allocator-api2", "equivalent", "foldhash 0.2.0", "serde", @@ -3139,114 +3760,272 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - -[[package]] -name = "image" -version = "0.25.10" +name = "httlib-huffman" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" -dependencies = [ - "bytemuck", - "byteorder-lite", - "moxcms", - "num-traits", - "png", -] +checksum = "1a9fcbcc408c5526c3ab80d534e5c86e7967c1fb7aa0a8c76abd1edc27deb877" [[package]] -name = "indexmap" -version = "2.13.1" +name = "http" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ - "equivalent", - "hashbrown 0.16.1", - "serde", - "serde_core", + "bytes", + "itoa", ] [[package]] -name = "inflections" -version = "1.1.1" +name = "httparse" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] -name = "inotify" -version = "0.11.1" +name = "iana-time-zone" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ - "bitflags 2.11.0", - "inotify-sys", - "libc", + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", ] [[package]] -name = "inotify-sys" -version = "0.1.5" +name = "iana-time-zone-haiku" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "libc", + "cc", ] [[package]] -name = "inventory" -version = "0.3.24" +name = "icu_collections" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ - "rustversion", + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "is-terminal" -version = "0.4.17" +name = "icu_locale_core" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.61.2", + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", ] [[package]] -name = "itertools" -version = "0.10.5" +name = "icu_normalizer" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ - "either", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", ] [[package]] -name = "itertools" -version = "0.13.0" +name = "icu_normalizer_data" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] -name = "itertools" -version = "0.14.0" +name = "icu_properties" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "either", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", ] [[package]] -name = "itoa" -version = "1.0.18" +name = "icu_properties_data" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png", +] + +[[package]] +name = "indexmap" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "inflections" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" + +[[package]] +name = "inotify" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" +dependencies = [ + "bitflags 2.11.0", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + +[[package]] +name = "inventory" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +dependencies = [ + "rustversion", +] + +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" @@ -3436,6 +4215,34 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leafwing-input-manager" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed83d1d7334e742aab3409782cdbb2bc96cc017df9ff342dd5aeb80eed1b784" +dependencies = [ + "bevy", + "dyn-clone", + "dyn-eq", + "dyn-hash", + "itertools 0.14.0", + "leafwing_input_manager_macros", + "serde", + "serde_flexitos", +] + +[[package]] +name = "leafwing_input_manager_macros" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2226cb83129176a6c634f2ce0828c2c29896ea0898fc198636f98696b8056890" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "leb128fmt" version = "0.1.0" @@ -3443,113 +4250,743 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] -name = "lexical" -version = "7.0.5" +name = "lexical" +version = "7.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc8a009b2ff1f419ccc62706f04fe0ca6e67b37460513964a3dfdb919bb37d6" +dependencies = [ + "lexical-core", +] + +[[package]] +name = "lexical-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d8d125a277f807e55a77304455eb7b1cb52f2b18c143b60e766c120bd64a594" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a9f232fbd6f550bc0137dcb5f99ab674071ac2d690ac69704593cb4abbea56" +dependencies = [ + "lexical-parse-integer", + "lexical-util", +] + +[[package]] +name = "lexical-parse-integer" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a7a039f8fb9c19c996cd7b2fcce303c1b2874fe1aca544edc85c4a5f8489b34" +dependencies = [ + "lexical-util", +] + +[[package]] +name = "lexical-util" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2604dd126bb14f13fb5d1bd6a66155079cb9fa655b37f875b3a742c705dbed17" + +[[package]] +name = "lexical-write-float" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c438c87c013188d415fbabbb1dceb44249ab81664efbd31b14ae55dabb6361" +dependencies = [ + "lexical-util", + "lexical-write-integer", +] + +[[package]] +name = "lexical-write-integer" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "409851a618475d2d5796377cad353802345cba92c867d9fbcde9cf4eac4e14df" +dependencies = [ + "lexical-util", +] + +[[package]] +name = "libc" +version = "0.2.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +dependencies = [ + "bitflags 2.11.0", + "libc", + "plain", + "redox_syscall 0.7.3", +] + +[[package]] +name = "libudev-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "lightyear" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be51d4b8fe01a81efe7b0e53f1d5577719a507ca3bbd40cadcbf3ccaea82030d" +dependencies = [ + "aeronet_io", + "bevy_app", + "bevy_ecs", + "console_error_panic_hook", + "document-features", + "lightyear_aeronet", + "lightyear_avian2d", + "lightyear_avian3d", + "lightyear_connection", + "lightyear_core", + "lightyear_frame_interpolation", + "lightyear_inputs", + "lightyear_inputs_bei", + "lightyear_inputs_leafwing", + "lightyear_inputs_native", + "lightyear_interpolation", + "lightyear_link", + "lightyear_messages", + "lightyear_metrics", + "lightyear_netcode", + "lightyear_prediction", + "lightyear_raw_connection", + "lightyear_replication", + "lightyear_serde", + "lightyear_steam", + "lightyear_sync", + "lightyear_transport", + "lightyear_udp", + "lightyear_ui", + "lightyear_utils", + "lightyear_web", + "lightyear_websocket", + "lightyear_webtransport", + "serde", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "lightyear_aeronet" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a8e7f2b66a63bba410403708bf9c98a7c8e0834a0a069db010e63e669e6735b" +dependencies = [ + "aeronet_io", + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "lightyear_core", + "lightyear_link", + "tracing", +] + +[[package]] +name = "lightyear_avian2d" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3229fb076a2750bcf41037c6af553a8cb1dc59e3cdd1f7c8e0d6ae7cd855dc03" +dependencies = [ + "avian2d", + "bevy_app", + "bevy_ecs", + "bevy_math", + "bevy_time", + "bevy_transform", + "bevy_utils", + "lightyear_core", + "lightyear_frame_interpolation", + "lightyear_interpolation", + "lightyear_link", + "lightyear_prediction", + "lightyear_replication", + "tracing", +] + +[[package]] +name = "lightyear_avian3d" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca582724703dccafe64991bbe0d480e616de7e1056b07cd9c6862a48196b9ce0" +dependencies = [ + "avian3d", + "bevy_app", + "bevy_ecs", + "bevy_math", + "bevy_time", + "bevy_transform", + "bevy_utils", + "lightyear_core", + "lightyear_frame_interpolation", + "lightyear_interpolation", + "lightyear_link", + "lightyear_prediction", + "lightyear_replication", + "tracing", +] + +[[package]] +name = "lightyear_connection" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad7fa5c7b928074895a56e96d0154e78cbc4e751f37e1a9b0b5fda469eb28c74" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bytes", + "lightyear_core", + "lightyear_link", + "lightyear_serde", + "serde", + "smallvec", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "lightyear_core" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a310d13cb0059fd20f59ec60b24056403ffc2388daabbc663c8eb1d4a08ddf4" +dependencies = [ + "bevy_app", + "bevy_derive", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_time", + "chrono", + "fixed", + "lightyear_serde", + "lightyear_utils", + "serde", + "tracing", +] + +[[package]] +name = "lightyear_frame_interpolation" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66ce32814bfcd07d1b694443dd988d3e842976e87223ec48fc18283e8e0046ab" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "bevy_time", + "bevy_transform", + "bevy_utils", + "lightyear_connection", + "lightyear_core", + "lightyear_interpolation", + "lightyear_replication", + "serde", + "tracing", +] + +[[package]] +name = "lightyear_inputs" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4bbfad8e59fbd0d569a2e359be47a7a1b28fc8e494ae124eb2b5efbec54b8e2" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_utils", + "lightyear_connection", + "lightyear_core", + "lightyear_interpolation", + "lightyear_link", + "lightyear_messages", + "lightyear_prediction", + "lightyear_replication", + "lightyear_sync", + "lightyear_transport", + "serde", + "tracing", +] + +[[package]] +name = "lightyear_inputs_bei" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2266633e2eeebfe5fcd5d3cea8984bc26b24b13942fd9c1aa9123da4de6c1a02" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_enhanced_input", + "bevy_reflect", + "bevy_utils", + "lightyear_connection", + "lightyear_core", + "lightyear_inputs", + "lightyear_link", + "lightyear_messages", + "lightyear_replication", + "lightyear_serde", + "serde", + "tracing", +] + +[[package]] +name = "lightyear_inputs_leafwing" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2cfbd794d8a42f06796acc6b8d4274d3fb53cd58f480881d2dd59176f076e49" +dependencies = [ + "bevy_app", + "bevy_derive", + "bevy_ecs", + "bevy_input", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "bevy_utils", + "leafwing-input-manager", + "lightyear_core", + "lightyear_inputs", + "serde", + "tracing", +] + +[[package]] +name = "lightyear_inputs_native" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c992924e07b463528f34987fbd6b2248f37a66cfd41757dd9b9f8b5085765cdc" +dependencies = [ + "bevy_app", + "bevy_derive", + "bevy_ecs", + "bevy_reflect", + "lightyear_core", + "lightyear_inputs", + "serde", + "tracing", +] + +[[package]] +name = "lightyear_interpolation" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4545cb52f0232da161dd93836e5b4f23816850330ef322ba6bd3abba2a20f21" +dependencies = [ + "bevy_app", + "bevy_derive", + "bevy_ecs", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "bevy_time", + "bevy_utils", + "lightyear_connection", + "lightyear_core", + "lightyear_messages", + "lightyear_replication", + "lightyear_serde", + "lightyear_sync", + "lightyear_utils", + "serde", + "tracing", +] + +[[package]] +name = "lightyear_link" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ede74a86374f21606be56aaf1c1bf9dd333f473866bd780ab449653f0caca24" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "bevy_utils", + "bytes", + "lightyear_core", + "lightyear_utils", + "rand 0.9.2", + "tracing", +] + +[[package]] +name = "lightyear_messages" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1141fb3d9895f5c9e8aa5d723d9b9bf9db800fd044ba8c8b542ac660beeab47" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "bevy_utils", + "bytes", + "lightyear_connection", + "lightyear_core", + "lightyear_link", + "lightyear_serde", + "lightyear_transport", + "lightyear_utils", + "serde", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "lightyear_metrics" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d3264ac1729043c949bf2c9526bfa712a1c7e683e4e0034ce7cac0f233c19db" +dependencies = [ + "bevy_app", + "bevy_color", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_text", + "bevy_time", + "bevy_ui", + "bevy_utils", + "metrics", + "metrics-util", + "tracing", +] + +[[package]] +name = "lightyear_netcode" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db834d08f6826a2c25c9a355a33bb0db036da2da98b5f43b3982e6b5c41a0f4e" +dependencies = [ + "aeronet_io", + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "bevy_time", + "bytes", + "chacha20poly1305", + "lightyear_connection", + "lightyear_core", + "lightyear_link", + "lightyear_serde", + "lightyear_transport", + "lightyear_utils", + "no_std_io2", + "rand 0.9.2", + "thiserror 2.0.18", + "tracing", + "web-time", +] + +[[package]] +name = "lightyear_prediction" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ddda7d875590a2f91c082dd339507b79eb3221661f50fca18e6c2fdafbcc6c" +dependencies = [ + "bevy_app", + "bevy_derive", + "bevy_diagnostic", + "bevy_ecs", + "bevy_math", + "bevy_platform", + "bevy_reflect", + "bevy_time", + "bevy_utils", + "lightyear_connection", + "lightyear_core", + "lightyear_frame_interpolation", + "lightyear_interpolation", + "lightyear_messages", + "lightyear_replication", + "lightyear_sync", + "lightyear_utils", + "parking_lot", + "seahash", + "serde", + "tracing", +] + +[[package]] +name = "lightyear_raw_connection" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "631b5527b4f11d1e199f823ecdcd02585136fc55dd3261d5280e03bbcc29cdd3" +dependencies = [ + "aeronet_io", + "bevy_app", + "bevy_ecs", + "lightyear_connection", + "lightyear_core", + "lightyear_link", + "lightyear_transport", + "tracing", +] + +[[package]] +name = "lightyear_replication" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a451536b73e618035472548e8d7f1af51e193649f556318f7836ddc70e6f73d2" +dependencies = [ + "avian2d", + "avian3d", + "bevy_app", + "bevy_derive", + "bevy_ecs", + "bevy_math", + "bevy_platform", + "bevy_ptr", + "bevy_reflect", + "bevy_time", + "bevy_transform", + "bevy_utils", + "bytes", + "dashmap", + "indexmap", + "lightyear_connection", + "lightyear_core", + "lightyear_link", + "lightyear_messages", + "lightyear_serde", + "lightyear_sync", + "lightyear_transport", + "lightyear_utils", + "seahash", + "serde", + "smallvec", + "thiserror 2.0.18", + "tracing", +] + +[[package]] +name = "lightyear_serde" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc8a009b2ff1f419ccc62706f04fe0ca6e67b37460513964a3dfdb919bb37d6" +checksum = "6c00dfe55ea4ba8413424616564b36c64d404fe9f5c68e4d71c4a97193da3d6e" dependencies = [ - "lexical-core", + "bevy_derive", + "bevy_ecs", + "bevy_platform", + "bevy_ptr", + "bevy_reflect", + "bevy_utils", + "bincode", + "bytes", + "no_std_io2", + "serde", + "thiserror 2.0.18", + "tracing", + "variadics_please", ] [[package]] -name = "lexical-core" -version = "1.0.6" +name = "lightyear_steam" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d8d125a277f807e55a77304455eb7b1cb52f2b18c143b60e766c120bd64a594" +checksum = "02b513c7aaeeaee3fbfe82e4ab7698cc3360d42526d167054af357920a166566" dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", + "aeronet_io", + "aeronet_steam", + "bevy_app", + "bevy_ecs", + "lightyear_aeronet", + "lightyear_connection", + "lightyear_core", + "lightyear_link", + "thiserror 2.0.18", + "tracing", ] [[package]] -name = "lexical-parse-float" -version = "1.0.6" +name = "lightyear_sync" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a9f232fbd6f550bc0137dcb5f99ab674071ac2d690ac69704593cb4abbea56" +checksum = "834af4e025c9d7954c9684d82255e5ed639e0ce4482e3c674582687ce1f2dbfd" dependencies = [ - "lexical-parse-integer", - "lexical-util", + "bevy_app", + "bevy_derive", + "bevy_diagnostic", + "bevy_ecs", + "bevy_reflect", + "bevy_time", + "bevy_utils", + "lightyear_connection", + "lightyear_core", + "lightyear_link", + "lightyear_messages", + "lightyear_serde", + "lightyear_transport", + "lightyear_utils", + "serde", + "tracing", ] [[package]] -name = "lexical-parse-integer" -version = "1.0.6" +name = "lightyear_transport" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a7a039f8fb9c19c996cd7b2fcce303c1b2874fe1aca544edc85c4a5f8489b34" +checksum = "272b66fae233f66887cbef40c30d2a7673d299d327a9fdd2becbd3b2ae59336b" dependencies = [ - "lexical-util", + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_time", + "bevy_utils", + "bytes", + "crossbeam-channel", + "enum_dispatch", + "governor", + "indexmap", + "lightyear_connection", + "lightyear_core", + "lightyear_link", + "lightyear_serde", + "lightyear_utils", + "nonzero_ext", + "ringbuffer", + "serde", + "thiserror 2.0.18", + "tracing", ] [[package]] -name = "lexical-util" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2604dd126bb14f13fb5d1bd6a66155079cb9fa655b37f875b3a742c705dbed17" - -[[package]] -name = "lexical-write-float" -version = "1.0.6" +name = "lightyear_udp" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c438c87c013188d415fbabbb1dceb44249ab81664efbd31b14ae55dabb6361" +checksum = "367cdb2e11ac6448bec036a26ce1aa7a97a695e1a50a28e2d3d4e3f8ae34c670" dependencies = [ - "lexical-util", - "lexical-write-integer", + "aeronet_io", + "bevy_app", + "bevy_ecs", + "bevy_platform", + "bytes", + "lightyear_core", + "lightyear_link", + "thiserror 2.0.18", + "tracing", ] [[package]] -name = "lexical-write-integer" -version = "1.0.6" +name = "lightyear_ui" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "409851a618475d2d5796377cad353802345cba92c867d9fbcde9cf4eac4e14df" +checksum = "bd20cb05463553dd19006a2e318b86b2afb6db8e9e8e46931fc6592d8069e3c2" dependencies = [ - "lexical-util", + "bevy_app", + "bevy_color", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_text", + "bevy_time", + "bevy_ui", + "bevy_utils", + "lightyear_metrics", + "metrics", + "metrics-util", + "tracing", ] [[package]] -name = "libc" -version = "0.2.184" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" - -[[package]] -name = "libloading" -version = "0.8.9" +name = "lightyear_utils" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +checksum = "b9a54a63441f9001dc834fc8e6b4bb23eeb8f6b2ef28db8c65b4bfbf9496b139" dependencies = [ - "cfg-if", - "windows-link 0.2.1", + "bevy_ecs", + "bevy_platform", + "bevy_reflect", + "bevy_utils", + "hashbrown 0.16.1", + "paste", + "seahash", + "tracing", ] [[package]] -name = "libm" -version = "0.2.16" +name = "lightyear_web" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +checksum = "72450d46e6c5052c174e3723e14fd78726ffca7e00e64b6f9342cdd642621eb6" +dependencies = [ + "bevy_app", + "bevy_ecs", + "bevy_winit", + "wasm-bindgen", + "web-sys", +] [[package]] -name = "libredox" -version = "0.1.15" +name = "lightyear_websocket" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "c3e5ee75b46e0be8f9e746f1b53464376715d400fbddb4a3faf8fb348eec2919" dependencies = [ - "bitflags 2.11.0", - "libc", - "plain", - "redox_syscall 0.7.3", + "aeronet_io", + "aeronet_websocket", + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "lightyear_aeronet", + "lightyear_link", + "thiserror 2.0.18", + "tracing", ] [[package]] -name = "libudev-sys" -version = "0.1.4" +name = "lightyear_webtransport" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +checksum = "8c100a3f88ced77327f04ab3e583ecca627e53d93031c5aaf7c2260d6c9faf25" dependencies = [ - "libc", - "pkg-config", + "aeronet_io", + "aeronet_webtransport", + "bevy_app", + "bevy_ecs", + "bevy_reflect", + "lightyear_aeronet", + "lightyear_link", + "thiserror 2.0.18", + "tracing", ] [[package]] @@ -3570,6 +5007,12 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + [[package]] name = "litrs" version = "1.0.0" @@ -3638,6 +5081,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "mach2" version = "0.4.3" @@ -3695,6 +5144,36 @@ dependencies = [ "paste", ] +[[package]] +name = "metrics" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5312e9ba3771cfa961b585728215e3d972c950a3eed9252aa093d6301277e8" +dependencies = [ + "ahash", + "portable-atomic", +] + +[[package]] +name = "metrics-util" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdfb1365fea27e6dd9dc1dbc19f570198bc86914533ad639dae939635f096be4" +dependencies = [ + "aho-corasick", + "crossbeam-epoch", + "crossbeam-utils", + "hashbrown 0.16.1", + "indexmap", + "metrics", + "ordered-float", + "quanta", + "radix_trie", + "rand 0.9.2", + "rand_xoshiro", + "sketches-ddsketch", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3836,6 +5315,15 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + [[package]] name = "nix" version = "0.30.1" @@ -3860,6 +5348,15 @@ dependencies = [ "libc", ] +[[package]] +name = "no_std_io2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b51ed7824b6e07d354605f4abb3d9d300350701299da96642ee084f5ce631550" +dependencies = [ + "memchr", +] + [[package]] name = "noise" version = "0.9.0" @@ -3887,6 +5384,12 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + [[package]] name = "notify" version = "8.2.0" @@ -3945,6 +5448,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-conv" version = "0.2.1" @@ -3962,6 +5475,15 @@ dependencies = [ "syn", ] +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -4267,6 +5789,12 @@ dependencies = [ "cc", ] +[[package]] +name = "octets" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8311fa8ab7a57759b4ff1f851a3048d9ef0effaa0130726426b742d26d8a88e7" + [[package]] name = "offset-allocator" version = "0.2.0" @@ -4277,18 +5805,45 @@ dependencies = [ "nonmax", ] +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "oneshot" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "269bca4c2591a28585d6bf10d9ed0332b7d76900a1b02bec41bdc3a2cdcda107" + [[package]] name = "oorandom" version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "option-ext" version = "0.2.0" @@ -4358,6 +5913,31 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64", + "serde_core", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -4500,6 +6080,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures 0.2.17", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.13.1" @@ -4512,7 +6103,16 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" dependencies = [ - "portable-atomic", + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", ] [[package]] @@ -4570,6 +6170,28 @@ dependencies = [ "toml_edit 0.25.11+spec-1.1.0", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -4591,6 +6213,21 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" +[[package]] +name = "quanta" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + [[package]] name = "quick-xml" version = "0.39.2" @@ -4600,6 +6237,61 @@ dependencies = [ "memchr", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.2", + "rustls", + "socket2 0.6.3", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash 2.1.2", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.3", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.45" @@ -4621,6 +6313,16 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + [[package]] name = "radsort" version = "0.1.1" @@ -4661,6 +6363,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] [[package]] name = "rand_core" @@ -4690,6 +6395,15 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core 0.9.5", +] + [[package]] name = "range-alloc" version = "0.1.5" @@ -4702,6 +6416,15 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -4728,6 +6451,19 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rcgen" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time", + "yasna", +] + [[package]] name = "read-fonts" version = "0.36.0" @@ -4828,6 +6564,26 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ringbuffer" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b0b88a509053cbfd535726dcaaceee631313cef981266119527a1d110f6d2b" + [[package]] name = "rodio" version = "0.20.1" @@ -4891,6 +6647,15 @@ dependencies = [ "semver", ] +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + [[package]] name = "rustix" version = "0.38.44" @@ -4917,6 +6682,65 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "rustls" +version = "0.23.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -4941,6 +6765,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -4966,6 +6799,35 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "self_cell" version = "1.2.2" @@ -5014,6 +6876,16 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_flexitos" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3323d093d7597660758b742dd7a1525539613f6182b306a4e1dd6e01a89bada9" +dependencies = [ + "erased-serde", + "serde", +] + [[package]] name = "serde_json" version = "1.0.149" @@ -5027,6 +6899,28 @@ dependencies = [ "zmij", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + [[package]] name = "sha3" version = "0.10.8" @@ -5080,6 +6974,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +[[package]] +name = "sketches-ddsketch" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6f73aeb92d671e0cc4dca167e59b2deb6387c375391bc99ee743f326994a2b" + [[package]] name = "skrifa" version = "0.39.0" @@ -5120,6 +7020,9 @@ name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] [[package]] name = "smithay-client-toolkit" @@ -5155,6 +7058,26 @@ dependencies = [ "serde", ] +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "spin" version = "0.10.0" @@ -5164,6 +7087,15 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" @@ -5173,6 +7105,17 @@ dependencies = [ "bitflags 2.11.0", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", + "sha2", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -5194,6 +7137,24 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "steamworks" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "722f54c70818b8debdc25b18618b77a0a69fa280012c29e7904d32f9136299fc" +dependencies = [ + "bitflags 2.11.0", + "paste", + "steamworks-sys", + "thiserror 2.0.18", +] + +[[package]] +name = "steamworks-sys" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42862065c9e685d08cc3d9f6c609d4b46bd9684ec7e9420688eb979213469582" + [[package]] name = "strict-num" version = "0.1.1" @@ -5212,6 +7173,12 @@ dependencies = [ "precomputed-hash", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "svg_fmt" version = "0.4.5" @@ -5230,14 +7197,31 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.117" +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + +[[package]] +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "unicode-ident", + "syn", ] [[package]] @@ -5400,6 +7384,16 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -5425,6 +7419,79 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tls_codec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio" +version = "1.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2 0.6.3", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" +dependencies = [ + "futures-util", + "log", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tungstenite", +] + [[package]] name = "tokrepr" version = "0.1.1" @@ -5625,6 +7692,25 @@ dependencies = [ "core_maths", ] +[[package]] +name = "tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.2", + "rustls", + "rustls-pki-types", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + [[package]] name = "twox-hash" version = "2.1.2" @@ -5691,6 +7777,52 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" version = "1.23.0" @@ -5722,6 +7854,7 @@ dependencies = [ "futures-lite", "glob", "image", + "lightyear", "noise", "offset-allocator", "rand 0.9.2", @@ -5743,6 +7876,7 @@ name = "vantablock-server" version = "0.0.1" dependencies = [ "bevy", + "lightyear", "tracing", "tracing-subscriber", "vantablock-shared", @@ -5758,6 +7892,7 @@ dependencies = [ "crossbeam", "derive_more", "futures-lite", + "lightyear", "noise", "rand 0.9.2", "ron 0.11.0", @@ -6044,6 +8179,31 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-sys-async-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65a1ea96a932ec2252276bc517eb4fccaebc0ecfea2faa49e242de769d188409" +dependencies = [ + "js-sys", + "tokio", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys-stream-utils" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90a913a6d558dbf153010d8add2f27bf5964427aa395299b57a7680a5e971cc7" +dependencies = [ + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-time" version = "1.1.0" @@ -6054,6 +8214,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-wt-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2793e7e95a0f1564bf1e029e4f8ff397b95998fe03fa7f9dd72682f127473c68" +dependencies = [ + "js-sys", + "pastey", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wesl" version = "0.2.0" @@ -6962,6 +9135,49 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "wtransport" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e5e745c8789c20095c9061d292098d4106660efe2d172efd8ae7a369fe28e3e" +dependencies = [ + "bytes", + "pem", + "quinn", + "rcgen", + "rustls", + "rustls-native-certs", + "rustls-pemfile", + "rustls-pki-types", + "sha2", + "socket2 0.5.10", + "thiserror 2.0.18", + "time", + "tokio", + "tracing", + "url", + "wtransport-proto", + "x509-parser", +] + +[[package]] +name = "wtransport-proto" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a09d89a8dba201c2439d9d5eca55a0faa08909d69da50decdb5ec00be0ac504" +dependencies = [ + "httlib-huffman", + "octets", + "thiserror 2.0.18", + "url", +] + [[package]] name = "x11-dl" version = "2.21.0" @@ -6994,6 +9210,35 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" +[[package]] +name = "x509-cert" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" +dependencies = [ + "const-oid", + "der", + "spki", + "tls_codec", +] + +[[package]] +name = "x509-parser" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + [[package]] name = "xcursor" version = "0.3.10" @@ -7025,12 +9270,79 @@ version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" +[[package]] +name = "xwt-core" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "647e17b66bd49bfebe8fe73d327358432f298bb41227600f47fb07fa4f7c1eef" + +[[package]] +name = "xwt-web" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f80997b90d89451537f2866130f52b1e4be4d29cfadf9183081b24542f1abdf0" +dependencies = [ + "js-sys", + "thiserror 2.0.18", + "tokio", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-sys-async-io", + "web-sys-stream-utils", + "web-wt-sys", + "xwt-core", +] + +[[package]] +name = "xwt-wtransport" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8623c2ddff8a7321feb12b484094be0341a9203dc46eb4060fc2e852841d8786" +dependencies = [ + "thiserror 2.0.18", + "wtransport", + "xwt-core", +] + +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + [[package]] name = "yazi" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zeno" version = "0.3.3" @@ -7057,6 +9369,80 @@ dependencies = [ "syn", ] +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zmij" version = "1.0.21" diff --git a/Cargo.toml b/Cargo.toml index 44837a4e..5b023c98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,6 +72,7 @@ bevy = { version = "0.18.1", default-features = false, features = [ "bevy_asset", "bevy_state", ] } +lightyear = "0.26.4" futures-lite = "2.6.1" # future utils # util deps diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 001ef2eb..49ae2c71 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -75,6 +75,7 @@ offset-allocator = { workspace = true } # gpu buffer allocation # -------------------------------- bevy = { workspace = true } +lightyear = { workspace = true } futures-lite = { workspace = true } # future utils # INFO: --------------- diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml index 23cc330a..8316b045 100644 --- a/crates/server/Cargo.toml +++ b/crates/server/Cargo.toml @@ -32,3 +32,4 @@ tracing-subscriber = { workspace = true } # -------------------------------- bevy = { workspace = true } +lightyear = { workspace = true } diff --git a/crates/shared/Cargo.toml b/crates/shared/Cargo.toml index d9f784ab..93532f4f 100644 --- a/crates/shared/Cargo.toml +++ b/crates/shared/Cargo.toml @@ -32,6 +32,7 @@ bytemuck = { workspace = true } # gpu friendly data # -------------------------------- bevy = { workspace = true } +lightyear = { workspace = true } futures-lite = { workspace = true } # future utils # INFO: --------------- From 7e8a4d4e425e90c859b7b766899d60cdcc219748 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 01:37:31 +0000 Subject: [PATCH 012/106] basic network protocl plugin --- crates/shared/src/lib.rs | 1 + crates/shared/src/protocol/client.rs | 2 +- crates/shared/src/protocol/mod.rs | 19 +++++++++++++++++++ crates/shared/src/protocol/server.rs | 2 +- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index a380c38a..49ba9122 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -20,6 +20,7 @@ impl PluginGroup for SharedPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() .add(state::SimulationLifecyclePlugin) + .add(protocol::NetworkProtoclPlugin) .add(simulation::asset::AssetPlugin) .add(simulation::biome::BiomePlugin) .add(simulation::block::BlockPlugin) diff --git a/crates/shared/src/protocol/client.rs b/crates/shared/src/protocol/client.rs index 145833d6..0f710f02 100644 --- a/crates/shared/src/protocol/client.rs +++ b/crates/shared/src/protocol/client.rs @@ -3,7 +3,7 @@ use crate::simulation::input::types::SimulationAction; use bevy::prelude::*; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Message, Serialize, Deserialize, Debug, Clone)] pub enum ClientMessage { /// A discrete input action performed by the player. Action(SimulationAction), diff --git a/crates/shared/src/protocol/mod.rs b/crates/shared/src/protocol/mod.rs index b15140c1..d9377ea6 100644 --- a/crates/shared/src/protocol/mod.rs +++ b/crates/shared/src/protocol/mod.rs @@ -3,3 +3,22 @@ pub mod server; pub use client::ClientMessage; pub use server::ServerMessage; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +use bevy::prelude::*; +use lightyear::prelude::{AppMessageExt, NetworkDirection}; + +pub struct NetworkProtoclPlugin; + +/// A plugin that defines the shared client-server networking protocols +impl Plugin for NetworkProtoclPlugin { + fn build(&self, app: &mut App) { + app.register_message::() + .add_direction(NetworkDirection::ClientToServer); + app.register_message::() + .add_direction(NetworkDirection::ServerToClient); + } +} diff --git a/crates/shared/src/protocol/server.rs b/crates/shared/src/protocol/server.rs index be03beac..b1a4b2e5 100644 --- a/crates/shared/src/protocol/server.rs +++ b/crates/shared/src/protocol/server.rs @@ -2,7 +2,7 @@ use crate::simulation::chunk::ChunkCoord; use bevy::prelude::*; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Message, Serialize, Deserialize, Debug, Clone)] pub enum ServerMessage { /// Initial state sent to the client upon joining. Welcome { entity_id: Entity, spawn_pos: Vec3 }, From 2cb4806b075689ec3690b4b71c9ce4b69d1bb40b Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 02:22:03 +0000 Subject: [PATCH 013/106] reduce fake work time --- crates/shared/src/load/systems/fake_work_system.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/shared/src/load/systems/fake_work_system.rs b/crates/shared/src/load/systems/fake_work_system.rs index f117899b..c33dddab 100644 --- a/crates/shared/src/load/systems/fake_work_system.rs +++ b/crates/shared/src/load/systems/fake_work_system.rs @@ -4,7 +4,7 @@ use crate::{ }; use bevy::ecs::system::Commands; use bevy::tasks::AsyncComputeTaskPool; -use crossbeam::channel::{Receiver, Sender, unbounded}; +use crossbeam::channel::{unbounded, Receiver, Sender}; use rand::random_range; use std::{thread, time::Duration}; @@ -16,14 +16,14 @@ pub fn start_fake_work_system(mut commands: Commands) { let entity = commands.spawn_empty().id(); AsyncComputeTaskPool::get() .spawn(async move { - const WORK_DURATION: u64 = 5; + const WORK_DURATION: u64 = 3; for i in 1..=WORK_DURATION { info!( "[BACKGROUND {}] Fake working... step {}/{}", entity, i, WORK_DURATION ); - let sleep_time = random_range(0.75..1.5); + let sleep_time = random_range(0.25..0.75); thread::sleep(Duration::from_secs_f32(sleep_time)); } info!("[BACKGROUND {}] Fake work finished!", entity); From 3c4e5e26f45fec23be1c800a4a26b10893f8cb3d Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 02:33:44 +0000 Subject: [PATCH 014/106] add bevy fps overlay --- crates/client/Cargo.toml | 2 +- crates/client/src/main.rs | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 49ae2c71..a419f3aa 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -29,7 +29,7 @@ name = "generation_benchmarks" harness = false [features] -dev = ["bevy/dev"] +dev = ["bevy/dev", "bevy/bevy_dev_tools"] tracy = ["dep:tracy-client", "dep:tracing-tracy"] distribution = ["tracing/release_max_level_error"] diff --git a/crates/client/src/main.rs b/crates/client/src/main.rs index 3840ddfa..0fb65c07 100644 --- a/crates/client/src/main.rs +++ b/crates/client/src/main.rs @@ -1,11 +1,14 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +#[cfg(feature = "dev")] +use bevy::dev_tools::fps_overlay::{FpsOverlayConfig, FpsOverlayPlugin}; + use bevy::{ app::{App, FixedUpdate, PostUpdate}, log::LogPlugin, prelude::{ - AssetPlugin, ClearColor, Color, DefaultPlugins, IntoScheduleConfigs, PluginGroup, Window, - WindowPlugin, default, info, + default, info, AssetPlugin, ClearColor, Color, DefaultPlugins, IntoScheduleConfigs, + PluginGroup, Window, WindowPlugin, }, window::WindowResolution, }; @@ -27,7 +30,7 @@ fn main() { let persistent_paths = PersistentPaths::resolve(); // config of default bevy plugins - app.add_plugins( + app.add_plugins(( DefaultPlugins .set(WindowPlugin { primary_window: Some(Window { @@ -43,7 +46,11 @@ fn main() { ..default() }) .disable::(), - ); + #[cfg(feature = "dev")] + FpsOverlayPlugin { + config: FpsOverlayConfig { ..default() }, + }, + )); // red clear color to prevent white screen flash app.insert_resource(ClearColor(Color::linear_rgb(1.0, 0.0, 0.0))); From b5ec9aa973bd226c2bcc66f65f8a046e5d1c53bf Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 15:24:06 +0000 Subject: [PATCH 015/106] set up channels --- crates/shared/src/lib.rs | 4 +- crates/shared/src/network/channel.rs | 6 +++ crates/shared/src/network/mod.rs | 52 +++++++++++++++++++ .../src/{ => network}/protocol/client.rs | 0 .../shared/src/{ => network}/protocol/mod.rs | 0 .../src/{ => network}/protocol/server.rs | 0 6 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 crates/shared/src/network/channel.rs create mode 100644 crates/shared/src/network/mod.rs rename crates/shared/src/{ => network}/protocol/client.rs (100%) rename crates/shared/src/{ => network}/protocol/mod.rs (100%) rename crates/shared/src/{ => network}/protocol/server.rs (100%) diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index 49ba9122..55f43ea8 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -1,6 +1,6 @@ pub mod load; +pub mod network; pub mod prelude; -pub mod protocol; pub mod simulation; pub mod state; @@ -20,7 +20,7 @@ impl PluginGroup for SharedPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() .add(state::SimulationLifecyclePlugin) - .add(protocol::NetworkProtoclPlugin) + .add(network::NetworkPlugin) .add(simulation::asset::AssetPlugin) .add(simulation::biome::BiomePlugin) .add(simulation::block::BlockPlugin) diff --git a/crates/shared/src/network/channel.rs b/crates/shared/src/network/channel.rs new file mode 100644 index 00000000..7c1c31d1 --- /dev/null +++ b/crates/shared/src/network/channel.rs @@ -0,0 +1,6 @@ +pub struct PlayerMovement; +pub struct BlockUpdates; +pub struct ChunkData; +pub struct EntityLifecycle; +pub struct ModStateSync; +pub struct ChatAndSystem; diff --git a/crates/shared/src/network/mod.rs b/crates/shared/src/network/mod.rs new file mode 100644 index 00000000..5dc23028 --- /dev/null +++ b/crates/shared/src/network/mod.rs @@ -0,0 +1,52 @@ +pub mod channel; +pub mod protocol; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +use bevy::prelude::*; +use channel::{ + BlockUpdates, ChatAndSystem, ChunkData, EntityLifecycle, ModStateSync, PlayerMovement, +}; +use lightyear::prelude::{AppChannelExt, ChannelMode, ChannelSettings, ReliableSettings}; +use protocol::NetworkProtoclPlugin; + +pub struct NetworkPlugin; + +/// A plugin that defines sets up the shared network stuff +impl Plugin for NetworkPlugin { + fn build(&self, app: &mut App) { + app.add_plugins(NetworkProtoclPlugin); + + app.add_channel::(ChannelSettings { + mode: ChannelMode::SequencedUnreliable, + ..default() + }); + + app.add_channel::(ChannelSettings { + mode: ChannelMode::OrderedReliable(ReliableSettings { ..default() }), + ..default() + }); + + app.add_channel::(ChannelSettings { + mode: ChannelMode::UnorderedReliable(ReliableSettings { ..default() }), + ..default() + }); + + app.add_channel::(ChannelSettings { + mode: ChannelMode::OrderedReliable(ReliableSettings { ..default() }), + ..default() + }); + + app.add_channel::(ChannelSettings { + mode: ChannelMode::OrderedReliable(ReliableSettings { ..default() }), + ..default() + }); + + app.add_channel::(ChannelSettings { + mode: ChannelMode::OrderedReliable(ReliableSettings { ..default() }), + ..default() + }); + } +} diff --git a/crates/shared/src/protocol/client.rs b/crates/shared/src/network/protocol/client.rs similarity index 100% rename from crates/shared/src/protocol/client.rs rename to crates/shared/src/network/protocol/client.rs diff --git a/crates/shared/src/protocol/mod.rs b/crates/shared/src/network/protocol/mod.rs similarity index 100% rename from crates/shared/src/protocol/mod.rs rename to crates/shared/src/network/protocol/mod.rs diff --git a/crates/shared/src/protocol/server.rs b/crates/shared/src/network/protocol/server.rs similarity index 100% rename from crates/shared/src/protocol/server.rs rename to crates/shared/src/network/protocol/server.rs From 643f817f453a4edb7759a845751ef1e2bfa023a4 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 15:49:44 +0000 Subject: [PATCH 016/106] clean up client/main a bit --- crates/client/src/main.rs | 11 ++--------- crates/client/src/render/mod.rs | 6 ++++++ crates/server/src/lib.rs | 3 +-- crates/server/src/main.rs | 12 +++++++----- crates/shared/src/lib.rs | 1 + .../shared/src/load/components/loading_task.rs | 7 ++----- crates/shared/src/load/components/mod.rs | 4 +--- crates/shared/src/load/mod.rs | 16 ++++++++++++++++ 8 files changed, 36 insertions(+), 24 deletions(-) diff --git a/crates/client/src/main.rs b/crates/client/src/main.rs index 0fb65c07..5a5e7965 100644 --- a/crates/client/src/main.rs +++ b/crates/client/src/main.rs @@ -7,16 +7,13 @@ use bevy::{ app::{App, FixedUpdate, PostUpdate}, log::LogPlugin, prelude::{ - default, info, AssetPlugin, ClearColor, Color, DefaultPlugins, IntoScheduleConfigs, + default, info, AssetPlugin, DefaultPlugins, IntoScheduleConfigs, PluginGroup, Window, WindowPlugin, }, window::WindowResolution, }; use client::prelude::*; -use shared::{ - load::LoadingTracker, - simulation::scheduling::{FixedUpdateSet, RenderPrepSet}, -}; +use shared::simulation::scheduling::{FixedUpdateSet, RenderPrepSet}; use utils::PersistentPaths; #[instrument(skip_all, fields(name = "main"))] @@ -52,13 +49,9 @@ fn main() { }, )); - // red clear color to prevent white screen flash - app.insert_resource(ClearColor(Color::linear_rgb(1.0, 0.0, 0.0))); - // load config & loading trackers into main world app.insert_resource(ClientSettings::load_or_create(&persistent_paths)); app.insert_resource(persistent_paths); - app.insert_resource(LoadingTracker::default()); // configure schedule sets app.configure_sets( diff --git a/crates/client/src/render/mod.rs b/crates/client/src/render/mod.rs index 6f109ca4..b2d5e753 100644 --- a/crates/client/src/render/mod.rs +++ b/crates/client/src/render/mod.rs @@ -33,6 +33,8 @@ use bevy::{ RenderApp, }, }; +#[cfg(feature = "dev")] +use bevy::{camera::ClearColor, color::Color}; use shared::simulation::block::TargetedBlock; /// Plugin responsible for attaching custom render logic to Bevy's native RenderApp @@ -54,6 +56,10 @@ impl Plugin for VantablockRenderPlugin { ExtractResourcePlugin::::default(), )); + // red clear color for dev testing + #[cfg(feature = "dev")] + app.insert_resource(ClearColor(Color::linear_rgb(1.0, 0.0, 0.0))); + // INFO: ------------------------------------ // main world synchronization // ------------------------------------------ diff --git a/crates/server/src/lib.rs b/crates/server/src/lib.rs index 32ac51af..48a2f7da 100644 --- a/crates/server/src/lib.rs +++ b/crates/server/src/lib.rs @@ -2,13 +2,12 @@ pub mod state; use bevy::app::PluginGroupBuilder; use bevy::prelude::PluginGroup; -use shared::SharedPlugins; /// Server-side simulation and orchestration plugins. pub struct ServerPlugins; impl PluginGroup for ServerPlugins { fn build(self) -> PluginGroupBuilder { - PluginGroupBuilder::start::().add_group(SharedPlugins) + PluginGroupBuilder::start::() } } diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 86f707b1..2fbb488a 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -1,19 +1,21 @@ use bevy::{ - MinimalPlugins, app::{App, ScheduleRunnerPlugin}, asset::AssetPlugin, - prelude::{PluginGroup, default, info}, + prelude::{default, info, PluginGroup}, + MinimalPlugins, }; use server::ServerPlugins; -use shared::load::LoadingTracker; +use shared::SharedPlugins; use std::time::Duration; use utils::PersistentPaths; +/// This is the entrypoint for a dedicated server. The server logic is also used +/// for a client running singleplayer, though not through the main entrypoint. fn main() { // setup headless bevy app let mut app = App::new(); - // Resolve platform paths and initialize application paths + // resolve platform paths and initialize application paths let persistent_paths = PersistentPaths::resolve(); app.add_plugins( @@ -30,10 +32,10 @@ fn main() { // load config & loading trackers into main world app.insert_resource(persistent_paths); - app.insert_resource(LoadingTracker::default()); // add server-side and shared plugins app.add_plugins(ServerPlugins); + app.add_plugins(SharedPlugins); info!("Server started successfully!"); app.run(); diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index 55f43ea8..846c68fb 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -19,6 +19,7 @@ pub struct SharedPlugins; impl PluginGroup for SharedPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() + .add(load::LoadPlugin) .add(state::SimulationLifecyclePlugin) .add(network::NetworkPlugin) .add(simulation::asset::AssetPlugin) diff --git a/crates/shared/src/load/components/loading_task.rs b/crates/shared/src/load/components/loading_task.rs index b43f34cf..f8fc004d 100644 --- a/crates/shared/src/load/components/loading_task.rs +++ b/crates/shared/src/load/components/loading_task.rs @@ -3,12 +3,9 @@ use crossbeam::channel::Receiver; pub type TaskResultCallback = Box; -#[derive(Component)] -pub struct SimulationWorldLoadingTaskComponent { - pub receiver: Receiver, -} +// TODO: no longer need with bevy tasks #[derive(Component)] -pub struct RenderWorldLoadingTaskComponent { +pub struct SimulationWorldLoadingTaskComponent { pub receiver: Receiver, } diff --git a/crates/shared/src/load/components/mod.rs b/crates/shared/src/load/components/mod.rs index 630468fb..7fca383c 100644 --- a/crates/shared/src/load/components/mod.rs +++ b/crates/shared/src/load/components/mod.rs @@ -1,5 +1,3 @@ pub mod loading_task; -pub use loading_task::{ - RenderWorldLoadingTaskComponent, SimulationWorldLoadingTaskComponent, TaskResultCallback, -}; +pub use loading_task::{SimulationWorldLoadingTaskComponent, TaskResultCallback}; diff --git a/crates/shared/src/load/mod.rs b/crates/shared/src/load/mod.rs index 4fd069e5..b7ff9d2a 100644 --- a/crates/shared/src/load/mod.rs +++ b/crates/shared/src/load/mod.rs @@ -10,3 +10,19 @@ pub mod systems; pub use components::*; pub use resources::*; pub use systems::*; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +// TODO: more robust loading setup, also add other loading systems to the plugin + +use bevy::prelude::{App, Plugin}; + +pub struct LoadPlugin; + +impl Plugin for LoadPlugin { + fn build(&self, app: &mut App) { + app.init_resource::(); + } +} From b058189423fe584c3091cc239d9d3577f9009b7d Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:12:47 +0000 Subject: [PATCH 017/106] networking mode state --- crates/client/src/state/lifecycle.rs | 8 +++----- crates/client/src/state/mod.rs | 18 ++++++++++++++++++ crates/shared/src/network/mod.rs | 7 +++++++ crates/shared/src/network/state.rs | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 crates/shared/src/network/state.rs diff --git a/crates/client/src/state/lifecycle.rs b/crates/client/src/state/lifecycle.rs index 9e228c33..9b772b7a 100644 --- a/crates/client/src/state/lifecycle.rs +++ b/crates/client/src/state/lifecycle.rs @@ -2,11 +2,11 @@ use crate::state::enums::{ClientAppState, ClientGameState}; use bevy::prelude::*; use bevy::window::PrimaryWindow; use shared::{ - FixedUpdateSet, RenderPrepSet, load::{ - LoadingTracker, OnLoadComplete, master_finalize_loading_system, - reset_loading_tracker_system, + master_finalize_loading_system, reset_loading_tracker_system, LoadingTracker, + OnLoadComplete, }, + FixedUpdateSet, RenderPrepSet, }; pub struct ClientLifecyclePlugin; @@ -37,8 +37,6 @@ impl Plugin for ClientLifecyclePlugin { // INFO: --------------------------- // state transitions // --------------------------------- - app.init_state::() - .add_sub_state::(); app.add_systems( Update, diff --git a/crates/client/src/state/mod.rs b/crates/client/src/state/mod.rs index 1e806cc7..06d4c9b3 100644 --- a/crates/client/src/state/mod.rs +++ b/crates/client/src/state/mod.rs @@ -3,3 +3,21 @@ pub mod lifecycle; pub use enums::*; pub use lifecycle::*; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +use bevy::{ + prelude::{App, Plugin}, + state::app::AppExtStates, +}; + +pub struct StatePlugin; + +impl Plugin for StatePlugin { + fn build(&self, app: &mut App) { + app.init_state::() + .add_sub_state::(); + } +} diff --git a/crates/shared/src/network/mod.rs b/crates/shared/src/network/mod.rs index 5dc23028..c0f889f1 100644 --- a/crates/shared/src/network/mod.rs +++ b/crates/shared/src/network/mod.rs @@ -1,5 +1,6 @@ pub mod channel; pub mod protocol; +pub mod state; // INFO: --------------------------- // plugin definition @@ -12,6 +13,8 @@ use channel::{ use lightyear::prelude::{AppChannelExt, ChannelMode, ChannelSettings, ReliableSettings}; use protocol::NetworkProtoclPlugin; +use crate::network::state::NetworkingMode; + pub struct NetworkPlugin; /// A plugin that defines sets up the shared network stuff @@ -19,6 +22,10 @@ impl Plugin for NetworkPlugin { fn build(&self, app: &mut App) { app.add_plugins(NetworkProtoclPlugin); + // add states + app.init_state::(); + + // add channels app.add_channel::(ChannelSettings { mode: ChannelMode::SequencedUnreliable, ..default() diff --git a/crates/shared/src/network/state.rs b/crates/shared/src/network/state.rs new file mode 100644 index 00000000..24bdf72a --- /dev/null +++ b/crates/shared/src/network/state.rs @@ -0,0 +1,16 @@ +use bevy::state::state::States; + +/// An enum representing the networking mode of the server module. +#[derive(States, Default, Debug, Clone, Eq, PartialEq, Hash)] +pub enum NetworkingMode { + #[default] + /// The networking module is inactive. This may be, for example, the case on a client + /// which is in the main menu. + Inactive, + /// Networking is active externally. This happens when the client is connected to a + /// remote dedicated server. + External, + /// Networking is active internally. This happens when the client is running its own + /// local server instance and connecting to it. + Internal, +} From 13cafee3019108c7629fa10d790c7f00df3fe87b Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:27:14 +0000 Subject: [PATCH 018/106] refactor client app state --- crates/client/src/state/enums.rs | 7 +++---- crates/shared/src/network/mod.rs | 2 +- crates/shared/src/network/state.rs | 6 ++++-- crates/shared/src/state/enums.rs | 25 +++++++++++++++++++++++-- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/crates/client/src/state/enums.rs b/crates/client/src/state/enums.rs index 0af1a53e..427d2855 100644 --- a/crates/client/src/state/enums.rs +++ b/crates/client/src/state/enums.rs @@ -1,10 +1,9 @@ -use bevy::prelude::{Resource, StateSet, States, SubStates}; -use bevy::render::extract_resource::ExtractResource; +use bevy::prelude::{StateSet, States, SubStates}; /// The state of the overall client app runtime. /// /// This represents the wrapping program itself, unrelated to game logic. -#[derive(States, Resource, Debug, Clone, Copy, PartialEq, Eq, Hash, Default, ExtractResource)] +#[derive(States, Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ClientAppState { /// The client is loading up essential data. The app loop has not started. #[default] @@ -18,7 +17,7 @@ pub enum ClientAppState { /// A sub-state of `ClientAppState::Running`. /// /// Represents the game state and lifecycle. -#[derive(SubStates, Resource, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +#[derive(SubStates, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] #[source(ClientAppState = ClientAppState::Running)] pub enum ClientGameState { /// The user is navigating the main menu UI. diff --git a/crates/shared/src/network/mod.rs b/crates/shared/src/network/mod.rs index c0f889f1..46d12e3f 100644 --- a/crates/shared/src/network/mod.rs +++ b/crates/shared/src/network/mod.rs @@ -23,7 +23,7 @@ impl Plugin for NetworkPlugin { app.add_plugins(NetworkProtoclPlugin); // add states - app.init_state::(); + app.add_sub_state::(); // add channels app.add_channel::(ChannelSettings { diff --git a/crates/shared/src/network/state.rs b/crates/shared/src/network/state.rs index 24bdf72a..aa86ace3 100644 --- a/crates/shared/src/network/state.rs +++ b/crates/shared/src/network/state.rs @@ -1,7 +1,9 @@ -use bevy::state::state::States; +use crate::state::enums::AppState; +use bevy::prelude::{StateSet, SubStates}; /// An enum representing the networking mode of the server module. -#[derive(States, Default, Debug, Clone, Eq, PartialEq, Hash)] +#[derive(SubStates, Default, Debug, Clone, Eq, PartialEq, Hash)] +#[source(AppState = AppState::Running)] pub enum NetworkingMode { #[default] /// The networking module is inactive. This may be, for example, the case on a client diff --git a/crates/shared/src/state/enums.rs b/crates/shared/src/state/enums.rs index 95803130..e462b1ed 100644 --- a/crates/shared/src/state/enums.rs +++ b/crates/shared/src/state/enums.rs @@ -1,7 +1,28 @@ -use bevy::prelude::{Resource, States}; +use bevy::prelude::States; + +/// The current state of the highest level application lifecycle. +#[derive(States, Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum AppState { + #[default] + /// The app is loading up essential data. The run loop has not started. + /// + /// The only work done during this phase should be work required for the window + /// to render a startup/loading screen. Any non-essential work done during this + /// state is just extra time spent hiding the main window/gui. + StartingUp, + /// The main application loop is active and executing. + /// + /// This is where the entire app logic is executed. + Running, + /// The application is performing cleanup operations before process termination. + /// + /// This is the final state of the app. Any essential saving or final actions must + /// be done during this state, as it is their last chance. + ShuttingDown, +} /// A state representing whether the server simulation is currently loading, paused or executing. -#[derive(States, Resource, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +#[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum SimulationState { #[default] Loading, From 9df4a588a37ede12eefe5bbf9b52f2722f2cc530 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:36:17 +0000 Subject: [PATCH 019/106] refactor load/state/lifecycle in shared --- crates/client/src/lib.rs | 1 + crates/client/src/load/registries.rs | 2 +- crates/client/src/player/camera/mod.rs | 4 ++-- crates/client/src/state/enums.rs | 19 +++------------ crates/client/src/state/lifecycle.rs | 13 +++++----- crates/client/src/state/mod.rs | 3 +-- crates/client/src/ui/mod.rs | 8 +++---- crates/shared/src/lib.rs | 6 ++--- .../load/components/loading_task.rs | 0 .../{ => lifecycle}/load/components/mod.rs | 0 crates/shared/src/{ => lifecycle}/load/mod.rs | 0 .../load/resources/load_tracking.rs | 0 .../src/{ => lifecycle}/load/resources/mod.rs | 0 .../load/resources/on_load_complete.rs | 0 .../load/systems/async_task_poller.rs | 2 +- .../load/systems/fake_work_system.rs | 2 +- .../load/systems/master_loading_finalizer.rs | 2 +- .../src/{ => lifecycle}/load/systems/mod.rs | 0 .../load/systems/reset_loader_tracker.rs | 2 +- crates/shared/src/lifecycle/mod.rs | 20 ++++++++++++++++ .../shared/src/{ => lifecycle}/state/enums.rs | 3 +++ .../src/{ => lifecycle}/state/lifecycle.rs | 4 ++-- crates/shared/src/lifecycle/state/mod.rs | 24 +++++++++++++++++++ crates/shared/src/network/state.rs | 2 +- crates/shared/src/simulation/time/mod.rs | 2 +- crates/shared/src/state/mod.rs | 5 ---- 26 files changed, 76 insertions(+), 48 deletions(-) rename crates/shared/src/{ => lifecycle}/load/components/loading_task.rs (100%) rename crates/shared/src/{ => lifecycle}/load/components/mod.rs (100%) rename crates/shared/src/{ => lifecycle}/load/mod.rs (100%) rename crates/shared/src/{ => lifecycle}/load/resources/load_tracking.rs (100%) rename crates/shared/src/{ => lifecycle}/load/resources/mod.rs (100%) rename crates/shared/src/{ => lifecycle}/load/resources/on_load_complete.rs (100%) rename crates/shared/src/{ => lifecycle}/load/systems/async_task_poller.rs (94%) rename crates/shared/src/{ => lifecycle}/load/systems/fake_work_system.rs (94%) rename crates/shared/src/{ => lifecycle}/load/systems/master_loading_finalizer.rs (95%) rename crates/shared/src/{ => lifecycle}/load/systems/mod.rs (100%) rename crates/shared/src/{ => lifecycle}/load/systems/reset_loader_tracker.rs (87%) create mode 100644 crates/shared/src/lifecycle/mod.rs rename crates/shared/src/{ => lifecycle}/state/enums.rs (90%) rename crates/shared/src/{ => lifecycle}/state/lifecycle.rs (95%) create mode 100644 crates/shared/src/lifecycle/state/mod.rs delete mode 100644 crates/shared/src/state/mod.rs diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index c161cd04..2e371f8d 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -23,6 +23,7 @@ pub struct ClientPlugins; impl PluginGroup for ClientPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() + .add(state::StatePlugin) .add(state::ClientLifecyclePlugin) .add(load::ClientLoadPlugin) .add(input::InputModulePlugin) diff --git a/crates/client/src/load/registries.rs b/crates/client/src/load/registries.rs index a265446d..8fde9f45 100644 --- a/crates/client/src/load/registries.rs +++ b/crates/client/src/load/registries.rs @@ -10,7 +10,7 @@ use bevy::{ }; use crossbeam::channel::unbounded; use shared::{ - load::{SimulationWorldLoadingTaskComponent, TaskResultCallback}, + lifecycle::load::{SimulationWorldLoadingTaskComponent, TaskResultCallback}, simulation::block::BlockRegistry, }; use utils::PersistentPaths; diff --git a/crates/client/src/player/camera/mod.rs b/crates/client/src/player/camera/mod.rs index 70cb9ae0..ad9b2a75 100644 --- a/crates/client/src/player/camera/mod.rs +++ b/crates/client/src/player/camera/mod.rs @@ -6,7 +6,7 @@ pub use movement::*; // camera plugin // ----------------------------- -use crate::state::ClientAppState; +use shared::lifecycle::state::enums::AppState; use bevy::prelude::{App, IntoScheduleConfigs, Plugin, Startup, Update, in_state}; use shared::simulation::player::initialize_camera::spawn_camera_system; @@ -20,7 +20,7 @@ impl Plugin for CameraPlugin { Update, (camera_movement_system, update_camera_chunk_chord_system) .chain() - .run_if(in_state(ClientAppState::Running)), + .run_if(in_state(AppState::Running)), ); } } diff --git a/crates/client/src/state/enums.rs b/crates/client/src/state/enums.rs index 427d2855..1dcaa5c8 100644 --- a/crates/client/src/state/enums.rs +++ b/crates/client/src/state/enums.rs @@ -1,24 +1,11 @@ -use bevy::prelude::{StateSet, States, SubStates}; - -/// The state of the overall client app runtime. -/// -/// This represents the wrapping program itself, unrelated to game logic. -#[derive(States, Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum ClientAppState { - /// The client is loading up essential data. The app loop has not started. - #[default] - StartingUp, - /// The main application loop is active and executing. - Running, - /// The application is performing cleanup operations before process termination. - ShuttingDown, -} +use bevy::prelude::{StateSet, SubStates}; +use shared::lifecycle::state::enums::AppState; /// A sub-state of `ClientAppState::Running`. /// /// Represents the game state and lifecycle. #[derive(SubStates, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] -#[source(ClientAppState = ClientAppState::Running)] +#[source(AppState = AppState::Running)] pub enum ClientGameState { /// The user is navigating the main menu UI. #[default] diff --git a/crates/client/src/state/lifecycle.rs b/crates/client/src/state/lifecycle.rs index 9b772b7a..191005d8 100644 --- a/crates/client/src/state/lifecycle.rs +++ b/crates/client/src/state/lifecycle.rs @@ -1,8 +1,9 @@ -use crate::state::enums::{ClientAppState, ClientGameState}; +use crate::state::enums::ClientGameState; use bevy::prelude::*; use bevy::window::PrimaryWindow; +use shared::lifecycle::state::enums::AppState; use shared::{ - load::{ + lifecycle::load::{ master_finalize_loading_system, reset_loading_tracker_system, LoadingTracker, OnLoadComplete, }, @@ -15,7 +16,7 @@ impl Plugin for ClientLifecyclePlugin { fn build(&self, app: &mut App) { // load cleanup to run after transitions app.add_systems( - OnExit(ClientAppState::StartingUp), + OnExit(AppState::StartingUp), reset_loading_tracker_system, ); @@ -41,16 +42,16 @@ impl Plugin for ClientLifecyclePlugin { app.add_systems( Update, ( - master_finalize_loading_system::, + master_finalize_loading_system::, master_finalize_loading_system::, show_window_when_ready, ) - .run_if(in_state(ClientAppState::StartingUp)), + .run_if(in_state(AppState::StartingUp)), ); // initial startup loading state should take us from loading // to running/playing once they finish. - app.insert_resource(OnLoadComplete::new(ClientAppState::Running)) + app.insert_resource(OnLoadComplete::new(AppState::Running)) .insert_resource(OnLoadComplete::new(ClientGameState::Playing)); } } diff --git a/crates/client/src/state/mod.rs b/crates/client/src/state/mod.rs index 06d4c9b3..36a17ba3 100644 --- a/crates/client/src/state/mod.rs +++ b/crates/client/src/state/mod.rs @@ -17,7 +17,6 @@ pub struct StatePlugin; impl Plugin for StatePlugin { fn build(&self, app: &mut App) { - app.init_state::() - .add_sub_state::(); + app.add_sub_state::(); } } diff --git a/crates/client/src/ui/mod.rs b/crates/client/src/ui/mod.rs index cc8e464e..712a8638 100644 --- a/crates/client/src/ui/mod.rs +++ b/crates/client/src/ui/mod.rs @@ -1,6 +1,6 @@ -use crate::state::ClientAppState; +use shared::lifecycle::state::enums::AppState; use bevy::prelude::*; -use shared::state::SimulationState; +use shared::lifecycle::state::SimulationState; pub mod systems; @@ -13,11 +13,11 @@ pub struct VantablockUiPlugin; impl Plugin for VantablockUiPlugin { fn build(&self, app: &mut App) { app.add_systems( - OnEnter(ClientAppState::Running), + OnEnter(AppState::Running), systems::spawning::spawn_ui_system, ) .add_systems( - OnExit(ClientAppState::Running), + OnExit(AppState::Running), systems::spawning::despawn_ui_system, ); diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index 846c68fb..057c98e5 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -1,8 +1,7 @@ -pub mod load; +pub mod lifecycle; pub mod network; pub mod prelude; pub mod simulation; -pub mod state; pub use prelude::*; @@ -19,8 +18,7 @@ pub struct SharedPlugins; impl PluginGroup for SharedPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() - .add(load::LoadPlugin) - .add(state::SimulationLifecyclePlugin) + .add_group(lifecycle::SharedLifecyclePlugins) .add(network::NetworkPlugin) .add(simulation::asset::AssetPlugin) .add(simulation::biome::BiomePlugin) diff --git a/crates/shared/src/load/components/loading_task.rs b/crates/shared/src/lifecycle/load/components/loading_task.rs similarity index 100% rename from crates/shared/src/load/components/loading_task.rs rename to crates/shared/src/lifecycle/load/components/loading_task.rs diff --git a/crates/shared/src/load/components/mod.rs b/crates/shared/src/lifecycle/load/components/mod.rs similarity index 100% rename from crates/shared/src/load/components/mod.rs rename to crates/shared/src/lifecycle/load/components/mod.rs diff --git a/crates/shared/src/load/mod.rs b/crates/shared/src/lifecycle/load/mod.rs similarity index 100% rename from crates/shared/src/load/mod.rs rename to crates/shared/src/lifecycle/load/mod.rs diff --git a/crates/shared/src/load/resources/load_tracking.rs b/crates/shared/src/lifecycle/load/resources/load_tracking.rs similarity index 100% rename from crates/shared/src/load/resources/load_tracking.rs rename to crates/shared/src/lifecycle/load/resources/load_tracking.rs diff --git a/crates/shared/src/load/resources/mod.rs b/crates/shared/src/lifecycle/load/resources/mod.rs similarity index 100% rename from crates/shared/src/load/resources/mod.rs rename to crates/shared/src/lifecycle/load/resources/mod.rs diff --git a/crates/shared/src/load/resources/on_load_complete.rs b/crates/shared/src/lifecycle/load/resources/on_load_complete.rs similarity index 100% rename from crates/shared/src/load/resources/on_load_complete.rs rename to crates/shared/src/lifecycle/load/resources/on_load_complete.rs diff --git a/crates/shared/src/load/systems/async_task_poller.rs b/crates/shared/src/lifecycle/load/systems/async_task_poller.rs similarity index 94% rename from crates/shared/src/load/systems/async_task_poller.rs rename to crates/shared/src/lifecycle/load/systems/async_task_poller.rs index 5dd7338e..e2102419 100644 --- a/crates/shared/src/load/systems/async_task_poller.rs +++ b/crates/shared/src/lifecycle/load/systems/async_task_poller.rs @@ -1,5 +1,5 @@ use crate::{ - load::{LoadingTracker, SimulationWorldLoadingTaskComponent}, + lifecycle::load::{LoadingTracker, SimulationWorldLoadingTaskComponent}, prelude::*, }; use bevy::ecs::prelude::*; diff --git a/crates/shared/src/load/systems/fake_work_system.rs b/crates/shared/src/lifecycle/load/systems/fake_work_system.rs similarity index 94% rename from crates/shared/src/load/systems/fake_work_system.rs rename to crates/shared/src/lifecycle/load/systems/fake_work_system.rs index c33dddab..91a9c826 100644 --- a/crates/shared/src/load/systems/fake_work_system.rs +++ b/crates/shared/src/lifecycle/load/systems/fake_work_system.rs @@ -1,5 +1,5 @@ use crate::{ - load::{SimulationWorldLoadingTaskComponent, TaskResultCallback}, + lifecycle::load::{SimulationWorldLoadingTaskComponent, TaskResultCallback}, prelude::*, }; use bevy::ecs::system::Commands; diff --git a/crates/shared/src/load/systems/master_loading_finalizer.rs b/crates/shared/src/lifecycle/load/systems/master_loading_finalizer.rs similarity index 95% rename from crates/shared/src/load/systems/master_loading_finalizer.rs rename to crates/shared/src/lifecycle/load/systems/master_loading_finalizer.rs index fab59d4f..cfcc90ab 100644 --- a/crates/shared/src/load/systems/master_loading_finalizer.rs +++ b/crates/shared/src/lifecycle/load/systems/master_loading_finalizer.rs @@ -1,5 +1,5 @@ use crate::{ - load::{LoadingTracker, OnLoadComplete}, + lifecycle::load::{LoadingTracker, OnLoadComplete}, prelude::*, }; use bevy::ecs::prelude::*; diff --git a/crates/shared/src/load/systems/mod.rs b/crates/shared/src/lifecycle/load/systems/mod.rs similarity index 100% rename from crates/shared/src/load/systems/mod.rs rename to crates/shared/src/lifecycle/load/systems/mod.rs diff --git a/crates/shared/src/load/systems/reset_loader_tracker.rs b/crates/shared/src/lifecycle/load/systems/reset_loader_tracker.rs similarity index 87% rename from crates/shared/src/load/systems/reset_loader_tracker.rs rename to crates/shared/src/lifecycle/load/systems/reset_loader_tracker.rs index 7796e404..af414095 100644 --- a/crates/shared/src/load/systems/reset_loader_tracker.rs +++ b/crates/shared/src/lifecycle/load/systems/reset_loader_tracker.rs @@ -1,4 +1,4 @@ -use crate::load::LoadingTracker; +use crate::lifecycle::load::LoadingTracker; use crate::prelude::*; use bevy::ecs::prelude::*; diff --git a/crates/shared/src/lifecycle/mod.rs b/crates/shared/src/lifecycle/mod.rs new file mode 100644 index 00000000..cf745bc8 --- /dev/null +++ b/crates/shared/src/lifecycle/mod.rs @@ -0,0 +1,20 @@ +pub mod load; +pub mod state; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +use bevy::app::PluginGroupBuilder; +use bevy::prelude::PluginGroup; + +/// A plugin group containing shared lifecycle stuff. +pub struct SharedLifecyclePlugins; + +impl PluginGroup for SharedLifecyclePlugins { + fn build(self) -> PluginGroupBuilder { + PluginGroupBuilder::start::() + .add(load::LoadPlugin) + .add(state::StatePlugin) + } +} diff --git a/crates/shared/src/state/enums.rs b/crates/shared/src/lifecycle/state/enums.rs similarity index 90% rename from crates/shared/src/state/enums.rs rename to crates/shared/src/lifecycle/state/enums.rs index e462b1ed..957cf8bd 100644 --- a/crates/shared/src/state/enums.rs +++ b/crates/shared/src/lifecycle/state/enums.rs @@ -25,7 +25,10 @@ pub enum AppState { #[derive(States, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum SimulationState { #[default] + /// The simulation is preparing to start. Loading, + /// The simulation is active and ticking. Running, + /// The simulation is paused. Paused, } diff --git a/crates/shared/src/state/lifecycle.rs b/crates/shared/src/lifecycle/state/lifecycle.rs similarity index 95% rename from crates/shared/src/state/lifecycle.rs rename to crates/shared/src/lifecycle/state/lifecycle.rs index a9660004..5f06f888 100644 --- a/crates/shared/src/state/lifecycle.rs +++ b/crates/shared/src/lifecycle/state/lifecycle.rs @@ -1,8 +1,8 @@ -use crate::load::{ +use crate::lifecycle::load::{ OnLoadComplete, master_finalize_loading_system, poll_simulation_loading_tasks, reset_loading_tracker_system, start_fake_work_system, }; -use crate::state::SimulationState; +use crate::lifecycle::state::SimulationState; use bevy::prelude::{ App, AppExtStates, IntoScheduleConfigs, OnExit, Plugin, Startup, Update, in_state, }; diff --git a/crates/shared/src/lifecycle/state/mod.rs b/crates/shared/src/lifecycle/state/mod.rs new file mode 100644 index 00000000..4b0deca4 --- /dev/null +++ b/crates/shared/src/lifecycle/state/mod.rs @@ -0,0 +1,24 @@ +pub mod enums; +pub mod lifecycle; + +pub use enums::SimulationState; +pub use lifecycle::SimulationLifecyclePlugin; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +use bevy::{ + prelude::{App, Plugin}, + state::app::AppExtStates, +}; +use enums::AppState; + +pub struct StatePlugin; + +impl Plugin for StatePlugin { + fn build(&self, app: &mut App) { + app.init_state::(); + app.add_plugins(SimulationLifecyclePlugin); + } +} diff --git a/crates/shared/src/network/state.rs b/crates/shared/src/network/state.rs index aa86ace3..0864903f 100644 --- a/crates/shared/src/network/state.rs +++ b/crates/shared/src/network/state.rs @@ -1,4 +1,4 @@ -use crate::state::enums::AppState; +use crate::lifecycle::state::enums::AppState; use bevy::prelude::{StateSet, SubStates}; /// An enum representing the networking mode of the server module. diff --git a/crates/shared/src/simulation/time/mod.rs b/crates/shared/src/simulation/time/mod.rs index 21bf85e1..2ee7a620 100644 --- a/crates/shared/src/simulation/time/mod.rs +++ b/crates/shared/src/simulation/time/mod.rs @@ -17,7 +17,7 @@ use crate::simulation::{ simulation_tick::run_fixed_update_schedule, world_clock::update_world_clock_system, }, }; -use crate::state::SimulationState; +use crate::lifecycle::state::SimulationState; use bevy::{ app::{App, FixedUpdate, Plugin, PreUpdate, Update}, ecs::prelude::*, diff --git a/crates/shared/src/state/mod.rs b/crates/shared/src/state/mod.rs deleted file mode 100644 index a3166d1c..00000000 --- a/crates/shared/src/state/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod enums; -pub mod lifecycle; - -pub use enums::SimulationState; -pub use lifecycle::SimulationLifecyclePlugin; From fdb596d308267c66c6931d2acf895fa409e85e1a Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:33:25 +0000 Subject: [PATCH 020/106] use bevy tasks in shared load system --- crates/client/src/load/registries.rs | 75 ++++++++----------- .../lifecycle/load/components/loading_task.rs | 11 +-- .../src/lifecycle/load/components/mod.rs | 2 +- .../load/systems/async_task_poller.rs | 29 +++---- .../load/systems/fake_work_system.rs | 56 ++++++-------- 5 files changed, 68 insertions(+), 105 deletions(-) diff --git a/crates/client/src/load/registries.rs b/crates/client/src/load/registries.rs index 8fde9f45..85c90a51 100644 --- a/crates/client/src/load/registries.rs +++ b/crates/client/src/load/registries.rs @@ -3,16 +3,13 @@ use crate::render::{ block::BlockRenderDataRegistry, texture::{BlockTextureArray, VoxelTextureProcessor}, }; +use bevy::ecs::world::CommandQueue; use bevy::{ asset::Assets, prelude::{Commands, Image, Res, World}, tasks::AsyncComputeTaskPool, }; -use crossbeam::channel::unbounded; -use shared::{ - lifecycle::load::{SimulationWorldLoadingTaskComponent, TaskResultCallback}, - simulation::block::BlockRegistry, -}; +use shared::{lifecycle::load::LoadingTaskComponent, simulation::block::BlockRegistry}; use utils::PersistentPaths; /// A system that starts the asynchronous initialization of texture and block registries @@ -23,57 +20,47 @@ pub fn start_async_registry_initialization( ) { info!("Starting asynchronous simulation registry initialization..."); - let (sender, _receiver) = unbounded(); - let receiver = _receiver; let settings = client_settings.clone(); let paths = persistent_paths.clone(); - AsyncComputeTaskPool::get() - .spawn(async move { - info!("Initializing simulation registries in background..."); - - // texture stitching - let (texture_array_image, texture_registry) = - VoxelTextureProcessor::new(paths.assets_dir.clone(), &settings.texture_pack) - .load_and_stitch() - .expect("Failed to load and stitch textures"); + let task = AsyncComputeTaskPool::get().spawn(async move { + info!("Initializing simulation registries in background..."); - // independent simulation block loading - let block_registry = BlockRegistry::load_from_disk(&paths); + // texture stitching + let (texture_array_image, texture_registry) = + VoxelTextureProcessor::new(paths.assets_dir.clone(), &settings.texture_pack) + .load_and_stitch() + .expect("Failed to load and stitch textures"); - // independent client render block loading (resolves IDs via simulation registry) - let render_registry = - BlockRenderDataRegistry::load_from_disk(&paths, &block_registry, &texture_registry); + // independent simulation block loading + let block_registry = BlockRegistry::load_from_disk(&paths); - // prepare callback to apply results on main thread - let callback: TaskResultCallback = Box::new(move |commands: &mut Commands| { - info!("Applying simulation registry results to the world."); + // independent client render block loading (resolves IDs via simulation registry) + let render_registry = + BlockRenderDataRegistry::load_from_disk(&paths, &block_registry, &texture_registry); - // access world via commands to insert resources - commands.queue(move |world: &mut World| { - let mut image_assets = world.resource_mut::>(); - let texture_handle = image_assets.add(texture_array_image); + info!("Applying simulation registry results to the world."); - // insert all registries - world.insert_resource(texture_registry); - world.insert_resource(block_registry); - world.insert_resource(render_registry); + let mut queue = CommandQueue::default(); + queue.push(move |world: &mut World| { + let mut image_assets = world.resource_mut::>(); + let texture_handle = image_assets.add(texture_array_image); - // insert texture array handle - world.insert_resource(BlockTextureArray { - handle: texture_handle, - }); - }); + // insert all registries + world.insert_resource(texture_registry); + world.insert_resource(block_registry); + world.insert_resource(render_registry); - info!("Simulation registries initialized successfully."); + // insert texture array handle + world.insert_resource(BlockTextureArray { + handle: texture_handle, }); - sender - .send(callback) - .expect("Failed to send registry task result"); - }) - .detach(); + info!("Simulation registries initialized successfully."); + }); + queue + }); // register this as a loading task so the game waits for it - commands.spawn(SimulationWorldLoadingTaskComponent { receiver }); + commands.spawn(LoadingTaskComponent(task)); } diff --git a/crates/shared/src/lifecycle/load/components/loading_task.rs b/crates/shared/src/lifecycle/load/components/loading_task.rs index f8fc004d..44fbabcc 100644 --- a/crates/shared/src/lifecycle/load/components/loading_task.rs +++ b/crates/shared/src/lifecycle/load/components/loading_task.rs @@ -1,11 +1,6 @@ use bevy::ecs::prelude::*; -use crossbeam::channel::Receiver; - -pub type TaskResultCallback = Box; - -// TODO: no longer need with bevy tasks +use bevy::ecs::world::CommandQueue; +use bevy::tasks::Task; #[derive(Component)] -pub struct SimulationWorldLoadingTaskComponent { - pub receiver: Receiver, -} +pub struct LoadingTaskComponent(pub Task); diff --git a/crates/shared/src/lifecycle/load/components/mod.rs b/crates/shared/src/lifecycle/load/components/mod.rs index 7fca383c..b6c930ad 100644 --- a/crates/shared/src/lifecycle/load/components/mod.rs +++ b/crates/shared/src/lifecycle/load/components/mod.rs @@ -1,3 +1,3 @@ pub mod loading_task; -pub use loading_task::{SimulationWorldLoadingTaskComponent, TaskResultCallback}; +pub use loading_task::LoadingTaskComponent; diff --git a/crates/shared/src/lifecycle/load/systems/async_task_poller.rs b/crates/shared/src/lifecycle/load/systems/async_task_poller.rs index e2102419..8bd103e6 100644 --- a/crates/shared/src/lifecycle/load/systems/async_task_poller.rs +++ b/crates/shared/src/lifecycle/load/systems/async_task_poller.rs @@ -1,15 +1,15 @@ use crate::{ - lifecycle::load::{LoadingTracker, SimulationWorldLoadingTaskComponent}, + lifecycle::load::{LoadingTaskComponent, LoadingTracker}, prelude::*, }; -use bevy::ecs::prelude::*; -use crossbeam::channel::TryRecvError; +use bevy::tasks::block_on; +use bevy::{ecs::prelude::*, tasks::poll_once}; /// Polls simulation-specific tasks and updates the shared `LoadingTracker`. #[instrument(skip_all)] pub fn poll_simulation_loading_tasks( // input - mut tasks: Query<(Entity, &mut SimulationWorldLoadingTaskComponent)>, + mut tasks: Query<(Entity, &mut LoadingTaskComponent)>, // output mut commands: Commands, @@ -21,21 +21,12 @@ pub fn poll_simulation_loading_tasks( let mut remaining_tasks = 0; - for (entity, task) in &mut tasks { - match task.receiver.try_recv() { - Ok(callback) => { - callback(&mut commands); - commands.entity(entity).despawn(); - } - Err(TryRecvError::Empty) => { - remaining_tasks += 1; - } - Err(TryRecvError::Disconnected) => { - // This could happen if a thread panicked or dropped the sender. - // It shouldn't happen during normal execution. - warn!("Simulation task failed: Channel disconnected!"); - commands.entity(entity).despawn(); - } + for (entity, mut task) in &mut tasks { + if let Some(mut command_queue) = block_on(poll_once(&mut task.0)) { + commands.append(&mut command_queue); + commands.entity(entity).despawn(); + } else { + remaining_tasks += 1; } } diff --git a/crates/shared/src/lifecycle/load/systems/fake_work_system.rs b/crates/shared/src/lifecycle/load/systems/fake_work_system.rs index 91a9c826..fc68647a 100644 --- a/crates/shared/src/lifecycle/load/systems/fake_work_system.rs +++ b/crates/shared/src/lifecycle/load/systems/fake_work_system.rs @@ -1,45 +1,35 @@ -use crate::{ - lifecycle::load::{SimulationWorldLoadingTaskComponent, TaskResultCallback}, - prelude::*, -}; +use crate::{lifecycle::load::LoadingTaskComponent, prelude::*}; use bevy::ecs::system::Commands; +use bevy::ecs::world::{CommandQueue, World}; use bevy::tasks::AsyncComputeTaskPool; -use crossbeam::channel::{unbounded, Receiver, Sender}; use rand::random_range; use std::{thread, time::Duration}; #[instrument(skip_all)] pub fn start_fake_work_system(mut commands: Commands) { - let (sender, receiver): (Sender, Receiver) = - unbounded(); - let entity = commands.spawn_empty().id(); - AsyncComputeTaskPool::get() - .spawn(async move { - const WORK_DURATION: u64 = 3; - for i in 1..=WORK_DURATION { - info!( - "[BACKGROUND {}] Fake working... step {}/{}", - entity, i, WORK_DURATION - ); - - let sleep_time = random_range(0.25..0.75); - thread::sleep(Duration::from_secs_f32(sleep_time)); - } - info!("[BACKGROUND {}] Fake work finished!", entity); + let task = AsyncComputeTaskPool::get().spawn(async move { + const WORK_DURATION: u64 = 3; + for i in 1..=WORK_DURATION { + info!( + "[BACKGROUND {}] Fake working... step {}/{}", + entity, i, WORK_DURATION + ); - let callback: TaskResultCallback = Box::new(move |_: &mut Commands| { - info!( - "[MAIN THREAD {}] Applying fake work result to the world.", - entity - ); - }); + let sleep_time = random_range(0.25..0.75); + thread::sleep(Duration::from_secs_f32(sleep_time)); + } + info!("[BACKGROUND {}] Fake work finished!", entity); - sender.send(callback).expect("Failed to send task result"); - }) - .detach(); + let mut queue = CommandQueue::default(); + queue.push(move |_: &mut World| { + info!( + "[MAIN THREAD {}] Applying fake work result to the world.", + entity + ); + }); + queue + }); - commands - .entity(entity) - .insert(SimulationWorldLoadingTaskComponent { receiver }); + commands.entity(entity).insert(LoadingTaskComponent(task)); } From 00114655b5f0b45a23c061ea3a89dc517f2cff44 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:44:04 +0000 Subject: [PATCH 021/106] generic loading task poller --- crates/client/src/load/mod.rs | 6 +- crates/client/src/load/registries.rs | 7 ++- crates/client/src/state/lifecycle.rs | 60 +++++++++---------- .../loading_task.rs => components.rs} | 7 +++ .../src/lifecycle/load/components/mod.rs | 3 - crates/shared/src/lifecycle/load/mod.rs | 21 +++++-- .../lifecycle/load/resources/load_tracking.rs | 33 ---------- .../src/lifecycle/load/resources/mod.rs | 5 -- .../load/resources/on_load_complete.rs | 24 -------- .../load/systems/async_task_poller.rs | 38 ------------ .../load/systems/fake_work_system.rs | 17 ++++-- .../lifecycle/load/systems/loading_tasks.rs | 56 +++++++++++++++++ .../load/systems/master_loading_finalizer.rs | 37 ------------ .../shared/src/lifecycle/load/systems/mod.rs | 8 +-- .../load/systems/reset_loader_tracker.rs | 13 ---- .../shared/src/lifecycle/state/lifecycle.rs | 37 +++++------- crates/shared/src/lifecycle/state/mod.rs | 2 + crates/shared/src/lifecycle/state/systems.rs | 10 ++++ justfile | 2 +- 19 files changed, 158 insertions(+), 228 deletions(-) rename crates/shared/src/lifecycle/load/{components/loading_task.rs => components.rs} (53%) delete mode 100644 crates/shared/src/lifecycle/load/components/mod.rs delete mode 100644 crates/shared/src/lifecycle/load/resources/load_tracking.rs delete mode 100644 crates/shared/src/lifecycle/load/resources/mod.rs delete mode 100644 crates/shared/src/lifecycle/load/resources/on_load_complete.rs delete mode 100644 crates/shared/src/lifecycle/load/systems/async_task_poller.rs create mode 100644 crates/shared/src/lifecycle/load/systems/loading_tasks.rs delete mode 100644 crates/shared/src/lifecycle/load/systems/master_loading_finalizer.rs delete mode 100644 crates/shared/src/lifecycle/load/systems/reset_loader_tracker.rs create mode 100644 crates/shared/src/lifecycle/state/systems.rs diff --git a/crates/client/src/load/mod.rs b/crates/client/src/load/mod.rs index 6121e987..19346574 100644 --- a/crates/client/src/load/mod.rs +++ b/crates/client/src/load/mod.rs @@ -1,7 +1,9 @@ pub mod registries; use crate::load::registries::start_async_registry_initialization; -use bevy::app::{App, Plugin, Startup}; +use bevy::app::{App, Plugin}; +use bevy::prelude::OnEnter; +use shared::lifecycle::state::enums::AppState; /// Plugin responsible for managing client-side asset and registry loading. pub struct ClientLoadPlugin; @@ -9,6 +11,6 @@ pub struct ClientLoadPlugin; impl Plugin for ClientLoadPlugin { fn build(&self, app: &mut App) { // start background registry initialization - app.add_systems(Startup, start_async_registry_initialization); + app.add_systems(OnEnter(AppState::StartingUp), start_async_registry_initialization); } } diff --git a/crates/client/src/load/registries.rs b/crates/client/src/load/registries.rs index 85c90a51..50753923 100644 --- a/crates/client/src/load/registries.rs +++ b/crates/client/src/load/registries.rs @@ -9,7 +9,10 @@ use bevy::{ prelude::{Commands, Image, Res, World}, tasks::AsyncComputeTaskPool, }; -use shared::{lifecycle::load::LoadingTaskComponent, simulation::block::BlockRegistry}; +use shared::{ + lifecycle::load::{AppStartupLoadingPhase, LoadingTaskComponent}, + simulation::block::BlockRegistry, +}; use utils::PersistentPaths; /// A system that starts the asynchronous initialization of texture and block registries @@ -62,5 +65,5 @@ pub fn start_async_registry_initialization( }); // register this as a loading task so the game waits for it - commands.spawn(LoadingTaskComponent(task)); + commands.spawn((LoadingTaskComponent(task), AppStartupLoadingPhase)); } diff --git a/crates/client/src/state/lifecycle.rs b/crates/client/src/state/lifecycle.rs index 191005d8..67a043a1 100644 --- a/crates/client/src/state/lifecycle.rs +++ b/crates/client/src/state/lifecycle.rs @@ -1,23 +1,37 @@ use crate::state::enums::ClientGameState; use bevy::prelude::*; use bevy::window::PrimaryWindow; -use shared::lifecycle::state::enums::AppState; -use shared::{ - lifecycle::load::{ - master_finalize_loading_system, reset_loading_tracker_system, LoadingTracker, - OnLoadComplete, - }, - FixedUpdateSet, RenderPrepSet, +use shared::lifecycle::load::{ + check_loading_complete, cleanup_orphaned_tasks, poll_tasks, AppStartupLoadingPhase, + LoadingTaskComponent, }; +use shared::lifecycle::state::enums::AppState; +use shared::{FixedUpdateSet, RenderPrepSet}; pub struct ClientLifecyclePlugin; impl Plugin for ClientLifecyclePlugin { fn build(&self, app: &mut App) { + // INFO: ----------------------- + // async loading + // ----------------------------- + + // polling systems for simulation-linked client state transitions + app.add_systems( + Update, + ( + check_loading_complete::( + ClientGameState::Playing, + ) + .run_if(in_state(ClientGameState::MainMenu)), + ) + .run_if(in_state(AppState::Running)), + ); + // load cleanup to run after transitions app.add_systems( OnExit(AppState::StartingUp), - reset_loading_tracker_system, + cleanup_orphaned_tasks::, ); // configure system sets to be state-bound @@ -40,30 +54,12 @@ impl Plugin for ClientLifecyclePlugin { // --------------------------------- app.add_systems( - Update, - ( - master_finalize_loading_system::, - master_finalize_loading_system::, - show_window_when_ready, - ) - .run_if(in_state(AppState::StartingUp)), + OnExit(AppState::StartingUp), + |mut window: Query<&mut Window, With>| { + if let Ok(mut win) = window.single_mut() { + win.visible = true; + } + }, ); - - // initial startup loading state should take us from loading - // to running/playing once they finish. - app.insert_resource(OnLoadComplete::new(AppState::Running)) - .insert_resource(OnLoadComplete::new(ClientGameState::Playing)); - } -} - -/// A system that makes the window visible once the loading tracker reports readiness. -fn show_window_when_ready( - mut query: Query<&mut Window, With>, - loading_tracker: Res, -) { - if loading_tracker.is_ready() - && let Ok(mut window) = query.single_mut() - { - window.visible = true; } } diff --git a/crates/shared/src/lifecycle/load/components/loading_task.rs b/crates/shared/src/lifecycle/load/components.rs similarity index 53% rename from crates/shared/src/lifecycle/load/components/loading_task.rs rename to crates/shared/src/lifecycle/load/components.rs index 44fbabcc..abab3291 100644 --- a/crates/shared/src/lifecycle/load/components/loading_task.rs +++ b/crates/shared/src/lifecycle/load/components.rs @@ -4,3 +4,10 @@ use bevy::tasks::Task; #[derive(Component)] pub struct LoadingTaskComponent(pub Task); + +/// A loading phase for app startup. +#[derive(Component)] +pub struct AppStartupLoadingPhase; + +#[derive(Component)] +pub struct SimulationPhase; diff --git a/crates/shared/src/lifecycle/load/components/mod.rs b/crates/shared/src/lifecycle/load/components/mod.rs deleted file mode 100644 index b6c930ad..00000000 --- a/crates/shared/src/lifecycle/load/components/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod loading_task; - -pub use loading_task::LoadingTaskComponent; diff --git a/crates/shared/src/lifecycle/load/mod.rs b/crates/shared/src/lifecycle/load/mod.rs index b7ff9d2a..86d6d0e5 100644 --- a/crates/shared/src/lifecycle/load/mod.rs +++ b/crates/shared/src/lifecycle/load/mod.rs @@ -4,25 +4,34 @@ // tasks complete. pub mod components; -pub mod resources; pub mod systems; pub use components::*; -pub use resources::*; pub use systems::*; // INFO: --------------------------- // plugin definition // --------------------------------- -// TODO: more robust loading setup, also add other loading systems to the plugin - -use bevy::prelude::{App, Plugin}; +use crate::lifecycle::{ + load::loading_tasks::loading_is_complete, state::enums::AppState, state::transition_to, +}; +use bevy::prelude::*; pub struct LoadPlugin; impl Plugin for LoadPlugin { fn build(&self, app: &mut App) { - app.init_resource::(); + // polling systems and tracking load state for app startup + app.add_systems( + Update, + ( + poll_tasks::, + transition_to(AppState::Running) + .run_if(loading_is_complete::), + ) + .chain() + .run_if(in_state(AppState::StartingUp)), + ); } } diff --git a/crates/shared/src/lifecycle/load/resources/load_tracking.rs b/crates/shared/src/lifecycle/load/resources/load_tracking.rs deleted file mode 100644 index 85c248cc..00000000 --- a/crates/shared/src/lifecycle/load/resources/load_tracking.rs +++ /dev/null @@ -1,33 +0,0 @@ -use bevy::ecs::resource::Resource; -use std::sync::{Arc, Mutex}; - -/// Loading tracker is a NonSend Resource that the outer app loop orchestrates -/// to enable both worlds to perform loading tasks in parallel before a state -/// transition occurs. -#[derive(Default)] -struct LoadingTrackerInner { - pub is_simulation_ready: bool, -} - -#[derive(Resource, Clone, Default)] -pub struct LoadingTracker { - inner: Arc>, -} - -impl LoadingTracker { - /// Returns true only if all worlds have reported that they are ready. - pub fn is_ready(&self) -> bool { - let guard = self.inner.lock().unwrap(); - guard.is_simulation_ready - } - - /// Resets the tracker to its initial state. - pub fn reset(&self) { - let mut guard = self.inner.lock().unwrap(); - guard.is_simulation_ready = false; - } - - pub fn set_simulation_ready(&self, is_ready: bool) { - self.inner.lock().unwrap().is_simulation_ready = is_ready; - } -} diff --git a/crates/shared/src/lifecycle/load/resources/mod.rs b/crates/shared/src/lifecycle/load/resources/mod.rs deleted file mode 100644 index 61600fc4..00000000 --- a/crates/shared/src/lifecycle/load/resources/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod load_tracking; -pub mod on_load_complete; - -pub use load_tracking::LoadingTracker; -pub use on_load_complete::OnLoadComplete; diff --git a/crates/shared/src/lifecycle/load/resources/on_load_complete.rs b/crates/shared/src/lifecycle/load/resources/on_load_complete.rs deleted file mode 100644 index bac411fd..00000000 --- a/crates/shared/src/lifecycle/load/resources/on_load_complete.rs +++ /dev/null @@ -1,24 +0,0 @@ -use bevy::ecs::prelude::*; -use bevy::state::state::States; -use std::marker::PhantomData; - -/// A temporary resource that tells the master finalizer system which state -/// to transition to when the current loading process is complete. -/// -/// It is generic over the state machine it should operate on (e.g., AppState). -#[derive(Resource, Debug)] -pub struct OnLoadComplete { - /// The destination state for the transition. - pub destination: S, - /// A marker to make the compiler happy with the generic type `S`. - _marker: PhantomData, -} - -impl OnLoadComplete { - pub fn new(destination: S) -> Self { - Self { - destination, - _marker: PhantomData, - } - } -} diff --git a/crates/shared/src/lifecycle/load/systems/async_task_poller.rs b/crates/shared/src/lifecycle/load/systems/async_task_poller.rs deleted file mode 100644 index 8bd103e6..00000000 --- a/crates/shared/src/lifecycle/load/systems/async_task_poller.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::{ - lifecycle::load::{LoadingTaskComponent, LoadingTracker}, - prelude::*, -}; -use bevy::tasks::block_on; -use bevy::{ecs::prelude::*, tasks::poll_once}; - -/// Polls simulation-specific tasks and updates the shared `LoadingTracker`. -#[instrument(skip_all)] -pub fn poll_simulation_loading_tasks( - // input - mut tasks: Query<(Entity, &mut LoadingTaskComponent)>, - - // output - mut commands: Commands, - loading_tracker: Option>, -) { - let Some(loading_tracker) = loading_tracker else { - return; - }; - - let mut remaining_tasks = 0; - - for (entity, mut task) in &mut tasks { - if let Some(mut command_queue) = block_on(poll_once(&mut task.0)) { - commands.append(&mut command_queue); - commands.entity(entity).despawn(); - } else { - remaining_tasks += 1; - } - } - - if remaining_tasks == 0 { - loading_tracker.set_simulation_ready(true); - } else { - loading_tracker.set_simulation_ready(false); - } -} diff --git a/crates/shared/src/lifecycle/load/systems/fake_work_system.rs b/crates/shared/src/lifecycle/load/systems/fake_work_system.rs index fc68647a..b49f84b3 100644 --- a/crates/shared/src/lifecycle/load/systems/fake_work_system.rs +++ b/crates/shared/src/lifecycle/load/systems/fake_work_system.rs @@ -1,7 +1,12 @@ -use crate::{lifecycle::load::LoadingTaskComponent, prelude::*}; -use bevy::ecs::system::Commands; -use bevy::ecs::world::{CommandQueue, World}; -use bevy::tasks::AsyncComputeTaskPool; +use crate::{ + lifecycle::load::components::{LoadingTaskComponent, SimulationPhase}, + prelude::*, +}; +use bevy::{ + ecs::system::Commands, + ecs::world::{CommandQueue, World}, + tasks::AsyncComputeTaskPool, +}; use rand::random_range; use std::{thread, time::Duration}; @@ -31,5 +36,7 @@ pub fn start_fake_work_system(mut commands: Commands) { queue }); - commands.entity(entity).insert(LoadingTaskComponent(task)); + commands + .entity(entity) + .insert((LoadingTaskComponent(task), SimulationPhase)); } diff --git a/crates/shared/src/lifecycle/load/systems/loading_tasks.rs b/crates/shared/src/lifecycle/load/systems/loading_tasks.rs new file mode 100644 index 00000000..9e6f51af --- /dev/null +++ b/crates/shared/src/lifecycle/load/systems/loading_tasks.rs @@ -0,0 +1,56 @@ +use crate::{lifecycle::load::components::LoadingTaskComponent, prelude::*}; +use bevy::{ + ecs::prelude::*, + prelude::{NextState, States}, + state::state::FreelyMutableState, + tasks::{block_on, poll_once}, +}; + +/// A generic polling system that checks if tasks of a specific marker have finished. +/// +/// When a task finishes, this system applies the tasks' returned commands and despawns +/// the task entity. +pub fn poll_tasks( + mut tasks: Query<(Entity, &mut LoadingTaskComponent), With>, + mut commands: Commands, +) { + for (entity, mut task) in &mut tasks { + if let Some(mut queue) = block_on(poll_once(&mut task.0)) { + commands.append(&mut queue); + commands.entity(entity).despawn(); + } + } +} + +/// A generic cleanup system for orphaned tasks. +pub fn cleanup_orphaned_tasks( + mut commands: Commands, + query: Query, With)>, +) { + for entity in &query { + warn!( + "Cleaning up orphaned task for marker: {}", + std::any::type_name::() + ); + commands.entity(entity).despawn(); + } +} + +/// Returns true if there are no entities with the given Marker component. +/// +/// On debug builds, prints a warning if it returns true on the first call +/// which is useful to catch accidental race conditions or useless polling. +pub fn loading_is_complete(query: Query<(), With>) -> bool { + query.is_empty() +} + +/// A transition checker that moves to a target state when all entities with a marker are gone. +pub fn check_loading_complete( + target_state: S, +) -> impl FnMut(Query<(), With>, ResMut>) { + move |tasks_query, mut next_state| { + if tasks_query.is_empty() { + next_state.set(target_state); + } + } +} diff --git a/crates/shared/src/lifecycle/load/systems/master_loading_finalizer.rs b/crates/shared/src/lifecycle/load/systems/master_loading_finalizer.rs deleted file mode 100644 index cfcc90ab..00000000 --- a/crates/shared/src/lifecycle/load/systems/master_loading_finalizer.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::{ - lifecycle::load::{LoadingTracker, OnLoadComplete}, - prelude::*, -}; -use bevy::ecs::prelude::*; -use bevy::prelude::{NextState, States}; -use bevy::state::state::FreelyMutableState; - -/// The master system that runs in the simulation world. It checks the shared -/// LoadingTracker and the OnLoadComplete resource to make the final decision -/// on when to transition the app's state. -#[instrument(skip_all)] -pub fn master_finalize_loading_system( - // Input - loading_tracker: Option>, - on_complete: Option>>, - - // Output (set the next state) - mut next_state: ResMut>, -) { - let Some(loading_tracker) = loading_tracker else { - return; - }; - - // if we have both the tracker and the "what to do next" instruction - if let Some(on_complete) = on_complete - && loading_tracker.is_ready() - { - info!( - "Loading is done. Transitioning to {:?}.", - on_complete.destination - ); - - // set the next state - next_state.set(on_complete.destination); - } -} diff --git a/crates/shared/src/lifecycle/load/systems/mod.rs b/crates/shared/src/lifecycle/load/systems/mod.rs index 77b8a161..2705c563 100644 --- a/crates/shared/src/lifecycle/load/systems/mod.rs +++ b/crates/shared/src/lifecycle/load/systems/mod.rs @@ -1,9 +1,5 @@ -pub mod async_task_poller; pub mod fake_work_system; -pub mod master_loading_finalizer; -pub mod reset_loader_tracker; +pub mod loading_tasks; -pub use async_task_poller::poll_simulation_loading_tasks; pub use fake_work_system::start_fake_work_system; -pub use master_loading_finalizer::master_finalize_loading_system; -pub use reset_loader_tracker::reset_loading_tracker_system; +pub use loading_tasks::{check_loading_complete, cleanup_orphaned_tasks, poll_tasks}; diff --git a/crates/shared/src/lifecycle/load/systems/reset_loader_tracker.rs b/crates/shared/src/lifecycle/load/systems/reset_loader_tracker.rs deleted file mode 100644 index af414095..00000000 --- a/crates/shared/src/lifecycle/load/systems/reset_loader_tracker.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::lifecycle::load::LoadingTracker; -use crate::prelude::*; -use bevy::ecs::prelude::*; - -#[instrument(skip_all)] -pub fn reset_loading_tracker_system(loading_tracker: Option>) { - let Some(loading_tracker) = loading_tracker else { - return; - }; - - info!("Resetting loading tracker..."); - loading_tracker.reset(); -} diff --git a/crates/shared/src/lifecycle/state/lifecycle.rs b/crates/shared/src/lifecycle/state/lifecycle.rs index 5f06f888..d7893179 100644 --- a/crates/shared/src/lifecycle/state/lifecycle.rs +++ b/crates/shared/src/lifecycle/state/lifecycle.rs @@ -1,10 +1,10 @@ use crate::lifecycle::load::{ - OnLoadComplete, master_finalize_loading_system, poll_simulation_loading_tasks, - reset_loading_tracker_system, start_fake_work_system, + SimulationPhase, check_loading_complete, cleanup_orphaned_tasks, poll_tasks, + start_fake_work_system, }; use crate::lifecycle::state::SimulationState; use bevy::prelude::{ - App, AppExtStates, IntoScheduleConfigs, OnExit, Plugin, Startup, Update, in_state, + App, AppExtStates, IntoScheduleConfigs, OnEnter, OnExit, Plugin, Update, in_state, }; pub struct SimulationLifecyclePlugin; @@ -14,6 +14,11 @@ pub struct SimulationLifecyclePlugin; /// involves orchestration of loading tasks and state transitions. impl Plugin for SimulationLifecyclePlugin { fn build(&self, app: &mut App) { + // INFO: --------------------------- + // state transitions + // --------------------------------- + app.init_state::(); + // INFO: ----------------------- // async loading // ----------------------------- @@ -21,31 +26,21 @@ impl Plugin for SimulationLifecyclePlugin { // polling systems and tracking load state app.add_systems( Update, - (poll_simulation_loading_tasks.run_if(in_state(SimulationState::Loading)),), + ( + poll_tasks::, + check_loading_complete::(SimulationState::Running) + .after(poll_tasks::), + ) + .run_if(in_state(SimulationState::Loading)), ); // load cleanup to run after transitions app.add_systems( OnExit(SimulationState::Loading), - reset_loading_tracker_system, + cleanup_orphaned_tasks::, ); // systems to ensure rigidity - app.add_systems(Startup, start_fake_work_system); - - // INFO: --------------------------- - // state transitions - // --------------------------------- - app.init_state::(); - - app.add_systems( - Update, - (master_finalize_loading_system::,) - .run_if(in_state(SimulationState::Loading)), - ); - - // initial startup loading state should take us from loading - // to running/playing once they finish. - app.insert_resource(OnLoadComplete::new(SimulationState::Running)); + app.add_systems(OnEnter(SimulationState::Loading), start_fake_work_system); } } diff --git a/crates/shared/src/lifecycle/state/mod.rs b/crates/shared/src/lifecycle/state/mod.rs index 4b0deca4..4c436e1f 100644 --- a/crates/shared/src/lifecycle/state/mod.rs +++ b/crates/shared/src/lifecycle/state/mod.rs @@ -1,8 +1,10 @@ pub mod enums; pub mod lifecycle; +pub mod systems; pub use enums::SimulationState; pub use lifecycle::SimulationLifecyclePlugin; +pub use systems::transition_to; // INFO: --------------------------- // plugin definition diff --git a/crates/shared/src/lifecycle/state/systems.rs b/crates/shared/src/lifecycle/state/systems.rs new file mode 100644 index 00000000..a89a79fc --- /dev/null +++ b/crates/shared/src/lifecycle/state/systems.rs @@ -0,0 +1,10 @@ +use bevy::{prelude::*, state::state::FreelyMutableState}; + +/// A generic system that unconditionally transitions to the target state. +pub fn transition_to( + target_state: S, +) -> impl FnMut(ResMut>) { + move |mut next_state| { + next_state.set(target_state); + } +} diff --git a/justfile b/justfile index 366e4d89..550b6e15 100644 --- a/justfile +++ b/justfile @@ -146,7 +146,7 @@ debug *args: set -- {{args}} if [ "$#" -eq 0 ]; then echo -e "\033[1;33mNo debug targets specified. Available targets are:\033[0m" - rg --no-heading -o --replace '$f:$1' 'target\s*:\s*"([^"]+)"' crates/{{client}}/src/ \ + rg --no-heading -o --replace '$f:$1' 'target\s*:\s*"([^"]+)"' crates/ \ | awk -F: '{print $NF}' | sort | uniq -c | sort -rn \ | while read -r count target; do printf ' - \033[1;35m%s\033[0m (%sx)\n' "$target" "$count" From 417389b606a8ad887b4f60d78d1cde22bb15e080 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 21:54:09 +0000 Subject: [PATCH 022/106] refactor some state transitions --- .../shared/src/lifecycle/load/components.rs | 9 +++++-- crates/shared/src/lifecycle/load/mod.rs | 15 +++++++++++- .../load/systems/fake_work_system.rs | 4 ++-- .../shared/src/lifecycle/state/lifecycle.rs | 24 ++++--------------- crates/shared/src/lifecycle/state/mod.rs | 2 ++ 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/crates/shared/src/lifecycle/load/components.rs b/crates/shared/src/lifecycle/load/components.rs index abab3291..ebedbc14 100644 --- a/crates/shared/src/lifecycle/load/components.rs +++ b/crates/shared/src/lifecycle/load/components.rs @@ -5,9 +5,14 @@ use bevy::tasks::Task; #[derive(Component)] pub struct LoadingTaskComponent(pub Task); -/// A loading phase for app startup. +/// A loading phase for app startup. This phase should include +/// essential rendering tasks that must be done before the first +/// pixel of the startup screen displays. Anything else should be +/// done during the actual startup screen instead. #[derive(Component)] pub struct AppStartupLoadingPhase; +/// A loading phase for all tasks necessary to complete before the +/// simulation itself starts running. #[derive(Component)] -pub struct SimulationPhase; +pub struct SimulationLoadingPhase; diff --git a/crates/shared/src/lifecycle/load/mod.rs b/crates/shared/src/lifecycle/load/mod.rs index 86d6d0e5..c041d578 100644 --- a/crates/shared/src/lifecycle/load/mod.rs +++ b/crates/shared/src/lifecycle/load/mod.rs @@ -14,7 +14,8 @@ pub use systems::*; // --------------------------------- use crate::lifecycle::{ - load::loading_tasks::loading_is_complete, state::enums::AppState, state::transition_to, + load::loading_tasks::loading_is_complete, + state::{enums::AppState, transition_to, SimulationState}, }; use bevy::prelude::*; @@ -33,5 +34,17 @@ impl Plugin for LoadPlugin { .chain() .run_if(in_state(AppState::StartingUp)), ); + + // polling systems and tracking load state for simulation loading + app.add_systems( + Update, + ( + poll_tasks::, + transition_to(SimulationState::Running) + .run_if(loading_is_complete::), + ) + .chain() + .run_if(in_state(SimulationState::Loading)), + ); } } diff --git a/crates/shared/src/lifecycle/load/systems/fake_work_system.rs b/crates/shared/src/lifecycle/load/systems/fake_work_system.rs index b49f84b3..c3f24002 100644 --- a/crates/shared/src/lifecycle/load/systems/fake_work_system.rs +++ b/crates/shared/src/lifecycle/load/systems/fake_work_system.rs @@ -1,5 +1,5 @@ use crate::{ - lifecycle::load::components::{LoadingTaskComponent, SimulationPhase}, + lifecycle::load::components::{LoadingTaskComponent, SimulationLoadingPhase}, prelude::*, }; use bevy::{ @@ -38,5 +38,5 @@ pub fn start_fake_work_system(mut commands: Commands) { commands .entity(entity) - .insert((LoadingTaskComponent(task), SimulationPhase)); + .insert((LoadingTaskComponent(task), SimulationLoadingPhase)); } diff --git a/crates/shared/src/lifecycle/state/lifecycle.rs b/crates/shared/src/lifecycle/state/lifecycle.rs index d7893179..e3a70403 100644 --- a/crates/shared/src/lifecycle/state/lifecycle.rs +++ b/crates/shared/src/lifecycle/state/lifecycle.rs @@ -1,10 +1,10 @@ use crate::lifecycle::load::{ - SimulationPhase, check_loading_complete, cleanup_orphaned_tasks, poll_tasks, - start_fake_work_system, + check_loading_complete, cleanup_orphaned_tasks, poll_tasks, start_fake_work_system, + SimulationLoadingPhase, }; use crate::lifecycle::state::SimulationState; use bevy::prelude::{ - App, AppExtStates, IntoScheduleConfigs, OnEnter, OnExit, Plugin, Update, in_state, + in_state, App, AppExtStates, IntoScheduleConfigs, OnEnter, OnExit, Plugin, Update, }; pub struct SimulationLifecyclePlugin; @@ -14,30 +14,14 @@ pub struct SimulationLifecyclePlugin; /// involves orchestration of loading tasks and state transitions. impl Plugin for SimulationLifecyclePlugin { fn build(&self, app: &mut App) { - // INFO: --------------------------- - // state transitions - // --------------------------------- - app.init_state::(); - // INFO: ----------------------- // async loading // ----------------------------- - // polling systems and tracking load state - app.add_systems( - Update, - ( - poll_tasks::, - check_loading_complete::(SimulationState::Running) - .after(poll_tasks::), - ) - .run_if(in_state(SimulationState::Loading)), - ); - // load cleanup to run after transitions app.add_systems( OnExit(SimulationState::Loading), - cleanup_orphaned_tasks::, + cleanup_orphaned_tasks::, ); // systems to ensure rigidity diff --git a/crates/shared/src/lifecycle/state/mod.rs b/crates/shared/src/lifecycle/state/mod.rs index 4c436e1f..22ec666f 100644 --- a/crates/shared/src/lifecycle/state/mod.rs +++ b/crates/shared/src/lifecycle/state/mod.rs @@ -21,6 +21,8 @@ pub struct StatePlugin; impl Plugin for StatePlugin { fn build(&self, app: &mut App) { app.init_state::(); + app.init_state::(); + app.add_plugins(SimulationLifecyclePlugin); } } From 84a1f415e5a0e897cae0562d71279d5200add89b Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 22:12:21 +0000 Subject: [PATCH 023/106] remove lifecycle plugin --- crates/client/src/load/mod.rs | 5 +++- crates/client/src/main.rs | 4 +-- crates/client/src/player/camera/mod.rs | 2 +- crates/client/src/render/mod.rs | 8 ++--- crates/client/src/render/passes/mod.rs | 11 ++++--- .../src/render/passes/opaque/mesh/pipeline.rs | 4 +-- crates/client/src/render/passes/opaque/mod.rs | 2 +- .../client/src/render/passes/opaque/render.rs | 4 +-- crates/client/src/state/lifecycle.rs | 3 +- crates/client/src/ui/mod.rs | 2 +- crates/server/src/main.rs | 4 +-- crates/shared/src/lifecycle/load/mod.rs | 18 +++++++---- .../shared/src/lifecycle/load/systems/mod.rs | 4 ++- crates/shared/src/lifecycle/mod.rs | 3 ++ .../shared/src/lifecycle/state/lifecycle.rs | 30 ------------------- crates/shared/src/lifecycle/state/mod.rs | 7 +---- crates/shared/src/simulation/time/mod.rs | 2 +- 17 files changed, 46 insertions(+), 67 deletions(-) delete mode 100644 crates/shared/src/lifecycle/state/lifecycle.rs diff --git a/crates/client/src/load/mod.rs b/crates/client/src/load/mod.rs index 19346574..1aabdf63 100644 --- a/crates/client/src/load/mod.rs +++ b/crates/client/src/load/mod.rs @@ -11,6 +11,9 @@ pub struct ClientLoadPlugin; impl Plugin for ClientLoadPlugin { fn build(&self, app: &mut App) { // start background registry initialization - app.add_systems(OnEnter(AppState::StartingUp), start_async_registry_initialization); + app.add_systems( + OnEnter(AppState::StartingUp), + start_async_registry_initialization, + ); } } diff --git a/crates/client/src/main.rs b/crates/client/src/main.rs index 5a5e7965..3ca9c186 100644 --- a/crates/client/src/main.rs +++ b/crates/client/src/main.rs @@ -7,8 +7,8 @@ use bevy::{ app::{App, FixedUpdate, PostUpdate}, log::LogPlugin, prelude::{ - default, info, AssetPlugin, DefaultPlugins, IntoScheduleConfigs, - PluginGroup, Window, WindowPlugin, + AssetPlugin, DefaultPlugins, IntoScheduleConfigs, PluginGroup, Window, WindowPlugin, + default, info, }, window::WindowResolution, }; diff --git a/crates/client/src/player/camera/mod.rs b/crates/client/src/player/camera/mod.rs index ad9b2a75..7f241c2a 100644 --- a/crates/client/src/player/camera/mod.rs +++ b/crates/client/src/player/camera/mod.rs @@ -6,8 +6,8 @@ pub use movement::*; // camera plugin // ----------------------------- -use shared::lifecycle::state::enums::AppState; use bevy::prelude::{App, IntoScheduleConfigs, Plugin, Startup, Update, in_state}; +use shared::lifecycle::state::enums::AppState; use shared::simulation::player::initialize_camera::spawn_camera_system; pub struct CameraPlugin; diff --git a/crates/client/src/render/mod.rs b/crates/client/src/render/mod.rs index b2d5e753..74ee9867 100644 --- a/crates/client/src/render/mod.rs +++ b/crates/client/src/render/mod.rs @@ -20,8 +20,8 @@ use crate::prelude::*; use crate::render::{ chunk::{OpaqueMeshComponent, TransparentMeshComponent}, passes::{ - opaque::extract::extract_opaque_meshes, transparent::extract::extract_transparent_meshes, - RenderGraphEdgesPlugin, WorldRenderPassesPlugin, + RenderGraphEdgesPlugin, WorldRenderPassesPlugin, opaque::extract::extract_opaque_meshes, + transparent::extract::extract_transparent_meshes, }, texture::BlockTextureArray, }; @@ -29,8 +29,8 @@ use bevy::{ app::{App, Plugin, SubApp}, prelude::{Add, Commands, On}, render::{ - extract_resource::ExtractResourcePlugin, sync_world::SyncToRenderWorld, ExtractSchedule, - RenderApp, + ExtractSchedule, RenderApp, extract_resource::ExtractResourcePlugin, + sync_world::SyncToRenderWorld, }, }; #[cfg(feature = "dev")] diff --git a/crates/client/src/render/passes/mod.rs b/crates/client/src/render/passes/mod.rs index 67c682f9..e8a95f37 100644 --- a/crates/client/src/render/passes/mod.rs +++ b/crates/client/src/render/passes/mod.rs @@ -8,25 +8,24 @@ pub mod transparent; // --------------------------------- use crate::{ + VantablockNode, render::{ passes::{ bounding_box::WireframeRenderPassPlugin, opaque::OpaqueRenderPassPlugin, shadow::ShadowRenderPassPlugin, transparent::TransparentRenderPassPlugin, }, resources::{ - prepare_texture_array_system, update_camera_view_buffer_system, - update_environment_uniform_buffer_system, - world_uniforms::{ChunkStorageBindGroupLayout, ChunkStorageManager}, CentralCameraViewBindGroupLayout, CentralCameraViewUniform, EnvironmentBindGroupLayout, - EnvironmentUniforms, TextureArrayBindGroupLayout, + EnvironmentUniforms, TextureArrayBindGroupLayout, prepare_texture_array_system, + update_camera_view_buffer_system, update_environment_uniform_buffer_system, + world_uniforms::{ChunkStorageBindGroupLayout, ChunkStorageManager}, }, }, - VantablockNode, }; use bevy::prelude::IntoScheduleConfigs; use bevy::{ app::{App, Plugin}, - render::{render_graph::RenderGraphExt, Render, RenderSystems}, + render::{Render, RenderSystems, render_graph::RenderGraphExt}, }; /// A plugin that sets up all the necessary resources and render diff --git a/crates/client/src/render/passes/opaque/mesh/pipeline.rs b/crates/client/src/render/passes/opaque/mesh/pipeline.rs index 6770d0b6..8d537540 100644 --- a/crates/client/src/render/passes/opaque/mesh/pipeline.rs +++ b/crates/client/src/render/passes/opaque/mesh/pipeline.rs @@ -3,8 +3,8 @@ use crate::{ prelude::*, render::{ resources::{ - world_uniforms::ChunkStorageBindGroupLayout, CentralCameraViewBindGroupLayout, - EnvironmentBindGroupLayout, TextureArrayBindGroupLayout, + CentralCameraViewBindGroupLayout, EnvironmentBindGroupLayout, + TextureArrayBindGroupLayout, world_uniforms::ChunkStorageBindGroupLayout, }, shaders::{OPAQUE_FRAG_SHADER_HANDLE, OPAQUE_VERT_SHADER_HANDLE}, }, diff --git a/crates/client/src/render/passes/opaque/mod.rs b/crates/client/src/render/passes/opaque/mod.rs index 7506c3f8..1f2693e9 100644 --- a/crates/client/src/render/passes/opaque/mod.rs +++ b/crates/client/src/render/passes/opaque/mod.rs @@ -10,8 +10,8 @@ pub use render::OpaquePassRenderNode; // --------------------------------- use crate::{ - render::passes::opaque::{mesh::pipeline::Opaque3dPipeline, skybox::OpaqueSkyboxPipeline}, VantablockNode, + render::passes::opaque::{mesh::pipeline::Opaque3dPipeline, skybox::OpaqueSkyboxPipeline}, }; use bevy::{ prelude::{App, IntoScheduleConfigs, Plugin}, diff --git a/crates/client/src/render/passes/opaque/render.rs b/crates/client/src/render/passes/opaque/render.rs index 10714fa7..22a42c9f 100644 --- a/crates/client/src/render/passes/opaque/render.rs +++ b/crates/client/src/render/passes/opaque/render.rs @@ -3,8 +3,8 @@ use crate::render::{ data::RenderMeshStorageResource, passes::opaque::{extract::OpaqueRenderMeshComponent, queue::Opaque3dRenderPhase}, resources::{ - world_uniforms::ChunkStorageManager, CentralCameraViewUniform, EnvironmentUniforms, - TextureArrayUniforms, + CentralCameraViewUniform, EnvironmentUniforms, TextureArrayUniforms, + world_uniforms::ChunkStorageManager, }, }; use bevy::{ diff --git a/crates/client/src/state/lifecycle.rs b/crates/client/src/state/lifecycle.rs index 67a043a1..92ed9139 100644 --- a/crates/client/src/state/lifecycle.rs +++ b/crates/client/src/state/lifecycle.rs @@ -2,8 +2,7 @@ use crate::state::enums::ClientGameState; use bevy::prelude::*; use bevy::window::PrimaryWindow; use shared::lifecycle::load::{ - check_loading_complete, cleanup_orphaned_tasks, poll_tasks, AppStartupLoadingPhase, - LoadingTaskComponent, + AppStartupLoadingPhase, LoadingTaskComponent, check_loading_complete, cleanup_orphaned_tasks, }; use shared::lifecycle::state::enums::AppState; use shared::{FixedUpdateSet, RenderPrepSet}; diff --git a/crates/client/src/ui/mod.rs b/crates/client/src/ui/mod.rs index 712a8638..f3ea126a 100644 --- a/crates/client/src/ui/mod.rs +++ b/crates/client/src/ui/mod.rs @@ -1,6 +1,6 @@ -use shared::lifecycle::state::enums::AppState; use bevy::prelude::*; use shared::lifecycle::state::SimulationState; +use shared::lifecycle::state::enums::AppState; pub mod systems; diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 2fbb488a..4695f8ec 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -1,8 +1,8 @@ use bevy::{ + MinimalPlugins, app::{App, ScheduleRunnerPlugin}, asset::AssetPlugin, - prelude::{default, info, PluginGroup}, - MinimalPlugins, + prelude::{PluginGroup, default, info}, }; use server::ServerPlugins; use shared::SharedPlugins; diff --git a/crates/shared/src/lifecycle/load/mod.rs b/crates/shared/src/lifecycle/load/mod.rs index c041d578..7e8b572a 100644 --- a/crates/shared/src/lifecycle/load/mod.rs +++ b/crates/shared/src/lifecycle/load/mod.rs @@ -4,7 +4,7 @@ // tasks complete. pub mod components; -pub mod systems; +mod systems; pub use components::*; pub use systems::*; @@ -13,16 +13,16 @@ pub use systems::*; // plugin definition // --------------------------------- -use crate::lifecycle::{ - load::loading_tasks::loading_is_complete, - state::{enums::AppState, transition_to, SimulationState}, -}; +use crate::lifecycle::state::{SimulationState, enums::AppState, transition_to}; use bevy::prelude::*; pub struct LoadPlugin; impl Plugin for LoadPlugin { fn build(&self, app: &mut App) { + // TODO: remove temp fake work system for testing + app.add_systems(OnEnter(SimulationState::Loading), start_fake_work_system); + // polling systems and tracking load state for app startup app.add_systems( Update, @@ -33,6 +33,10 @@ impl Plugin for LoadPlugin { ) .chain() .run_if(in_state(AppState::StartingUp)), + ) + .add_systems( + OnExit(AppState::StartingUp), + cleanup_orphaned_tasks::, ); // polling systems and tracking load state for simulation loading @@ -45,6 +49,10 @@ impl Plugin for LoadPlugin { ) .chain() .run_if(in_state(SimulationState::Loading)), + ) + .add_systems( + OnExit(SimulationState::Loading), + cleanup_orphaned_tasks::, ); } } diff --git a/crates/shared/src/lifecycle/load/systems/mod.rs b/crates/shared/src/lifecycle/load/systems/mod.rs index 2705c563..479bc1e1 100644 --- a/crates/shared/src/lifecycle/load/systems/mod.rs +++ b/crates/shared/src/lifecycle/load/systems/mod.rs @@ -2,4 +2,6 @@ pub mod fake_work_system; pub mod loading_tasks; pub use fake_work_system::start_fake_work_system; -pub use loading_tasks::{check_loading_complete, cleanup_orphaned_tasks, poll_tasks}; +pub use loading_tasks::{ + check_loading_complete, cleanup_orphaned_tasks, loading_is_complete, poll_tasks, +}; diff --git a/crates/shared/src/lifecycle/mod.rs b/crates/shared/src/lifecycle/mod.rs index cf745bc8..36d897f1 100644 --- a/crates/shared/src/lifecycle/mod.rs +++ b/crates/shared/src/lifecycle/mod.rs @@ -1,6 +1,9 @@ pub mod load; pub mod state; +pub use load::*; +pub use state::*; + // INFO: --------------------------- // plugin definition // --------------------------------- diff --git a/crates/shared/src/lifecycle/state/lifecycle.rs b/crates/shared/src/lifecycle/state/lifecycle.rs deleted file mode 100644 index e3a70403..00000000 --- a/crates/shared/src/lifecycle/state/lifecycle.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::lifecycle::load::{ - check_loading_complete, cleanup_orphaned_tasks, poll_tasks, start_fake_work_system, - SimulationLoadingPhase, -}; -use crate::lifecycle::state::SimulationState; -use bevy::prelude::{ - in_state, App, AppExtStates, IntoScheduleConfigs, OnEnter, OnExit, Plugin, Update, -}; - -pub struct SimulationLifecyclePlugin; - -/// A plugin for the simulation world that sets up the necessary -/// systems for handling the application lifecycle. This primarily -/// involves orchestration of loading tasks and state transitions. -impl Plugin for SimulationLifecyclePlugin { - fn build(&self, app: &mut App) { - // INFO: ----------------------- - // async loading - // ----------------------------- - - // load cleanup to run after transitions - app.add_systems( - OnExit(SimulationState::Loading), - cleanup_orphaned_tasks::, - ); - - // systems to ensure rigidity - app.add_systems(OnEnter(SimulationState::Loading), start_fake_work_system); - } -} diff --git a/crates/shared/src/lifecycle/state/mod.rs b/crates/shared/src/lifecycle/state/mod.rs index 22ec666f..9f6f7cd1 100644 --- a/crates/shared/src/lifecycle/state/mod.rs +++ b/crates/shared/src/lifecycle/state/mod.rs @@ -1,9 +1,7 @@ pub mod enums; -pub mod lifecycle; pub mod systems; -pub use enums::SimulationState; -pub use lifecycle::SimulationLifecyclePlugin; +pub use enums::{AppState, SimulationState}; pub use systems::transition_to; // INFO: --------------------------- @@ -14,7 +12,6 @@ use bevy::{ prelude::{App, Plugin}, state::app::AppExtStates, }; -use enums::AppState; pub struct StatePlugin; @@ -22,7 +19,5 @@ impl Plugin for StatePlugin { fn build(&self, app: &mut App) { app.init_state::(); app.init_state::(); - - app.add_plugins(SimulationLifecyclePlugin); } } diff --git a/crates/shared/src/simulation/time/mod.rs b/crates/shared/src/simulation/time/mod.rs index 2ee7a620..f50b1310 100644 --- a/crates/shared/src/simulation/time/mod.rs +++ b/crates/shared/src/simulation/time/mod.rs @@ -10,6 +10,7 @@ use world_clock::{jump_world_clock_backwards_system, jump_world_clock_forward_sy // Time plugin // --------------------------- +use crate::lifecycle::state::SimulationState; use crate::simulation::{ input::{resources::ActionStateResource, types::simulation_action::SimulationAction}, time::{ @@ -17,7 +18,6 @@ use crate::simulation::{ simulation_tick::run_fixed_update_schedule, world_clock::update_world_clock_system, }, }; -use crate::lifecycle::state::SimulationState; use bevy::{ app::{App, FixedUpdate, Plugin, PreUpdate, Update}, ecs::prelude::*, From 45d099bf2077fa9853082c282791131049334abf Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 22:34:17 +0000 Subject: [PATCH 024/106] refactor client folder --- crates/client/src/lib.rs | 7 ++--- crates/client/src/{ => lifecycle}/load/mod.rs | 2 +- .../src/{ => lifecycle}/load/registries.rs | 0 crates/client/src/lifecycle/mod.rs | 23 ++++++++++++++ .../client/src/{ => lifecycle}/state/enums.rs | 3 ++ .../lifecycle.rs => lifecycle/state/mod.rs} | 30 ++++++++++++++----- crates/client/src/state/mod.rs | 22 -------------- justfile | 1 + 8 files changed, 53 insertions(+), 35 deletions(-) rename crates/client/src/{ => lifecycle}/load/mod.rs (88%) rename crates/client/src/{ => lifecycle}/load/registries.rs (100%) create mode 100644 crates/client/src/lifecycle/mod.rs rename crates/client/src/{ => lifecycle}/state/enums.rs (80%) rename crates/client/src/{state/lifecycle.rs => lifecycle/state/mod.rs} (75%) delete mode 100644 crates/client/src/state/mod.rs diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index 2e371f8d..4809932b 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -1,11 +1,10 @@ pub mod input; -pub mod load; +pub mod lifecycle; pub mod player; pub mod prelude; pub mod render; pub mod settings; pub mod showcase; -pub mod state; pub mod ui; pub use prelude::*; @@ -23,9 +22,7 @@ pub struct ClientPlugins; impl PluginGroup for ClientPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() - .add(state::StatePlugin) - .add(state::ClientLifecyclePlugin) - .add(load::ClientLoadPlugin) + .add_group(lifecycle::LifecyclePlugins) .add(input::InputModulePlugin) .add(player::PlayerPlugin) .add(showcase::ShowcasePlugin) diff --git a/crates/client/src/load/mod.rs b/crates/client/src/lifecycle/load/mod.rs similarity index 88% rename from crates/client/src/load/mod.rs rename to crates/client/src/lifecycle/load/mod.rs index 1aabdf63..66ce4a72 100644 --- a/crates/client/src/load/mod.rs +++ b/crates/client/src/lifecycle/load/mod.rs @@ -1,8 +1,8 @@ pub mod registries; -use crate::load::registries::start_async_registry_initialization; use bevy::app::{App, Plugin}; use bevy::prelude::OnEnter; +use registries::start_async_registry_initialization; use shared::lifecycle::state::enums::AppState; /// Plugin responsible for managing client-side asset and registry loading. diff --git a/crates/client/src/load/registries.rs b/crates/client/src/lifecycle/load/registries.rs similarity index 100% rename from crates/client/src/load/registries.rs rename to crates/client/src/lifecycle/load/registries.rs diff --git a/crates/client/src/lifecycle/mod.rs b/crates/client/src/lifecycle/mod.rs new file mode 100644 index 00000000..949c5213 --- /dev/null +++ b/crates/client/src/lifecycle/mod.rs @@ -0,0 +1,23 @@ +pub mod load; +pub mod state; + +pub use load::*; +pub use state::*; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +use bevy::app::PluginGroupBuilder; +use bevy::prelude::PluginGroup; + +/// A plugin group containing client lifecycle stuff. +pub struct LifecyclePlugins; + +impl PluginGroup for LifecyclePlugins { + fn build(self) -> PluginGroupBuilder { + PluginGroupBuilder::start::() + .add(ClientStatePlugin) + .add(ClientLoadPlugin) + } +} diff --git a/crates/client/src/state/enums.rs b/crates/client/src/lifecycle/state/enums.rs similarity index 80% rename from crates/client/src/state/enums.rs rename to crates/client/src/lifecycle/state/enums.rs index 1dcaa5c8..8f50f588 100644 --- a/crates/client/src/state/enums.rs +++ b/crates/client/src/lifecycle/state/enums.rs @@ -7,6 +7,9 @@ use shared::lifecycle::state::enums::AppState; #[derive(SubStates, Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] #[source(AppState = AppState::Running)] pub enum ClientGameState { + /// The client is currently launching and loading data before hitting the main menu. + // TODO: make launching default + Launching, /// The user is navigating the main menu UI. #[default] MainMenu, diff --git a/crates/client/src/state/lifecycle.rs b/crates/client/src/lifecycle/state/mod.rs similarity index 75% rename from crates/client/src/state/lifecycle.rs rename to crates/client/src/lifecycle/state/mod.rs index 92ed9139..5ce90656 100644 --- a/crates/client/src/state/lifecycle.rs +++ b/crates/client/src/lifecycle/state/mod.rs @@ -1,16 +1,32 @@ -use crate::state::enums::ClientGameState; +pub mod enums; + +pub use enums::*; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + use bevy::prelude::*; use bevy::window::PrimaryWindow; -use shared::lifecycle::load::{ - AppStartupLoadingPhase, LoadingTaskComponent, check_loading_complete, cleanup_orphaned_tasks, +use bevy::{ + prelude::{App, Plugin}, + state::app::AppExtStates, +}; +use shared::{ + lifecycle::load::{ + check_loading_complete, cleanup_orphaned_tasks, AppStartupLoadingPhase, + LoadingTaskComponent, + }, + lifecycle::state::enums::AppState, + {FixedUpdateSet, RenderPrepSet}, }; -use shared::lifecycle::state::enums::AppState; -use shared::{FixedUpdateSet, RenderPrepSet}; -pub struct ClientLifecyclePlugin; +pub struct ClientStatePlugin; -impl Plugin for ClientLifecyclePlugin { +impl Plugin for ClientStatePlugin { fn build(&self, app: &mut App) { + app.add_sub_state::(); + // INFO: ----------------------- // async loading // ----------------------------- diff --git a/crates/client/src/state/mod.rs b/crates/client/src/state/mod.rs deleted file mode 100644 index 36a17ba3..00000000 --- a/crates/client/src/state/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -pub mod enums; -pub mod lifecycle; - -pub use enums::*; -pub use lifecycle::*; - -// INFO: --------------------------- -// plugin definition -// --------------------------------- - -use bevy::{ - prelude::{App, Plugin}, - state::app::AppExtStates, -}; - -pub struct StatePlugin; - -impl Plugin for StatePlugin { - fn build(&self, app: &mut App) { - app.add_sub_state::(); - } -} diff --git a/justfile b/justfile index 550b6e15..f44c22af 100644 --- a/justfile +++ b/justfile @@ -65,6 +65,7 @@ fmt: # cleans ephemeral dirs clean: rm -rf target/ + rm -rf .dev_data/ alias clip := clippy From 28d7663faa24cea420bd87130db484a4ede9e36b Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 23:14:16 +0000 Subject: [PATCH 025/106] scheduliing subfolder --- crates/client/src/lifecycle/mod.rs | 8 ++++--- crates/client/src/lifecycle/scheduling/mod.rs | 23 ++++++++++++++++++ .../client/src/lifecycle/scheduling/sets.rs | 6 +++++ crates/client/src/lifecycle/state/mod.rs | 24 +++++-------------- crates/client/src/main.rs | 16 +++---------- crates/client/src/render/chunk/mod.rs | 2 +- .../lifecycle/load/systems/loading_tasks.rs | 13 ---------- .../shared/src/lifecycle/load/systems/mod.rs | 4 +--- crates/shared/src/lifecycle/mod.rs | 3 +++ crates/shared/src/lifecycle/scheduling/mod.rs | 20 ++++++++++++++++ .../scheduling/sets.rs} | 5 ---- crates/shared/src/prelude.rs | 2 +- crates/shared/src/simulation/chunk/mod.rs | 2 +- crates/shared/src/simulation/mod.rs | 1 - 14 files changed, 70 insertions(+), 59 deletions(-) create mode 100644 crates/client/src/lifecycle/scheduling/mod.rs create mode 100644 crates/client/src/lifecycle/scheduling/sets.rs create mode 100644 crates/shared/src/lifecycle/scheduling/mod.rs rename crates/shared/src/{simulation/scheduling.rs => lifecycle/scheduling/sets.rs} (65%) diff --git a/crates/client/src/lifecycle/mod.rs b/crates/client/src/lifecycle/mod.rs index 949c5213..d2118363 100644 --- a/crates/client/src/lifecycle/mod.rs +++ b/crates/client/src/lifecycle/mod.rs @@ -1,4 +1,5 @@ pub mod load; +pub mod scheduling; pub mod state; pub use load::*; @@ -8,8 +9,8 @@ pub use state::*; // plugin definition // --------------------------------- -use bevy::app::PluginGroupBuilder; -use bevy::prelude::PluginGroup; +use bevy::{app::PluginGroupBuilder, prelude::PluginGroup}; +use scheduling::ClientSchedulingPlugin; /// A plugin group containing client lifecycle stuff. pub struct LifecyclePlugins; @@ -17,7 +18,8 @@ pub struct LifecyclePlugins; impl PluginGroup for LifecyclePlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() - .add(ClientStatePlugin) .add(ClientLoadPlugin) + .add(ClientSchedulingPlugin) + .add(ClientStatePlugin) } } diff --git a/crates/client/src/lifecycle/scheduling/mod.rs b/crates/client/src/lifecycle/scheduling/mod.rs new file mode 100644 index 00000000..b721bcdf --- /dev/null +++ b/crates/client/src/lifecycle/scheduling/mod.rs @@ -0,0 +1,23 @@ +pub mod sets; + +pub use sets::RenderPrepSet; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +use crate::lifecycle::ClientGameState; +use bevy::prelude::*; + +pub struct ClientSchedulingPlugin; + +impl Plugin for ClientSchedulingPlugin { + fn build(&self, app: &mut App) { + app.configure_sets( + PostUpdate, + RenderPrepSet.run_if( + in_state(ClientGameState::Playing).or(in_state(ClientGameState::Connecting)), + ), + ); + } +} diff --git a/crates/client/src/lifecycle/scheduling/sets.rs b/crates/client/src/lifecycle/scheduling/sets.rs new file mode 100644 index 00000000..49d1aba5 --- /dev/null +++ b/crates/client/src/lifecycle/scheduling/sets.rs @@ -0,0 +1,6 @@ +use bevy::ecs::prelude::SystemSet; + +/// Systems that prepare data for the render world. +/// These typically run at the very end of Bevy's native `PostUpdate` schedule. +#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)] +pub struct RenderPrepSet; diff --git a/crates/client/src/lifecycle/state/mod.rs b/crates/client/src/lifecycle/state/mod.rs index 5ce90656..04029475 100644 --- a/crates/client/src/lifecycle/state/mod.rs +++ b/crates/client/src/lifecycle/state/mod.rs @@ -13,13 +13,11 @@ use bevy::{ state::app::AppExtStates, }; use shared::{ - lifecycle::load::{ - check_loading_complete, cleanup_orphaned_tasks, AppStartupLoadingPhase, - LoadingTaskComponent, - }, + FixedUpdateSet, + lifecycle::load::{AppStartupLoadingPhase, LoadingTaskComponent, cleanup_orphaned_tasks}, lifecycle::state::enums::AppState, - {FixedUpdateSet, RenderPrepSet}, }; +use shared::{loading_is_complete, transition_to}; pub struct ClientStatePlugin; @@ -34,12 +32,9 @@ impl Plugin for ClientStatePlugin { // polling systems for simulation-linked client state transitions app.add_systems( Update, - ( - check_loading_complete::( - ClientGameState::Playing, - ) - .run_if(in_state(ClientGameState::MainMenu)), - ) + (transition_to(ClientGameState::Playing) + .run_if(loading_is_complete::) + .run_if(in_state(ClientGameState::MainMenu)),) .run_if(in_state(AppState::Running)), ); @@ -57,13 +52,6 @@ impl Plugin for ClientStatePlugin { ), ); - app.configure_sets( - PostUpdate, - RenderPrepSet.run_if( - in_state(ClientGameState::Playing).or(in_state(ClientGameState::Connecting)), - ), - ); - // INFO: --------------------------- // state transitions // --------------------------------- diff --git a/crates/client/src/main.rs b/crates/client/src/main.rs index 3ca9c186..a1eb9a46 100644 --- a/crates/client/src/main.rs +++ b/crates/client/src/main.rs @@ -4,16 +4,12 @@ use bevy::dev_tools::fps_overlay::{FpsOverlayConfig, FpsOverlayPlugin}; use bevy::{ - app::{App, FixedUpdate, PostUpdate}, + app::{App, PostUpdate}, log::LogPlugin, - prelude::{ - AssetPlugin, DefaultPlugins, IntoScheduleConfigs, PluginGroup, Window, WindowPlugin, - default, info, - }, + prelude::{AssetPlugin, DefaultPlugins, PluginGroup, Window, WindowPlugin, default, info}, window::WindowResolution, }; -use client::prelude::*; -use shared::simulation::scheduling::{FixedUpdateSet, RenderPrepSet}; +use client::{lifecycle::scheduling::RenderPrepSet, prelude::*}; use utils::PersistentPaths; #[instrument(skip_all, fields(name = "main"))] @@ -53,12 +49,6 @@ fn main() { app.insert_resource(ClientSettings::load_or_create(&persistent_paths)); app.insert_resource(persistent_paths); - // configure schedule sets - app.configure_sets( - FixedUpdate, - (FixedUpdateSet::PreUpdate, FixedUpdateSet::MainLogic).chain(), - ); - app.configure_sets(PostUpdate, RenderPrepSet); // initialize simulation and renderer diff --git a/crates/client/src/render/chunk/mod.rs b/crates/client/src/render/chunk/mod.rs index ca2a6846..7ab54f31 100644 --- a/crates/client/src/render/chunk/mod.rs +++ b/crates/client/src/render/chunk/mod.rs @@ -5,6 +5,7 @@ pub mod tasks; pub use asset::VoxelMeshAsset; pub use components::{OpaqueMeshComponent, TransparentMeshComponent}; +use shared::FixedUpdateSet; pub use shared::simulation::chunk::ChunkMeshDirty; use crate::prelude::*; @@ -13,7 +14,6 @@ use bevy::asset::AssetApp; use bevy::ecs::prelude::*; use bevy::prelude::{Camera, Camera3d}; use shared::simulation::chunk::{ChunkCoord, ChunkStateManager}; -use shared::simulation::scheduling::FixedUpdateSet; pub struct ChunkMeshingPlugin; diff --git a/crates/shared/src/lifecycle/load/systems/loading_tasks.rs b/crates/shared/src/lifecycle/load/systems/loading_tasks.rs index 9e6f51af..c55c0aeb 100644 --- a/crates/shared/src/lifecycle/load/systems/loading_tasks.rs +++ b/crates/shared/src/lifecycle/load/systems/loading_tasks.rs @@ -1,8 +1,6 @@ use crate::{lifecycle::load::components::LoadingTaskComponent, prelude::*}; use bevy::{ ecs::prelude::*, - prelude::{NextState, States}, - state::state::FreelyMutableState, tasks::{block_on, poll_once}, }; @@ -43,14 +41,3 @@ pub fn cleanup_orphaned_tasks( pub fn loading_is_complete(query: Query<(), With>) -> bool { query.is_empty() } - -/// A transition checker that moves to a target state when all entities with a marker are gone. -pub fn check_loading_complete( - target_state: S, -) -> impl FnMut(Query<(), With>, ResMut>) { - move |tasks_query, mut next_state| { - if tasks_query.is_empty() { - next_state.set(target_state); - } - } -} diff --git a/crates/shared/src/lifecycle/load/systems/mod.rs b/crates/shared/src/lifecycle/load/systems/mod.rs index 479bc1e1..83e6cdfc 100644 --- a/crates/shared/src/lifecycle/load/systems/mod.rs +++ b/crates/shared/src/lifecycle/load/systems/mod.rs @@ -2,6 +2,4 @@ pub mod fake_work_system; pub mod loading_tasks; pub use fake_work_system::start_fake_work_system; -pub use loading_tasks::{ - check_loading_complete, cleanup_orphaned_tasks, loading_is_complete, poll_tasks, -}; +pub use loading_tasks::{cleanup_orphaned_tasks, loading_is_complete, poll_tasks}; diff --git a/crates/shared/src/lifecycle/mod.rs b/crates/shared/src/lifecycle/mod.rs index 36d897f1..09844606 100644 --- a/crates/shared/src/lifecycle/mod.rs +++ b/crates/shared/src/lifecycle/mod.rs @@ -1,7 +1,9 @@ pub mod load; +pub mod scheduling; pub mod state; pub use load::*; +pub use scheduling::*; pub use state::*; // INFO: --------------------------- @@ -18,6 +20,7 @@ impl PluginGroup for SharedLifecyclePlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::() .add(load::LoadPlugin) + .add(scheduling::SharedSchedulingPlugin) .add(state::StatePlugin) } } diff --git a/crates/shared/src/lifecycle/scheduling/mod.rs b/crates/shared/src/lifecycle/scheduling/mod.rs new file mode 100644 index 00000000..58641ee8 --- /dev/null +++ b/crates/shared/src/lifecycle/scheduling/mod.rs @@ -0,0 +1,20 @@ +pub mod sets; + +pub use sets::FixedUpdateSet; + +// INFO: --------------------------- +// plugin definition +// --------------------------------- + +use bevy::prelude::*; + +pub struct SharedSchedulingPlugin; + +impl Plugin for SharedSchedulingPlugin { + fn build(&self, app: &mut App) { + app.configure_sets( + FixedUpdate, + (FixedUpdateSet::PreUpdate, FixedUpdateSet::MainLogic).chain(), + ); + } +} diff --git a/crates/shared/src/simulation/scheduling.rs b/crates/shared/src/lifecycle/scheduling/sets.rs similarity index 65% rename from crates/shared/src/simulation/scheduling.rs rename to crates/shared/src/lifecycle/scheduling/sets.rs index 6757f961..2f9a6195 100644 --- a/crates/shared/src/simulation/scheduling.rs +++ b/crates/shared/src/lifecycle/scheduling/sets.rs @@ -9,8 +9,3 @@ pub enum FixedUpdateSet { /// The main sim logic: player movement, AI, block breaking, etc. MainLogic, } - -/// Systems that prepare data for the render world. -/// These typically run at the very end of Bevy's native `PostUpdate` schedule. -#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)] -pub struct RenderPrepSet; diff --git a/crates/shared/src/prelude.rs b/crates/shared/src/prelude.rs index fe63bbd1..4948f030 100644 --- a/crates/shared/src/prelude.rs +++ b/crates/shared/src/prelude.rs @@ -2,7 +2,7 @@ // crate imports // ----------------------------- -pub use crate::simulation::scheduling::*; +pub use crate::lifecycle::*; pub use utils::*; // INFO: ------------------------------- diff --git a/crates/shared/src/simulation/chunk/mod.rs b/crates/shared/src/simulation/chunk/mod.rs index 9118ea71..fbe91145 100644 --- a/crates/shared/src/simulation/chunk/mod.rs +++ b/crates/shared/src/simulation/chunk/mod.rs @@ -14,7 +14,7 @@ pub use types::*; // chunk loading plugin // ------------------------------------ -use crate::simulation::scheduling::FixedUpdateSet; +use crate::FixedUpdateSet; use bevy::app::{App, FixedUpdate, Plugin, PreUpdate}; use bevy::ecs::prelude::*; use bevy::prelude::{Camera, Camera3d}; diff --git a/crates/shared/src/simulation/mod.rs b/crates/shared/src/simulation/mod.rs index 1b818490..fa77439d 100644 --- a/crates/shared/src/simulation/mod.rs +++ b/crates/shared/src/simulation/mod.rs @@ -4,6 +4,5 @@ pub mod block; pub mod chunk; pub mod input; pub mod player; -pub mod scheduling; pub mod terrain; pub mod time; From ee2f231d7212046fd76cdb59f327f82c15b59522 Mon Sep 17 00:00:00 2001 From: mason <58895787+masoniis@users.noreply.github.com> Date: Fri, 10 Apr 2026 23:38:32 +0000 Subject: [PATCH 026/106] add a launching screen/main menu --- crates/client/src/lifecycle/state/enums.rs | 17 +++- crates/client/src/lifecycle/state/mod.rs | 15 +-- crates/client/src/ui/mod.rs | 11 ++- crates/client/src/ui/systems/main_menu.rs | 96 +++++++++++++++++++ crates/client/src/ui/systems/mod.rs | 1 + .../client/src/ui/systems/starting_up_ui.rs | 12 +-- 6 files changed, 130 insertions(+), 22 deletions(-) create mode 100644 crates/client/src/ui/systems/main_menu.rs diff --git a/crates/client/src/lifecycle/state/enums.rs b/crates/client/src/lifecycle/state/enums.rs index 8f50f588..c2e82cee 100644 --- a/crates/client/src/lifecycle/state/enums.rs +++ b/crates/client/src/lifecycle/state/enums.rs @@ -8,13 +8,22 @@ use shared::lifecycle::state::enums::AppState; #[source(AppState = AppState::Running)] pub enum ClientGameState { /// The client is currently launching and loading data before hitting the main menu. - // TODO: make launching default - Launching, - /// The user is navigating the main menu UI. #[default] + Loading, + /// The user is navigating the main menu UI. MainMenu, - /// The client is attempting to establish a connection to a server or load into a world. + /// The client is attempting to establish a connection to a server. Connecting, + /// A server connection is formed but the client is waiting for initial chunk data + /// to arrive. + WorldLoading, /// The client is actively connected and in a game session. Playing, + /// The pause menu is open. In single-player, this stops the clock. In multiplayer, + /// it doesn't. + Paused, + /// Disconnect requested, clean up world/meshes, serialization, etc. + Disconnecting, + /// An error occurred (kick reason, connection failure) + Error, } diff --git a/crates/client/src/lifecycle/state/mod.rs b/crates/client/src/lifecycle/state/mod.rs index 04029475..50ecaf6b 100644 --- a/crates/client/src/lifecycle/state/mod.rs +++ b/crates/client/src/lifecycle/state/mod.rs @@ -14,10 +14,10 @@ use bevy::{ }; use shared::{ FixedUpdateSet, - lifecycle::load::{AppStartupLoadingPhase, LoadingTaskComponent, cleanup_orphaned_tasks}, - lifecycle::state::enums::AppState, + lifecycle::load::{AppStartupLoadingPhase, cleanup_orphaned_tasks}, + lifecycle::state::{SimulationState, enums::AppState}, }; -use shared::{loading_is_complete, transition_to}; +use shared::transition_to; pub struct ClientStatePlugin; @@ -32,9 +32,12 @@ impl Plugin for ClientStatePlugin { // polling systems for simulation-linked client state transitions app.add_systems( Update, - (transition_to(ClientGameState::Playing) - .run_if(loading_is_complete::) - .run_if(in_state(ClientGameState::MainMenu)),) + ( + // transition from loading to main menu once simulation is ready + transition_to(ClientGameState::MainMenu) + .run_if(in_state(ClientGameState::Loading)) + .run_if(in_state(SimulationState::Running)), + ) .run_if(in_state(AppState::Running)), ); diff --git a/crates/client/src/ui/mod.rs b/crates/client/src/ui/mod.rs index f3ea126a..7fed210e 100644 --- a/crates/client/src/ui/mod.rs +++ b/crates/client/src/ui/mod.rs @@ -2,6 +2,7 @@ use bevy::prelude::*; use shared::lifecycle::state::SimulationState; use shared::lifecycle::state::enums::AppState; +use crate::lifecycle::state::ClientGameState; pub mod systems; // INFO: ------------------- @@ -25,10 +26,16 @@ impl Plugin for VantablockUiPlugin { app.add_systems( OnEnter(SimulationState::Loading), systems::starting_up_ui::spawn_starting_up_ui, + ); + + // main menu ui + app.add_systems( + OnEnter(ClientGameState::MainMenu), + systems::main_menu::spawn_main_menu, ) .add_systems( - OnExit(SimulationState::Loading), - systems::starting_up_ui::despawn_starting_up_ui, + Update, + systems::main_menu::main_menu_button_interaction_system.run_if(in_state(ClientGameState::MainMenu)), ); } } diff --git a/crates/client/src/ui/systems/main_menu.rs b/crates/client/src/ui/systems/main_menu.rs new file mode 100644 index 00000000..6f92ab4e --- /dev/null +++ b/crates/client/src/ui/systems/main_menu.rs @@ -0,0 +1,96 @@ +use crate::lifecycle::state::ClientGameState; +use bevy::prelude::*; + +#[derive(Component)] +pub struct MainMenuUiRoot; + +pub fn spawn_main_menu(mut commands: Commands, asset_server: Res) { + info!("Spawning Main Menu UI..."); + + let font = asset_server.load("client/font/Recursive_variable.ttf"); + + commands + .spawn(( + Node { + width: Val::Percent(100.0), + height: Val::Percent(100.0), + display: Display::Flex, + flex_direction: FlexDirection::Column, + align_items: AlignItems::Center, + justify_content: JustifyContent::Center, + ..Default::default() + }, + MainMenuUiRoot, + DespawnOnExit(ClientGameState::MainMenu), + )) + .with_children(|parent| { + // title + parent.spawn(( + Text::new("VANTABLOCK"), + TextFont { + font: font.clone(), + font_size: 72.0, + ..Default::default() + }, + TextColor(Color::WHITE), + Node { + margin: UiRect::bottom(Val::Px(40.0)), + ..Default::default() + }, + )); + + // play button + parent + .spawn(( + Button, + Node { + width: Val::Px(250.0), + height: Val::Px(65.0), + border: UiRect::all(Val::Px(2.0)), + justify_content: JustifyContent::Center, + align_items: AlignItems::Center, + ..Default::default() + }, + BorderColor::all(Color::WHITE), + BackgroundColor(Color::LinearRgba(LinearRgba::new(0.1, 0.1, 0.1, 0.9))), + )) + .with_children(|parent| { + parent.spawn(( + Text::new("PLAY"), + TextFont { + font: font.clone(), + font_size: 32.0, + ..Default::default() + }, + TextColor(Color::WHITE), + )); + }); + }); +} + +pub fn main_menu_button_interaction_system( + mut interaction_query: Query< + (&Interaction, &mut BackgroundColor, &mut BorderColor), + (Changed, With