M .cargo/config.toml => .cargo/config.toml +3 -0
@@ 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"]
M Cargo.lock => Cargo.lock +129 -0
@@ 779,6 779,55 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1291,6 1340,7 @@ dependencies = [
"bevy_time",
"bevy_transform",
"bevy_ui",
+ "bevy_ui_render",
"bevy_utils",
"bevy_window",
"bevy_winit",
@@ 1401,6 1451,42 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 2003,6 2089,7 @@ version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
dependencies = [
+ "bytemuck",
"serde_core",
]
@@ 2066,6 2153,17 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 3807,6 3905,15 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 5142,6 5249,15 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 5729,6 5845,17 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 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",
M crates/unified/Cargo.toml => crates/unified/Cargo.toml +6 -1
@@ 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]
M crates/unified/src/client/mod.rs => crates/unified/src/client/mod.rs +3 -1
@@ 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();
M crates/unified/src/client/ui.rs => crates/unified/src/client/ui.rs +3 -2
@@ 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(
M crates/unified/src/client_plugins.rs => crates/unified/src/client_plugins.rs +8 -0
@@ 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())
}
}
M crates/unified/src/main.rs => crates/unified/src/main.rs +61 -28
@@ 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 {