From 66ecf5a99f256b08f04b394146eb4a362306273c Mon Sep 17 00:00:00 2001 From: core Date: Sun, 29 Jun 2025 21:17:54 -0400 Subject: [PATCH] client start --- Cargo.lock | 334 +++++++++++++++------- crates/proc/Cargo.toml | 12 - crates/proc/src/lib.rs | 23 -- crates/unified/Cargo.toml | 19 +- crates/unified/src/client/mod.rs | 42 +++ crates/unified/src/client_plugins.rs | 21 ++ crates/unified/src/ecs.rs | 0 crates/unified/src/main.rs | 30 +- crates/unified/src/replication/message.rs | 10 - crates/unified/src/replication/mod.rs | 132 --------- crates/unified/src/server/mod.rs | 71 +++-- crates/unified/src/server_plugins.rs | 20 +- crates/unified/src/shared_plugins.rs | 7 +- 13 files changed, 367 insertions(+), 354 deletions(-) delete mode 100644 crates/proc/Cargo.toml delete mode 100644 crates/proc/src/lib.rs create mode 100644 crates/unified/src/client/mod.rs create mode 100644 crates/unified/src/client_plugins.rs create mode 100644 crates/unified/src/ecs.rs delete mode 100644 crates/unified/src/replication/message.rs delete mode 100644 crates/unified/src/replication/mod.rs diff --git a/Cargo.lock b/Cargo.lock index baeaad9ea1ed92f86c831b389928a46153bfbcfb..6be48cd7c72557ca4adb1729679d6a64efd074d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,10 @@ name = "accesskit" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "becf0eb5215b6ecb0a739c31c21bd83c4f326524c9b46b7e882d77559b60a529" +dependencies = [ + "enumn", + "serde", +] [[package]] name = "accesskit_consumer" @@ -146,6 +150,16 @@ 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 = "aes" version = "0.8.4" @@ -612,30 +626,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "bevy-trait-query" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0536fb7ec58a26201bd1a30b89267bb100ee0dcb12edc6c472b3bc38f45f1447" -dependencies = [ - "bevy-trait-query-impl", - "bevy_app 0.16.1", - "bevy_ecs 0.16.1", - "tracing", -] - -[[package]] -name = "bevy-trait-query-impl" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d62739c868c0dcbf469df5235b738be46510dd6fc8fc7f2240106ba6610d0754" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "bevy_a11y" version = "0.13.2" @@ -659,6 +649,7 @@ dependencies = [ "bevy_derive 0.16.1", "bevy_ecs 0.16.1", "bevy_reflect 0.16.1", + "serde", ] [[package]] @@ -1309,6 +1300,7 @@ dependencies = [ "bevy_utils 0.16.1", "derive_more", "log", + "serde", "smol_str", "thiserror 2.0.12", ] @@ -1881,6 +1873,48 @@ dependencies = [ "syn 2.0.104", ] +[[package]] +name = "bevy_renet2" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d238ee38a3a9aa6dc2360fe27103ef93090d7107793da3ef1d6660d7b28e9e5a" +dependencies = [ + "bevy_app 0.16.1", + "bevy_ecs 0.16.1", + "bevy_time 0.16.1", + "renet2", + "renet2_netcode", +] + +[[package]] +name = "bevy_replicon" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4ce1947bc4f59da376589e1b019def816b49ecb9d23ecf0233211d137ac9fe" +dependencies = [ + "bevy 0.16.1", + "bitflags 2.9.1", + "bytes", + "log", + "petgraph 0.8.2", + "postcard", + "serde", + "typeid", + "variadics_please", +] + +[[package]] +name = "bevy_replicon_renet2" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbcacc0928f78601b7ce3f4c1d8b9314689d75fc93c9f7375a35af6bf16ba74" +dependencies = [ + "bevy 0.16.1", + "bevy_renet2", + "bevy_replicon", + "log", +] + [[package]] name = "bevy_scene" version = "0.13.2" @@ -2205,6 +2239,7 @@ dependencies = [ "bytemuck", "derive_more", "nonmax", + "serde", "smallvec", "taffy 0.7.7", "thiserror 2.0.12", @@ -2368,6 +2403,7 @@ dependencies = [ "cfg-if", "crossbeam-channel", "raw-window-handle", + "serde", "tracing", "wasm-bindgen", "web-sys", @@ -2628,6 +2664,9 @@ name = "bytes" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +dependencies = [ + "portable-atomic", +] [[package]] name = "bzip2" @@ -2789,6 +2828,30 @@ dependencies = [ "libc", ] +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[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.41" @@ -2844,6 +2907,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", + "zeroize", ] [[package]] @@ -2897,6 +2961,15 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.12", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -3325,6 +3398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] @@ -3693,6 +3767,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" +[[package]] +name = "enumn" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "env_logger" version = "0.10.2" @@ -4606,6 +4691,12 @@ dependencies = [ "digest", ] +[[package]] +name = "hmac-sha256" +version = "1.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad6880c8d4a9ebf39c6e8b77007ce223f646a4d21ce29d99f70cb16420545425" + [[package]] name = "home" version = "0.5.11" @@ -4939,15 +5030,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "inventory" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83" -dependencies = [ - "rustversion", -] - [[package]] name = "io-kit-sys" version = "0.4.1" @@ -6167,6 +6249,12 @@ dependencies = [ "cc", ] +[[package]] +name = "octets" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109983a091271ee8916076731ba5fdc9ee22fea871bc7c6ceab9bfd423eb1d99" + [[package]] name = "offset-allocator" version = "0.2.0" @@ -6204,6 +6292,12 @@ 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 = "orbclient" version = "0.3.48" @@ -6350,6 +6444,18 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "petgraph" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca" +dependencies = [ + "fixedbitset 0.5.7", + "hashbrown 0.15.4", + "indexmap", + "serde", +] + [[package]] name = "pico-args" version = "0.5.0" @@ -6492,6 +6598,17 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.11.1" @@ -6507,6 +6624,28 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "postcard" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c1de96e20f51df24ca73cafcc4690e044854d803259db27a00a461cb3b9d17a" +dependencies = [ + "cobs", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f049d94cb6dda6938cc8a531d2898e7c08d71c6de63d8e67123cca6cdde2cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "potential_utf" version = "0.1.2" @@ -6926,6 +7065,45 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "renet2" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6024b28b4d37cf4d4d0e0dc31d3a4ebb61880da278d77547bb94055a2a164f5" +dependencies = [ + "bevy_ecs 0.16.1", + "bytes", + "log", + "octets", +] + +[[package]] +name = "renet2_netcode" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee5d017932669cb57862c8c24ad5294d4fff877ace85487bc771b36ab958a054" +dependencies = [ + "bevy_ecs 0.16.1", + "bytes", + "hmac-sha256", + "log", + "octets", + "renet2", + "renetcode2", + "serde", + "url", +] + +[[package]] +name = "renetcode2" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a232e1196d6bef6f57e02fbe83fadd88ceb894bfff369cbbe27044559d06d89a" +dependencies = [ + "chacha20poly1305", + "log", +] + [[package]] name = "resvg" version = "0.45.1" @@ -7444,16 +7622,6 @@ 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 = "socks" version = "0.3.4" @@ -7512,17 +7680,12 @@ name = "starkingdoms" version = "0.1.0" dependencies = [ "bevy 0.16.1", - "bevy-trait-query", + "bevy_replicon", + "bevy_replicon_renet2", "clap", "crossbeam-channel", - "inventory", "serde", - "serde_json", - "starkingdoms-proc", - "tokio", - "tokio-tungstenite", "tracing-subscriber", - "typetag", ] [[package]] @@ -7574,15 +7737,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "starkingdoms-proc" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "starkingdoms-server" version = "0.1.0-alpha1" @@ -8016,33 +8170,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" -[[package]] -name = "tokio" -version = "1.45.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "pin-project-lite", - "socket2", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite 0.26.2", -] - [[package]] name = "toml" version = "0.7.8" @@ -8348,30 +8475,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" -[[package]] -name = "typetag" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f22b40dd7bfe8c14230cf9702081366421890435b2d625fa92b4acc4c3de6f" -dependencies = [ - "erased-serde", - "inventory", - "once_cell", - "serde", - "typetag-impl", -] - -[[package]] -name = "typetag-impl" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35f5380909ffc31b4de4f4bdf96b877175a016aa2ca98cee39fcfd8c4d53d952" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "unicode-bidi" version = "0.3.18" @@ -8456,6 +8559,16 @@ 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" @@ -8490,6 +8603,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] diff --git a/crates/proc/Cargo.toml b/crates/proc/Cargo.toml deleted file mode 100644 index 6b85d905bbfa00fe09620fcd7d73d09cf80121c3..0000000000000000000000000000000000000000 --- a/crates/proc/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "starkingdoms-proc" -version = "0.1.0" -edition = "2024" - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "1" -quote = "1" -syn = { version = "2", features = ["full"] } \ No newline at end of file diff --git a/crates/proc/src/lib.rs b/crates/proc/src/lib.rs deleted file mode 100644 index 17d6bb285f69f7c4cebb274d3e6792f772aefba4..0000000000000000000000000000000000000000 --- a/crates/proc/src/lib.rs +++ /dev/null @@ -1,23 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; -use syn::{parse_macro_input, DeriveInput}; - -#[proc_macro_attribute] -pub fn replicable(_metadata: proc_macro::TokenStream, input: proc_macro::TokenStream) - -> proc_macro::TokenStream { - let input: TokenStream = input.into(); - let output = quote! { - #[derive(::serde::Serialize, ::serde::Deserialize, ::starkingdoms_proc::_Replicable)] - #input - }; - output.into() -} -#[proc_macro_derive(_Replicable)] -pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let DeriveInput { ident, .. } = parse_macro_input!(input); - let output = quote! { - #[typetag::serde] - impl crate::replication::Replicable for #ident {} - }; - output.into() -} \ No newline at end of file diff --git a/crates/unified/Cargo.toml b/crates/unified/Cargo.toml index 31d2dbf12c3ebd79042ffc0cea0003030d81a7e7..2d79285eba683ad7f2314dc61040368190fbf1c6 100644 --- a/crates/unified/Cargo.toml +++ b/crates/unified/Cargo.toml @@ -5,25 +5,14 @@ edition = "2024" version = "0.1.0" [dependencies] -bevy = "0.16" -bevy-trait-query = "0.16" +bevy = { version = "0.16", features = ["serialize"] } -tokio = { version = "1", optional = true, features = ["rt-multi-thread"] } -tokio-tungstenite = { version = "0.26", optional = true } - -serde = { version = "1", features = ["derive"] } -serde_json = "1" -typetag = "0.2" -starkingdoms-proc = { path = "../proc" } -inventory = "0.3" +bevy_replicon = "0.34" +bevy_replicon_renet2 = { version = "0.10", features = ["native_transport"] } clap = { version = "4", features = ["derive", "cargo"] } tracing-subscriber = "0.3" crossbeam-channel = "0.5" - -[features] -default = [] -server = ["dep:tokio", "dep:tokio-tungstenite"] -client = [] \ No newline at end of file +serde = { version = "1", features = ["derive"] } \ No newline at end of file diff --git a/crates/unified/src/client/mod.rs b/crates/unified/src/client/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..24100fbd9ebb77357028cafbe75075d6a1d9ed7b --- /dev/null +++ b/crates/unified/src/client/mod.rs @@ -0,0 +1,42 @@ +use std::net::{SocketAddr, UdpSocket}; +use std::time::SystemTime; +use bevy::prelude::*; +use bevy_replicon::prelude::RepliconChannels; +use bevy_replicon_renet2::netcode::{ClientAuthentication, NetcodeClientTransport, NativeSocket}; +use bevy_replicon_renet2::renet2::{ConnectionConfig, RenetClient}; +use bevy_replicon_renet2::RenetChannelsExt; + + + +pub struct ClientPlugin { + pub server: SocketAddr +} +impl Plugin for ClientPlugin { + fn build(&self, app: &mut App) { + let server = self.server.clone(); + app + .add_systems(Startup, move |mut commands: Commands, channels: Res| { + let client = RenetClient::new( + ConnectionConfig::from_channels(channels.server_configs(), channels.client_configs()), + false + ); + let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let client_id = current_time.as_millis() as u64; + let socket = UdpSocket::bind(SocketAddr::new("::1".parse().unwrap(), 0)).unwrap(); + let authentication = ClientAuthentication::Unsecure { + client_id, + protocol_id: 0, + socket_id: 0, + server_addr: server, + user_data: None + }; + let transport = NetcodeClientTransport::new(current_time, authentication, NativeSocket::new(socket).unwrap()).unwrap(); + + commands.insert_resource(client); + commands.insert_resource(transport); + + info!(?client_id, "connected!"); + }); + + } +} \ No newline at end of file diff --git a/crates/unified/src/client_plugins.rs b/crates/unified/src/client_plugins.rs new file mode 100644 index 0000000000000000000000000000000000000000..5f6144c9491dfd24a4c39bb7fc2c18bb1574151b --- /dev/null +++ b/crates/unified/src/client_plugins.rs @@ -0,0 +1,21 @@ +use std::net::SocketAddr; +use bevy::app::{PluginGroup, PluginGroupBuilder}; +use bevy::DefaultPlugins; +use bevy_replicon::RepliconPlugins; +use bevy_replicon_renet2::RepliconRenetClientPlugin; +use crate::client::ClientPlugin; + +pub struct ClientPluginGroup { + pub server: SocketAddr +} +impl PluginGroup for ClientPluginGroup { + fn build(self) -> PluginGroupBuilder { + PluginGroupBuilder::start::() + .add_group(DefaultPlugins) + .add_group( + RepliconPlugins + ) + .add(RepliconRenetClientPlugin) + .add(ClientPlugin { server: self.server }) + } +} \ No newline at end of file diff --git a/crates/unified/src/ecs.rs b/crates/unified/src/ecs.rs new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/crates/unified/src/main.rs b/crates/unified/src/main.rs index e898adfe6549f8ccb59d7b1e907ffa0a4fd6e545..b1165dc446e189a4b63f0f3bae864130f4911d7b 100644 --- a/crates/unified/src/main.rs +++ b/crates/unified/src/main.rs @@ -1,13 +1,16 @@ -pub mod replication; pub mod server_plugins; -mod shared_plugins; -mod server; +pub mod shared_plugins; +pub mod server; +pub mod client; +pub mod ecs; +mod client_plugins; use std::net::SocketAddr; use std::process::exit; use bevy::log::tracing_subscriber; use clap::Parser; use bevy::prelude::*; +use crate::client_plugins::ClientPluginGroup; use crate::server_plugins::ServerPluginGroup; use crate::shared_plugins::SharedPluginGroup; @@ -19,10 +22,12 @@ enum Cli { server: SocketAddr }, Server { - #[arg(short, long)] + #[arg(short = 'b', long)] bind: SocketAddr, - #[arg(short, long)] - tick_rate: f64 + #[arg(short = 'r', long)] + tick_rate: f64, + #[arg(short = 'C', long)] + max_clients: usize } } @@ -36,9 +41,15 @@ fn main() -> AppExit { let mut app = App::new(); + + match cli { - Cli::Client { server } => { todo!() }, - Cli::Server { bind, tick_rate } => { + Cli::Client { server } => { + app.add_plugins(ClientPluginGroup { + server + }); + }, + Cli::Server { bind, tick_rate, max_clients } => { if cfg!(target_family = "wasm") { eprintln!("the server cannot run on webassembly"); exit(1); @@ -46,7 +57,8 @@ fn main() -> AppExit { app.add_plugins(ServerPluginGroup { bind, - tick_rate + tick_rate, + max_clients }); } } diff --git a/crates/unified/src/replication/message.rs b/crates/unified/src/replication/message.rs deleted file mode 100644 index e3b90c2d1852126b51a9b7c6b950ea115ac21b3e..0000000000000000000000000000000000000000 --- a/crates/unified/src/replication/message.rs +++ /dev/null @@ -1,10 +0,0 @@ -use serde::{Deserialize, Serialize}; -use crate::replication::ReplicatedEntityID; - -#[derive(Serialize, Deserialize, Debug)] -pub enum ReplicationMessage { - AddEntity(ReplicatedEntityID), - UpdateComponent(ReplicatedEntityID, serde_json::Value), - RemoveComponent(ReplicatedEntityID, String), - RemoveEntity(ReplicatedEntityID) -} \ No newline at end of file diff --git a/crates/unified/src/replication/mod.rs b/crates/unified/src/replication/mod.rs deleted file mode 100644 index 8a8ec222e68ee10ab4758b644e1798b1e633d858..0000000000000000000000000000000000000000 --- a/crates/unified/src/replication/mod.rs +++ /dev/null @@ -1,132 +0,0 @@ -mod message; - -use std::collections::{HashMap, HashSet}; -use std::sync::atomic::AtomicU64; -use bevy::ecs::component::HookContext; -use bevy::ecs::world::DeferredWorld; -use bevy::prelude::Component; -use starkingdoms_proc::replicable; -use bevy::prelude::*; -use bevy::tasks::AsyncComputeTaskPool; -use bevy_trait_query::{All, RegisterExt}; -use serde::{Deserialize, Serialize}; -use crate::replication::message::ReplicationMessage; - -pub struct ReplicationServerPlugin; -impl Plugin for ReplicationServerPlugin { - fn build(&self, app: &mut App) { - let (tx_to_io_task, rx_from_io_task) = crossbeam_channel::unbounded(); - let res = ReplicationServerResource { message_sender: tx_to_io_task, component_tracking_map: HashMap::new() }; - - let task_pool = AsyncComputeTaskPool::get(); - task_pool.spawn(async move { - while let Ok(message) = rx_from_io_task.recv() { - debug!(?message, "broadcasting to clients"); - } - }).detach(); - - app - .insert_resource(res) - .replicate::() - .add_systems(Update, replicate); - - } -} - -#[derive(Resource)] -struct ReplicationServerResource { - message_sender: crossbeam_channel::Sender, - component_tracking_map: HashMap>, -} - -/// Implement this trait on a component to enable replication for that component. -#[bevy_trait_query::queryable] -#[typetag::serde(tag = "component")] -pub trait Replicable { - fn component_id(&self) -> &'static str { - std::any::type_name::() - } -} - -/// Add this component to an entity to replicate it, and all of it's `Replicatable` components to clients -#[derive(Component)] -#[replicable] -#[require(ReplicatedEntityID)] -#[component(on_add = replicated_add_hook)] -#[component(on_remove = replicated_remove_hook)] -pub struct Replicated; - -fn replicated_add_hook(mut world: DeferredWorld, context: HookContext) { - world.get_resource_mut::().unwrap().component_tracking_map.insert(context.entity, HashSet::new()); - - let replicated_id = world.get::(context.entity).unwrap(); - world.get_resource::().unwrap().message_sender.send(ReplicationMessage::AddEntity(*replicated_id)).unwrap(); -} -fn replicated_remove_hook(mut world: DeferredWorld, context: HookContext) { - world.get_resource_mut::().unwrap().component_tracking_map.remove(&context.entity); - - let replicated_id = world.get::(context.entity).unwrap(); - world.get_resource::().unwrap().message_sender.send(ReplicationMessage::RemoveEntity(*replicated_id)).unwrap(); -} - -static ID_COUNTER: AtomicU64 = AtomicU64::new(0); - -#[derive(Component, Debug, Serialize, Deserialize, Copy, Clone)] -struct ReplicatedEntityID(u64); -impl Default for ReplicatedEntityID { - fn default() -> Self { - Self(ID_COUNTER.fetch_add(1, std::sync::atomic::Ordering::SeqCst)) - } -} - - -/// The main server-side replication system. Tracks all changes and produce replication messages -fn replicate( - replicated_query: Query<(Entity, &ReplicatedEntityID, All<&dyn Replicable>), With>, - mut replication_server_resource: ResMut -) { - for (server_entity, replicated_entity, replicated_components) in &replicated_query { - for added_component in replicated_components.iter_added() { - let our_entry = replication_server_resource.component_tracking_map.get_mut(&server_entity).unwrap(); - our_entry.insert(added_component.component_id().to_string()); - } - - for updated_component in replicated_components.iter_changed() { - let serialized_update = serde_json::to_value(updated_component.into_inner()).unwrap(); - replication_server_resource.message_sender.send(ReplicationMessage::UpdateComponent( - *replicated_entity, - serialized_update - )).unwrap(); - } - - let mut existing_component_ids = vec![]; - for component in replicated_components.iter() { - existing_component_ids.push(component.component_id()); - } - let our_entry = replication_server_resource.component_tracking_map.get_mut(&server_entity).unwrap(); - let mut removed_component_ids = vec![]; - our_entry.retain(|u| { - if !existing_component_ids.contains(&&**u) { - removed_component_ids.push(u.clone()); - false - } else { true } - }); - - for removed_component in &removed_component_ids { - replication_server_resource.message_sender.send(ReplicationMessage::RemoveComponent( - *replicated_entity, - removed_component.to_string() - )).unwrap(); - } - } -} - -pub trait ReplicateExt { - fn replicate(&mut self) -> &mut Self; -} -impl ReplicateExt for App { - fn replicate(&mut self) -> &mut Self { - self.register_component_as::(); - self - } -} \ No newline at end of file diff --git a/crates/unified/src/server/mod.rs b/crates/unified/src/server/mod.rs index e733971027346fdcafc38408f7521baafa218b69..fd0384b07d6b354fed3a0907ca18b8f021dd457d 100644 --- a/crates/unified/src/server/mod.rs +++ b/crates/unified/src/server/mod.rs @@ -1,44 +1,43 @@ -use std::time::Duration; +use std::net::{SocketAddr, UdpSocket}; +use std::time::{SystemTime, UNIX_EPOCH}; use bevy::prelude::*; -use starkingdoms_proc::replicable; -use crate::replication::{ReplicateExt, Replicated, ReplicationServerPlugin}; +use bevy_replicon::prelude::RepliconChannels; +use bevy_replicon_renet2::netcode::{NativeSocket, NetcodeServerTransport, ServerAuthentication, ServerSetupConfig}; +use bevy_replicon_renet2::renet2::{ConnectionConfig, RenetServer}; +use bevy_replicon_renet2::RenetChannelsExt; -pub fn server_plugin(app: &mut App) { - app - .replicate::() - .add_systems(Startup, spawn_test_thingy) - .add_systems(FixedUpdate, update_test_thingy) - .add_systems(Update, remove_test_thingy); +pub struct ServerPlugin { + pub bind: SocketAddr, + pub max_clients: usize, } +impl Plugin for ServerPlugin { + fn build(&self, app: &mut App) { + let bind = self.bind.clone(); + let max_clients = self.max_clients.clone(); -#[derive(Component)] -struct TestComponent2; + app + .add_systems(FixedPreUpdate, bevy_replicon::server::increment_tick) // !!important!! do not remove or move + .add_systems(Startup, move |mut commands: Commands, channels: Res| { + let server = RenetServer::new(ConnectionConfig::from_channels( + channels.server_configs(), + channels.client_configs() + )); -#[derive(Component)] -#[replicable] -pub struct TestComponent { - hi: i32 -} + let server_config = ServerSetupConfig { + current_time: SystemTime::now().duration_since(UNIX_EPOCH).unwrap(), + max_clients: max_clients, + protocol_id: 0, + authentication: ServerAuthentication::Unsecure, + socket_addresses: vec![vec![bind]] + }; + let socket = UdpSocket::bind(bind).unwrap(); -fn spawn_test_thingy(mut commands: Commands) { - commands.spawn(( - Replicated, - TestComponent2, - TestComponent { hi: 123 }, - )); -} -fn update_test_thingy(mut query: Query<&mut TestComponent>) { - for mut thingy in query.iter_mut() { - thingy.hi += 1; - } -} -fn remove_test_thingy(mut commands: Commands, query: Query>, time: Res