M Cargo.lock => Cargo.lock +224 -110
@@ 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"
@@ 147,6 151,16 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 613,30 627,6 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 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",
]
@@ 1882,6 1874,48 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 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"
@@ 2790,6 2829,30 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 2844,6 2907,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
+ "zeroize",
]
[[package]]
@@ 2898,6 2962,15 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 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",
]
@@ 3694,6 3768,17 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 4607,6 4692,12 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 4940,15 5031,6 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6168,6 6250,12 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6205,6 6293,12 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6351,6 6445,18 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6493,6 6599,17 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6508,6 6625,28 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6927,6 7066,45 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 7445,16 7623,6 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 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]]
@@ 7575,15 7738,6 @@ dependencies = [
]
[[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"
dependencies = [
@@ 8017,33 8171,6 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 8349,30 8476,6 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 8457,6 8560,16 @@ 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"
@@ 8490,6 8603,7 @@ dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
+ "serde",
]
[[package]]
D crates/proc/Cargo.toml => crates/proc/Cargo.toml +0 -12
@@ 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
D crates/proc/src/lib.rs => crates/proc/src/lib.rs +0 -23
@@ 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
M crates/unified/Cargo.toml => crates/unified/Cargo.toml +4 -15
@@ 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
A crates/unified/src/client/mod.rs => crates/unified/src/client/mod.rs +42 -0
@@ 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<RepliconChannels>| {
+ 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
A crates/unified/src/client_plugins.rs => crates/unified/src/client_plugins.rs +21 -0
@@ 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::<Self>()
+ .add_group(DefaultPlugins)
+ .add_group(
+ RepliconPlugins
+ )
+ .add(RepliconRenetClientPlugin)
+ .add(ClientPlugin { server: self.server })
+ }
+}<
\ No newline at end of file
A crates/unified/src/ecs.rs => crates/unified/src/ecs.rs +0 -0
M crates/unified/src/main.rs => crates/unified/src/main.rs +21 -9
@@ 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
});
}
}
D crates/unified/src/replication/message.rs => crates/unified/src/replication/message.rs +0 -10
@@ 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
D crates/unified/src/replication/mod.rs => crates/unified/src/replication/mod.rs +0 -132
@@ 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::<Replicated>()
- .add_systems(Update, replicate);
-
- }
-}
-
-#[derive(Resource)]
-struct ReplicationServerResource {
- message_sender: crossbeam_channel::Sender<message::ReplicationMessage>,
- component_tracking_map: HashMap<Entity, HashSet<String>>,
-}
-
-/// 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::<Self>()
- }
-}
-
-/// 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::<ReplicationServerResource>().unwrap().component_tracking_map.insert(context.entity, HashSet::new());
-
- let replicated_id = world.get::<ReplicatedEntityID>(context.entity).unwrap();
- world.get_resource::<ReplicationServerResource>().unwrap().message_sender.send(ReplicationMessage::AddEntity(*replicated_id)).unwrap();
-}
-fn replicated_remove_hook(mut world: DeferredWorld, context: HookContext) {
- world.get_resource_mut::<ReplicationServerResource>().unwrap().component_tracking_map.remove(&context.entity);
-
- let replicated_id = world.get::<ReplicatedEntityID>(context.entity).unwrap();
- world.get_resource::<ReplicationServerResource>().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<Replicated>>,
- mut replication_server_resource: ResMut<ReplicationServerResource>
-) {
- 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<T: Replicable + Component>(&mut self) -> &mut Self;
-}
-impl ReplicateExt for App {
- fn replicate<T: Replicable + Component>(&mut self) -> &mut Self {
- self.register_component_as::<dyn Replicable, T>();
- self
- }
-}>
\ No newline at end of file
M crates/unified/src/server/mod.rs => crates/unified/src/server/mod.rs +35 -36
@@ 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::<TestComponent>()
- .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<RepliconChannels>| {
+ 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<Entity, With<TestComponent2>>, time: Res<Time>) {
- if time.elapsed() < Duration::from_secs(10) { return; }
- for entity in query.iter() {
- commands.entity(entity).remove::<TestComponent>();
- }
- if time.elapsed() < Duration::from_secs(20) { return; }
- for entity in query.iter() {
- commands.entity(entity).despawn();
+ let transport = NetcodeServerTransport::new(server_config, NativeSocket::new(socket).unwrap()).unwrap();
+
+ commands.insert_resource(server);
+ commands.insert_resource(transport);
+
+ info!("websocket server listening");
+ });
}
}=
\ No newline at end of file
M crates/unified/src/server_plugins.rs => crates/unified/src/server_plugins.rs +14 -6
@@ 2,14 2,14 @@ use std::net::SocketAddr;
use std::time::Duration;
use bevy::app::{PluginGroup, PluginGroupBuilder, ScheduleRunnerPlugin, TaskPoolPlugin};
use bevy::diagnostic::FrameCountPlugin;
-use bevy::log::LogPlugin;
use bevy::time::TimePlugin;
-use crate::replication::ReplicationServerPlugin;
-use crate::server::server_plugin;
+use bevy_replicon::RepliconPlugins;
+use bevy_replicon_renet2::RepliconRenetServerPlugin;
pub struct ServerPluginGroup {
pub bind: SocketAddr,
- pub tick_rate: f64
+ pub tick_rate: f64,
+ pub max_clients: usize
}
impl PluginGroup for ServerPluginGroup {
fn build(self) -> PluginGroupBuilder {
@@ 20,7 20,15 @@ impl PluginGroup for ServerPluginGroup {
.add(ScheduleRunnerPlugin::run_loop(
Duration::from_secs_f64(1.0 / self.tick_rate)
))
- .add(ReplicationServerPlugin)
- .add(server_plugin)
+ .add_group(
+ RepliconPlugins
+ )
+ .add(
+ RepliconRenetServerPlugin
+ )
+ .add(crate::server::ServerPlugin {
+ bind: self.bind,
+ max_clients: self.max_clients,
+ })
}
}=
\ No newline at end of file
M crates/unified/src/shared_plugins.rs => crates/unified/src/shared_plugins.rs +6 -1
@@ 1,9 1,14 @@
-use bevy::app::{PluginGroup, PluginGroupBuilder};
+use bevy::app::{App, PluginGroup, PluginGroupBuilder};
pub struct SharedPluginGroup;
impl PluginGroup for SharedPluginGroup {
fn build(self) -> PluginGroupBuilder {
PluginGroupBuilder::start::<Self>()
+ .add(register_everything)
}
+}
+
+pub fn register_everything(app: &mut App) {
+ app;
}=
\ No newline at end of file