mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Move common components to shared lib
This commit is contained in:
18
Cargo.lock
generated
18
Cargo.lock
generated
@@ -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",
|
||||
]
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
11
README.md
11
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.
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<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<polariton_server::Server<crate::UserTy>>) {
|
||||
async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAddr, server: std::sync::Arc<polariton_server::Server<crate::UserTy>>, users: std::sync::Arc<rc_core::persist::user::UserImpl>) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@ impl <C> Operation<C> for MoreLobbyAuth {
|
||||
fn handle(&self, params: polariton::operation::ParameterTable<C>, _: &mut Self::State, user: &Self::User) -> polariton::operation::OperationResponse<C> {
|
||||
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 {
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
14
rc_core/Cargo.toml
Normal file
14
rc_core/Cargo.toml
Normal file
@@ -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"] }
|
||||
39
rc_core/src/data/mod.rs
Normal file
39
rc_core/src/data/mod.rs
Normal file
@@ -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<u8> {
|
||||
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<usize> {
|
||||
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()
|
||||
}
|
||||
8
rc_core/src/lib.rs
Normal file
8
rc_core/src/lib.rs
Normal file
@@ -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};
|
||||
@@ -153,6 +153,7 @@ impl <C: Clone> super::User<C> 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 <C: Clone> super::User<C> for UserData {
|
||||
super::since_windows_epoch(0)
|
||||
}
|
||||
|
||||
fn singleplayer_robots(&self) -> Result<polariton::operation::Typed<C>, 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)]
|
||||
@@ -22,6 +22,7 @@ pub trait User<C> {
|
||||
fn slot_by_id(&self, id: i32) -> Result<UserSlotData<C>, i16>;
|
||||
fn save_slot(&self, vehicle: VehicleData) -> Result<(), i16>;
|
||||
fn signup_date(&self) -> i64;
|
||||
fn singleplayer_robots(&self) -> Result<polariton::operation::Typed<C>, i16>;
|
||||
}
|
||||
|
||||
pub struct UserSlots<C> {
|
||||
@@ -41,6 +42,7 @@ pub struct UserSlotData<C> {
|
||||
pub robot_rank: polariton::operation::Typed<C>,
|
||||
pub cpu: polariton::operation::Typed<C>,
|
||||
pub cosmetic_cpu: polariton::operation::Typed<C>,
|
||||
pub uuid: polariton::operation::Typed<C>,
|
||||
}
|
||||
|
||||
pub struct VehicleData {
|
||||
@@ -1,12 +1,15 @@
|
||||
use crate::persist::user::UserProvider;
|
||||
use polariton_server::ToSend;
|
||||
|
||||
pub struct UserState<C: Clone> {
|
||||
state: InitState<C>,
|
||||
pub struct UserState<C: Clone = ()> {
|
||||
state: std::sync::RwLock<InitState<C>>,
|
||||
event_tx: tokio::sync::mpsc::UnboundedSender<ToSend<C>>,
|
||||
}
|
||||
|
||||
impl <C: Clone> UserState<C> {
|
||||
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 <C: Clone> UserState<C> {
|
||||
};
|
||||
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 <C: Clone> UserState<C> {
|
||||
|
||||
}
|
||||
|
||||
pub fn new(provider: std::sync::Arc<crate::persist::user::UserImpl>) -> Self {
|
||||
pub fn new(provider: std::sync::Arc<crate::persist::user::UserImpl>, event_tx: tokio::sync::mpsc::UnboundedSender<ToSend<C>>) -> 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<C>, i16> {
|
||||
match &self.state {
|
||||
pub fn user(&self) -> Result<std::sync::Arc<Box<dyn crate::persist::user::User<C> + 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<C>) {
|
||||
self.event_tx.send(event_data).unwrap()
|
||||
}
|
||||
|
||||
pub fn event_sender(&self) -> tokio::sync::mpsc::UnboundedSender<ToSend<C>> {
|
||||
self.event_tx.clone()
|
||||
}
|
||||
}
|
||||
|
||||
enum InitState<C> {
|
||||
Unauthenticated(std::sync::Arc<crate::persist::user::UserImpl>),
|
||||
Authenticated(Box<dyn crate::persist::user::User<C> + Send + Sync>),
|
||||
Authenticated(std::sync::Arc<Box<dyn crate::persist::user::User<C> + Send + Sync>>),
|
||||
}
|
||||
@@ -16,3 +16,4 @@ hex = "0.4"
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
chrono = "0.4"
|
||||
rc_core = { version = "*", path = "../rc_core" }
|
||||
|
||||
@@ -30,21 +30,21 @@ impl ItemShopBundle {
|
||||
|
||||
fn dump(&self, writer: &mut dyn Write) -> std::io::Result<usize> {
|
||||
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())?;
|
||||
|
||||
@@ -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<u8> {
|
||||
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<usize> {
|
||||
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;
|
||||
|
||||
@@ -43,9 +43,9 @@ pub struct QuestInfo {
|
||||
|
||||
impl QuestInfo {
|
||||
fn dump(&self, writer: &mut dyn Write) -> std::io::Result<usize> {
|
||||
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())?;
|
||||
|
||||
@@ -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<state::UserState<()>>;
|
||||
pub type UserTy = rc_core::UserState<()>;
|
||||
|
||||
pub struct InitConfig {
|
||||
pub cubes: persist::config::ConfigImpl,
|
||||
pub users: std::sync::Arc<persist::user::UserImpl>,
|
||||
pub cubes: rc_core::persist::config::ConfigImpl,
|
||||
pub users: std::sync::Arc<rc_core::persist::user::UserImpl>,
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ParameterTable, i16>) + Sync + Sync> {
|
||||
let cube_ids = <crate::persist::config::ConfigImpl as ConfigProvider<()>>::ids(cubes);
|
||||
pub(super) fn cube_inv_provider(cubes: &rc_core::ConfigImpl) -> SimpleFunc<16, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
|
||||
let cube_ids = <rc_core::ConfigImpl as ConfigProvider<()>>::ids(cubes);
|
||||
SimpleFunc::new(move |params, _| {
|
||||
let mut params = params.to_dict();
|
||||
params.insert(PARAM_KEY, Typed::Dict(Dict {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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<ParameterTable, i16>) + Sync + Sync> {
|
||||
pub(super) fn game_mode_config_provider(conf: &rc_core::ConfigImpl) -> SimpleFunc<113, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
|
||||
let game_config = conf.game_mode_config();
|
||||
SimpleFunc::new(move |params, _| {
|
||||
let mut params = params.to_dict();
|
||||
|
||||
@@ -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<ParameterTable, i16>) + 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())
|
||||
|
||||
@@ -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<ParameterTable, i16>) + 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);
|
||||
|
||||
@@ -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<ParameterTable, i16>) + 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,
|
||||
|
||||
@@ -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<ParameterTable, i16>) + 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)?;
|
||||
|
||||
@@ -14,8 +14,8 @@ impl <C> Operation<C> for MoreLobbyAuth {
|
||||
fn handle(&self, params: polariton::operation::ParameterTable<C>, _: &mut Self::State, user: &Self::User) -> polariton::operation::OperationResponse<C> {
|
||||
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 {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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<ParameterTable, i16>) + 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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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<ParameterTable, i16>) + 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())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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<ParameterTable, i16>) + Sync + Sync> {
|
||||
let campaign_details = <crate::persist::config::ConfigImpl as crate::persist::config::ConfigProvider<()>>::campaign_details(conf);
|
||||
pub(super) fn singleplayer_complete_campaign_provider(conf: &rc_core::ConfigImpl) -> SimpleFunc<64, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
|
||||
let campaign_details = <rc_core::ConfigImpl as rc_core::ConfigProvider<()>>::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<ParameterTable, i16>) + Sync + Sync> {
|
||||
//let campaign_details = <crate::persist::config::ConfigImpl as crate::persist::config::ConfigProvider<()>>::campaign_details(conf);
|
||||
//let campaign_details = <rc_core::ConfigImpl as rc_core::ConfigProvider<()>>::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();
|
||||
}
|
||||
|
||||
@@ -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![
|
||||
|
||||
@@ -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<ParameterTable, i16>) + 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()));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
pub mod player_data;
|
||||
|
||||
pub(self) fn encode_7_bit_i32(mut src: i32) -> Vec<u8> {
|
||||
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<usize> {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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<polariton_server::Server<crate::UserTy>>) {
|
||||
async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAddr, server: std::sync::Arc<polariton_server::Server<crate::UserTy>>, users: std::sync::Arc<rc_core::persist::user::UserImpl>) {
|
||||
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);
|
||||
|
||||
@@ -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<ParameterTable, i16>) + 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::<Vec<_>>().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::<Vec<_>>().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())
|
||||
})
|
||||
|
||||
@@ -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<UserAuthInfo>,
|
||||
pub event_tx: UnboundedSender<ToSend>,
|
||||
}
|
||||
|
||||
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<ToSend>) -> crate::UserTy {
|
||||
UserState {
|
||||
auth: RwLock::new(Default::default()),
|
||||
event_tx,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<state::UserState>;
|
||||
pub type UserTy = rc_core::UserState<crate::data::custom::CustomType>;
|
||||
|
||||
#[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<polariton_server::Server<crate::UserTy, crate::data::custom::CustomType>>) {
|
||||
async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAddr, server: std::sync::Arc<polariton_server::Server<crate::UserTy, crate::data::custom::CustomType>>, users: std::sync::Arc<rc_core::UserImpl>) {
|
||||
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::<crate::data::custom::CustomType>::new(users, chann_tx.clone());
|
||||
let op_ctx = polariton::serdes::SerdesContext::<crate::data::custom::CustomType, crate::data::custom::CustomTypeSerdes>::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);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,8 @@ impl <C> Operation<C> for MoreLobbyAuth {
|
||||
fn handle(&self, params: polariton::operation::ParameterTable<C>, _: &mut Self::State, user: &Self::User) -> polariton::operation::OperationResponse<C> {
|
||||
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,
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user