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",
|
||||||
"polariton_auth",
|
"polariton_auth",
|
||||||
"polariton_server",
|
"polariton_server",
|
||||||
|
"rc_core",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rc_core"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"hex",
|
||||||
|
"log",
|
||||||
|
"polariton",
|
||||||
|
"polariton_server",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1782,6 +1797,7 @@ dependencies = [
|
|||||||
"polariton",
|
"polariton",
|
||||||
"polariton_auth",
|
"polariton_auth",
|
||||||
"polariton_server",
|
"polariton_server",
|
||||||
|
"rc_core",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -1810,6 +1826,7 @@ dependencies = [
|
|||||||
"polariton",
|
"polariton",
|
||||||
"polariton_auth",
|
"polariton_auth",
|
||||||
"polariton_server",
|
"polariton_server",
|
||||||
|
"rc_core",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1836,6 +1853,7 @@ dependencies = [
|
|||||||
"polariton",
|
"polariton",
|
||||||
"polariton_auth",
|
"polariton_auth",
|
||||||
"polariton_server",
|
"polariton_server",
|
||||||
|
"rc_core",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ members = [
|
|||||||
"rc_static_data", "rc_microtransactions",
|
"rc_static_data", "rc_microtransactions",
|
||||||
"rc_social", "rc_social_room",
|
"rc_social", "rc_social_room",
|
||||||
"rc_chat", "rc_chat_room",
|
"rc_chat", "rc_chat_room",
|
||||||
"rc_singleplayer", "rc_singleplayer_room",
|
"rc_singleplayer", "rc_singleplayer_room", "rc_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[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
|
## 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
|
## 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.
|
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
|
## 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.
|
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.workspace = true
|
||||||
polariton_auth = { version = "*", path = "../polariton_auth" }
|
polariton_auth = { version = "*", path = "../polariton_auth" }
|
||||||
polariton_server.workspace = true
|
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()})]
|
#[arg(long, default_value_t = {"127.0.0.1".to_string()})]
|
||||||
pub ip: 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
|
/// Handle one connection and then exit
|
||||||
#[arg(short = '1', long)]
|
#[arg(short = '1', long)]
|
||||||
pub once: bool,
|
pub once: bool,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
mod cli;
|
mod cli;
|
||||||
mod state;
|
|
||||||
|
|
||||||
mod data;
|
mod data;
|
||||||
mod operations;
|
mod operations;
|
||||||
@@ -10,7 +9,7 @@ use tokio::net;
|
|||||||
use polariton::packet::{Data, Message, Packet, StandardMessage};
|
use polariton::packet::{Data, Message, Packet, StandardMessage};
|
||||||
use polariton::operation::{OperationResponse, Typed};
|
use polariton::operation::{OperationResponse, Typed};
|
||||||
|
|
||||||
pub type UserTy = std::sync::RwLock<state::UserState>;
|
pub type UserTy = rc_core::UserState;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
@@ -18,6 +17,9 @@ async fn main() -> std::io::Result<()> {
|
|||||||
let args = cli::CliArgs::get();
|
let args = cli::CliArgs::get();
|
||||||
log::debug!("Got cli args {:?}", args);
|
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 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");
|
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 {
|
if args.once {
|
||||||
log::warn!("Handling first connection and then exiting");
|
log::warn!("Handling first connection and then exiting");
|
||||||
let (socket, address) = listener.accept().await?;
|
let (socket, address) = listener.accept().await?;
|
||||||
process_socket(socket, address, server.clone()).await;
|
process_socket(socket, address, server.clone(), users.clone()).await;
|
||||||
} else {
|
} else {
|
||||||
loop {
|
loop {
|
||||||
let (socket, address) = listener.accept().await?;
|
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();
|
server.join();
|
||||||
@@ -39,7 +41,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
Ok(())
|
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);
|
log::debug!("Accepting connection from address {}", address);
|
||||||
let enc = match do_connect_handshake(&mut socket).await {
|
let enc = match do_connect_handshake(&mut socket).await {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
@@ -48,9 +50,10 @@ async fn process_socket(mut socket: net::TcpStream, address: std::net::SocketAdd
|
|||||||
return;
|
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 (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);
|
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> {
|
fn handle(&self, params: polariton::operation::ParameterTable<C>, _: &mut Self::State, user: &Self::User) -> polariton::operation::OperationResponse<C> {
|
||||||
let params_dict = params.to_dict();
|
let params_dict = params.to_dict();
|
||||||
if let Some(Typed::Str(auth_payload)) = params_dict.get(&Self::AUTH_PAYLOAD_KEY) {
|
if let Some(Typed::Str(auth_payload)) = params_dict.get(&Self::AUTH_PAYLOAD_KEY) {
|
||||||
let mut write_lock = user.write().unwrap();
|
if user.update_with_auth(&auth_payload.string) {
|
||||||
if write_lock.update_with_auth(&auth_payload.string) {
|
|
||||||
let mut resp_params = std::collections::HashMap::new();
|
let mut resp_params = std::collections::HashMap::new();
|
||||||
resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0));
|
resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0));
|
||||||
return polariton::operation::OperationResponse {
|
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 _),
|
robot_rank: polariton::operation::Typed::Int(slot.total_robot_ranking as _),
|
||||||
cpu: polariton::operation::Typed::Int(slot.total_robot_cpu as _),
|
cpu: polariton::operation::Typed::Int(slot.total_robot_cpu as _),
|
||||||
cosmetic_cpu: polariton::operation::Typed::Int(slot.total_cosmetic_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) => {
|
Err(e) => {
|
||||||
@@ -200,6 +201,37 @@ impl <C: Clone> super::User<C> for UserData {
|
|||||||
super::since_windows_epoch(0)
|
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)]
|
#[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 slot_by_id(&self, id: i32) -> Result<UserSlotData<C>, i16>;
|
||||||
fn save_slot(&self, vehicle: VehicleData) -> Result<(), i16>;
|
fn save_slot(&self, vehicle: VehicleData) -> Result<(), i16>;
|
||||||
fn signup_date(&self) -> i64;
|
fn signup_date(&self) -> i64;
|
||||||
|
fn singleplayer_robots(&self) -> Result<polariton::operation::Typed<C>, i16>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UserSlots<C> {
|
pub struct UserSlots<C> {
|
||||||
@@ -41,6 +42,7 @@ pub struct UserSlotData<C> {
|
|||||||
pub robot_rank: polariton::operation::Typed<C>,
|
pub robot_rank: polariton::operation::Typed<C>,
|
||||||
pub cpu: polariton::operation::Typed<C>,
|
pub cpu: polariton::operation::Typed<C>,
|
||||||
pub cosmetic_cpu: polariton::operation::Typed<C>,
|
pub cosmetic_cpu: polariton::operation::Typed<C>,
|
||||||
|
pub uuid: polariton::operation::Typed<C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VehicleData {
|
pub struct VehicleData {
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
use crate::persist::user::UserProvider;
|
use crate::persist::user::UserProvider;
|
||||||
|
use polariton_server::ToSend;
|
||||||
|
|
||||||
pub struct UserState<C: Clone> {
|
pub struct UserState<C: Clone = ()> {
|
||||||
state: InitState<C>,
|
state: std::sync::RwLock<InitState<C>>,
|
||||||
|
event_tx: tokio::sync::mpsc::UnboundedSender<ToSend<C>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <C: Clone> UserState<C> {
|
impl <C: Clone> UserState<C> {
|
||||||
pub fn update_with_auth(&mut self, auth_str: &str) -> bool {
|
pub fn update_with_auth(&self, auth_str: &str) -> bool {
|
||||||
match &self.state {
|
let mut lock = self.state.write().unwrap();
|
||||||
|
match &*lock {
|
||||||
InitState::Unauthenticated(auth) => {
|
InitState::Unauthenticated(auth) => {
|
||||||
let splits: Vec<&str> = auth_str.split(';').collect();
|
let splits: Vec<&str> = auth_str.split(';').collect();
|
||||||
if splits.len() != 3 {
|
if splits.len() != 3 {
|
||||||
@@ -20,7 +23,7 @@ impl <C: Clone> UserState<C> {
|
|||||||
};
|
};
|
||||||
match auth.authenticate(token) {
|
match auth.authenticate(token) {
|
||||||
Ok(user) => {
|
Ok(user) => {
|
||||||
self.state = InitState::Authenticated(user);
|
*lock = InitState::Authenticated(std::sync::Arc::new(user));
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
Err(e) => {
|
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 {
|
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> {
|
pub fn user(&self) -> Result<std::sync::Arc<Box<dyn crate::persist::user::User<C> + Send + Sync>>, i16> {
|
||||||
match &self.state {
|
let lock = self.state.read().unwrap();
|
||||||
|
match &*lock {
|
||||||
InitState::Unauthenticated(_) => Err(120),
|
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> {
|
enum InitState<C> {
|
||||||
Unauthenticated(std::sync::Arc<crate::persist::user::UserImpl>),
|
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.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
chrono = "0.4"
|
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> {
|
fn dump(&self, writer: &mut dyn Write) -> std::io::Result<usize> {
|
||||||
let sku_bytes = self.sku.as_bytes();
|
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)?;
|
total_len += writer.write(sku_bytes)?;
|
||||||
|
|
||||||
let bundle_name_key_bytes = self.bundle_name_key.as_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)?;
|
total_len += writer.write(bundle_name_key_bytes)?;
|
||||||
|
|
||||||
let sprite_bytes = self.sprite.as_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(sprite_bytes)?;
|
||||||
|
|
||||||
total_len += writer.write(&[self.is_sprite_full_size as u8])?;
|
total_len += writer.write(&[self.is_sprite_full_size as u8])?;
|
||||||
|
|
||||||
let currency_bytes = self.currency.as_str().as_bytes();
|
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(currency_bytes)?;
|
||||||
|
|
||||||
total_len += writer.write(&self.price.to_le_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 special_item;
|
||||||
pub mod premium_config;
|
pub mod premium_config;
|
||||||
pub mod palette;
|
pub mod palette;
|
||||||
pub mod client_config;
|
pub mod client_config;
|
||||||
pub mod crf_config;
|
pub mod crf_config;
|
||||||
pub mod weapon_list;
|
pub use rc_core::data::weapon_list;
|
||||||
pub mod movement_list;
|
//pub use rc_core::data::movement_list;
|
||||||
pub mod damage_boost;
|
pub mod damage_boost;
|
||||||
pub mod battle_arena_config;
|
pub mod battle_arena_config;
|
||||||
pub mod cpu_limits;
|
pub mod cpu_limits;
|
||||||
pub mod cosmetic_limits;
|
pub mod cosmetic_limits;
|
||||||
pub mod taunts_config;
|
pub mod taunts_config;
|
||||||
pub mod customisation_info;
|
pub mod customisation_info;
|
||||||
pub mod garage_bay;
|
pub use rc_core::data::garage_bay;
|
||||||
pub mod custom_games;
|
pub mod custom_games;
|
||||||
pub mod tech_tree;
|
//pub use rc_core::data::tech_tree;
|
||||||
pub mod item_shop_bundle;
|
pub mod item_shop_bundle;
|
||||||
pub mod player_robopass_season;
|
pub mod player_robopass_season;
|
||||||
pub mod weapon_upgrade;
|
//pub use rc_core::data::weapon_upgrade;
|
||||||
pub mod player_rank;
|
pub mod player_rank;
|
||||||
pub mod robot_data;
|
pub mod robot_data;
|
||||||
pub mod quest;
|
pub mod quest;
|
||||||
pub mod auto_regen;
|
//pub use rc_core::data::auto_regen;
|
||||||
pub mod voting;
|
//pub use rc_core::data::voting;
|
||||||
pub mod lobby;
|
pub mod lobby;
|
||||||
pub mod error_codes;
|
pub use rc_core::data::error_codes;
|
||||||
pub mod game_mode;
|
//pub use rc_core::data::game_mode;
|
||||||
pub mod score_multipliers;
|
pub mod score_multipliers;
|
||||||
pub mod campaign;
|
//pub use rc_core::data::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()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ pub struct QuestInfo {
|
|||||||
|
|
||||||
impl QuestInfo {
|
impl QuestInfo {
|
||||||
fn dump(&self, writer: &mut dyn Write) -> std::io::Result<usize> {
|
fn dump(&self, writer: &mut dyn Write) -> std::io::Result<usize> {
|
||||||
let mut total_len = super::write_str_for_binreader(&self.id, writer)?;
|
let mut total_len = rc_core::data::write_str_for_binreader(&self.id, writer)?;
|
||||||
total_len += super::write_str_for_binreader(&self.name, writer)?;
|
total_len += rc_core::data::write_str_for_binreader(&self.name, writer)?;
|
||||||
total_len += super::write_str_for_binreader(&self.description, 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.xp.to_le_bytes())?;
|
||||||
total_len += writer.write(&self.premium_xp.to_le_bytes())?;
|
total_len += writer.write(&self.premium_xp.to_le_bytes())?;
|
||||||
total_len += writer.write(&self.robits.to_le_bytes())?;
|
total_len += writer.write(&self.robits.to_le_bytes())?;
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
mod cli;
|
mod cli;
|
||||||
mod state;
|
|
||||||
|
|
||||||
mod data;
|
mod data;
|
||||||
mod events;
|
mod events;
|
||||||
mod operations;
|
mod operations;
|
||||||
mod persist;
|
|
||||||
|
|
||||||
use polariton_auth::Handshake;
|
use polariton_auth::Handshake;
|
||||||
use tokio::net;
|
use tokio::net;
|
||||||
@@ -12,11 +10,11 @@ use tokio::net;
|
|||||||
use polariton::packet::{Data, Message, Packet, StandardMessage};
|
use polariton::packet::{Data, Message, Packet, StandardMessage};
|
||||||
use polariton::operation::{OperationResponse, Typed};
|
use polariton::operation::{OperationResponse, Typed};
|
||||||
|
|
||||||
pub type UserTy = std::sync::RwLock<state::UserState<()>>;
|
pub type UserTy = rc_core::UserState<()>;
|
||||||
|
|
||||||
pub struct InitConfig {
|
pub struct InitConfig {
|
||||||
pub cubes: persist::config::ConfigImpl,
|
pub cubes: rc_core::persist::config::ConfigImpl,
|
||||||
pub users: std::sync::Arc<persist::user::UserImpl>,
|
pub users: std::sync::Arc<rc_core::persist::user::UserImpl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@@ -25,8 +23,8 @@ async fn main() -> std::io::Result<()> {
|
|||||||
let args = cli::CliArgs::get();
|
let args = cli::CliArgs::get();
|
||||||
log::debug!("Got cli args {:?}", args);
|
log::debug!("Got cli args {:?}", args);
|
||||||
|
|
||||||
let cubes = persist::config::ConfigImpl::load(&args.assets).expect("Bad config data");
|
let cubes = rc_core::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 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 {
|
let init_ctx = std::sync::Arc::new(InitConfig {
|
||||||
cubes,
|
cubes,
|
||||||
users,
|
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 (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);
|
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);
|
log::debug!("Goodbye connection from address {}", address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use polariton_server::operations::SimpleFunc;
|
use polariton_server::operations::SimpleFunc;
|
||||||
use polariton::{operation::{Dict, ParameterTable, Typed}, serdes::TypePrefix};
|
use polariton::{operation::{Dict, ParameterTable, Typed}, serdes::TypePrefix};
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 16;
|
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> {
|
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 = <crate::persist::config::ConfigImpl as ConfigProvider<()>>::ids(cubes);
|
let cube_ids = <rc_core::ConfigImpl as ConfigProvider<()>>::ids(cubes);
|
||||||
SimpleFunc::new(move |params, _| {
|
SimpleFunc::new(move |params, _| {
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
params.insert(PARAM_KEY, Typed::Dict(Dict {
|
params.insert(PARAM_KEY, Typed::Dict(Dict {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use polariton_server::operations::Immediate;
|
use polariton_server::operations::Immediate;
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 1;
|
const PARAM_KEY: u8 = 1;
|
||||||
//const DEFAULT_CUBE_ID: u32 = 227205318;
|
//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(|| {
|
Immediate::new(|| {
|
||||||
let mut params = std::collections::HashMap::with_capacity(2);
|
let mut params = std::collections::HashMap::with_capacity(2);
|
||||||
params.insert(PARAM_KEY, cubes.cube_list());
|
params.insert(PARAM_KEY, cubes.cube_list());
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use polariton_server::operations::SimpleFunc;
|
use polariton_server::operations::SimpleFunc;
|
||||||
use polariton::operation::ParameterTable;
|
use polariton::operation::ParameterTable;
|
||||||
|
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 1;
|
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();
|
let game_config = conf.game_mode_config();
|
||||||
SimpleFunc::new(move |params, _| {
|
SimpleFunc::new(move |params, _| {
|
||||||
let mut params = params.to_dict();
|
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> {
|
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| {
|
SimpleFunc::new(|params, user: &crate::UserTy| {
|
||||||
let lock = user.read().unwrap();
|
let user_info = user.user()?;
|
||||||
let user_info = lock.user()?;
|
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
params.insert(PARAM_KEY, Typed::Str(user_info.selected_garage_uuid().into()));
|
params.insert(PARAM_KEY, Typed::Str(user_info.selected_garage_uuid().into()));
|
||||||
Ok(params.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> {
|
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| {
|
SimpleFunc::new(|params, user: &crate::UserTy| {
|
||||||
let lock = user.read().unwrap();
|
let user_info = user.user()?;
|
||||||
let user_info = lock.user()?;
|
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
let all_slots = user_info.all_slots_by_id();
|
let all_slots = user_info.all_slots_by_id();
|
||||||
params.insert(SLOTS_PARAM_KEY, all_slots.slot_info);
|
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> {
|
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| {
|
SimpleFunc::new(|params, user: &crate::UserTy| {
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
let lock = user.read().unwrap();
|
let user_info = user.user()?;
|
||||||
let user_info = lock.user()?;
|
|
||||||
if let Some(Typed::Int(garage_slot)) = params.get(&SLOT_PARAM_KEY) {
|
if let Some(Typed::Int(garage_slot)) = params.get(&SLOT_PARAM_KEY) {
|
||||||
log::debug!("Got machine request for slot {:?}", garage_slot);
|
log::debug!("Got machine request for slot {:?}", garage_slot);
|
||||||
let machine = user_info.slot_by_id(*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::Bytes(colour_data)) = params.remove(&COMPRESSED_COLOUR_DATA_PARAM_KEY) {
|
||||||
if let Some(Typed::Arr(weapon_order)) = params.remove(&WEAPON_ORDER_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 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 = user.user()?;
|
||||||
let user_info = lock.user()?;
|
let vehicle_data = rc_core::persist::user::VehicleData {
|
||||||
let vehicle_data = crate::persist::user::VehicleData {
|
|
||||||
id: slot_index,
|
id: slot_index,
|
||||||
robot_data: robot_data.vec,
|
robot_data: robot_data.vec,
|
||||||
colour_data: colour_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> {
|
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| {
|
SimpleFunc::new(|params, user: &crate::UserTy| {
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
let lock = user.read().unwrap();
|
let user_info = user.user()?;
|
||||||
let user_info = lock.user()?;
|
|
||||||
if let Some(Typed::Int(garage_slot)) = params.get(&SLOT_PARAM_KEY) {
|
if let Some(Typed::Int(garage_slot)) = params.get(&SLOT_PARAM_KEY) {
|
||||||
log::debug!("Got machine colour request for slot {:?}", garage_slot);
|
log::debug!("Got machine colour request for slot {:?}", garage_slot);
|
||||||
let machine = user_info.slot_by_id(*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> {
|
fn handle(&self, params: polariton::operation::ParameterTable<C>, _: &mut Self::State, user: &Self::User) -> polariton::operation::OperationResponse<C> {
|
||||||
let params_dict = params.to_dict();
|
let params_dict = params.to_dict();
|
||||||
if let Some(Typed::Str(auth_payload)) = params_dict.get(&Self::AUTH_PAYLOAD_KEY) {
|
if let Some(Typed::Str(auth_payload)) = params_dict.get(&Self::AUTH_PAYLOAD_KEY) {
|
||||||
let mut write_lock = user.write().unwrap();
|
//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();
|
let mut resp_params = std::collections::HashMap::new();
|
||||||
resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0));
|
resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0));
|
||||||
return polariton::operation::OperationResponse {
|
return polariton::operation::OperationResponse {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
//use polariton::serdes::TypePrefix;
|
//use polariton::serdes::TypePrefix;
|
||||||
use polariton_server::operations::Immediate;
|
use polariton_server::operations::Immediate;
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 1;
|
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(|| {
|
Immediate::new(|| {
|
||||||
let mut params = std::collections::HashMap::with_capacity(2);
|
let mut params = std::collections::HashMap::with_capacity(2);
|
||||||
params.insert(PARAM_KEY, cubes.movement_list());
|
params.insert(PARAM_KEY, cubes.movement_list());
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use polariton_server::operations::Immediate;
|
use polariton_server::operations::Immediate;
|
||||||
|
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 203; // bytes
|
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(|| {
|
Immediate::new(|| {
|
||||||
let mut params = std::collections::HashMap::with_capacity(1);
|
let mut params = std::collections::HashMap::with_capacity(1);
|
||||||
params.insert(PARAM_KEY, conf.after_battle_vote_config());
|
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> {
|
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| {
|
SimpleFunc::new(|params, user: &crate::UserTy| {
|
||||||
let lock = user.read().unwrap();
|
let user = user.user()?;
|
||||||
let user = lock.user()?;
|
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
if let Some(Typed::Str(username)) = params.get(&USERNAME_PARAM_KEY) {
|
if let Some(Typed::Str(username)) = params.get(&USERNAME_PARAM_KEY) {
|
||||||
log::debug!("Get robot rank for user {}", username.string);
|
log::debug!("Get robot rank for user {}", username.string);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use polariton_server::operations::Immediate;
|
use polariton_server::operations::Immediate;
|
||||||
|
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 37; // bytes
|
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(|| {
|
Immediate::new(|| {
|
||||||
let mut params = std::collections::HashMap::with_capacity(1);
|
let mut params = std::collections::HashMap::with_capacity(1);
|
||||||
params.insert(PARAM_KEY, conf.regen_config());
|
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> {
|
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| {
|
SimpleFunc::new(|params, user: &crate::UserTy| {
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
let lock = user.read().unwrap();
|
let user = user.user()?;
|
||||||
let user_info = lock.user()?;
|
params.insert(PARAM_KEY, Typed::Long(user.signup_date()));
|
||||||
params.insert(PARAM_KEY, Typed::Long(user_info.signup_date()));
|
|
||||||
Ok(params.into())
|
Ok(params.into())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
use polariton_server::operations::{Immediate, SimpleFunc};
|
use polariton_server::operations::{Immediate, SimpleFunc};
|
||||||
use polariton::operation::{ParameterTable, Typed};
|
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_BYTES_PARAM_KEY: u8 = 64; // list of bytes (serialised data)
|
||||||
const CAMPAIGNS_WAVES_PARAM_KEY: u8 = 70; // hashtable
|
const CAMPAIGNS_WAVES_PARAM_KEY: u8 = 70; // hashtable
|
||||||
const CAMPAIGNS_VERSIONS_PARAM_KEY: u8 = 69; // 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(|| {
|
Immediate::new(|| {
|
||||||
let mut params = std::collections::HashMap::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
|
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_DIFFICULTY_PARAM_KEY: u8 = 23; // i32; in
|
||||||
const CAMPAIGN_WAVES_PARAM_KEY: u8 = 75; // bytes; out
|
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> {
|
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 = <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, _| {
|
SimpleFunc::new(move |params, _| {
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
if let Some(Typed::Str(campaign_id)) = params.get(&CAMPAIGN_ID_PARAM_KEY) {
|
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;
|
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> {
|
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| {
|
SimpleFunc::new(move |params, user: &crate::UserTy| {
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
if let Some(Typed::Str(campaign_id)) = params.get(&CAMPAIGN_ID_PARAM_KEY) {
|
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(campaign_difficulty)) = params.get(&CAMPAIGN_DIFFICULTY_PARAM_KEY) {
|
||||||
if let Some(Typed::Int(wave_number)) = params.get(&CAMPAIGN_WAVE_NUMBER_PARAM_KEYL) {
|
if let Some(Typed::Int(wave_number)) = params.get(&CAMPAIGN_WAVE_NUMBER_PARAM_KEYL) {
|
||||||
let user_lock = user.read().unwrap();
|
let user_info = user.user()?;
|
||||||
log::info!("User {} completed campaign {} difficulty {} wave {}", user_lock.user()?.token().uuid, campaign_id.string, campaign_difficulty, wave_number);
|
log::info!("User {} completed campaign {} difficulty {} wave {}", user_info.token().uuid, campaign_id.string, campaign_difficulty, wave_number);
|
||||||
// TODO save wave as completed
|
// TODO save wave as completed
|
||||||
params.clear();
|
params.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use polariton_server::operations::Immediate;
|
use polariton_server::operations::Immediate;
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 210;
|
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(|| {
|
Immediate::new(|| {
|
||||||
let mut params = std::collections::HashMap::with_capacity(2);
|
let mut params = std::collections::HashMap::with_capacity(2);
|
||||||
params.insert(PARAM_KEY, cubes.tech_tree_nodes(&vec![
|
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> {
|
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| {
|
SimpleFunc::new(|params, user: &crate::UserTy| {
|
||||||
let lock = user.read().unwrap();
|
let user_info = user.user()?;
|
||||||
let user_info = lock.user()?;
|
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
params.insert(MOD_PARAM_KEY, Typed::Bool(user_info.is_mod()));
|
params.insert(MOD_PARAM_KEY, Typed::Bool(user_info.is_mod()));
|
||||||
params.insert(DEV_PARAM_KEY, Typed::Bool(user_info.is_dev()));
|
params.insert(DEV_PARAM_KEY, Typed::Bool(user_info.is_dev()));
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use polariton_server::operations::Immediate;
|
use polariton_server::operations::Immediate;
|
||||||
|
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
pub const DEFAULT_WEAPON_ORDER_PARAM_KEY: u8 = 138;
|
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();
|
let weapon_orders = conf.weapon_keys();
|
||||||
Immediate::new(|| {
|
Immediate::new(|| {
|
||||||
let mut params = std::collections::HashMap::with_capacity(1);
|
let mut params = std::collections::HashMap::with_capacity(1);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use polariton_server::operations::Immediate;
|
use polariton_server::operations::Immediate;
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 57;
|
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(|| {
|
Immediate::new(|| {
|
||||||
let mut params = std::collections::HashMap::with_capacity(2);
|
let mut params = std::collections::HashMap::with_capacity(2);
|
||||||
params.insert(PARAM_KEY, cubes.weapon_list());
|
params.insert(PARAM_KEY, cubes.weapon_list());
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use polariton_server::operations::Immediate;
|
use polariton_server::operations::Immediate;
|
||||||
use crate::persist::config::ConfigProvider;
|
use rc_core::ConfigProvider;
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 38;
|
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(|| {
|
Immediate::new(|| {
|
||||||
let mut params = std::collections::HashMap::with_capacity(2);
|
let mut params = std::collections::HashMap::with_capacity(2);
|
||||||
params.insert(PARAM_KEY, cubes.weapon_upgrade_list());
|
params.insert(PARAM_KEY, cubes.weapon_upgrade_list());
|
||||||
|
|||||||
@@ -11,3 +11,4 @@ clap.workspace = true
|
|||||||
polariton.workspace = true
|
polariton.workspace = true
|
||||||
polariton_auth = { version = "*", path = "../polariton_auth" }
|
polariton_auth = { version = "*", path = "../polariton_auth" }
|
||||||
polariton_server.workspace = true
|
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()})]
|
#[arg(long, default_value_t = {"127.0.0.1".to_string()})]
|
||||||
pub ip: 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
|
/// Handle one connection and then exit
|
||||||
#[arg(short = '1', long)]
|
#[arg(short = '1', long)]
|
||||||
pub once: bool,
|
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 cli;
|
||||||
mod state;
|
|
||||||
|
|
||||||
mod data;
|
mod data;
|
||||||
mod operations;
|
mod operations;
|
||||||
@@ -10,7 +9,7 @@ use tokio::net;
|
|||||||
use polariton::packet::{Data, Message, Packet, StandardMessage};
|
use polariton::packet::{Data, Message, Packet, StandardMessage};
|
||||||
use polariton::operation::{OperationResponse, Typed};
|
use polariton::operation::{OperationResponse, Typed};
|
||||||
|
|
||||||
pub type UserTy = state::UserState;
|
pub type UserTy = rc_core::UserState<()>;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
@@ -18,6 +17,9 @@ async fn main() -> std::io::Result<()> {
|
|||||||
let args = cli::CliArgs::get();
|
let args = cli::CliArgs::get();
|
||||||
log::debug!("Got cli args {:?}", args);
|
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 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");
|
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 {
|
if args.once {
|
||||||
log::warn!("Handling first connection and then exiting");
|
log::warn!("Handling first connection and then exiting");
|
||||||
let (socket, address) = listener.accept().await?;
|
let (socket, address) = listener.accept().await?;
|
||||||
process_socket(socket, address, server.clone()).await;
|
process_socket(socket, address, server.clone(), users.clone()).await;
|
||||||
} else {
|
} else {
|
||||||
loop {
|
loop {
|
||||||
let (socket, address) = listener.accept().await?;
|
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();
|
server.join();
|
||||||
@@ -39,7 +41,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
Ok(())
|
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);
|
log::debug!("Accepting connection from address {}", address);
|
||||||
let enc = match do_connect_handshake(&mut socket).await {
|
let enc = match do_connect_handshake(&mut socket).await {
|
||||||
Some(x) => x,
|
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 (socket_r, socket_w) = socket.into_split();
|
||||||
let (chann_tx, chann_rx) = tokio::sync::mpsc::unbounded_channel();
|
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);
|
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;
|
server.handle_async_with_channel(socket_r, socket_w, user_state, ctx, chann_tx, chann_rx).await;
|
||||||
log::debug!("Goodbye connection from address {}", address);
|
log::debug!("Goodbye connection from address {}", address);
|
||||||
|
|||||||
@@ -1,878 +1,37 @@
|
|||||||
use polariton_server::operations::SimpleFunc;
|
use polariton_server::operations::SimpleFunc;
|
||||||
use polariton::operation::{ParameterTable, Typed};
|
use polariton::operation::{ParameterTable, Typed};
|
||||||
|
|
||||||
use crate::data::player_data::*;
|
|
||||||
|
|
||||||
const PARAM_KEY: u8 = 8;
|
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> {
|
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| {
|
SimpleFunc::new(|params, user: &crate::UserTy| {
|
||||||
let ulock = user.auth.read().unwrap();
|
let ulock = user.user()?;
|
||||||
let mut params = params.to_dict();
|
let mut params = params.to_dict();
|
||||||
params.insert(PARAM_KEY, PlayerDatas {
|
params.insert(PARAM_KEY, ulock.singleplayer_robots()?);
|
||||||
players: vec![
|
let event_tx = user.event_sender();
|
||||||
PlayerData {
|
let user_bot_data = ulock.slot_by_id(ulock.selected_garage_slot() as _)?;
|
||||||
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();
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
|
tokio::time::sleep(std::time::Duration::from_secs(20)).await;
|
||||||
log::debug!("Sending singleplayer events");
|
log::debug!("Sending singleplayer event");
|
||||||
let mut spawn_params = std::collections::HashMap::with_capacity(4);
|
let mut spawn_params = std::collections::HashMap::with_capacity(4);
|
||||||
spawn_params.insert(2 /* robot GUID */, Typed::Str("12_12".into()));
|
spawn_params.insert(2 /* robot GUID */, Typed::Str("1337_1337".into()));
|
||||||
spawn_params.insert(3 /* machine model */, Typed::Bytes(VALID_ROBOT.iter().map(|x| *x).collect::<Vec<_>>().into()));
|
spawn_params.insert(3 /* machine model */, user_bot_data.data);
|
||||||
spawn_params.insert(4 /* robot name */, Typed::Str("RE_robot_spawn_name0".into()));
|
spawn_params.insert(4 /* robot name */, Typed::Str("RE_robot_spawn_name0".into())); // FIXME
|
||||||
spawn_params.insert(7 /* color model */, Typed::Bytes(VALID_COLOUR.iter().map(|x| *x).collect::<Vec<_>>().into()));
|
spawn_params.insert(7 /* color model */, user_bot_data.colour_data);
|
||||||
event_tx.send(polariton_server::ToSend::Data {
|
event_tx.send(polariton_server::ToSend::Data {
|
||||||
data: polariton::packet::Data::Event(polariton::operation::Event { code: 3, params: spawn_params.into() }),
|
data: polariton::packet::Data::Event(polariton::operation::Event { code: 3, params: spawn_params.into() }),
|
||||||
encrypt: true,
|
encrypt: true,
|
||||||
channel: 0,
|
channel: 0,
|
||||||
reliable: true,
|
reliable: true,
|
||||||
}).unwrap();
|
}).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));
|
update_params.insert(6 /* ??? */, Typed::Int(5));
|
||||||
event_tx.send(polariton_server::ToSend::Data {
|
event_tx.send(polariton_server::ToSend::Data {
|
||||||
data: polariton::packet::Data::Event(polariton::operation::Event { code: 5, params: update_params.into() }),
|
data: polariton::packet::Data::Event(polariton::operation::Event { code: 5, params: update_params.into() }),
|
||||||
encrypt: true,
|
encrypt: true,
|
||||||
channel: 0,
|
channel: 0,
|
||||||
reliable: true,
|
reliable: true,
|
||||||
}).unwrap();
|
}).unwrap();*/
|
||||||
});
|
});
|
||||||
Ok(params.into())
|
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.workspace = true
|
||||||
polariton_auth = { version = "*", path = "../polariton_auth" }
|
polariton_auth = { version = "*", path = "../polariton_auth" }
|
||||||
polariton_server.workspace = true
|
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()})]
|
#[arg(long, default_value_t = {"127.0.0.1".to_string()})]
|
||||||
pub ip: 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
|
/// Handle one connection and then exit
|
||||||
#[arg(short = '1', long)]
|
#[arg(short = '1', long)]
|
||||||
pub once: bool,
|
pub once: bool,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
mod cli;
|
mod cli;
|
||||||
mod state;
|
|
||||||
|
|
||||||
mod data;
|
mod data;
|
||||||
mod operations;
|
mod operations;
|
||||||
@@ -10,7 +9,7 @@ use tokio::net;
|
|||||||
use polariton::packet::{Data, Message, Packet, StandardMessage};
|
use polariton::packet::{Data, Message, Packet, StandardMessage};
|
||||||
use polariton::operation::{OperationResponse, Typed};
|
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]
|
#[tokio::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
@@ -18,6 +17,9 @@ async fn main() -> std::io::Result<()> {
|
|||||||
let args = cli::CliArgs::get();
|
let args = cli::CliArgs::get();
|
||||||
log::debug!("Got cli args {:?}", args);
|
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 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");
|
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 {
|
if args.once {
|
||||||
log::warn!("Handling first connection and then exiting");
|
log::warn!("Handling first connection and then exiting");
|
||||||
let (socket, address) = listener.accept().await?;
|
let (socket, address) = listener.accept().await?;
|
||||||
process_socket(socket, address, server.clone()).await;
|
process_socket(socket, address, server.clone(), users.clone()).await;
|
||||||
} else {
|
} else {
|
||||||
loop {
|
loop {
|
||||||
let (socket, address) = listener.accept().await?;
|
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();
|
server.join();
|
||||||
@@ -39,7 +41,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
Ok(())
|
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);
|
log::debug!("Accepting connection from address {}", address);
|
||||||
let enc = match do_connect_handshake(&mut socket).await {
|
let enc = match do_connect_handshake(&mut socket).await {
|
||||||
Some(x) => x,
|
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 (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 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);
|
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);
|
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> {
|
fn handle(&self, params: polariton::operation::ParameterTable<C>, _: &mut Self::State, user: &Self::User) -> polariton::operation::OperationResponse<C> {
|
||||||
let params_dict = params.to_dict();
|
let params_dict = params.to_dict();
|
||||||
if let Some(Typed::Str(auth_payload)) = params_dict.get(&Self::AUTH_PAYLOAD_KEY) {
|
if let Some(Typed::Str(auth_payload)) = params_dict.get(&Self::AUTH_PAYLOAD_KEY) {
|
||||||
let mut write_lock = user.write().unwrap();
|
if user.update_with_auth(&auth_payload.string) {
|
||||||
if write_lock.update_with_auth(&auth_payload.string) {
|
let mut resp_params = std::collections::HashMap::with_capacity(1);
|
||||||
let mut resp_params = std::collections::HashMap::new();
|
|
||||||
resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0));
|
resp_params.insert(Self::AUTH_PAYLOAD_KEY, polariton::operation::Typed::Byte(0));
|
||||||
return polariton::operation::OperationResponse {
|
return polariton::operation::OperationResponse {
|
||||||
code: 230,
|
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