From c2dc6088a06642a28e1774d603b2d919f5d5aa0a Mon Sep 17 00:00:00 2001 From: "NG (Graham)" Date: Tue, 1 Jul 2025 20:04:11 -0400 Subject: [PATCH] Create initial multiplayer server skeleton --- Cargo.lock | 200 ++++++++++++++++---- Cargo.toml | 1 + rc_lobby_room/src/lobby.rs | 2 +- rc_multiplayer/Cargo.toml | 21 +++ rc_multiplayer/run_debug.sh | 3 + rc_multiplayer/src/cli.rs | 27 +++ rc_multiplayer/src/data/mod.rs | 2 + rc_multiplayer/src/data/net_msg_ty.rs | 18 ++ rc_multiplayer/src/handler.rs | 256 ++++++++++++++++++++++++++ rc_multiplayer/src/main.rs | 32 ++++ rc_multiplayer/src/traits.rs | 7 + 11 files changed, 537 insertions(+), 32 deletions(-) create mode 100644 rc_multiplayer/Cargo.toml create mode 100755 rc_multiplayer/run_debug.sh create mode 100644 rc_multiplayer/src/cli.rs create mode 100644 rc_multiplayer/src/data/mod.rs create mode 100644 rc_multiplayer/src/data/net_msg_ty.rs create mode 100644 rc_multiplayer/src/handler.rs create mode 100644 rc_multiplayer/src/main.rs create mode 100644 rc_multiplayer/src/traits.rs diff --git a/Cargo.lock b/Cargo.lock index d980604..4f258eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "bytes", "futures-core", "futures-sink", @@ -29,7 +29,7 @@ dependencies = [ "actix-service", "actix-utils", "actix-web", - "bitflags 2.8.0", + "bitflags 2.9.1", "bytes", "derive_more 0.99.20", "futures-core", @@ -53,7 +53,7 @@ dependencies = [ "actix-service", "actix-utils", "base64 0.22.1", - "bitflags 2.8.0", + "bitflags 2.9.1", "brotli", "bytes", "bytestring", @@ -384,6 +384,17 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -508,9 +519,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" dependencies = [ "serde", ] @@ -631,9 +642,28 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "byteserde" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4dd3b475a835b18659784f3f891dfdbc8dc97b13529b151924fcc3e274c618" +dependencies = [ + "bytes", +] + +[[package]] +name = "byteserde_derive" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8916aaf54883b8780e6b29901298853a47de431ecb5d62a4317d658d4c18868d" +dependencies = [ + "quote", + "syn 2.0.96", +] [[package]] name = "bytestring" @@ -1028,7 +1058,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b035a542cf7abf01f2e3c4d5a7acbaebfefe120ae4efc7bde3df98186e4b8af7" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "proc-macro2", "proc-macro2-diagnostics", "quote", @@ -2071,7 +2101,7 @@ dependencies = [ "half", "highhash", "libfj_parsable_macro_derive", - "num_enum", + "num_enum 0.5.11", "obj", "reqwest", "serde", @@ -2122,7 +2152,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "libc", "redox_syscall", ] @@ -2159,6 +2189,26 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +[[package]] +name = "literustlib" +version = "0.1.0" +dependencies = [ + "bytes", + "num_enum 0.7.4", +] + +[[package]] +name = "literustlib_server" +version = "0.1.0" +dependencies = [ + "async-recursion", + "async-trait", + "bytes", + "literustlib", + "log", + "tokio", +] + [[package]] name = "local-channel" version = "0.1.5" @@ -2321,7 +2371,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "crossbeam-channel", "filetime", "fsevent-sys", @@ -2466,7 +2516,17 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.5.11", +] + +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive 0.7.4", + "rustversion", ] [[package]] @@ -2481,6 +2541,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro-crate 3.3.0", + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "obj" version = "0.10.2" @@ -2535,7 +2607,7 @@ version = "0.3.0" dependencies = [ "log", "num", - "polariton", + "polariton 0.3.0", "rand 0.9.0", "ring", "simple-rijndael", @@ -2549,7 +2621,7 @@ dependencies = [ "env_logger", "log", "oj_polariton_auth", - "polariton", + "polariton 0.3.0", "polariton_server", "tokio", ] @@ -2564,7 +2636,7 @@ dependencies = [ "log", "oj_polariton_auth", "oj_rc_core", - "polariton", + "polariton 0.3.0", "polariton_server", "regex", "serde", @@ -2585,7 +2657,7 @@ dependencies = [ "log", "oj_rc_database", "oj_rc_factory", - "polariton", + "polariton 0.3.0", "polariton_server", "rand 0.9.0", "serde", @@ -2622,7 +2694,7 @@ dependencies = [ "env_logger", "log", "oj_polariton_auth", - "polariton", + "polariton 0.3.0", "polariton_server", "tokio", ] @@ -2637,7 +2709,7 @@ dependencies = [ "log", "oj_polariton_auth", "oj_rc_core", - "polariton", + "polariton 0.3.0", "polariton_server", "tokio", ] @@ -2661,7 +2733,7 @@ dependencies = [ "env_logger", "log", "oj_polariton_auth", - "polariton", + "polariton 0.3.0", "polariton_server", "tokio", ] @@ -2681,7 +2753,7 @@ dependencies = [ "oj_polariton_auth", "oj_rc_core", "oj_rc_factory", - "polariton", + "polariton 0.3.0", "polariton_server", "rand 0.9.0", "serde", @@ -2697,7 +2769,7 @@ dependencies = [ "env_logger", "log", "oj_polariton_auth", - "polariton", + "polariton 0.3.0", "polariton_server", "tokio", ] @@ -2712,7 +2784,7 @@ dependencies = [ "log", "oj_polariton_auth", "oj_rc_core", - "polariton", + "polariton 0.3.0", "polariton_server", "tokio", ] @@ -2725,7 +2797,7 @@ dependencies = [ "env_logger", "log", "oj_polariton_auth", - "polariton", + "polariton 0.3.0", "polariton_server", "tokio", ] @@ -2740,7 +2812,7 @@ dependencies = [ "log", "oj_polariton_auth", "oj_rc_core", - "polariton", + "polariton 0.3.0", "polariton_server", "tokio", ] @@ -2981,6 +3053,11 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "polariton" +version = "0.2.0" +source = "git+https://git.ngram.ca/OpenJam/polariton.git?rev=a27e90106037555d4aa10059270df9bdc9080d76#a27e90106037555d4aa10059270df9bdc9080d76" + [[package]] name = "polariton" version = "0.3.0" @@ -2994,7 +3071,7 @@ version = "0.3.0" dependencies = [ "async-trait", "log", - "polariton", + "polariton 0.3.0", "tokio", ] @@ -3252,6 +3329,22 @@ dependencies = [ "zerocopy 0.8.14", ] +[[package]] +name = "rc_multiplayer" +version = "0.3.0" +dependencies = [ + "async-trait", + "bytes", + "clap", + "env_logger", + "literustlib", + "literustlib_server", + "log", + "oj_rc_core", + "rlnl", + "tokio", +] + [[package]] name = "rdrand" version = "0.4.0" @@ -3267,7 +3360,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", ] [[package]] @@ -3436,6 +3529,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rlnl" +version = "0.1.0" +dependencies = [ + "bitflags 2.9.1", + "byteserde", + "byteserde_derive", + "polariton 0.2.0", + "sealed", + "strum 0.27.1", +] + [[package]] name = "rocket" version = "0.5.1" @@ -3594,7 +3699,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", "errno", "libc", "linux-raw-sys", @@ -3712,7 +3817,7 @@ dependencies = [ "serde", "serde_json", "sqlx", - "strum", + "strum 0.26.3", "thiserror 2.0.11", "time", "tracing", @@ -3843,6 +3948,17 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "sealed" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "semver" version = "1.0.26" @@ -4141,7 +4257,7 @@ dependencies = [ "atoi", "base64 0.22.1", "bigdecimal", - "bitflags 2.8.0", + "bitflags 2.9.1", "byteorder", "bytes", "chrono", @@ -4188,7 +4304,7 @@ dependencies = [ "atoi", "base64 0.22.1", "bigdecimal", - "bitflags 2.8.0", + "bitflags 2.9.1", "byteorder", "chrono", "crc", @@ -4320,6 +4436,28 @@ version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.96", +] + [[package]] name = "subtle" version = "2.6.1" @@ -5256,7 +5394,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 6ac0b19..b5173bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ members = [ "rc_singleplayer", "rc_singleplayer_room", "rc_lobby", "rc_lobby_room", "rc_core", "rc_database", "rc_factory", + "rc_multiplayer", ] [workspace.dependencies] diff --git a/rc_lobby_room/src/lobby.rs b/rc_lobby_room/src/lobby.rs index 7981ebc..2d070b2 100644 --- a/rc_lobby_room/src/lobby.rs +++ b/rc_lobby_room/src/lobby.rs @@ -62,7 +62,7 @@ impl QueueHandler { } async fn send_events_to_player(enter_event: std::sync::Arc, sender: polariton_server::events::EventEmitter) { - const WAIT_BEFORE_ENTER: std::time::Duration = std::time::Duration::from_secs(2); + const WAIT_BEFORE_ENTER: std::time::Duration = std::time::Duration::from_secs(1); if sender.emit(crate::events::battle_found::BattleFound) { tokio::time::sleep(WAIT_BEFORE_ENTER).await; sender.emit(enter_event.as_ref()); diff --git a/rc_multiplayer/Cargo.toml b/rc_multiplayer/Cargo.toml new file mode 100644 index 0000000..d68c54f --- /dev/null +++ b/rc_multiplayer/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "rc_multiplayer" +version.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true +authors.workspace = true +readme.workspace = true + +[dependencies] +log.workspace = true +env_logger.workspace = true +tokio = { version = "1.43", features = [ "net", "macros", "rt-multi-thread", "io-util" ] } +clap.workspace = true +oj_rc_core = { version = "*", path = "../rc_core" } +async-trait.workspace = true +bytes = "1.10" + +literustlib_server = { version = "0.1", path = "../../LiteRustLib/server" } +literustlib = { version = "0.1", path = "../../LiteRustLib" } +rlnl = { version = "0.1", path = "../../rlnl" } diff --git a/rc_multiplayer/run_debug.sh b/rc_multiplayer/run_debug.sh new file mode 100755 index 0000000..3f65ccd --- /dev/null +++ b/rc_multiplayer/run_debug.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +RUST_BACKTRACE=1 RUST_LOG=debug cargo run -- diff --git a/rc_multiplayer/src/cli.rs b/rc_multiplayer/src/cli.rs new file mode 100644 index 0000000..a77e9cf --- /dev/null +++ b/rc_multiplayer/src/cli.rs @@ -0,0 +1,27 @@ +use clap::Parser; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +pub struct CliArgs { + /// UDP port on which to accept connections + #[arg(short, long, default_value_t = 4542)] + pub port: u16, + + /// IP Address on which to accept connections + #[arg(long, default_value_t = {"127.0.0.1".to_string()})] + pub ip: String, + + /// Assets root + #[arg(long, default_value_t = {"../assets/robocraft".to_string()})] + pub assets: String, + + /// User data root + #[arg(long, default_value_t = {"../data/robocraft".to_string()})] + pub data: String, +} + +impl CliArgs { + pub fn get() -> Self { + Self::parse() + } +} diff --git a/rc_multiplayer/src/data/mod.rs b/rc_multiplayer/src/data/mod.rs new file mode 100644 index 0000000..529efc9 --- /dev/null +++ b/rc_multiplayer/src/data/mod.rs @@ -0,0 +1,2 @@ +pub mod net_msg_ty; +pub use net_msg_ty::MessageType; diff --git a/rc_multiplayer/src/data/net_msg_ty.rs b/rc_multiplayer/src/data/net_msg_ty.rs new file mode 100644 index 0000000..00181bb --- /dev/null +++ b/rc_multiplayer/src/data/net_msg_ty.rs @@ -0,0 +1,18 @@ +#[repr(i16)] +#[derive(Debug, Clone, Copy)] +pub enum MessageType { + ClientMsg = 48, + ServerMsg = 49, + RobotMotion = 50, +} + +impl MessageType { + pub fn from_i16(num: i16) -> Option { + match num { + 48 => Some(Self::ClientMsg), + 49 => Some(Self::ServerMsg), + 50 => Some(Self::RobotMotion), + _ => None, + } + } +} diff --git a/rc_multiplayer/src/handler.rs b/rc_multiplayer/src/handler.rs new file mode 100644 index 0000000..88ec31d --- /dev/null +++ b/rc_multiplayer/src/handler.rs @@ -0,0 +1,256 @@ +pub struct LnlEventHandler { + event_handlers: std::collections::HashMap>, +} + +impl LnlEventHandler { + pub async fn new(init_ctx: &crate::InitConfig) -> Self { + let mut event_handlers = std::collections::HashMap::new(); + // init event code handlers + Self { + event_handlers + } + } +} + +#[async_trait::async_trait] +impl literustlib_server::EventHandler for LnlEventHandler { + type PacketData = super::PacketData; + type UserData = super::UserData; + + async fn on_receive(&self, data: Self::PacketData, _header: &literustlib::packet::Header, peer: &mut literustlib_server::Connection, user: &Self::UserData, sender: &literustlib_server::DataSender) { + log::debug!("Got event {:?} (len: {}) from connection id {}", data.variant, data.data.len(), peer.id()); + if let Some(handler) = self.event_handlers.get(&(data.variant as u16)) { + handler.handle(&data.data, peer, user, sender).await; + } else { + #[cfg(debug_assertions)] + { + panic!("Unsupported event variant {:?} ({}), pls fix!!!\n {:?}", data.variant, data.variant as u16, &data.data[..]); + } + #[cfg(not(debug_assertions))] + { + log::warn!("Unsupported event variant {:?} ({}), pls fix!!!", data.variant, data.variant as u16); + } + } + } + + async fn on_connect_start(&self, addr: &core::net::SocketAddr, key: String, peer: &mut literustlib_server::Connection) -> Option { + log::debug!("New connection started from {}!!! (key:{}, id:{})", addr, key, peer.id()); + //let mut buf = Vec::new(); + //literustlib::packet::Packet::with_data(literustlib::packet::Property::Reliable, &[9, 0, 0, 0, 0, 0]).dump(&mut buf).unwrap_or_default(); + //socket.send_to(&buf, addr).await.unwrap_or_default(); + Some(()) + } + + async fn on_connect_done(&self, peer: &mut literustlib_server::Connection, _user: &Self::UserData, sender: &literustlib_server::DataSender) { + log::debug!("New connection completed (id:{})", peer.id()); + //let mut buf = Vec::new(); + //literustlib::packet::Packet::with_data(literustlib::packet::Property::Reliable, &[9, 0, 0, 0, 0, 0]).dump(&mut buf).unwrap_or_default(); + //socket.send_to(&buf, addr).await.unwrap_or_default(); + if let Err(e) = sender.send_to(bytes::Bytes::from_static(&[49, 0, 9, 0, 0, 0]), literustlib::packet::Property::Reliable, peer).await { + log::error!("Failed to send rlnl OnConnectedToGameServer event: {}", e); + } + + } +} + +#[derive(Debug)] +pub struct EventData { + pub message_ty: crate::data::MessageType, + pub variant: rlnl::event_code::NetworkEvent, + pub data_size: u16, + pub data: bytes::Bytes, +} + +impl literustlib::packet::PacketData for EventData { + fn parse(bytes: bytes::Bytes, _header: &literustlib::packet::Header) -> std::io::Result { + if bytes.len() >= 6 { + let data = bytes.slice(6..); + let slice: &[u8] = &bytes[0..6]; + let net_message_num = i16::from_le_bytes([bytes[0], bytes[1]]); + let net_message_type = crate::data::MessageType::from_i16(net_message_num).ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Unsupported, format!("Unsupported message type {}", net_message_num)))?; + let event_code = i16::from_le_bytes([bytes[2], bytes[3]]); + let data_size = u16::from_le_bytes([bytes[4], bytes[5]]); + if let Some(event_variant) = i16_to_event(event_code) { + Ok(Self { + message_ty: net_message_type, + variant: event_variant, + data_size, + data, + }) + } else { + Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Invalid packet code")) + } + } else { + Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "Packet data is not long enough")) + } + + } + + fn dump(&self) -> Vec { + use std::io::Write; + let mut buf = Vec::new(); + buf.write_all(&(self.variant as u16).to_be_bytes()).unwrap(); + buf.write_all(&self.data).unwrap(); + buf + } +} + +fn i16_to_event(num: i16) -> Option { + match num { + 0 => Some(rlnl::event_code::NetworkEvent::OnFailedToConnectToMasterServer), + 1 => Some(rlnl::event_code::NetworkEvent::OnConnectingToLobbyServer), + 2 => Some(rlnl::event_code::NetworkEvent::OnConnectedToLobbyServer), + 3 => Some(rlnl::event_code::NetworkEvent::OnDisconnectingFromLobbyServer), + 4 => Some(rlnl::event_code::NetworkEvent::OnDisconnectedFromLobbyServer), + 5 => Some(rlnl::event_code::NetworkEvent::OnConnectedToServer), + 6 => Some(rlnl::event_code::NetworkEvent::OnFailedToConnectToServer), + 7 => Some(rlnl::event_code::NetworkEvent::OnConnectionLost), + 8 => Some(rlnl::event_code::NetworkEvent::OnDisconnectedFromServer), + 9 => Some(rlnl::event_code::NetworkEvent::OnConnectedToGameServer), + 10 => Some(rlnl::event_code::NetworkEvent::OnServerStarted), + 11 => Some(rlnl::event_code::NetworkEvent::OnServerStopped), + 12 => Some(rlnl::event_code::NetworkEvent::OnPlayerConnectedToServer), + 13 => Some(rlnl::event_code::NetworkEvent::OnPlayerDisconnectedFromServer), + 14 => Some(rlnl::event_code::NetworkEvent::RequestRespawnPoint), + 15 => Some(rlnl::event_code::NetworkEvent::FreeSpawnPoint), + 16 => Some(rlnl::event_code::NetworkEvent::RequestTeamBaseModel), + 17 => Some(rlnl::event_code::NetworkEvent::RequestCapturePoints), + 18 => Some(rlnl::event_code::NetworkEvent::RequestEqualizerModel), + 19 => Some(rlnl::event_code::NetworkEvent::TeamBase), + 20 => Some(rlnl::event_code::NetworkEvent::RegisterCapturePoints), + 21 => Some(rlnl::event_code::NetworkEvent::RegisterEqualizer), + 22 => Some(rlnl::event_code::NetworkEvent::FreeRespawnPoint), + 23 => Some(rlnl::event_code::NetworkEvent::PlayerIDs), + 24 => Some(rlnl::event_code::NetworkEvent::SyncMachineCubes), + 25 => Some(rlnl::event_code::NetworkEvent::MachineDestroyed), + 26 => Some(rlnl::event_code::NetworkEvent::GameStarted), + 27 => Some(rlnl::event_code::NetworkEvent::OnPlayerInputChanged), + 28 => Some(rlnl::event_code::NetworkEvent::OnServerReceivedInputChange), + 29 => Some(rlnl::event_code::NetworkEvent::ClientUnregistered), + 30 => Some(rlnl::event_code::NetworkEvent::OnAnotherClientDisconnected), + 31 => Some(rlnl::event_code::NetworkEvent::OnClientReconnected), + 32 => Some(rlnl::event_code::NetworkEvent::DamageCube), + 33 => Some(rlnl::event_code::NetworkEvent::FireWeaponEffect), + 35 => Some(rlnl::event_code::NetworkEvent::FireMiss), + 36 => Some(rlnl::event_code::NetworkEvent::MultipleFireMisses), + 37 => Some(rlnl::event_code::NetworkEvent::CurrentGameTime), + 38 => Some(rlnl::event_code::NetworkEvent::EndGame), + 39 => Some(rlnl::event_code::NetworkEvent::GameWon), + 40 => Some(rlnl::event_code::NetworkEvent::GameLost), + 41 => Some(rlnl::event_code::NetworkEvent::GameWonBaseDestroyed), + 42 => Some(rlnl::event_code::NetworkEvent::GameLostBaseDestroyed), + 43 => Some(rlnl::event_code::NetworkEvent::BuffTeamPlayers), + 44 => Some(rlnl::event_code::NetworkEvent::PlayerThreateningBase), + 45 => Some(rlnl::event_code::NetworkEvent::TimeToGameStart), + 46 => Some(rlnl::event_code::NetworkEvent::SetRespawnWaitingTime), + 47 => Some(rlnl::event_code::NetworkEvent::TeamBaseState), + 48 => Some(rlnl::event_code::NetworkEvent::TeamBaseCaptureStart), + 49 => Some(rlnl::event_code::NetworkEvent::TeamBaseCaptureReset), + 50 => Some(rlnl::event_code::NetworkEvent::TeamBaseCaptureStop), + 51 => Some(rlnl::event_code::NetworkEvent::TeamBaseSectionComplete), + 52 => Some(rlnl::event_code::NetworkEvent::TeamBaseFinalSectionComplete), + 53 => Some(rlnl::event_code::NetworkEvent::TeamBaseInitialise), + 54 => Some(rlnl::event_code::NetworkEvent::GetClientPings), + 55 => Some(rlnl::event_code::NetworkEvent::SetClientPing), + 56 => Some(rlnl::event_code::NetworkEvent::WarnPlayer), + 57 => Some(rlnl::event_code::NetworkEvent::EnemySpotted), + 58 => Some(rlnl::event_code::NetworkEvent::RemoteEnemySpotted), + 59 => Some(rlnl::event_code::NetworkEvent::AssistBonusRequest), + 60 => Some(rlnl::event_code::NetworkEvent::TeamBaseContested), + 61 => Some(rlnl::event_code::NetworkEvent::AcquireRemoteAI), + 63 => Some(rlnl::event_code::NetworkEvent::KillBonusRequest), + 64 => Some(rlnl::event_code::NetworkEvent::EACRegisterToken), + 65 => Some(rlnl::event_code::NetworkEvent::HeallingAssistBonusRequest), + 66 => Some(rlnl::event_code::NetworkEvent::ProtectTeamMateBonusRequest), + 67 => Some(rlnl::event_code::NetworkEvent::DefendTheBaseBonusRequest), + 68 => Some(rlnl::event_code::NetworkEvent::DestroyCubesBonusRequest), + 69 => Some(rlnl::event_code::NetworkEvent::DestroyHealCubesPointsAwarded), + 70 => Some(rlnl::event_code::NetworkEvent::ConfirmedKill), + 71 => Some(rlnl::event_code::NetworkEvent::BonusesFlushDone), + 72 => Some(rlnl::event_code::NetworkEvent::AlignmentRectifierStarted), + 73 => Some(rlnl::event_code::NetworkEvent::HealCubesBonusRequest), + 74 => Some(rlnl::event_code::NetworkEvent::SetShieldState), + 75 => Some(rlnl::event_code::NetworkEvent::TeamBaseLowHealth), + 76 => Some(rlnl::event_code::NetworkEvent::AwardTeamBaseProtoniumDestroyedRequest), + 77 => Some(rlnl::event_code::NetworkEvent::InitialiseGameStats), + 78 => Some(rlnl::event_code::NetworkEvent::UpdateGameStats), + 79 => Some(rlnl::event_code::NetworkEvent::MapPingEvent), + 80 => Some(rlnl::event_code::NetworkEvent::SurrenderRequest), + 81 => Some(rlnl::event_code::NetworkEvent::HealSelf), + 82 => Some(rlnl::event_code::NetworkEvent::HealSelfResponse), + 83 => Some(rlnl::event_code::NetworkEvent::SurrenderVoteStarted), + 84 => Some(rlnl::event_code::NetworkEvent::SurrenderVoteCast), + 85 => Some(rlnl::event_code::NetworkEvent::CurrentSurrenderVotes), + 86 => Some(rlnl::event_code::NetworkEvent::SurrenderAccepted), + 87 => Some(rlnl::event_code::NetworkEvent::SurrenderDeclined), + 88 => Some(rlnl::event_code::NetworkEvent::SetSurrenderTimes), + 89 => Some(rlnl::event_code::NetworkEvent::SetFinalGameScore), + 90 => Some(rlnl::event_code::NetworkEvent::PitLeaderBoardUpdate), + 91 => Some(rlnl::event_code::NetworkEvent::PitModeState), + 93 => Some(rlnl::event_code::NetworkEvent::ValidateGameGuid), + 94 => Some(rlnl::event_code::NetworkEvent::GameGuidValidated), + 95 => Some(rlnl::event_code::NetworkEvent::PlayerInsideBase), + 97 => Some(rlnl::event_code::NetworkEvent::ConfirmedAssist), + 98 => Some(rlnl::event_code::NetworkEvent::LockOnNotification), + 99 => Some(rlnl::event_code::NetworkEvent::LockOnNotificationBroadcast), + 100 => Some(rlnl::event_code::NetworkEvent::ShieldSpawned), + 101 => Some(rlnl::event_code::NetworkEvent::SpawnShield), + 102 => Some(rlnl::event_code::NetworkEvent::BroadcastOpenShield), + 103 => Some(rlnl::event_code::NetworkEvent::OpenShield), + 104 => Some(rlnl::event_code::NetworkEvent::BroadcastInvisible), + 105 => Some(rlnl::event_code::NetworkEvent::MakeInvisible), + 106 => Some(rlnl::event_code::NetworkEvent::BroadcastVisible), + 107 => Some(rlnl::event_code::NetworkEvent::MakeVisible), + 108 => Some(rlnl::event_code::NetworkEvent::BroadcastActivateTeleportEffect), + 109 => Some(rlnl::event_code::NetworkEvent::ActivateTeleportEffect), + 110 => Some(rlnl::event_code::NetworkEvent::BroadcastActivateReadyEffect), + 111 => Some(rlnl::event_code::NetworkEvent::ActivateReadyEffect), + 112 => Some(rlnl::event_code::NetworkEvent::BroadcastSpawnEmpLocator), + 113 => Some(rlnl::event_code::NetworkEvent::SpawnEmpLocator), + 114 => Some(rlnl::event_code::NetworkEvent::BroadcastSpawnEmpMachineEffect), + 115 => Some(rlnl::event_code::NetworkEvent::SpawnEmpMachineEffect), + 116 => Some(rlnl::event_code::NetworkEvent::WeaponSelect), + 117 => Some(rlnl::event_code::NetworkEvent::BroadcastWeaponSelect), + 118 => Some(rlnl::event_code::NetworkEvent::HostAIs), + 119 => Some(rlnl::event_code::NetworkEvent::HealAlly), + 120 => Some(rlnl::event_code::NetworkEvent::HealAllyResponse), + 121 => Some(rlnl::event_code::NetworkEvent::SelfDestructClassicMode), + 122 => Some(rlnl::event_code::NetworkEvent::GameModeSettings), + 123 => Some(rlnl::event_code::NetworkEvent::TeamDeathMatchState), + 124 => Some(rlnl::event_code::NetworkEvent::ClientDisconnecting), + 125 => Some(rlnl::event_code::NetworkEvent::SendBonus), + 126 => Some(rlnl::event_code::NetworkEvent::TestConnection), + 127 => Some(rlnl::event_code::NetworkEvent::MachineDestroyedConfirmed), + 128 => Some(rlnl::event_code::NetworkEvent::EnergyModuleActivated), + 129 => Some(rlnl::event_code::NetworkEvent::BroadcastLoadingProgress), + 130 => Some(rlnl::event_code::NetworkEvent::RequestLoadingProgressAllUsers), + 131 => Some(rlnl::event_code::NetworkEvent::LoadingComplete), + 132 => Some(rlnl::event_code::NetworkEvent::GameAborted), + 134 => Some(rlnl::event_code::NetworkEvent::SendDamagedByEnemyShield), + 135 => Some(rlnl::event_code::NetworkEvent::DamagedByEnemyShield), + 136 => Some(rlnl::event_code::NetworkEvent::EqualizerNotification), + 137 => Some(rlnl::event_code::NetworkEvent::CapturePointProgress), + 138 => Some(rlnl::event_code::NetworkEvent::CapturePointNotification), + 140 => Some(rlnl::event_code::NetworkEvent::RadarModuleActivated), + 141 => Some(rlnl::event_code::NetworkEvent::RemoteRadarModuleActivated), + 142 => Some(rlnl::event_code::NetworkEvent::EACMessage), + 143 => Some(rlnl::event_code::NetworkEvent::Taunt), + 144 => Some(rlnl::event_code::NetworkEvent::MachineFullHealth), + 145 => Some(rlnl::event_code::NetworkEvent::RequestSync), + 146 => Some(rlnl::event_code::NetworkEvent::BeginSync), + 147 => Some(rlnl::event_code::NetworkEvent::EndOfSync), + 148 => Some(rlnl::event_code::NetworkEvent::SyncTeamBaseCubes), + 150 => Some(rlnl::event_code::NetworkEvent::SyncEqualizerNotification), + 151 => Some(rlnl::event_code::NetworkEvent::PlayerQuitRequest), + 152 => Some(rlnl::event_code::NetworkEvent::PlayerQuitRequestComplete), + 153 => Some(rlnl::event_code::NetworkEvent::DamageCubeEffectOnly), + 154 => Some(rlnl::event_code::NetworkEvent::DamageCubeNoEffect), + 155 => Some(rlnl::event_code::NetworkEvent::DestroyCubeEffectOnly), + 156 => Some(rlnl::event_code::NetworkEvent::DestroyCubeNoEffect), + 157 => Some(rlnl::event_code::NetworkEvent::DestroyCubesFull), + 170 => Some(rlnl::event_code::NetworkEvent::LongPlayValue), + 171 => Some(rlnl::event_code::NetworkEvent::UpdateVotingAfterBattle), + 172 => Some(rlnl::event_code::NetworkEvent::CosmeticAction), + _ => None, + } +} diff --git a/rc_multiplayer/src/main.rs b/rc_multiplayer/src/main.rs new file mode 100644 index 0000000..1bc0e0f --- /dev/null +++ b/rc_multiplayer/src/main.rs @@ -0,0 +1,32 @@ +mod cli; +mod handler; +mod traits; +pub use traits::{EventCodeHandler, UserData, PacketData}; +mod data; + +pub struct InitConfig { + pub config: oj_rc_core::persist::config::ConfigImpl, + pub users: std::sync::Arc, + pub parsers: oj_rc_core::cubes::CubeParsers, +} + +#[tokio::main] +async fn main() -> std::io::Result<()> { + env_logger::init(); + let args = cli::CliArgs::get(); + log::debug!("Got cli args {:?}", args); + + let config = oj_rc_core::persist::config::ConfigImpl::load(&args.assets).expect("Bad config data"); + let users = std::sync::Arc::new(oj_rc_core::persist::user::UserImpl::load(&args.data, &config).await.expect("Bad user data")); + let parsers = oj_rc_core::cubes::CubeParsers::new(&config); + + let init_ctx = InitConfig { + config, + users, + parsers, + }; + + let event_handler = handler::LnlEventHandler::new(&init_ctx).await; + let server = literustlib_server::Server::new(event_handler, (args.ip, args.port), 4223).await.expect("Bad server"); + server.listen().await +} diff --git a/rc_multiplayer/src/traits.rs b/rc_multiplayer/src/traits.rs new file mode 100644 index 0000000..43096d6 --- /dev/null +++ b/rc_multiplayer/src/traits.rs @@ -0,0 +1,7 @@ +pub type UserData = (); +pub type PacketData = crate::handler::EventData; + +#[async_trait::async_trait] +pub trait EventCodeHandler: Send + Sync { + async fn handle(&self, data: &bytes::Bytes, peer: &mut literustlib_server::Connection, user: &UserData, sender: &literustlib_server::DataSender); +}