From e2f6d6a71c2f56b85c4727217dddf2e19040326e Mon Sep 17 00:00:00 2001 From: core Date: Mon, 17 Nov 2025 10:13:56 -0500 Subject: [PATCH] fix: ui --- .cargo/config.toml | 3 + Cargo.lock | 129 +++++++++++++++++++++++++++ crates/unified/Cargo.toml | 7 +- crates/unified/src/client/mod.rs | 4 +- crates/unified/src/client/ui.rs | 5 +- crates/unified/src/client_plugins.rs | 8 ++ crates/unified/src/main.rs | 89 ++++++++++++------ 7 files changed, 213 insertions(+), 32 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index f8e800027a55eb56620da3ccb99bb764c90a6363..04791d0ead1bdf08a9065432949d8a1db89bbeb5 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,9 @@ [alias] xtask = "run --release --package xtask --" +#[build] +#rustc-wrapper = "/usr/bin/sccache" + [target.x86_64-unknown-linux-gnu] #linker = "mold" rustflags = ["-C", "link-arg=-fuse-ld=mold"] diff --git a/Cargo.lock b/Cargo.lock index 78286f0ed227ab6682216142220620509501626c..fa9ea2448e48141a78eb22e173d8bc1f7cba8010 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -778,6 +778,55 @@ dependencies = [ "bevy_internal", ] +[[package]] +name = "bevy-inspector-egui" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3692cbc0a76398ee01dde2c49951c8a92c5373c58e8720a0909e9504d21e9ab" +dependencies = [ + "bevy-inspector-egui-derive", + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_core_pipeline", + "bevy_ecs", + "bevy_egui", + "bevy_image", + "bevy_light", + "bevy_log", + "bevy_math", + "bevy_mesh", + "bevy_pbr", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_state", + "bevy_time", + "bevy_utils", + "bevy_window", + "bytemuck", + "disqualified", + "egui 0.33.2", + "fuzzy-matcher", + "image", + "opener", + "smallvec", + "uuid", + "winit", +] + +[[package]] +name = "bevy-inspector-egui-derive" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9569b1caad44483de562c6115c773d4311374d1740f5e6e69413d92206363c3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bevy_a11y" version = "0.17.2" @@ -1291,6 +1340,7 @@ dependencies = [ "bevy_time", "bevy_transform", "bevy_ui", + "bevy_ui_render", "bevy_utils", "bevy_window", "bevy_winit", @@ -1400,6 +1450,42 @@ version = "0.17.0-dev" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef8e4b7e61dfe7719bb03c884dc270cd46a82efb40f93e9933b990c5c190c59" +[[package]] +name = "bevy_pbr" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8c76337a6ae9d73d50be168aeee974d05fdeda9129a413eaff719e3b7b5fea" +dependencies = [ + "bevy_app", + "bevy_asset", + "bevy_camera", + "bevy_color", + "bevy_core_pipeline", + "bevy_derive", + "bevy_diagnostic", + "bevy_ecs", + "bevy_image", + "bevy_light", + "bevy_math", + "bevy_mesh", + "bevy_platform", + "bevy_reflect", + "bevy_render", + "bevy_shader", + "bevy_transform", + "bevy_utils", + "bitflags 2.10.0", + "bytemuck", + "derive_more", + "fixedbitset", + "nonmax", + "offset-allocator", + "smallvec", + "static_assertions", + "thiserror 2.0.17", + "tracing", +] + [[package]] name = "bevy_picking" version = "0.17.2" @@ -2003,6 +2089,7 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" dependencies = [ + "bytemuck", "serde_core", ] @@ -2065,6 +2152,17 @@ dependencies = [ "piper", ] +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -3806,6 +3904,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fuzzy-matcher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" +dependencies = [ + "thread_local", +] + [[package]] name = "generational-box" version = "0.7.1" @@ -5141,6 +5248,15 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" +[[package]] +name = "normpath" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf23ab2b905654b4cb177e30b629937b3868311d4e1cba859f899c041046e69b" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "notify" version = "7.0.0" @@ -5728,6 +5844,17 @@ version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" +[[package]] +name = "opener" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9024962ab91e00c89d2a14352a8d0fc1a64346bf96f1839b45c09149564e47" +dependencies = [ + "bstr", + "normpath", + "windows-sys 0.60.2", +] + [[package]] name = "openssl-probe" version = "0.1.6" @@ -7159,12 +7286,14 @@ dependencies = [ "aeronet_transport", "aeronet_websocket", "bevy", + "bevy-inspector-egui", "bevy_common_assets", "bevy_egui", "bevy_rapier2d", "bevy_replicon", "clap", "console_error_panic_hook", + "ctrlc", "getrandom 0.3.4", "ordered-float 5.1.0", "rand 0.9.2", diff --git a/crates/unified/Cargo.toml b/crates/unified/Cargo.toml index 5d5c3beec403dc99374b196d55e19b0354c8d588..576c457c892cfb0576c95e72eee96e8e2241ae18 100644 --- a/crates/unified/Cargo.toml +++ b/crates/unified/Cargo.toml @@ -34,7 +34,8 @@ bevy = { version = "0.17", default-features = false, features = [ "bevy_gizmos", "bevy_post_process", "bevy_anti_alias", - "bevy_sprite_render" + "bevy_sprite_render", + "bevy_ui_render" ] } bevy_rapier2d = { features = ["serde-serialize", "simd-stable"], git = "https://github.com/Deniskore/bevy_rapier", branch = "bevy-0.17" } bevy_common_assets = { version = "0.14", features = ["toml"] } @@ -61,6 +62,10 @@ bevy_egui = "0.38" ordered-float = { version = "5", features = ["serde"] } ron = "0.12" +ctrlc = "3.5" + +bevy-inspector-egui = "0.35" + [target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/unified/src/client/mod.rs b/crates/unified/src/client/mod.rs index ed6af2e19070455ca8c282ee0bb1db59f067c6a8..18f873911311ea4d3fa0d53359a6d25fa6223fcd 100644 --- a/crates/unified/src/client/mod.rs +++ b/crates/unified/src/client/mod.rs @@ -22,6 +22,7 @@ use bevy::core_pipeline::tonemapping::DebandDither; use bevy::dev_tools::picking_debug::DebugPickingMode; use bevy::post_process::bloom::Bloom; use bevy::prelude::*; +use bevy::render::render_phase::DrawFunctions; use bevy::window::PrimaryWindow; use planet::incoming_planets::incoming_planets_plugin; @@ -31,7 +32,8 @@ pub struct ClientPlugin { impl Plugin for ClientPlugin { fn build(&self, app: &mut App) { let server = self.server.clone(); - app.insert_resource(CursorWorldCoordinates(None)) + app + .insert_resource(CursorWorldCoordinates(None)) .add_systems(Startup, move |mut commands: Commands| { let config = net::websocket_config(); diff --git a/crates/unified/src/client/ui.rs b/crates/unified/src/client/ui.rs index 4baaa5e145b7d16b687df4fa97b32b36b5dee5dd..5e875a3d91110e67240593be9336c3abfc5d89e0 100644 --- a/crates/unified/src/client/ui.rs +++ b/crates/unified/src/client/ui.rs @@ -11,7 +11,7 @@ pub fn ui_plugin(app: &mut App) { } fn setup_ui(mut commands: Commands) { - commands.spawn(( + let ui_id = commands.spawn(( Node { width: Val::Percent(100.0), height: Val::Percent(100.0), @@ -45,7 +45,8 @@ fn setup_ui(mut commands: Commands) { ], )], Visibility::Visible - )); + )).id(); + debug!(?ui_id, "spawned ui component"); } fn update_ui( diff --git a/crates/unified/src/client_plugins.rs b/crates/unified/src/client_plugins.rs index 66b978ac276ac277ae6a3d32e6c0f3c49aa0a10b..dadbdfb9d77ad21d2854df2556078c57897177f9 100644 --- a/crates/unified/src/client_plugins.rs +++ b/crates/unified/src/client_plugins.rs @@ -3,11 +3,15 @@ use aeronet_replicon::client::AeronetRepliconClientPlugin; use aeronet_websocket::client::WebSocketClientPlugin; use bevy::DefaultPlugins; use bevy::app::{PluginGroup, PluginGroupBuilder}; +use bevy::dev_tools::fps_overlay::FpsOverlayPlugin; use bevy::dev_tools::picking_debug::DebugPickingPlugin; use bevy::log::LogPlugin; use bevy::prelude::MeshPickingPlugin; +use bevy::ui::UiPlugin; +use bevy_egui::EguiPlugin; use bevy_rapier2d::prelude::RapierDebugRenderPlugin; use bevy_replicon::RepliconPlugins; +use bevy_inspector_egui::quick::WorldInspectorPlugin; pub struct ClientPluginGroup { pub server: String, @@ -21,9 +25,13 @@ impl PluginGroup for ClientPluginGroup { .add(AeronetRepliconClientPlugin) .add(MeshPickingPlugin) .add(DebugPickingPlugin) + .add(UiPlugin) .add(ClientPlugin { server: self.server, }) .add(RapierDebugRenderPlugin::default().disabled()) + //.add(FpsOverlayPlugin::default()) + //.add(EguiPlugin::default()) + //.add(WorldInspectorPlugin::new()) } } diff --git a/crates/unified/src/main.rs b/crates/unified/src/main.rs index 64f40d740081ca084824e92fca1cdac3f1cf5164..8f272ef97cd6c7375ce20335832d59a9dd39271b 100644 --- a/crates/unified/src/main.rs +++ b/crates/unified/src/main.rs @@ -1,3 +1,4 @@ +use std::io::Read; use bevy::log::tracing_subscriber; use bevy::prelude::*; use clap::Parser; @@ -18,6 +19,8 @@ enum Cli { Client { #[arg(short, long)] server: String, + #[arg(long, action)] + hotpatching_enabled: bool, }, #[cfg(not(target_arch = "wasm32"))] Server { @@ -28,7 +31,9 @@ enum Cli { #[arg(short = 'C', long)] max_clients: usize, #[arg(long, action)] - with_client: bool + with_client: bool, + #[arg(long, action)] + hotpatching_enabled: bool }, #[cfg(all(not(target_arch = "wasm32"), feature = "particle_editor"))] ParticleEditor {}, @@ -38,7 +43,12 @@ fn run(cli: Cli) -> AppExit { let mut app = App::new(); match cli { - Cli::Client { server } => { + Cli::Client { server, hotpatching_enabled } => { + if hotpatching_enabled { + warn!("-+-+-+-+-+-+- Starting with hotpatching enabled -+-+-+-+-+-+-"); + warn!("This can result in segfaults and inconsistent behavior! If there is weirdness, try disabling it."); + warn!("-+-+-+-+-+-+- Starting with hotpatching enabled -+-+-+-+-+-+-"); + } app.add_plugins(ClientPluginGroup { server }); app.add_plugins(SharedPluginGroup); } @@ -47,8 +57,14 @@ fn run(cli: Cli) -> AppExit { bind, tick_rate, max_clients, + hotpatching_enabled, .. } => { + if hotpatching_enabled { + warn!("-+-+-+-+-+-+- Starting with hotpatching enabled -+-+-+-+-+-+-"); + warn!("This can result in segfaults and inconsistent behavior! If there is weirdness, try disabling it."); + warn!("-+-+-+-+-+-+- Starting with hotpatching enabled -+-+-+-+-+-+-"); + } if cfg!(target_family = "wasm") { eprintln!("the server cannot run on webassembly"); exit(1); @@ -80,10 +96,15 @@ fn main() -> AppExit { .finish() .init(); + ctrlc::set_handler(|| { + info!("caught ^C, ciao!"); + exit(0); + }).unwrap(); + match cli { Cli::Client { .. } => { run(cli) }, Cli::ParticleEditor { .. } => { run(cli) }, - Cli::Server { with_client, bind, .. } => { + Cli::Server { with_client, bind, hotpatching_enabled, .. } => { if !with_client { run(cli) } else { @@ -97,31 +118,43 @@ fn main() -> AppExit { warn!("-----------------------------------------"); let scli_clone = cli.clone(); - let server_thread = std::thread::spawn(move || { - info!("starting server thread..."); - run(scli_clone) - }); - info!("starting client thread..."); - let is_multicast = bind.ip().is_unspecified(); - - let target_ip = if is_multicast { - if bind.ip().is_ipv4() { IpAddr::V4(Ipv4Addr::LOCALHOST) } else { IpAddr::V6(Ipv6Addr::LOCALHOST) } - } else { - bind.ip() - }; - let target_port = bind.port(); - let target_ip_str = match target_ip { - IpAddr::V4(a) => a.to_string(), - IpAddr::V6(a) => format!("[{a}]"), - }; - let target_url = format!("ws://{target_ip_str}:{target_port}"); - info!("starting the client with autocalculated target server url {target_url}"); - - let cli2 = Cli::Client { server: target_url }; - - let clt_exit = run(cli2); - - info!("waiting for server to exit..."); + let server_thread = std::thread::Builder::new() + .name("server".to_string()) + .spawn(move || { + info!("starting server thread..."); + run(scli_clone) + }) + .unwrap(); + + let mut clt_exit; + + info!("starting client thread..."); + + let is_multicast = bind.ip().is_unspecified(); + + let target_ip = if is_multicast { + if bind.ip().is_ipv4() { IpAddr::V4(Ipv4Addr::LOCALHOST) } else { IpAddr::V6(Ipv6Addr::LOCALHOST) } + } else { + bind.ip() + }; + let target_port = bind.port(); + let target_ip_str = match target_ip { + IpAddr::V4(a) => a.to_string(), + IpAddr::V6(a) => format!("[{a}]"), + }; + let target_url = format!("ws://{target_ip_str}:{target_port}"); + info!("starting the client with autocalculated target server url {target_url}"); + + let cli2 = Cli::Client { server: target_url, hotpatching_enabled }; + + clt_exit = run(cli2); + + if let AppExit::Error(c) = clt_exit { + error!("client exited with error {c}"); + } + info!("-------- CLIENT HAS EXITED --------"); + info!(" ^C to stop the server"); + let srv_exit = server_thread.join().unwrap(); match srv_exit {