diff --git a/Cargo.lock b/Cargo.lock index b407f48..c6ba81a 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" @@ -484,7 +488,7 @@ dependencies = [ "futures-task", "log", "pin-project-lite", - "tungstenite", + "tungstenite 0.27.0", ] [[package]] @@ -523,6 +527,61 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "axum" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" +dependencies = [ + "axum-core", + "base64 0.22.1", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sha1", + "sync_wrapper", + "tokio", + "tokio-tungstenite", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "base16ct" version = "0.2.0" @@ -567,6 +626,7 @@ dependencies = [ "bevy_derive", "bevy_ecs", "bevy_reflect", + "serde", ] [[package]] @@ -1020,6 +1080,7 @@ dependencies = [ "bevy_reflect", "derive_more", "log", + "serde", "smol_str", "thiserror 2.0.17", ] @@ -1151,8 +1212,10 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da96fc09dd7fa5a1384f6bc308e57a43aa366eda0ca719b89755842362433a8a" dependencies = [ + "async-compat", "bevy", "cfg-if", + "matchbox_signaling", "matchbox_socket", ] @@ -1196,6 +1259,7 @@ dependencies = [ "bytemuck", "derive_more", "hexasphere", + "serde", "thiserror 2.0.17", "tracing", "wgpu-types", @@ -1653,6 +1717,7 @@ dependencies = [ "bevy_utils", "bevy_window", "derive_more", + "serde", "smallvec", "taffy", "thiserror 2.0.17", @@ -2648,6 +2713,17 @@ dependencies = [ "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" @@ -3349,12 +3425,78 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", +] + +[[package]] +name = "hyper-util" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "hyper", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "icu_collections" version = "2.1.1" @@ -3794,6 +3936,28 @@ dependencies = [ "cfg-if", "derive_more", "serde", + "serde_json", + "uuid", +] + +[[package]] +name = "matchbox_signaling" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d223da7d999cf0567b4e37d230f5b95140d4bbd63834ba7ac46a9b8d3fffd1fd" +dependencies = [ + "async-trait", + "axum", + "futures", + "hyper", + "matchbox_protocol", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tower-http", + "tracing", "uuid", ] @@ -3838,6 +4002,12 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + [[package]] name = "matrixmultiply" version = "0.3.10" @@ -3897,6 +4067,12 @@ dependencies = [ "paste", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -4526,12 +4702,19 @@ dependencies = [ "bevy_matchbox", "orthros_network", "rand 0.9.2", + "rmp-serde", + "serde", "statrs", ] [[package]] name = "orthros_network" version = "0.1.0" +dependencies = [ + "bevy", + "rmp-serde", + "serde", +] [[package]] name = "owned_ttf_parser" @@ -5094,6 +5277,28 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "rodio" version = "0.20.1" @@ -5465,6 +5670,29 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha1" version = "0.10.6" @@ -5570,6 +5798,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" @@ -5751,6 +5982,12 @@ dependencies = [ "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" @@ -5964,6 +6201,29 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.28.0", +] + [[package]] name = "tokio-util" version = "0.7.16" @@ -6008,12 +6268,57 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.10.0", + "bytes", + "http", + "http-body", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -6127,6 +6432,23 @@ dependencies = [ "utf-8", ] +[[package]] +name = "tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.2", + "sha1", + "thiserror 2.0.17", + "utf-8", +] + [[package]] name = "turn" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index f6cb9cb..cea93fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,3 @@ members = ["orthros-client","orthros-network","orthros-server"] [dependencies] orthros_network = {path = "./orthros-network"} - diff --git a/orthros-network/Cargo.toml b/orthros-network/Cargo.toml index a816cb0..cf0d00c 100644 --- a/orthros-network/Cargo.toml +++ b/orthros-network/Cargo.toml @@ -4,3 +4,6 @@ version = "0.1.0" edition = "2024" [dependencies] +serde = { version = "1.0", features = ["derive"] } +bevy = {version = "0.17", features = ["serialize"]} +rmp-serde = "1.3.0" diff --git a/orthros-network/src/generic/mod.rs b/orthros-network/src/generic/mod.rs new file mode 100644 index 0000000..78907c2 --- /dev/null +++ b/orthros-network/src/generic/mod.rs @@ -0,0 +1,9 @@ +use crate::starchart::star::StarInfo; +use bevy::ecs::component::Component; +use serde::{Deserialize, Serialize}; +#[derive(Serialize, Deserialize, Debug)] +pub struct EntityID(pub u32); +#[derive(Serialize, Deserialize, Debug, Component)] +pub enum ObjectUpdate { + Star(StarInfo), +} diff --git a/orthros-network/src/lib.rs b/orthros-network/src/lib.rs index 22b7d4a..23962af 100644 --- a/orthros-network/src/lib.rs +++ b/orthros-network/src/lib.rs @@ -1,2 +1,3 @@ +pub mod generic; pub mod starchart; pub const SCALEAU: f32 = 1.0; diff --git a/orthros-network/src/starchart/star.rs b/orthros-network/src/starchart/star.rs index 9b3f957..7f6f33c 100644 --- a/orthros-network/src/starchart/star.rs +++ b/orthros-network/src/starchart/star.rs @@ -1,19 +1,24 @@ -use crate::SCALEAU; +use crate::{SCALEAU, generic::EntityID}; const SOLARRADIUSTOLY: f32 = 7.35355e-8; - +use bevy::{ecs::component::Component, transform::components::Transform}; +use serde::{Deserialize, Serialize}; fn solar_radius_to_ly_scaled(r: f32) -> f32 { r * SOLARRADIUSTOLY * SCALEAU } +#[derive(Serialize, Deserialize, Debug)] pub enum StarClass { MType, BType, GType, } +#[derive(Serialize, Deserialize, Debug, Component)] pub struct StarInfo { + pub id: EntityID, pub name: String, pub class: StarClass, pub diameter: f32, + pub transform: Transform, } pub fn star_diameter_range(class: &StarClass) -> std::ops::Range { match class { diff --git a/orthros-server/Cargo.toml b/orthros-server/Cargo.toml index 395bced..1681236 100644 --- a/orthros-server/Cargo.toml +++ b/orthros-server/Cargo.toml @@ -9,6 +9,9 @@ rand = "0.9.1" # rusqlite = "0.37.0" statrs = "0.18.0" orthros_network = {path = "../orthros-network"} -bevy_matchbox = "0.13" +bevy_matchbox = {version = "0.13", features= ["signaling"]} +serde = { version = "1.0", features = ["derive"] } + +rmp-serde = "1.3.0" [[bin]] name = "orthros-server" diff --git a/orthros-server/src/main.rs b/orthros-server/src/main.rs index aa7f9f9..4e2f68b 100644 --- a/orthros-server/src/main.rs +++ b/orthros-server/src/main.rs @@ -4,17 +4,26 @@ use bevy::{ render::{RenderPlugin, settings::WgpuSettings, view::Hdr}, time::common_conditions::on_timer, }; -use bevy_matchbox::prelude::*; -use orthros_network::starchart::star::{STARS, StarClass, StarInfo, star_diameter_range}; +use bevy_matchbox::{matchbox_signaling::SignalingServer, prelude::*}; +use orthros_network::{ + generic::EntityID, + starchart::star::{STARS, StarClass, StarInfo, star_diameter_range}, +}; use rand::{ Rng, distr::{Distribution, Uniform}, rng, }; -use std::time::Duration; +use std::{ + collections::HashSet, + net::{Ipv4Addr, SocketAddrV4}, + time::Duration, +}; const CHANNEL_ID: usize = 0; #[derive(Component)] -struct StarInfoComp(StarInfo); +struct NetworkObject; +#[derive(Component)] +struct Changed; fn main() { App::new() .add_plugins((DefaultPlugins.set(RenderPlugin { @@ -25,7 +34,14 @@ fn main() { .into(), ..default() }),)) - .add_systems(Startup, (setup_scene, start_socket)) + .add_systems( + Startup, + ( + start_signaling_server, + start_socket.after(start_signaling_server), + setup_scene.after(start_socket), + ), + ) .add_systems( Update, ( @@ -35,8 +51,29 @@ fn main() { ) .run(); } +fn start_signaling_server(mut commands: Commands) { + info!("Starting signaling server"); + let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 3536); + let signaling_server = MatchboxServer::from( + SignalingServer::client_server_builder(addr) + .on_connection_request(|connection| { + info!("Connecting: {connection:?}"); + Ok(true) // Allow all connections + }) + .on_id_assignment(|(socket, id)| info!("{socket} received {id}")) + .on_host_connected(|id| info!("Host joined: {id}")) + .on_host_disconnected(|id| info!("Host left: {id}")) + .on_client_connected(|id| info!("Client joined: {id}")) + .on_client_disconnected(|id| info!("Client left: {id}")) + .cors() + .trace() + .build(), + ); + commands.insert_resource(signaling_server); +} -fn setup_scene(mut commands: Commands) { +fn setup_scene(mut commands: Commands, mut socket: ResMut) { + let mut spawned_ids: HashSet = HashSet::new(); for _ in 0..4 { let x = Uniform::try_from(-2000..2000).unwrap().sample(&mut rng()); let z = Uniform::try_from(-8000..8000).unwrap().sample(&mut rng()); @@ -46,22 +83,36 @@ fn setup_scene(mut commands: Commands) { 2 => StarClass::GType, _ => todo!(), }; + let mut id: u32 = rng().random(); + while spawned_ids.contains(&id) { + id = rng().random(); + } + spawned_ids.insert(id); info!("{:?}", star_diameter_range(&star_class)); let star_info = StarInfo { + id: EntityID(id), name: STARS[(rng().random_range(0..100)) as usize].to_string(), diameter: rng().random_range(star_diameter_range(&star_class)), class: star_class, + transform: Transform::from_xyz(x as f32 / 100.0, z as f32 / 20000.0, z as f32 / 100.0), }; - commands.spawn(( - Transform::from_xyz(x as f32 / 100.0, z as f32 / 20000.0, z as f32 / 100.0), - StarInfoComp(star_info), - )); + commands.spawn((StarInfoComp(star_info), NetworkObject, Changed)); + let peers: Vec<_> = socket.connected_peers().collect(); + + for peer in peers { + let message = "Hello"; + info!("Sending message: {message:?} to {peer}"); + socket + .channel_mut(CHANNEL_ID) + .send(message.as_bytes().into(), peer); + } } } - +fn on_client_connect(mut socket: ResMut, Query<&StarInfo>) fn start_socket(mut commands: Commands) { let socket = MatchboxSocket::new_reliable("ws://localhost:3536/hello"); + info!("Created socket"); commands.insert_resource(socket); }