diff --git a/Cargo.lock b/Cargo.lock index d86b22d..3009724 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1743,6 +1743,21 @@ dependencies = [ "polariton", "polariton_auth", "polariton_server", + "rc_core", + "tokio", +] + +[[package]] +name = "rc_core" +version = "0.1.0" +dependencies = [ + "chrono", + "hex", + "log", + "polariton", + "polariton_server", + "serde", + "serde_json", "tokio", ] @@ -1782,6 +1797,7 @@ dependencies = [ "polariton", "polariton_auth", "polariton_server", + "rc_core", "serde", "serde_json", "tokio", @@ -1810,6 +1826,7 @@ dependencies = [ "polariton", "polariton_auth", "polariton_server", + "rc_core", "tokio", ] @@ -1836,6 +1853,7 @@ dependencies = [ "polariton", "polariton_auth", "polariton_server", + "rc_core", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 6260bfb..f2ccc7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ members = [ "rc_static_data", "rc_microtransactions", "rc_social", "rc_social_room", "rc_chat", "rc_chat_room", - "rc_singleplayer", "rc_singleplayer_room", + "rc_singleplayer", "rc_singleplayer_room", "rc_core", ] [workspace.dependencies] diff --git a/README.md b/README.md index b24ee38..a3b8d5f 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,12 @@ To get Robocraft to use these servers, place [this servenvmulti.config](assets/r ## Privacy -No data is collected or logged, except in dev mode. Some personal identifiers are sent but only exist ephemerally. +The minimum amount of data is (and should be) collected to provide the expected functionality. +In most cases, these means no data is collected or logged except some debug log messages in development versions. +Some personal identifiers are sent but only exist ephemerally. +The exception is Robocraft servers, which store the minimum account info possible on disk. +This includes a unique user identifier, username, vehicle data, and user configuration data. +The current PC's MAC address is also sent to the server (this is a Robocraft client """feature""", it is not recorded by any server). ## Development @@ -24,8 +29,10 @@ No data is collected or logged, except in dev mode. Some personal identifiers ar Run all of the servers using their respective `run_debug.sh` scripts and use the `dev` profile in `servenvmulti.config` to point the game to your local dev servers. +It is possible to remove the obfuscation from the Robocraft's `Assembly-CSharp.dll` if you need to figure out how it expects the server to behave. + ## Contributing -If you can program, pull requests are appreciated! If you can't and don't like learning, reporting issues is also welcome. +If you can program or are learning Rust, pull requests are appreciated! If you can't and would prefer not to learn, reporting issues is also welcome. If you'd like to discuss, contact NGnius on Signal `rfc.1149` or email `ngniusness@gmail.com`. I'll make a Signal group chat if there's enough interest. diff --git a/rc_chat_room/Cargo.toml b/rc_chat_room/Cargo.toml index a415aaf..6512a69 100644 --- a/rc_chat_room/Cargo.toml +++ b/rc_chat_room/Cargo.toml @@ -11,3 +11,4 @@ clap.workspace = true polariton.workspace = true polariton_auth = { version = "*", path = "../polariton_auth" } polariton_server.workspace = true +rc_core = { version = "*", path = "../rc_core" } diff --git a/rc_chat_room/src/cli.rs b/rc_chat_room/src/cli.rs index e8acaf1..788c912 100644 --- a/rc_chat_room/src/cli.rs +++ b/rc_chat_room/src/cli.rs @@ -11,6 +11,14 @@ pub struct CliArgs { #[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, + /// Handle one connection and then exit #[arg(short = '1', long)] pub once: bool, diff --git a/rc_chat_room/src/main.rs b/rc_chat_room/src/main.rs index 183c01c..cf59de5 100644 --- a/rc_chat_room/src/main.rs +++ b/rc_chat_room/src/main.rs @@ -1,5 +1,4 @@ mod cli; -mod state; mod data; mod operations; @@ -10,7 +9,7 @@ use tokio::net; use polariton::packet::{Data, Message, Packet, StandardMessage}; use polariton::operation::{OperationResponse, Typed}; -pub type UserTy = std::sync::RwLock; +pub type UserTy = rc_core::UserState; #[tokio::main] async fn main() -> std::io::Result<()> { @@ -18,6 +17,9 @@ async fn main() -> std::io::Result<()> { let args = cli::CliArgs::get(); log::debug!("Got cli args {:?}", args); + let cubes = rc_core::persist::config::ConfigImpl::load(&args.assets).expect("Bad config data"); + let users = std::sync::Arc::new(rc_core::persist::user::UserImpl::load(&args.data, &cubes).expect("Bad user data")); + let server = std::sync::Arc::new(polariton_server::Server::new(operations::handler(), polariton_server::events::EventsHandler::new())); let ip_addr: std::net::IpAddr = args.ip.parse().expect("Invalid IP address"); @@ -27,11 +29,11 @@ async fn main() -> std::io::Result<()> { if args.once { log::warn!("Handling first connection and then exiting"); let (socket, address) = listener.accept().await?; - process_socket(socket, address, server.clone()).await; + process_socket(socket, address, server.clone(), users.clone()).await; } else { loop { let (socket, address) = listener.accept().await?; - tokio::spawn(process_socket(socket, address, server.clone())); + tokio::spawn(process_socket(socket, address, server.clone(), users.clone())); } } server.join(); @@ -39,7 +41,7 @@ async fn main() -> std::io::Result<()> { Ok(()) } -async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAddr, server: std::sync::Arc>) { +async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAddr, server: std::sync::Arc>, users: std::sync::Arc) { log::debug!("Accepting connection from address {}", address); let enc = match do_connect_handshake(&mut socket).await { Some(x) => x, @@ -48,9 +50,10 @@ async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAdd return; } }; - let user_state = state::UserState::new(); + let (chann_tx, chann_rx) = tokio::sync::mpsc::unbounded_channel(); + let user_state = rc_core::UserState::<()>::new(users, chann_tx.clone()); let (socket_r, socket_w) = socket.into_split(); - let _packet_chann = server.handle_async(socket_r, socket_w, user_state, polariton::packet::SerdesContext::from_boxed(Default::default(), enc)).await; + server.handle_async_with_channel(socket_r, socket_w, user_state, polariton::packet::SerdesContext::from_boxed(Default::default(), enc), chann_tx, chann_rx).await; log::debug!("Goodbye connection from address {}", address); } diff --git a/rc_chat_room/src/operations/more_auth.rs b/rc_chat_room/src/operations/more_auth.rs index c1fc5ee..007d9fd 100644 --- a/rc_chat_room/src/operations/more_auth.rs +++ b/rc_chat_room/src/operations/more_auth.rs @@ -14,8 +14,7 @@ impl Operation for MoreLobbyAuth { fn handle(&self, params: polariton::operation::ParameterTable, _: &mut Self::State, user: &Self::User) -> polariton::operation::OperationResponse { let params_dict = params.to_dict(); if let Some(Typed::Str(auth_payload)) = params_dict.get(&Self::AUTH_PAYLOAD_KEY) { - let mut write_lock = user.write().unwrap(); - if write_lock.update_with_auth(&auth_payload.string) { + if user.update_with_auth(&auth_payload.string) { let mut resp_params = std::collections::HashMap::new(); resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0)); return polariton::operation::OperationResponse { diff --git a/rc_chat_room/src/state.rs b/rc_chat_room/src/state.rs deleted file mode 100644 index bc39273..0000000 --- a/rc_chat_room/src/state.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::sync::RwLock; - -#[derive(Default, Debug)] -pub struct UserState { - pub uuid: String, - pub token: String, - pub refresh_token: String, -} - -impl UserState { - pub fn update_with_auth(&mut self, auth_str: &str) -> bool { - let splits: Vec<&str> = auth_str.split(';').collect(); - if splits.len() != 3 { - log::warn!("Invalid auth payload: {}", auth_str); - false - } else { - self.uuid = splits[0].to_owned(); - self.token = splits[1].to_owned(); - self.refresh_token = splits[2].to_owned(); - true - } - } - - pub fn new() -> crate::UserTy { - RwLock::new(UserState::default()) - } -} diff --git a/rc_core/Cargo.toml b/rc_core/Cargo.toml new file mode 100644 index 0000000..0d36b75 --- /dev/null +++ b/rc_core/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rc_core" +version = "0.1.0" +edition = "2024" + +[dependencies] +log.workspace = true +polariton.workspace = true +hex = "0.4" +serde.workspace = true +serde_json.workspace = true +chrono = "0.4" +polariton_server.workspace = true +tokio = { version = "1.43", features = [ "net", "macros", "rt-multi-thread", "io-util", "time"] } diff --git a/rc_services_room/src/data/auto_regen.rs b/rc_core/src/data/auto_regen.rs similarity index 100% rename from rc_services_room/src/data/auto_regen.rs rename to rc_core/src/data/auto_regen.rs diff --git a/rc_services_room/src/data/campaign.rs b/rc_core/src/data/campaign.rs similarity index 100% rename from rc_services_room/src/data/campaign.rs rename to rc_core/src/data/campaign.rs diff --git a/rc_services_room/src/data/cube_list.rs b/rc_core/src/data/cube_list.rs similarity index 100% rename from rc_services_room/src/data/cube_list.rs rename to rc_core/src/data/cube_list.rs diff --git a/rc_services_room/src/data/error_codes.rs b/rc_core/src/data/error_codes.rs similarity index 100% rename from rc_services_room/src/data/error_codes.rs rename to rc_core/src/data/error_codes.rs diff --git a/rc_services_room/src/data/game_mode.rs b/rc_core/src/data/game_mode.rs similarity index 100% rename from rc_services_room/src/data/game_mode.rs rename to rc_core/src/data/game_mode.rs diff --git a/rc_services_room/src/data/garage_bay.rs b/rc_core/src/data/garage_bay.rs similarity index 100% rename from rc_services_room/src/data/garage_bay.rs rename to rc_core/src/data/garage_bay.rs diff --git a/rc_core/src/data/mod.rs b/rc_core/src/data/mod.rs new file mode 100644 index 0000000..e20fd4a --- /dev/null +++ b/rc_core/src/data/mod.rs @@ -0,0 +1,39 @@ +pub mod auto_regen; +pub mod campaign; +pub mod cube_list; +pub mod game_mode; +pub mod garage_bay; +pub mod movement_list; +pub mod player_data; +pub mod tech_tree; +pub mod voting; +pub mod weapon_list; +pub mod weapon_upgrade; + +pub mod error_codes; + +pub fn encode_7_bit_i32(mut src: i32) -> Vec { + if src == 0 { return vec![0] } + let mut out = Vec::with_capacity(5); + while src != 0 { + let last_7 = (src & 0x7F) as u8; + src = src >> 7; + if src != 0 { + out.push(last_7 | 0x80); + } else { + out.push(last_7); + } + } + out +} + +pub fn write_str_for_binreader(s: &str, writer: &mut dyn std::io::Write) -> std::io::Result { + let s_bytes = s.as_bytes(); + let mut total_len = writer.write(&encode_7_bit_i32(s_bytes.len() as i32))?; + total_len += writer.write(s_bytes)?; + Ok(total_len) +} + +pub fn cube_id_to_str(id: u32) -> String { + hex::encode(id.to_be_bytes()).into() +} diff --git a/rc_services_room/src/data/movement_list.rs b/rc_core/src/data/movement_list.rs similarity index 100% rename from rc_services_room/src/data/movement_list.rs rename to rc_core/src/data/movement_list.rs diff --git a/rc_singleplayer_room/src/data/player_data.rs b/rc_core/src/data/player_data.rs similarity index 100% rename from rc_singleplayer_room/src/data/player_data.rs rename to rc_core/src/data/player_data.rs diff --git a/rc_services_room/src/data/tech_tree.rs b/rc_core/src/data/tech_tree.rs similarity index 100% rename from rc_services_room/src/data/tech_tree.rs rename to rc_core/src/data/tech_tree.rs diff --git a/rc_services_room/src/data/voting.rs b/rc_core/src/data/voting.rs similarity index 100% rename from rc_services_room/src/data/voting.rs rename to rc_core/src/data/voting.rs diff --git a/rc_services_room/src/data/weapon_list.rs b/rc_core/src/data/weapon_list.rs similarity index 100% rename from rc_services_room/src/data/weapon_list.rs rename to rc_core/src/data/weapon_list.rs diff --git a/rc_services_room/src/data/weapon_upgrade.rs b/rc_core/src/data/weapon_upgrade.rs similarity index 100% rename from rc_services_room/src/data/weapon_upgrade.rs rename to rc_core/src/data/weapon_upgrade.rs diff --git a/rc_core/src/lib.rs b/rc_core/src/lib.rs new file mode 100644 index 0000000..3c8eeed --- /dev/null +++ b/rc_core/src/lib.rs @@ -0,0 +1,8 @@ +pub mod data; + +mod state; +pub use state::UserState; + +pub mod persist; +pub use persist::user::{UserImpl, UserProvider}; +pub use persist::config::{ConfigImpl, ConfigProvider}; diff --git a/rc_services_room/src/persist/combat.rs b/rc_core/src/persist/combat.rs similarity index 100% rename from rc_services_room/src/persist/combat.rs rename to rc_core/src/persist/combat.rs diff --git a/rc_services_room/src/persist/config/cubes_json.rs b/rc_core/src/persist/config/cubes_json.rs similarity index 100% rename from rc_services_room/src/persist/config/cubes_json.rs rename to rc_core/src/persist/config/cubes_json.rs diff --git a/rc_services_room/src/persist/config/mod.rs b/rc_core/src/persist/config/mod.rs similarity index 100% rename from rc_services_room/src/persist/config/mod.rs rename to rc_core/src/persist/config/mod.rs diff --git a/rc_services_room/src/persist/config/traits.rs b/rc_core/src/persist/config/traits.rs similarity index 100% rename from rc_services_room/src/persist/config/traits.rs rename to rc_core/src/persist/config/traits.rs diff --git a/rc_services_room/src/persist/cube_data.rs b/rc_core/src/persist/cube_data.rs similarity index 100% rename from rc_services_room/src/persist/cube_data.rs rename to rc_core/src/persist/cube_data.rs diff --git a/rc_services_room/src/persist/garage.rs b/rc_core/src/persist/garage.rs similarity index 100% rename from rc_services_room/src/persist/garage.rs rename to rc_core/src/persist/garage.rs diff --git a/rc_services_room/src/persist/mod.rs b/rc_core/src/persist/mod.rs similarity index 100% rename from rc_services_room/src/persist/mod.rs rename to rc_core/src/persist/mod.rs diff --git a/rc_services_room/src/persist/movement.rs b/rc_core/src/persist/movement.rs similarity index 100% rename from rc_services_room/src/persist/movement.rs rename to rc_core/src/persist/movement.rs diff --git a/rc_services_room/src/persist/singleplayer.rs b/rc_core/src/persist/singleplayer.rs similarity index 100% rename from rc_services_room/src/persist/singleplayer.rs rename to rc_core/src/persist/singleplayer.rs diff --git a/rc_services_room/src/persist/tech_tree.rs b/rc_core/src/persist/tech_tree.rs similarity index 100% rename from rc_services_room/src/persist/tech_tree.rs rename to rc_core/src/persist/tech_tree.rs diff --git a/rc_services_room/src/persist/user/account_json.rs b/rc_core/src/persist/user/account_json.rs similarity index 84% rename from rc_services_room/src/persist/user/account_json.rs rename to rc_core/src/persist/user/account_json.rs index f8d3be0..46d6dbd 100644 --- a/rc_services_room/src/persist/user/account_json.rs +++ b/rc_core/src/persist/user/account_json.rs @@ -153,6 +153,7 @@ impl super::User for UserData { robot_rank: polariton::operation::Typed::Int(slot.total_robot_ranking as _), cpu: polariton::operation::Typed::Int(slot.total_robot_cpu as _), cosmetic_cpu: polariton::operation::Typed::Int(slot.total_cosmetic_cpu as _), + uuid: polariton::operation::Typed::Str(format!("{}_{}", slot.uuid.0, slot.uuid.1).into()), }) }, Err(e) => { @@ -200,6 +201,37 @@ impl super::User for UserData { super::since_windows_epoch(0) } + fn singleplayer_robots(&self) -> Result, i16> { + let current_slot = self.load_garage_by_id(self.account.garage.slot).map_err(|e| { + log::error!("Failed to load current vehicle: {}", e); + INVALID_ROBOT_ERR + })?; + let user_uuid = self.token.uuid.clone(); + Ok(crate::data::player_data::PlayerDatas { + players: vec![ + crate::data::player_data::PlayerData { + name: user_uuid.clone(), + display_name: user_uuid, + mastery: current_slot.mastery_level, + tier: 1, // FIXME + robot_name: current_slot.name, + robot_map: current_slot.robot_data, + team: 0, + has_premium: true, // FIXME + robot_uuid: format!("{}_{}", current_slot.uuid.0, current_slot.uuid.1), + cpu: current_slot.total_robot_cpu as i32, + weapon_order: current_slot.weapon_order.clone(), + colour_map: current_slot.colour_data, + is_ai: false, + spawn_effect: "Spawn_Warp".to_owned(), // FIXME + death_effect: "Explosion_Warp".to_owned(), // FIXME + player_rank: 1, // FIXME + weapon_rank: current_slot.weapon_order.into_iter().map(|x| (x, if x == 0 { 0 } else { 1 })).collect(), + } + ], + }.as_transmissible()) + } + } #[derive(Serialize, Deserialize, Clone, Debug)] diff --git a/rc_services_room/src/persist/user/garage_data.rs b/rc_core/src/persist/user/garage_data.rs similarity index 100% rename from rc_services_room/src/persist/user/garage_data.rs rename to rc_core/src/persist/user/garage_data.rs diff --git a/rc_services_room/src/persist/user/initial_data.rs b/rc_core/src/persist/user/initial_data.rs similarity index 100% rename from rc_services_room/src/persist/user/initial_data.rs rename to rc_core/src/persist/user/initial_data.rs diff --git a/rc_services_room/src/persist/user/inventory.rs b/rc_core/src/persist/user/inventory.rs similarity index 100% rename from rc_services_room/src/persist/user/inventory.rs rename to rc_core/src/persist/user/inventory.rs diff --git a/rc_services_room/src/persist/user/mod.rs b/rc_core/src/persist/user/mod.rs similarity index 100% rename from rc_services_room/src/persist/user/mod.rs rename to rc_core/src/persist/user/mod.rs diff --git a/rc_services_room/src/persist/user/traits.rs b/rc_core/src/persist/user/traits.rs similarity index 92% rename from rc_services_room/src/persist/user/traits.rs rename to rc_core/src/persist/user/traits.rs index 1c938a6..9282444 100644 --- a/rc_services_room/src/persist/user/traits.rs +++ b/rc_core/src/persist/user/traits.rs @@ -22,6 +22,7 @@ pub trait User { fn slot_by_id(&self, id: i32) -> Result, i16>; fn save_slot(&self, vehicle: VehicleData) -> Result<(), i16>; fn signup_date(&self) -> i64; + fn singleplayer_robots(&self) -> Result, i16>; } pub struct UserSlots { @@ -41,6 +42,7 @@ pub struct UserSlotData { pub robot_rank: polariton::operation::Typed, pub cpu: polariton::operation::Typed, pub cosmetic_cpu: polariton::operation::Typed, + pub uuid: polariton::operation::Typed, } pub struct VehicleData { diff --git a/rc_services_room/src/persist/weapon.rs b/rc_core/src/persist/weapon.rs similarity index 100% rename from rc_services_room/src/persist/weapon.rs rename to rc_core/src/persist/weapon.rs diff --git a/rc_services_room/src/state.rs b/rc_core/src/state.rs similarity index 55% rename from rc_services_room/src/state.rs rename to rc_core/src/state.rs index 6ae2be5..9c970e5 100644 --- a/rc_services_room/src/state.rs +++ b/rc_core/src/state.rs @@ -1,12 +1,15 @@ use crate::persist::user::UserProvider; +use polariton_server::ToSend; -pub struct UserState { - state: InitState, +pub struct UserState { + state: std::sync::RwLock>, + event_tx: tokio::sync::mpsc::UnboundedSender>, } impl UserState { - pub fn update_with_auth(&mut self, auth_str: &str) -> bool { - match &self.state { + pub fn update_with_auth(&self, auth_str: &str) -> bool { + let mut lock = self.state.write().unwrap(); + match &*lock { InitState::Unauthenticated(auth) => { let splits: Vec<&str> = auth_str.split(';').collect(); if splits.len() != 3 { @@ -20,7 +23,7 @@ impl UserState { }; match auth.authenticate(token) { Ok(user) => { - self.state = InitState::Authenticated(user); + *lock = InitState::Authenticated(std::sync::Arc::new(user)); true }, Err(e) => { @@ -38,21 +41,31 @@ impl UserState { } - pub fn new(provider: std::sync::Arc) -> Self { + pub fn new(provider: std::sync::Arc, event_tx: tokio::sync::mpsc::UnboundedSender>) -> Self { Self { - state: InitState::Unauthenticated(provider), + state: std::sync::RwLock::new(InitState::Unauthenticated(provider)), + event_tx, } } - pub fn user(&self) -> Result<&dyn crate::persist::user::User, i16> { - match &self.state { + pub fn user(&self) -> Result + Send + Sync>>, i16> { + let lock = self.state.read().unwrap(); + match &*lock { InitState::Unauthenticated(_) => Err(120), - InitState::Authenticated(user) => Ok(user.as_ref()), + InitState::Authenticated(user) => Ok(user.clone()), } } + + pub fn event(&self, event_data: ToSend) { + self.event_tx.send(event_data).unwrap() + } + + pub fn event_sender(&self) -> tokio::sync::mpsc::UnboundedSender> { + self.event_tx.clone() + } } enum InitState { Unauthenticated(std::sync::Arc), - Authenticated(Box + Send + Sync>), + Authenticated(std::sync::Arc + Send + Sync>>), } diff --git a/rc_services_room/Cargo.toml b/rc_services_room/Cargo.toml index 5d941b8..57bba90 100644 --- a/rc_services_room/Cargo.toml +++ b/rc_services_room/Cargo.toml @@ -16,3 +16,4 @@ hex = "0.4" serde.workspace = true serde_json.workspace = true chrono = "0.4" +rc_core = { version = "*", path = "../rc_core" } diff --git a/rc_services_room/src/data/item_shop_bundle.rs b/rc_services_room/src/data/item_shop_bundle.rs index 764042b..16924d7 100644 --- a/rc_services_room/src/data/item_shop_bundle.rs +++ b/rc_services_room/src/data/item_shop_bundle.rs @@ -30,21 +30,21 @@ impl ItemShopBundle { fn dump(&self, writer: &mut dyn Write) -> std::io::Result { let sku_bytes = self.sku.as_bytes(); - let mut total_len = writer.write(&super::encode_7_bit_i32(sku_bytes.len() as i32))?; + let mut total_len = writer.write(&rc_core::data::encode_7_bit_i32(sku_bytes.len() as i32))?; total_len += writer.write(sku_bytes)?; let bundle_name_key_bytes = self.bundle_name_key.as_bytes(); - total_len += writer.write(&super::encode_7_bit_i32(bundle_name_key_bytes.len() as i32))?; + total_len += writer.write(&rc_core::data::encode_7_bit_i32(bundle_name_key_bytes.len() as i32))?; total_len += writer.write(bundle_name_key_bytes)?; let sprite_bytes = self.sprite.as_bytes(); - total_len += writer.write(&super::encode_7_bit_i32(sprite_bytes.len() as i32))?; + total_len += writer.write(&rc_core::data::encode_7_bit_i32(sprite_bytes.len() as i32))?; total_len += writer.write(sprite_bytes)?; total_len += writer.write(&[self.is_sprite_full_size as u8])?; let currency_bytes = self.currency.as_str().as_bytes(); - total_len += writer.write(&super::encode_7_bit_i32(currency_bytes.len() as i32))?; + total_len += writer.write(&rc_core::data::encode_7_bit_i32(currency_bytes.len() as i32))?; total_len += writer.write(currency_bytes)?; total_len += writer.write(&self.price.to_le_bytes())?; diff --git a/rc_services_room/src/data/mod.rs b/rc_services_room/src/data/mod.rs index 28f333c..0039fdc 100644 --- a/rc_services_room/src/data/mod.rs +++ b/rc_services_room/src/data/mod.rs @@ -1,56 +1,30 @@ -pub mod cube_list; +pub use rc_core::data::cube_list; pub mod special_item; pub mod premium_config; pub mod palette; pub mod client_config; pub mod crf_config; -pub mod weapon_list; -pub mod movement_list; +pub use rc_core::data::weapon_list; +//pub use rc_core::data::movement_list; pub mod damage_boost; pub mod battle_arena_config; pub mod cpu_limits; pub mod cosmetic_limits; pub mod taunts_config; pub mod customisation_info; -pub mod garage_bay; +pub use rc_core::data::garage_bay; pub mod custom_games; -pub mod tech_tree; +//pub use rc_core::data::tech_tree; pub mod item_shop_bundle; pub mod player_robopass_season; -pub mod weapon_upgrade; +//pub use rc_core::data::weapon_upgrade; pub mod player_rank; pub mod robot_data; pub mod quest; -pub mod auto_regen; -pub mod voting; +//pub use rc_core::data::auto_regen; +//pub use rc_core::data::voting; pub mod lobby; -pub mod error_codes; -pub mod game_mode; +pub use rc_core::data::error_codes; +//pub use rc_core::data::game_mode; pub mod score_multipliers; -pub mod campaign; - -pub(self) fn encode_7_bit_i32(mut src: i32) -> Vec { - if src == 0 { return vec![0] } - let mut out = Vec::with_capacity(5); - while src != 0 { - let last_7 = (src & 0x7F) as u8; - src = src >> 7; - if src != 0 { - out.push(last_7 | 0x80); - } else { - out.push(last_7); - } - } - out -} - -pub(self) fn write_str_for_binreader(s: &str, writer: &mut dyn std::io::Write) -> std::io::Result { - let s_bytes = s.as_bytes(); - let mut total_len = writer.write(&encode_7_bit_i32(s_bytes.len() as i32))?; - total_len += writer.write(s_bytes)?; - Ok(total_len) -} - -pub(self) fn cube_id_to_str(id: u32) -> String { - hex::encode(id.to_be_bytes()).into() -} +//pub use rc_core::data::campaign; diff --git a/rc_services_room/src/data/quest.rs b/rc_services_room/src/data/quest.rs index 7676241..94b7a8f 100644 --- a/rc_services_room/src/data/quest.rs +++ b/rc_services_room/src/data/quest.rs @@ -43,9 +43,9 @@ pub struct QuestInfo { impl QuestInfo { fn dump(&self, writer: &mut dyn Write) -> std::io::Result { - let mut total_len = super::write_str_for_binreader(&self.id, writer)?; - total_len += super::write_str_for_binreader(&self.name, writer)?; - total_len += super::write_str_for_binreader(&self.description, writer)?; + let mut total_len = rc_core::data::write_str_for_binreader(&self.id, writer)?; + total_len += rc_core::data::write_str_for_binreader(&self.name, writer)?; + total_len += rc_core::data::write_str_for_binreader(&self.description, writer)?; total_len += writer.write(&self.xp.to_le_bytes())?; total_len += writer.write(&self.premium_xp.to_le_bytes())?; total_len += writer.write(&self.robits.to_le_bytes())?; diff --git a/rc_services_room/src/main.rs b/rc_services_room/src/main.rs index a2c0249..f19e5d7 100644 --- a/rc_services_room/src/main.rs +++ b/rc_services_room/src/main.rs @@ -1,10 +1,8 @@ mod cli; -mod state; mod data; mod events; mod operations; -mod persist; use polariton_auth::Handshake; use tokio::net; @@ -12,11 +10,11 @@ use tokio::net; use polariton::packet::{Data, Message, Packet, StandardMessage}; use polariton::operation::{OperationResponse, Typed}; -pub type UserTy = std::sync::RwLock>; +pub type UserTy = rc_core::UserState<()>; pub struct InitConfig { - pub cubes: persist::config::ConfigImpl, - pub users: std::sync::Arc, + pub cubes: rc_core::persist::config::ConfigImpl, + pub users: std::sync::Arc, } #[tokio::main] @@ -25,8 +23,8 @@ async fn main() -> std::io::Result<()> { let args = cli::CliArgs::get(); log::debug!("Got cli args {:?}", args); - let cubes = persist::config::ConfigImpl::load(&args.assets).expect("Bad config data"); - let users = std::sync::Arc::new(persist::user::UserImpl::load(&args.data, &cubes).expect("Bad user data")); + let cubes = rc_core::persist::config::ConfigImpl::load(&args.assets).expect("Bad config data"); + let users = std::sync::Arc::new(rc_core::persist::user::UserImpl::load(&args.data, &cubes).expect("Bad user data")); let init_ctx = std::sync::Arc::new(InitConfig { cubes, users, @@ -63,9 +61,10 @@ async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAdd } }; let (socket_r, socket_w) = socket.into_split(); - let user_state = std::sync::RwLock::new(state::UserState::<()>::new(init_ctx.users.clone())); + let (chann_tx, chann_rx) = tokio::sync::mpsc::unbounded_channel(); + let user_state = rc_core::UserState::<()>::new(init_ctx.users.clone(), chann_tx.clone()); let ctx = polariton::packet::SerdesContext::from_boxed(Default::default(), enc); - server.handle_async(socket_r, socket_w, user_state, ctx).await; + server.handle_async_with_channel(socket_r, socket_w, user_state, ctx, chann_tx, chann_rx).await; log::debug!("Goodbye connection from address {}", address); } diff --git a/rc_services_room/src/operations/cube_inventory.rs b/rc_services_room/src/operations/cube_inventory.rs index a344b7e..6de6330 100644 --- a/rc_services_room/src/operations/cube_inventory.rs +++ b/rc_services_room/src/operations/cube_inventory.rs @@ -1,11 +1,11 @@ use polariton_server::operations::SimpleFunc; use polariton::{operation::{Dict, ParameterTable, Typed}, serdes::TypePrefix}; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const PARAM_KEY: u8 = 16; -pub(super) fn cube_inv_provider(cubes: &crate::persist::config::ConfigImpl) -> SimpleFunc<16, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { - let cube_ids = >::ids(cubes); +pub(super) fn cube_inv_provider(cubes: &rc_core::ConfigImpl) -> SimpleFunc<16, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { + let cube_ids = >::ids(cubes); SimpleFunc::new(move |params, _| { let mut params = params.to_dict(); params.insert(PARAM_KEY, Typed::Dict(Dict { diff --git a/rc_services_room/src/operations/cube_list.rs b/rc_services_room/src/operations/cube_list.rs index de43d90..950bd88 100644 --- a/rc_services_room/src/operations/cube_list.rs +++ b/rc_services_room/src/operations/cube_list.rs @@ -1,10 +1,10 @@ use polariton_server::operations::Immediate; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const PARAM_KEY: u8 = 1; //const DEFAULT_CUBE_ID: u32 = 227205318; -pub(super) fn cube_list_provider(cubes: &crate::persist::config::ConfigImpl) -> Immediate<2, crate::UserTy> { +pub(super) fn cube_list_provider(cubes: &rc_core::ConfigImpl) -> Immediate<2, crate::UserTy> { Immediate::new(|| { let mut params = std::collections::HashMap::with_capacity(2); params.insert(PARAM_KEY, cubes.cube_list()); diff --git a/rc_services_room/src/operations/game_mode_config.rs b/rc_services_room/src/operations/game_mode_config.rs index 37e405c..1d65a03 100644 --- a/rc_services_room/src/operations/game_mode_config.rs +++ b/rc_services_room/src/operations/game_mode_config.rs @@ -1,11 +1,11 @@ use polariton_server::operations::SimpleFunc; use polariton::operation::ParameterTable; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const PARAM_KEY: u8 = 1; -pub(super) fn game_mode_config_provider(conf: &crate::persist::config::ConfigImpl) -> SimpleFunc<113, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { +pub(super) fn game_mode_config_provider(conf: &rc_core::ConfigImpl) -> SimpleFunc<113, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { let game_config = conf.game_mode_config(); SimpleFunc::new(move |params, _| { let mut params = params.to_dict(); diff --git a/rc_services_room/src/operations/garage_bay_uuid.rs b/rc_services_room/src/operations/garage_bay_uuid.rs index 3a1aff0..cd30e70 100644 --- a/rc_services_room/src/operations/garage_bay_uuid.rs +++ b/rc_services_room/src/operations/garage_bay_uuid.rs @@ -5,8 +5,7 @@ const PARAM_KEY: u8 = 54; pub(super) fn garage_id_provider() -> SimpleFunc<177, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, user: &crate::UserTy| { - let lock = user.read().unwrap(); - let user_info = lock.user()?; + let user_info = user.user()?; let mut params = params.to_dict(); params.insert(PARAM_KEY, Typed::Str(user_info.selected_garage_uuid().into())); Ok(params.into()) diff --git a/rc_services_room/src/operations/garage_slots.rs b/rc_services_room/src/operations/garage_slots.rs index 0cc9d73..1c0427d 100644 --- a/rc_services_room/src/operations/garage_slots.rs +++ b/rc_services_room/src/operations/garage_slots.rs @@ -7,8 +7,7 @@ const SLOT_ORDER_PARAM_KEY: u8 = 58; pub(super) fn garage_slot_provider() -> SimpleFunc<40, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, user: &crate::UserTy| { - let lock = user.read().unwrap(); - let user_info = lock.user()?; + let user_info = user.user()?; let mut params = params.to_dict(); let all_slots = user_info.all_slots_by_id(); params.insert(SLOTS_PARAM_KEY, all_slots.slot_info); diff --git a/rc_services_room/src/operations/machine.rs b/rc_services_room/src/operations/machine.rs index dfee371..911d6db 100644 --- a/rc_services_room/src/operations/machine.rs +++ b/rc_services_room/src/operations/machine.rs @@ -13,8 +13,7 @@ const MASTERY_LEVEL_PARAM_KEY: u8 = 18; // int pub(super) fn garage_machine_provider() -> SimpleFunc<43, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, user: &crate::UserTy| { let mut params = params.to_dict(); - let lock = user.read().unwrap(); - let user_info = lock.user()?; + let user_info = user.user()?; if let Some(Typed::Int(garage_slot)) = params.get(&SLOT_PARAM_KEY) { log::debug!("Got machine request for slot {:?}", garage_slot); let machine = user_info.slot_by_id(*garage_slot)?; @@ -48,9 +47,8 @@ pub(super) fn garage_machine_save_provider() -> SimpleFunc<41, crate::UserTy, im if let Some(Typed::Bytes(colour_data)) = params.remove(&COMPRESSED_COLOUR_DATA_PARAM_KEY) { if let Some(Typed::Arr(weapon_order)) = params.remove(&WEAPON_ORDER_PARAM_KEY) { let weapon_order_filtered: Vec<_> = weapon_order.items.into_iter().filter_map(|ty| if let Typed::Int(i) = ty { Some(i) } else { None }).collect(); - let lock = user.read().unwrap(); - let user_info = lock.user()?; - let vehicle_data = crate::persist::user::VehicleData { + let user_info = user.user()?; + let vehicle_data = rc_core::persist::user::VehicleData { id: slot_index, robot_data: robot_data.vec, colour_data: colour_data.vec, diff --git a/rc_services_room/src/operations/machine_colour.rs b/rc_services_room/src/operations/machine_colour.rs index 48a48f2..ed20ad8 100644 --- a/rc_services_room/src/operations/machine_colour.rs +++ b/rc_services_room/src/operations/machine_colour.rs @@ -8,8 +8,7 @@ const DATA_PARAM_KEY: u8 = 33; // byte arr pub(super) fn garage_machine_colour_provider() -> SimpleFunc<33, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, user: &crate::UserTy| { let mut params = params.to_dict(); - let lock = user.read().unwrap(); - let user_info = lock.user()?; + let user_info = user.user()?; if let Some(Typed::Int(garage_slot)) = params.get(&SLOT_PARAM_KEY) { log::debug!("Got machine colour request for slot {:?}", garage_slot); let machine = user_info.slot_by_id(*garage_slot)?; diff --git a/rc_services_room/src/operations/more_auth.rs b/rc_services_room/src/operations/more_auth.rs index c1fc5ee..27504f3 100644 --- a/rc_services_room/src/operations/more_auth.rs +++ b/rc_services_room/src/operations/more_auth.rs @@ -14,8 +14,8 @@ impl Operation for MoreLobbyAuth { fn handle(&self, params: polariton::operation::ParameterTable, _: &mut Self::State, user: &Self::User) -> polariton::operation::OperationResponse { let params_dict = params.to_dict(); if let Some(Typed::Str(auth_payload)) = params_dict.get(&Self::AUTH_PAYLOAD_KEY) { - let mut write_lock = user.write().unwrap(); - if write_lock.update_with_auth(&auth_payload.string) { + //let mut write_lock = user.write().unwrap(); + if user.update_with_auth(&auth_payload.string) { let mut resp_params = std::collections::HashMap::new(); resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0)); return polariton::operation::OperationResponse { diff --git a/rc_services_room/src/operations/movement_stats.rs b/rc_services_room/src/operations/movement_stats.rs index 4e0203e..5b25b48 100644 --- a/rc_services_room/src/operations/movement_stats.rs +++ b/rc_services_room/src/operations/movement_stats.rs @@ -1,10 +1,10 @@ //use polariton::serdes::TypePrefix; use polariton_server::operations::Immediate; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const PARAM_KEY: u8 = 1; -pub(super) fn movement_config_provider(cubes: &crate::persist::config::ConfigImpl) -> Immediate<62, crate::UserTy> { +pub(super) fn movement_config_provider(cubes: &rc_core::ConfigImpl) -> Immediate<62, crate::UserTy> { Immediate::new(|| { let mut params = std::collections::HashMap::with_capacity(2); params.insert(PARAM_KEY, cubes.movement_list()); diff --git a/rc_services_room/src/operations/pageantry.rs b/rc_services_room/src/operations/pageantry.rs index 8d8952e..df79aa2 100644 --- a/rc_services_room/src/operations/pageantry.rs +++ b/rc_services_room/src/operations/pageantry.rs @@ -1,10 +1,10 @@ use polariton_server::operations::Immediate; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const PARAM_KEY: u8 = 203; // bytes -pub(super) fn after_battle_vote_thresholds_provider(conf: &crate::persist::config::ConfigImpl) -> Immediate<169, crate::UserTy> { +pub(super) fn after_battle_vote_thresholds_provider(conf: &rc_core::ConfigImpl) -> Immediate<169, crate::UserTy> { Immediate::new(|| { let mut params = std::collections::HashMap::with_capacity(1); params.insert(PARAM_KEY, conf.after_battle_vote_config()); diff --git a/rc_services_room/src/operations/player_robot_rank.rs b/rc_services_room/src/operations/player_robot_rank.rs index a7f48e0..56afe05 100644 --- a/rc_services_room/src/operations/player_robot_rank.rs +++ b/rc_services_room/src/operations/player_robot_rank.rs @@ -8,8 +8,7 @@ const COSMETIC_CPU_PARAM_KEY: u8 = 176; // out; int pub(super) fn player_robot_rank_provider() -> SimpleFunc<79, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, user: &crate::UserTy| { - let lock = user.read().unwrap(); - let user = lock.user()?; + let user = user.user()?; let mut params = params.to_dict(); if let Some(Typed::Str(username)) = params.get(&USERNAME_PARAM_KEY) { log::debug!("Get robot rank for user {}", username.string); diff --git a/rc_services_room/src/operations/regen_config.rs b/rc_services_room/src/operations/regen_config.rs index 65c8c08..33cf428 100644 --- a/rc_services_room/src/operations/regen_config.rs +++ b/rc_services_room/src/operations/regen_config.rs @@ -1,10 +1,10 @@ use polariton_server::operations::Immediate; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const PARAM_KEY: u8 = 37; // bytes -pub(super) fn auto_regen_config_provider(conf: &crate::persist::config::ConfigImpl) -> Immediate<35, crate::UserTy> { +pub(super) fn auto_regen_config_provider(conf: &rc_core::ConfigImpl) -> Immediate<35, crate::UserTy> { Immediate::new(|| { let mut params = std::collections::HashMap::with_capacity(1); params.insert(PARAM_KEY, conf.regen_config()); diff --git a/rc_services_room/src/operations/signup_time.rs b/rc_services_room/src/operations/signup_time.rs index e25797e..568233a 100644 --- a/rc_services_room/src/operations/signup_time.rs +++ b/rc_services_room/src/operations/signup_time.rs @@ -6,9 +6,8 @@ const PARAM_KEY: u8 = 71; // long pub(super) fn user_signup_date_provider() -> SimpleFunc<63, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, user: &crate::UserTy| { let mut params = params.to_dict(); - let lock = user.read().unwrap(); - let user_info = lock.user()?; - params.insert(PARAM_KEY, Typed::Long(user_info.signup_date())); + let user = user.user()?; + params.insert(PARAM_KEY, Typed::Long(user.signup_date())); Ok(params.into()) }) } diff --git a/rc_services_room/src/operations/singleplayer_campaigns.rs b/rc_services_room/src/operations/singleplayer_campaigns.rs index b6159b3..a38ae3a 100644 --- a/rc_services_room/src/operations/singleplayer_campaigns.rs +++ b/rc_services_room/src/operations/singleplayer_campaigns.rs @@ -1,13 +1,13 @@ use polariton_server::operations::{Immediate, SimpleFunc}; use polariton::operation::{ParameterTable, Typed}; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const CAMPAIGNS_BYTES_PARAM_KEY: u8 = 64; // list of bytes (serialised data) const CAMPAIGNS_WAVES_PARAM_KEY: u8 = 70; // hashtable const CAMPAIGNS_VERSIONS_PARAM_KEY: u8 = 69; // hashtable -pub(super) fn singleplayer_campaigns_provider(conf: &crate::persist::config::ConfigImpl) -> Immediate<65, crate::UserTy> { +pub(super) fn singleplayer_campaigns_provider(conf: &rc_core::ConfigImpl) -> Immediate<65, crate::UserTy> { Immediate::new(|| { let mut params = std::collections::HashMap::new(); params.insert(CAMPAIGNS_BYTES_PARAM_KEY, conf.campaigns_parameters()); // first 4 bytes are i32 for length of the rest @@ -29,8 +29,8 @@ const CAMPAIGN_ID_PARAM_KEY: u8 = 22; // string; in const CAMPAIGN_DIFFICULTY_PARAM_KEY: u8 = 23; // i32; in const CAMPAIGN_WAVES_PARAM_KEY: u8 = 75; // bytes; out -pub(super) fn singleplayer_complete_campaign_provider(conf: &crate::persist::config::ConfigImpl) -> SimpleFunc<64, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { - let campaign_details = >::campaign_details(conf); +pub(super) fn singleplayer_complete_campaign_provider(conf: &rc_core::ConfigImpl) -> SimpleFunc<64, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { + let campaign_details = >::campaign_details(conf); SimpleFunc::new(move |params, _| { let mut params = params.to_dict(); if let Some(Typed::Str(campaign_id)) = params.get(&CAMPAIGN_ID_PARAM_KEY) { @@ -47,14 +47,14 @@ pub(super) fn singleplayer_complete_campaign_provider(conf: &crate::persist::con const CAMPAIGN_WAVE_NUMBER_PARAM_KEYL: u8 = 73; pub(super) fn singleplayer_save_complete_campaign_provider() -> SimpleFunc<68, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { - //let campaign_details = >::campaign_details(conf); + //let campaign_details = >::campaign_details(conf); SimpleFunc::new(move |params, user: &crate::UserTy| { let mut params = params.to_dict(); if let Some(Typed::Str(campaign_id)) = params.get(&CAMPAIGN_ID_PARAM_KEY) { if let Some(Typed::Int(campaign_difficulty)) = params.get(&CAMPAIGN_DIFFICULTY_PARAM_KEY) { if let Some(Typed::Int(wave_number)) = params.get(&CAMPAIGN_WAVE_NUMBER_PARAM_KEYL) { - let user_lock = user.read().unwrap(); - log::info!("User {} completed campaign {} difficulty {} wave {}", user_lock.user()?.token().uuid, campaign_id.string, campaign_difficulty, wave_number); + let user_info = user.user()?; + log::info!("User {} completed campaign {} difficulty {} wave {}", user_info.token().uuid, campaign_id.string, campaign_difficulty, wave_number); // TODO save wave as completed params.clear(); } diff --git a/rc_services_room/src/operations/tech_tree_data.rs b/rc_services_room/src/operations/tech_tree_data.rs index 0bba717..29ccfea 100644 --- a/rc_services_room/src/operations/tech_tree_data.rs +++ b/rc_services_room/src/operations/tech_tree_data.rs @@ -1,9 +1,9 @@ use polariton_server::operations::Immediate; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const PARAM_KEY: u8 = 210; -pub(super) fn tech_tree_layout_provider(cubes: &crate::persist::config::ConfigImpl) -> Immediate<183, crate::UserTy> { +pub(super) fn tech_tree_layout_provider(cubes: &rc_core::ConfigImpl) -> Immediate<183, crate::UserTy> { Immediate::new(|| { let mut params = std::collections::HashMap::with_capacity(2); params.insert(PARAM_KEY, cubes.tech_tree_nodes(&vec![ diff --git a/rc_services_room/src/operations/user_perms.rs b/rc_services_room/src/operations/user_perms.rs index 4d91df6..b43f0c1 100644 --- a/rc_services_room/src/operations/user_perms.rs +++ b/rc_services_room/src/operations/user_perms.rs @@ -7,8 +7,7 @@ const ADM_PARAM_KEY: u8 = 12; pub(super) fn user_rights_provider() -> SimpleFunc<14, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, user: &crate::UserTy| { - let lock = user.read().unwrap(); - let user_info = lock.user()?; + let user_info = user.user()?; let mut params = params.to_dict(); params.insert(MOD_PARAM_KEY, Typed::Bool(user_info.is_mod())); params.insert(DEV_PARAM_KEY, Typed::Bool(user_info.is_dev())); diff --git a/rc_services_room/src/operations/weapon_order.rs b/rc_services_room/src/operations/weapon_order.rs index cfdebe1..9dd377d 100644 --- a/rc_services_room/src/operations/weapon_order.rs +++ b/rc_services_room/src/operations/weapon_order.rs @@ -1,10 +1,10 @@ use polariton_server::operations::Immediate; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; pub const DEFAULT_WEAPON_ORDER_PARAM_KEY: u8 = 138; -pub(super) fn weapon_order_provider(conf: &crate::persist::config::ConfigImpl) -> Immediate<118, crate::UserTy> { +pub(super) fn weapon_order_provider(conf: &rc_core::ConfigImpl) -> Immediate<118, crate::UserTy> { let weapon_orders = conf.weapon_keys(); Immediate::new(|| { let mut params = std::collections::HashMap::with_capacity(1); diff --git a/rc_services_room/src/operations/weapon_stats.rs b/rc_services_room/src/operations/weapon_stats.rs index c002c42..533a42d 100644 --- a/rc_services_room/src/operations/weapon_stats.rs +++ b/rc_services_room/src/operations/weapon_stats.rs @@ -1,9 +1,9 @@ use polariton_server::operations::Immediate; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const PARAM_KEY: u8 = 57; -pub(super) fn weapon_config_provider(cubes: &crate::persist::config::ConfigImpl) -> Immediate<47, crate::UserTy> { +pub(super) fn weapon_config_provider(cubes: &rc_core::ConfigImpl) -> Immediate<47, crate::UserTy> { Immediate::new(|| { let mut params = std::collections::HashMap::with_capacity(2); params.insert(PARAM_KEY, cubes.weapon_list()); diff --git a/rc_services_room/src/operations/weapon_upgrades.rs b/rc_services_room/src/operations/weapon_upgrades.rs index 4706f83..e7009bd 100644 --- a/rc_services_room/src/operations/weapon_upgrades.rs +++ b/rc_services_room/src/operations/weapon_upgrades.rs @@ -1,9 +1,9 @@ use polariton_server::operations::Immediate; -use crate::persist::config::ConfigProvider; +use rc_core::ConfigProvider; const PARAM_KEY: u8 = 38; -pub(super) fn weapons_upgrade_provider(cubes: &crate::persist::config::ConfigImpl) -> Immediate<82, crate::UserTy> { +pub(super) fn weapons_upgrade_provider(cubes: &rc_core::ConfigImpl) -> Immediate<82, crate::UserTy> { Immediate::new(|| { let mut params = std::collections::HashMap::with_capacity(2); params.insert(PARAM_KEY, cubes.weapon_upgrade_list()); diff --git a/rc_singleplayer_room/Cargo.toml b/rc_singleplayer_room/Cargo.toml index 6a8ad7f..363c0c3 100644 --- a/rc_singleplayer_room/Cargo.toml +++ b/rc_singleplayer_room/Cargo.toml @@ -11,3 +11,4 @@ clap.workspace = true polariton.workspace = true polariton_auth = { version = "*", path = "../polariton_auth" } polariton_server.workspace = true +rc_core = { version = "*", path = "../rc_core" } diff --git a/rc_singleplayer_room/src/cli.rs b/rc_singleplayer_room/src/cli.rs index 1ecd871..56d8497 100644 --- a/rc_singleplayer_room/src/cli.rs +++ b/rc_singleplayer_room/src/cli.rs @@ -11,6 +11,14 @@ pub struct CliArgs { #[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, + /// Handle one connection and then exit #[arg(short = '1', long)] pub once: bool, diff --git a/rc_singleplayer_room/src/data/mod.rs b/rc_singleplayer_room/src/data/mod.rs index 159a924..e69de29 100644 --- a/rc_singleplayer_room/src/data/mod.rs +++ b/rc_singleplayer_room/src/data/mod.rs @@ -1,23 +0,0 @@ -pub mod player_data; - -pub(self) fn encode_7_bit_i32(mut src: i32) -> Vec { - if src == 0 { return vec![0] } - let mut out = Vec::with_capacity(5); - while src != 0 { - let last_7 = (src & 0x7F) as u8; - src = src >> 7; - if src != 0 { - out.push(last_7 | 0x80); - } else { - out.push(last_7); - } - } - out -} - -pub(self) fn write_str_for_binreader(s: &str, writer: &mut dyn std::io::Write) -> std::io::Result { - let s_bytes = s.as_bytes(); - let mut total_len = writer.write(&encode_7_bit_i32(s_bytes.len() as i32))?; - total_len += writer.write(s_bytes)?; - Ok(total_len) -} diff --git a/rc_singleplayer_room/src/main.rs b/rc_singleplayer_room/src/main.rs index c767f84..2f1435d 100644 --- a/rc_singleplayer_room/src/main.rs +++ b/rc_singleplayer_room/src/main.rs @@ -1,5 +1,4 @@ mod cli; -mod state; mod data; mod operations; @@ -10,7 +9,7 @@ use tokio::net; use polariton::packet::{Data, Message, Packet, StandardMessage}; use polariton::operation::{OperationResponse, Typed}; -pub type UserTy = state::UserState; +pub type UserTy = rc_core::UserState<()>; #[tokio::main] async fn main() -> std::io::Result<()> { @@ -18,6 +17,9 @@ async fn main() -> std::io::Result<()> { let args = cli::CliArgs::get(); log::debug!("Got cli args {:?}", args); + let cubes = rc_core::persist::config::ConfigImpl::load(&args.assets).expect("Bad config data"); + let users = std::sync::Arc::new(rc_core::persist::user::UserImpl::load(&args.data, &cubes).expect("Bad user data")); + let server = std::sync::Arc::new(polariton_server::Server::new(operations::handler(), polariton_server::events::EventsHandler::new())); let ip_addr: std::net::IpAddr = args.ip.parse().expect("Invalid IP address"); @@ -27,11 +29,11 @@ async fn main() -> std::io::Result<()> { if args.once { log::warn!("Handling first connection and then exiting"); let (socket, address) = listener.accept().await?; - process_socket(socket, address, server.clone()).await; + process_socket(socket, address, server.clone(), users.clone()).await; } else { loop { let (socket, address) = listener.accept().await?; - tokio::spawn(process_socket(socket, address, server.clone())); + tokio::spawn(process_socket(socket, address, server.clone(), users.clone())); } } server.join(); @@ -39,7 +41,7 @@ async fn main() -> std::io::Result<()> { Ok(()) } -async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAddr, server: std::sync::Arc>) { +async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAddr, server: std::sync::Arc>, users: std::sync::Arc) { log::debug!("Accepting connection from address {}", address); let enc = match do_connect_handshake(&mut socket).await { Some(x) => x, @@ -50,7 +52,7 @@ async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAdd }; let (socket_r, socket_w) = socket.into_split(); let (chann_tx, chann_rx) = tokio::sync::mpsc::unbounded_channel(); - let user_state = state::UserState::new(chann_tx.clone()); + let user_state = rc_core::UserState::<()>::new(users, chann_tx.clone()); let ctx = polariton::packet::SerdesContext::from_boxed(Default::default(), enc); server.handle_async_with_channel(socket_r, socket_w, user_state, ctx, chann_tx, chann_rx).await; log::debug!("Goodbye connection from address {}", address); diff --git a/rc_singleplayer_room/src/operations/load_ai_robots.rs b/rc_singleplayer_room/src/operations/load_ai_robots.rs index 6616433..6e387ba 100644 --- a/rc_singleplayer_room/src/operations/load_ai_robots.rs +++ b/rc_singleplayer_room/src/operations/load_ai_robots.rs @@ -1,878 +1,37 @@ use polariton_server::operations::SimpleFunc; use polariton::operation::{ParameterTable, Typed}; -use crate::data::player_data::*; - const PARAM_KEY: u8 = 8; -const VALID_ROBOT: &[u8] = &[64, - 0, - 0, - 0, - 38, - 190, - 25, - 77, - 24, - 6, - 29, - 0, - 80, - 135, - 103, - 211, - 27, - 4, - 27, - 6, - 80, - 135, - 103, - 211, - 21, - 4, - 27, - 12, - 198, - 224, - 138, - 13, - 24, - 4, - 26, - 0, - 198, - 224, - 138, - 13, - 24, - 4, - 27, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 28, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 25, - 0, - 198, - 224, - 138, - 13, - 24, - 4, - 29, - 0, - 198, - 224, - 138, - 13, - 23, - 4, - 29, - 0, - 198, - 224, - 138, - 13, - 23, - 4, - 28, - 0, - 198, - 224, - 138, - 13, - 23, - 4, - 27, - 0, - 198, - 224, - 138, - 13, - 23, - 4, - 26, - 22, - 198, - 224, - 138, - 13, - 23, - 4, - 25, - 22, - 198, - 224, - 138, - 13, - 25, - 4, - 29, - 0, - 198, - 224, - 138, - 13, - 25, - 4, - 27, - 22, - 198, - 224, - 138, - 13, - 25, - 4, - 28, - 22, - 198, - 224, - 138, - 13, - 25, - 4, - 26, - 22, - 198, - 224, - 138, - 13, - 25, - 4, - 25, - 22, - 198, - 224, - 138, - 13, - 26, - 4, - 29, - 0, - 198, - 224, - 138, - 13, - 26, - 4, - 28, - 22, - 198, - 224, - 138, - 13, - 26, - 4, - 27, - 22, - 198, - 224, - 138, - 13, - 26, - 4, - 26, - 22, - 198, - 224, - 138, - 13, - 26, - 4, - 25, - 22, - 198, - 224, - 138, - 13, - 22, - 4, - 25, - 0, - 198, - 224, - 138, - 13, - 22, - 4, - 26, - 0, - 198, - 224, - 138, - 13, - 22, - 4, - 27, - 23, - 198, - 224, - 138, - 13, - 22, - 4, - 28, - 23, - 198, - 224, - 138, - 13, - 22, - 4, - 29, - 0, - 198, - 224, - 138, - 13, - 25, - 5, - 29, - 0, - 198, - 224, - 138, - 13, - 23, - 5, - 29, - 0, - 198, - 224, - 138, - 13, - 24, - 5, - 29, - 0, - 198, - 224, - 138, - 13, - 22, - 5, - 28, - 0, - 198, - 224, - 138, - 13, - 26, - 5, - 28, - 0, - 198, - 224, - 138, - 13, - 25, - 5, - 26, - 0, - 198, - 224, - 138, - 13, - 23, - 5, - 26, - 0, - 198, - 224, - 138, - 13, - 24, - 4, - 24, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 23, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 22, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 21, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 20, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 19, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 18, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 17, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 16, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 15, - 22, - 198, - 224, - 138, - 13, - 24, - 4, - 14, - 22, - 198, - 224, - 138, - 13, - 23, - 4, - 17, - 12, - 198, - 224, - 138, - 13, - 25, - 4, - 17, - 6, - 198, - 224, - 138, - 13, - 23, - 4, - 16, - 12, - 198, - 224, - 138, - 13, - 25, - 4, - 16, - 6, - 198, - 224, - 138, - 13, - 23, - 4, - 15, - 12, - 198, - 224, - 138, - 13, - 25, - 4, - 15, - 6, - 198, - 224, - 138, - 13, - 23, - 4, - 14, - 12, - 198, - 224, - 138, - 13, - 25, - 4, - 14, - 6, - 198, - 224, - 138, - 13, - 22, - 4, - 17, - 12, - 198, - 224, - 138, - 13, - 26, - 4, - 17, - 6, - 198, - 224, - 138, - 13, - 22, - 4, - 16, - 12, - 198, - 224, - 138, - 13, - 26, - 4, - 16, - 6, - 198, - 224, - 138, - 13, - 22, - 4, - 15, - 12, - 198, - 224, - 138, - 13, - 26, - 4, - 15, - 6, - 198, - 224, - 138, - 13, - 22, - 4, - 14, - 12, - 198, - 224, - 138, - 13, - 26, - 4, - 14, - 6, - 240, - 75, - 110, - 137, - 21, - 4, - 15, - 12, - 240, - 75, - 110, - 137, - 27, - 4, - 15, - 6]; - -const VALID_COLOUR: &[u8] = &[64, - 0, - 0, - 0, - 0, - 24, - 6, - 29, - 0, - 27, - 4, - 27, - 0, - 21, - 4, - 27, - 0, - 24, - 4, - 26, - 0, - 24, - 4, - 27, - 0, - 24, - 4, - 28, - 0, - 24, - 4, - 25, - 0, - 24, - 4, - 29, - 0, - 23, - 4, - 29, - 0, - 23, - 4, - 28, - 0, - 23, - 4, - 27, - 0, - 23, - 4, - 26, - 0, - 23, - 4, - 25, - 0, - 25, - 4, - 29, - 0, - 25, - 4, - 27, - 0, - 25, - 4, - 28, - 0, - 25, - 4, - 26, - 0, - 25, - 4, - 25, - 0, - 26, - 4, - 29, - 0, - 26, - 4, - 28, - 0, - 26, - 4, - 27, - 0, - 26, - 4, - 26, - 0, - 26, - 4, - 25, - 0, - 22, - 4, - 25, - 0, - 22, - 4, - 26, - 0, - 22, - 4, - 27, - 0, - 22, - 4, - 28, - 0, - 22, - 4, - 29, - 1, - 25, - 5, - 29, - 1, - 23, - 5, - 29, - 1, - 24, - 5, - 29, - 1, - 22, - 5, - 28, - 1, - 26, - 5, - 28, - 1, - 25, - 5, - 26, - 1, - 23, - 5, - 26, - 0, - 24, - 4, - 24, - 0, - 24, - 4, - 23, - 0, - 24, - 4, - 22, - 0, - 24, - 4, - 21, - 0, - 24, - 4, - 20, - 0, - 24, - 4, - 19, - 0, - 24, - 4, - 18, - 0, - 24, - 4, - 17, - 0, - 24, - 4, - 16, - 0, - 24, - 4, - 15, - 0, - 24, - 4, - 14, - 0, - 23, - 4, - 17, - 0, - 25, - 4, - 17, - 0, - 23, - 4, - 16, - 0, - 25, - 4, - 16, - 0, - 23, - 4, - 15, - 0, - 25, - 4, - 15, - 0, - 23, - 4, - 14, - 0, - 25, - 4, - 14, - 0, - 22, - 4, - 17, - 0, - 26, - 4, - 17, - 0, - 22, - 4, - 16, - 0, - 26, - 4, - 16, - 0, - 22, - 4, - 15, - 0, - 26, - 4, - 15, - 0, - 22, - 4, - 14, - 0, - 26, - 4, - 14, - 0, - 21, - 4, - 15, - 0, - 27, - 4, - 15]; - pub(super) fn tdm_machines_provider() -> SimpleFunc<1, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result) + Sync + Sync> { SimpleFunc::new(|params, user: &crate::UserTy| { - let ulock = user.auth.read().unwrap(); + let ulock = user.user()?; let mut params = params.to_dict(); - params.insert(PARAM_KEY, PlayerDatas { - players: vec![ - PlayerData { - name: ulock.uuid.clone(), - display_name: ulock.uuid.clone(), - mastery: 1, - tier: 1, - robot_name: "RE_machine_name_mine_sp".to_owned(), - robot_map: VALID_ROBOT.iter().map(|x| *x).collect(), - team: 0, - has_premium: false, - robot_uuid: "12345_12345".to_owned(), - cpu: 0, - weapon_order: vec![20000200, 0, 0], - colour_map: VALID_COLOUR.iter().map(|x| *x).collect(), - is_ai: false, - spawn_effect: "Spawn_Warp".to_owned(), - death_effect: "Explosion_Warp".to_owned(), - player_rank: 1, - weapon_rank: vec![(20000200, 1), (0, 0)].into_iter().collect(), - }, - // TODO: use SingleplayerEvent 3 (SpawnRobot) to spawn enemy bots instead - // doing it through this op response seems to have a bug/flaw (intentional?) in the code - /*PlayerData { - name: "RE_username0".to_owned(), - display_name: "RE_displayname0".to_owned(), - mastery: 1, - tier: 1, - robot_name: "RE_machine_name0_sp".to_owned(), - robot_map: VALID_ROBOT.iter().map(|x| *x).collect(), - team: 1, - has_premium: false, - robot_uuid: "123_123".to_owned(), - cpu: 0, - weapon_order: vec![20000200, 0, 0], - colour_map: VALID_COLOUR.iter().map(|x| *x).collect(), - is_ai: true, - spawn_effect: "Spawn_Warp".to_owned(), - death_effect: "Explosion_Warp".to_owned(), - player_rank: 1, - weapon_rank: vec![(20000200, 1), (0, 0)].into_iter().collect(), - }, - PlayerData { - name: "RE_username1".to_owned(), - display_name: "RE_displayname1".to_owned(), - mastery: 1, - tier: 1, - robot_name: "RE_machine_name1_sp".to_owned(), - robot_map: VALID_ROBOT.iter().map(|x| *x).collect(), - team: 1, - has_premium: false, - robot_uuid: "12_12".to_owned(), - cpu: 0, - weapon_order: vec![20000200, 0, 0], - colour_map: VALID_COLOUR.iter().map(|x| *x).collect(), - is_ai: true, - spawn_effect: "Spawn_Warp".to_owned(), - death_effect: "Explosion_Warp".to_owned(), - player_rank: 1, - weapon_rank: vec![(20000200, 1), (0, 0)].into_iter().collect(), - },*/ - ] - }.as_transmissible()); - let event_tx = user.event_tx.clone(); + params.insert(PARAM_KEY, ulock.singleplayer_robots()?); + let event_tx = user.event_sender(); + let user_bot_data = ulock.slot_by_id(ulock.selected_garage_slot() as _)?; tokio::spawn(async move { - tokio::time::sleep(std::time::Duration::from_secs(10)).await; - log::debug!("Sending singleplayer events"); + tokio::time::sleep(std::time::Duration::from_secs(20)).await; + log::debug!("Sending singleplayer event"); let mut spawn_params = std::collections::HashMap::with_capacity(4); - spawn_params.insert(2 /* robot GUID */, Typed::Str("12_12".into())); - spawn_params.insert(3 /* machine model */, Typed::Bytes(VALID_ROBOT.iter().map(|x| *x).collect::>().into())); - spawn_params.insert(4 /* robot name */, Typed::Str("RE_robot_spawn_name0".into())); - spawn_params.insert(7 /* color model */, Typed::Bytes(VALID_COLOUR.iter().map(|x| *x).collect::>().into())); + spawn_params.insert(2 /* robot GUID */, Typed::Str("1337_1337".into())); + spawn_params.insert(3 /* machine model */, user_bot_data.data); + spawn_params.insert(4 /* robot name */, Typed::Str("RE_robot_spawn_name0".into())); // FIXME + spawn_params.insert(7 /* color model */, user_bot_data.colour_data); event_tx.send(polariton_server::ToSend::Data { data: polariton::packet::Data::Event(polariton::operation::Event { code: 3, params: spawn_params.into() }), encrypt: true, channel: 0, reliable: true, }).unwrap(); - let mut update_params = std::collections::HashMap::with_capacity(1); + /*let mut update_params = std::collections::HashMap::with_capacity(1); update_params.insert(6 /* ??? */, Typed::Int(5)); event_tx.send(polariton_server::ToSend::Data { data: polariton::packet::Data::Event(polariton::operation::Event { code: 5, params: update_params.into() }), encrypt: true, channel: 0, reliable: true, - }).unwrap(); + }).unwrap();*/ }); Ok(params.into()) }) diff --git a/rc_singleplayer_room/src/state.rs b/rc_singleplayer_room/src/state.rs deleted file mode 100644 index 2d2c03e..0000000 --- a/rc_singleplayer_room/src/state.rs +++ /dev/null @@ -1,40 +0,0 @@ -use std::sync::RwLock; - -use tokio::sync::mpsc::UnboundedSender; -use polariton_server::ToSend; - -#[derive(Debug, Default)] -pub struct UserAuthInfo { - pub uuid: String, - pub token: String, - pub refresh_token: String, -} - -#[derive(Debug)] -pub struct UserState { - pub auth: RwLock, - pub event_tx: UnboundedSender, -} - -impl UserState { - pub fn update_with_auth(&self, auth_str: &str) -> bool { - let splits: Vec<&str> = auth_str.split(';').collect(); - if splits.len() != 3 { - log::warn!("Invalid auth payload: {}", auth_str); - false - } else { - let mut lock = self.auth.write().unwrap(); - lock.uuid = splits[0].to_owned(); - lock.token = splits[1].to_owned(); - lock.refresh_token = splits[2].to_owned(); - true - } - } - - pub fn new(event_tx: UnboundedSender) -> crate::UserTy { - UserState { - auth: RwLock::new(Default::default()), - event_tx, - } - } -} diff --git a/rc_social_room/Cargo.toml b/rc_social_room/Cargo.toml index 009f7fa..743ac02 100644 --- a/rc_social_room/Cargo.toml +++ b/rc_social_room/Cargo.toml @@ -11,3 +11,4 @@ clap.workspace = true polariton.workspace = true polariton_auth = { version = "*", path = "../polariton_auth" } polariton_server.workspace = true +rc_core = { version = "*", path = "../rc_core" } diff --git a/rc_social_room/src/cli.rs b/rc_social_room/src/cli.rs index 5dcfb3c..ebeab35 100644 --- a/rc_social_room/src/cli.rs +++ b/rc_social_room/src/cli.rs @@ -11,6 +11,14 @@ pub struct CliArgs { #[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, + /// Handle one connection and then exit #[arg(short = '1', long)] pub once: bool, diff --git a/rc_social_room/src/main.rs b/rc_social_room/src/main.rs index 1bc4e76..6fac940 100644 --- a/rc_social_room/src/main.rs +++ b/rc_social_room/src/main.rs @@ -1,5 +1,4 @@ mod cli; -mod state; mod data; mod operations; @@ -10,7 +9,7 @@ use tokio::net; use polariton::packet::{Data, Message, Packet, StandardMessage}; use polariton::operation::{OperationResponse, Typed}; -pub type UserTy = std::sync::RwLock; +pub type UserTy = rc_core::UserState; #[tokio::main] async fn main() -> std::io::Result<()> { @@ -18,6 +17,9 @@ async fn main() -> std::io::Result<()> { let args = cli::CliArgs::get(); log::debug!("Got cli args {:?}", args); + let cubes = rc_core::persist::config::ConfigImpl::load(&args.assets).expect("Bad config data"); + let users = std::sync::Arc::new(rc_core::persist::user::UserImpl::load(&args.data, &cubes).expect("Bad user data")); + let server = std::sync::Arc::new(polariton_server::Server::new(operations::handler(), polariton_server::events::EventsHandler::new())); let ip_addr: std::net::IpAddr = args.ip.parse().expect("Invalid IP address"); @@ -27,11 +29,11 @@ async fn main() -> std::io::Result<()> { if args.once { log::warn!("Handling first connection and then exiting"); let (socket, address) = listener.accept().await?; - process_socket(socket, address, server.clone()).await; + process_socket(socket, address, server.clone(), users.clone()).await; } else { loop { let (socket, address) = listener.accept().await?; - tokio::spawn(process_socket(socket, address, server.clone())); + tokio::spawn(process_socket(socket, address, server.clone(), users.clone())); } } server.join(); @@ -39,7 +41,7 @@ async fn main() -> std::io::Result<()> { Ok(()) } -async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAddr, server: std::sync::Arc>) { +async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAddr, server: std::sync::Arc>, users: std::sync::Arc) { log::debug!("Accepting connection from address {}", address); let enc = match do_connect_handshake(&mut socket).await { Some(x) => x, @@ -49,10 +51,11 @@ async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAdd } }; let (socket_r, socket_w) = socket.into_split(); - let user_state = state::UserState::new(); + let (chann_tx, chann_rx) = tokio::sync::mpsc::unbounded_channel(); + let user_state = rc_core::UserState::::new(users, chann_tx.clone()); let op_ctx = polariton::serdes::SerdesContext::::default_const(); let ctx = polariton::packet::SerdesContext::from_boxed(op_ctx, enc); - server.handle_async(socket_r, socket_w, user_state, ctx).await; + server.handle_async_with_channel(socket_r, socket_w, user_state, ctx, chann_tx, chann_rx).await; log::debug!("Goodbye connection from address {}", address); } diff --git a/rc_social_room/src/operations/more_auth.rs b/rc_social_room/src/operations/more_auth.rs index c1fc5ee..bd72f7f 100644 --- a/rc_social_room/src/operations/more_auth.rs +++ b/rc_social_room/src/operations/more_auth.rs @@ -14,9 +14,8 @@ impl Operation for MoreLobbyAuth { fn handle(&self, params: polariton::operation::ParameterTable, _: &mut Self::State, user: &Self::User) -> polariton::operation::OperationResponse { let params_dict = params.to_dict(); if let Some(Typed::Str(auth_payload)) = params_dict.get(&Self::AUTH_PAYLOAD_KEY) { - let mut write_lock = user.write().unwrap(); - if write_lock.update_with_auth(&auth_payload.string) { - let mut resp_params = std::collections::HashMap::new(); + if user.update_with_auth(&auth_payload.string) { + let mut resp_params = std::collections::HashMap::with_capacity(1); resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0)); return polariton::operation::OperationResponse { code: 230, diff --git a/rc_social_room/src/state.rs b/rc_social_room/src/state.rs deleted file mode 100644 index bc39273..0000000 --- a/rc_social_room/src/state.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::sync::RwLock; - -#[derive(Default, Debug)] -pub struct UserState { - pub uuid: String, - pub token: String, - pub refresh_token: String, -} - -impl UserState { - pub fn update_with_auth(&mut self, auth_str: &str) -> bool { - let splits: Vec<&str> = auth_str.split(';').collect(); - if splits.len() != 3 { - log::warn!("Invalid auth payload: {}", auth_str); - false - } else { - self.uuid = splits[0].to_owned(); - self.token = splits[1].to_owned(); - self.refresh_token = splits[2].to_owned(); - true - } - } - - pub fn new() -> crate::UserTy { - RwLock::new(UserState::default()) - } -}