mirror of
https://git.ngram.ca/OpenJam/rc-servers
synced 2026-08-23 23:08:52 +00:00
Get test mode working, complete #12
This commit is contained in:
19
rc_services_room/src/data/auto_regen.rs
Normal file
19
rc_services_room/src/data/auto_regen.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use polariton::operation::Typed;
|
||||
|
||||
pub struct AutoRegenHealthConfig {
|
||||
pub seconds_to_wait_for_heal: f32,
|
||||
pub seconds_to_full_heal: f32,
|
||||
pub threshold_to_start_sound: f32,
|
||||
pub enable_auto_heal: bool,
|
||||
}
|
||||
|
||||
impl AutoRegenHealthConfig {
|
||||
pub fn as_transmissible<C>(&self) -> Typed<C> {
|
||||
let mut bytes = Vec::with_capacity(13);
|
||||
bytes.extend_from_slice(&self.seconds_to_wait_for_heal.to_le_bytes());
|
||||
bytes.extend_from_slice(&self.seconds_to_full_heal.to_le_bytes());
|
||||
bytes.extend_from_slice(&self.threshold_to_start_sound.to_le_bytes());
|
||||
bytes.push(self.enable_auto_heal as u8);
|
||||
Typed::Bytes(bytes.into())
|
||||
}
|
||||
}
|
||||
38
rc_services_room/src/data/error_codes.rs
Normal file
38
rc_services_room/src/data/error_codes.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
#[repr(i16)]
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub enum WebServicesError {
|
||||
None = 0,
|
||||
CPUTooHigh = 1,
|
||||
CPUTooLow = 2,
|
||||
RobotTierNotAllowed = 3,
|
||||
CubeIDNotAllowed = 4,
|
||||
CubeTypeNotAllowed = 5,
|
||||
DatabaseError = 8,
|
||||
UnexpectedError = 9,
|
||||
WrongNumberOfAuthParams = 10,
|
||||
Banned = 11,
|
||||
EACValidationFailed = 12,
|
||||
NotSteamUser = 13,
|
||||
PromotionDoesntExist = 14,
|
||||
NotEnoughMoney = 17,
|
||||
MaxGarageSlots = 18,
|
||||
PlatformFeatureNotAvailable = 19,
|
||||
UserDoesNotHaveAllCubeTypes = 20,
|
||||
ReplaceDailyQuestLimit = 21,
|
||||
MaintenanceModeError = 125,
|
||||
RobotShopMaintenanceMode = 126,
|
||||
InvalidRobot = 140,
|
||||
ExpiredRobot = 144,
|
||||
RobotHasSanction = 145,
|
||||
CustomisationNotOwned = 146,
|
||||
ItemShopBundleExpired = 147,
|
||||
UserNotFound = 200,
|
||||
InvalidUsernameFormat = 201,
|
||||
UsernameTooLong = 202,
|
||||
InvalidUsername = 203,
|
||||
TencentValidationFail = 204,
|
||||
UsernameAlreadyTaken = 205,
|
||||
UsernameTooShort = 206,
|
||||
SaleEnded = 207
|
||||
}
|
||||
@@ -32,7 +32,7 @@ impl GarageSlotInfo {
|
||||
(Typed::Str("wasRated".into()), Typed::Bool(self.was_rated.into())),
|
||||
(Typed::Str("movementCategories".into()), Typed::Arr(Arr {
|
||||
ty: TypePrefix::Int, // int
|
||||
items: self.movement_categories.iter().map(|x| Typed::Int((*x as i32) * 100_000)).collect(),
|
||||
items: self.movement_categories.iter().map(|x| Typed::Int(x.but_bigger() as i32)).collect(),
|
||||
})),
|
||||
(Typed::Str("uniqueId1".into()), Typed::Int(self.uuid.0 as i32)),
|
||||
(Typed::Str("uniqueId2".into()), Typed::Int(self.uuid.1 as i32)),
|
||||
|
||||
20
rc_services_room/src/data/lobby.rs
Normal file
20
rc_services_room/src/data/lobby.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
#[repr(i8)]
|
||||
#[derive(Debug)]
|
||||
pub enum LobbyType {
|
||||
None = -1,
|
||||
CustomGame = 1,
|
||||
QuickPlay = 2,
|
||||
Solo = 3
|
||||
}
|
||||
|
||||
impl LobbyType {
|
||||
pub fn from_int(i: i32) -> Result<Self, i16> {
|
||||
match i {
|
||||
-1 => Ok(Self::None),
|
||||
1 => Ok(Self::CustomGame),
|
||||
2 => Ok(Self::QuickPlay),
|
||||
3 => Ok(Self::Solo),
|
||||
_ => Err(super::error_codes::WebServicesError::UnexpectedError as _),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,10 @@ pub mod weapon_upgrade;
|
||||
pub mod player_rank;
|
||||
pub mod robot_data;
|
||||
pub mod quest;
|
||||
pub mod auto_regen;
|
||||
pub mod voting;
|
||||
pub mod lobby;
|
||||
pub mod error_codes;
|
||||
|
||||
pub(self) fn encode_7_bit_i32(mut src: i32) -> Vec<u8> {
|
||||
let mut out = Vec::with_capacity(5);
|
||||
|
||||
@@ -54,6 +54,7 @@ pub enum MovementCategorySpecificData {
|
||||
SprinterLeg(MechLegCategoryData), // same as mech leg
|
||||
TankTrack,
|
||||
Rotor(RotorCategoryData),
|
||||
Ski,
|
||||
}
|
||||
|
||||
impl MovementCategorySpecificData {
|
||||
@@ -70,6 +71,7 @@ impl MovementCategorySpecificData {
|
||||
Self::SprinterLeg(x) => x.as_transmissible(),
|
||||
Self::TankTrack => Vec::default(),
|
||||
Self::Rotor(x) => x.as_transmissible(),
|
||||
Self::Ski => Vec::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -161,6 +163,7 @@ pub enum MovementSpecificData {
|
||||
SprinterLeg(MechLegData), // same as mech leg
|
||||
TankTrack(TankTrackData),
|
||||
Rotor(RotorData),
|
||||
Ski,
|
||||
}
|
||||
|
||||
impl MovementSpecificData {
|
||||
@@ -177,6 +180,7 @@ impl MovementSpecificData {
|
||||
Self::SprinterLeg(x) => x.as_transmissible(),
|
||||
Self::TankTrack(x) => x.as_transmissible(),
|
||||
Self::Rotor(x) => x.as_transmissible(),
|
||||
Self::Ski => Vec::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,7 +217,7 @@ impl WheelData {
|
||||
|
||||
pub struct HoverData {
|
||||
pub max_hover_height_light: f32,
|
||||
pub max_hover_height_heaver: f32,
|
||||
pub max_hover_height_heavy: f32,
|
||||
pub height_change_speed_light: f32,
|
||||
pub height_change_speed_heavy: f32,
|
||||
pub turn_torque_light: f32,
|
||||
@@ -230,7 +234,7 @@ impl HoverData {
|
||||
pub fn as_transmissible<C>(&self) -> Vec<(Typed<C>, Typed<C>)> {
|
||||
vec![
|
||||
(Typed::Str("maxHoverHeightLight".into()), Typed::Float(self.max_hover_height_light)),
|
||||
(Typed::Str("maxHoverHeightHeavy".into()), Typed::Float(self.max_hover_height_heaver)),
|
||||
(Typed::Str("maxHoverHeightHeavy".into()), Typed::Float(self.max_hover_height_heavy)),
|
||||
(Typed::Str("heightChangeSpeedLight".into()), Typed::Float(self.height_change_speed_light)),
|
||||
(Typed::Str("heightChangeSpeedHeavy".into()), Typed::Float(self.height_change_speed_heavy)),
|
||||
(Typed::Str("turnTorqueLight".into()), Typed::Float(self.turn_torque_light)),
|
||||
@@ -364,8 +368,8 @@ pub struct MechLegData {
|
||||
pub turn_acceleration_heavy: f32,
|
||||
pub legacy_turn_acceleration_light: f32,
|
||||
pub legacy_turn_acceleration_heavy: f32,
|
||||
pub long_jump_speec_scale_light: f32,
|
||||
pub long_jump_speec_scale_heavy: f32,
|
||||
pub long_jump_speed_scale_light: f32,
|
||||
pub long_jump_speed_scale_heavy: f32,
|
||||
pub max_lateral_force_light: f32,
|
||||
pub max_lateral_force_heavy: f32,
|
||||
pub max_damping_force_light: f32,
|
||||
@@ -383,8 +387,8 @@ impl MechLegData {
|
||||
(Typed::Str("turnAccelerationHeavy".into()), Typed::Float(self.turn_acceleration_heavy)),
|
||||
(Typed::Str("legacyTurnAccelerationLight".into()), Typed::Float(self.legacy_turn_acceleration_light)),
|
||||
(Typed::Str("legacyTurnAccelerationHeavy".into()), Typed::Float(self.legacy_turn_acceleration_heavy)),
|
||||
(Typed::Str("longJumpSpeedScaleLight".into()), Typed::Float(self.long_jump_speec_scale_light)),
|
||||
(Typed::Str("longJumpSpeedScaleHeavy".into()), Typed::Float(self.long_jump_speec_scale_heavy)),
|
||||
(Typed::Str("longJumpSpeedScaleLight".into()), Typed::Float(self.long_jump_speed_scale_light)),
|
||||
(Typed::Str("longJumpSpeedScaleHeavy".into()), Typed::Float(self.long_jump_speed_scale_heavy)),
|
||||
(Typed::Str("maxLateralForceLight".into()), Typed::Float(self.max_lateral_force_light)),
|
||||
(Typed::Str("maxLateralForceHeavy".into()), Typed::Float(self.max_lateral_force_heavy)),
|
||||
(Typed::Str("maxDampingForceLight".into()), Typed::Float(self.max_damping_force_light)),
|
||||
|
||||
37
rc_services_room/src/data/voting.rs
Normal file
37
rc_services_room/src/data/voting.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use polariton::{operation::Typed, serdes::TypePrefix};
|
||||
|
||||
pub struct VoteThresholdData {
|
||||
pub name: String,
|
||||
pub localised_name: String,
|
||||
pub color: String,
|
||||
pub votes_required: i32,
|
||||
}
|
||||
|
||||
impl VoteThresholdData {
|
||||
pub fn as_transmissible<C>(&self) -> Typed<C> {
|
||||
Typed::Dict(polariton::operation::Dict {
|
||||
key_ty: TypePrefix::Str,
|
||||
val_ty: TypePrefix::Any,
|
||||
items: vec![
|
||||
(Typed::Str("name".into()), Typed::Str(self.name.clone().into())),
|
||||
(Typed::Str("localisedName".into()), Typed::Str(self.localised_name.clone().into())),
|
||||
(Typed::Str("color".into()), Typed::Str(self.color.clone().into())),
|
||||
(Typed::Str("votesRequired".into()), Typed::Int(self.votes_required)),
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Vote {
|
||||
BestPlayed = 0,
|
||||
BestLooking = 1,
|
||||
}
|
||||
|
||||
impl Vote {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::BestPlayed => "BestPlayed",
|
||||
Self::BestLooking => "BestLooking",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,3 +76,16 @@ pub(super) fn garage_machine_save_provider() -> SimpleFunc<41, crate::UserTy, im
|
||||
})
|
||||
}
|
||||
|
||||
pub const DEFAULT_WEAPON_ORDER_PARAM_KEY: u8 = 138;
|
||||
|
||||
pub(super) fn weapon_order_provider() -> SimpleFunc<118, 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 weapon_order = user_info.slot_by_id(user_info.selected_garage_slot() as i32)?.weapon_order;
|
||||
params.insert(DEFAULT_WEAPON_ORDER_PARAM_KEY, weapon_order);
|
||||
Ok(params.into())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,10 @@ mod cube_awards;
|
||||
mod robot_sanction;
|
||||
mod building_xp;
|
||||
mod reconnect_game;
|
||||
mod regen_config;
|
||||
mod pageantry;
|
||||
mod signup_time;
|
||||
mod validate_machine;
|
||||
|
||||
use polariton_server::operations::OperationsHandler;
|
||||
|
||||
@@ -161,4 +165,9 @@ pub fn handler(init_ctx: &crate::InitConfig) -> OperationsHandler<crate::UserTy>
|
||||
.without_state(machine::garage_machine_save_provider())
|
||||
.without_state(polariton_server::operations::Ack::<32, _>::default()) // TODO handle SaveMachineColorRequest instead of ignoring it
|
||||
.without_state(polariton_server::operations::Ack::<45, _>::default()) // TODO handle UpdateThumbnailVersionRequest instead of ignoring it
|
||||
.without_state(machine::weapon_order_provider())
|
||||
.without_state(regen_config::auto_regen_config_provider(&init_ctx.cubes))
|
||||
.without_state(pageantry::after_battle_vote_thresholds_provider(&init_ctx.cubes))
|
||||
.without_state(signup_time::user_signup_date_provider())
|
||||
.without_state(validate_machine::validate_robot_provider())
|
||||
}
|
||||
|
||||
13
rc_services_room/src/operations/pageantry.rs
Normal file
13
rc_services_room/src/operations/pageantry.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use polariton_server::operations::Immediate;
|
||||
|
||||
use crate::persist::config::ConfigProvider;
|
||||
|
||||
const PARAM_KEY: u8 = 203; // bytes
|
||||
|
||||
pub(super) fn after_battle_vote_thresholds_provider(conf: &crate::persist::config::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());
|
||||
params.into()
|
||||
})
|
||||
}
|
||||
@@ -7,8 +7,8 @@ pub(super) fn power_bar_provider() -> SimpleFunc<51, crate::UserTy, impl (Fn(Par
|
||||
SimpleFunc::new(|params, _| {
|
||||
let mut params = params.to_dict();
|
||||
params.insert(PARAM_KEY, Typed::HashMap(vec![
|
||||
(Typed::Str("refillRatePerSecond".into()), Typed::Float(1.0)),
|
||||
(Typed::Str("powerForAllRobots".into()), Typed::Int(1_000 /* converted to u32 */)),
|
||||
(Typed::Str("refillRatePerSecond".into()), Typed::Float(1000.0)),
|
||||
(Typed::Str("powerForAllRobots".into()), Typed::Int(1_000_000 /* converted to u32 */)),
|
||||
].into()
|
||||
));
|
||||
Ok(params.into())
|
||||
|
||||
13
rc_services_room/src/operations/regen_config.rs
Normal file
13
rc_services_room/src/operations/regen_config.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use polariton_server::operations::Immediate;
|
||||
|
||||
use crate::persist::config::ConfigProvider;
|
||||
|
||||
const PARAM_KEY: u8 = 37; // bytes
|
||||
|
||||
pub(super) fn auto_regen_config_provider(conf: &crate::persist::config::ConfigImpl) -> Immediate<35, crate::UserTy> {
|
||||
Immediate::new(|| {
|
||||
let mut params = std::collections::HashMap::with_capacity(1);
|
||||
params.insert(PARAM_KEY, conf.regen_config());
|
||||
params.into()
|
||||
})
|
||||
}
|
||||
14
rc_services_room/src/operations/signup_time.rs
Normal file
14
rc_services_room/src/operations/signup_time.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use polariton_server::operations::SimpleFunc;
|
||||
use polariton::operation::{ParameterTable, Typed};
|
||||
|
||||
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()));
|
||||
Ok(params.into())
|
||||
})
|
||||
}
|
||||
@@ -14,7 +14,7 @@ pub(super) fn taunts_config_provider() -> SimpleFunc<164, crate::UserTy, impl (F
|
||||
items: vec![
|
||||
(Typed::Str("taunts".into()), TauntsData {
|
||||
taunts: vec![
|
||||
TauntData {
|
||||
/*TauntData {
|
||||
group_name: "totally_real_group_name".to_string(),
|
||||
assets: AssetData {
|
||||
idle_effect: "tbd".to_string(),
|
||||
@@ -33,7 +33,7 @@ pub(super) fn taunts_config_provider() -> SimpleFunc<164, crate::UserTy, impl (F
|
||||
rotation: 0,
|
||||
}
|
||||
]
|
||||
}
|
||||
}*/
|
||||
]
|
||||
}.as_transmissible())
|
||||
]
|
||||
|
||||
30
rc_services_room/src/operations/validate_machine.rs
Normal file
30
rc_services_room/src/operations/validate_machine.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use polariton_server::operations::SimpleFunc;
|
||||
use polariton::operation::{ParameterTable, Typed};
|
||||
|
||||
const LOBBY_PARAM_KEY: u8 = 134;
|
||||
const VALIDATE_ROBOT_RESULT_PARAM_KEY: u8 = 111;
|
||||
|
||||
// possible codes
|
||||
#[allow(dead_code)]
|
||||
#[repr(u8)]
|
||||
enum ValidateMachineResult {
|
||||
Invalid = 0,
|
||||
Ok = 1,
|
||||
NoWeapon = 2,
|
||||
NoMovement = 3,
|
||||
Sanctioned = 4,
|
||||
}
|
||||
|
||||
pub(super) fn validate_robot_provider() -> SimpleFunc<102, crate::UserTy, impl (Fn(ParameterTable, &crate::UserTy) -> Result<ParameterTable, i16>) + Sync + Sync> {
|
||||
SimpleFunc::new(|params, _user: &crate::UserTy| {
|
||||
let mut params = params.to_dict();
|
||||
if let Some(Typed::Int(lobby_ty)) = params.get(&LOBBY_PARAM_KEY) {
|
||||
log::info!("Got lobby type {} ({:?})", lobby_ty, crate::data::lobby::LobbyType::from_int(*lobby_ty));
|
||||
}
|
||||
// let lock = user.read().unwrap();
|
||||
// let user_info = lock.user()?;
|
||||
// TODO actually validate the vehicle
|
||||
params.insert(VALIDATE_ROBOT_RESULT_PARAM_KEY, Typed::Int(ValidateMachineResult::Ok as _));
|
||||
Ok(params.into())
|
||||
})
|
||||
}
|
||||
62
rc_services_room/src/persist/combat.rs
Normal file
62
rc_services_room/src/persist/combat.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct BattleConfig {
|
||||
pub regen: AutoRegenHealth,
|
||||
pub votes: HashMap<Vote, Vec<VoteThreshold>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct AutoRegenHealth {
|
||||
pub wait_for_heal_s: f32,
|
||||
pub wait_full_heal_s: f32,
|
||||
pub sound_start_s: f32,
|
||||
pub auto_heal: bool,
|
||||
}
|
||||
|
||||
impl std::convert::Into<crate::data::auto_regen::AutoRegenHealthConfig> for AutoRegenHealth {
|
||||
fn into(self) -> crate::data::auto_regen::AutoRegenHealthConfig {
|
||||
crate::data::auto_regen::AutoRegenHealthConfig {
|
||||
seconds_to_wait_for_heal: self.wait_for_heal_s,
|
||||
seconds_to_full_heal: self.wait_full_heal_s,
|
||||
threshold_to_start_sound: self.sound_start_s,
|
||||
enable_auto_heal: self.auto_heal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct VoteThreshold {
|
||||
pub name: String,
|
||||
pub localised_name: String,
|
||||
pub color: String,
|
||||
pub votes_required: i32,
|
||||
}
|
||||
|
||||
impl std::convert::Into<crate::data::voting::VoteThresholdData> for VoteThreshold {
|
||||
fn into(self) -> crate::data::voting::VoteThresholdData {
|
||||
crate::data::voting::VoteThresholdData {
|
||||
name: self.name,
|
||||
localised_name: self.localised_name,
|
||||
color: self.color,
|
||||
votes_required: self.votes_required,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Vote {
|
||||
BestPlayed,
|
||||
BestLooking,
|
||||
}
|
||||
|
||||
impl std::convert::Into<crate::data::voting::Vote> for Vote {
|
||||
fn into(self) -> crate::data::voting::Vote {
|
||||
match self {
|
||||
Self::BestPlayed => crate::data::voting::Vote::BestPlayed,
|
||||
Self::BestLooking => crate::data::voting::Vote::BestLooking,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,15 +5,16 @@ use serde::{Serialize, Deserialize};
|
||||
use polariton::operation::{Typed, Dict};
|
||||
use polariton::serdes::TypePrefix;
|
||||
|
||||
use super::super::{MovementCategoryData, MovementData, Cube, ItemCategory, ItemTier};
|
||||
use super::super::{MovementCategoryData, MovementData, Cube, ItemCategory, ItemTier, BattleConfig};
|
||||
|
||||
const CUBE_CONFIG_FILENAME: &str = "cubes.json";
|
||||
const CUBE_CONFIG_FILENAME: &str = "config.json";
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct CubeConfig {
|
||||
cubes: HashMap<String, Cube>,
|
||||
movement: HashMap<ItemCategory, MovementCategoryData>,
|
||||
lerp_value: f32,
|
||||
battle: BattleConfig,
|
||||
}
|
||||
|
||||
impl CubeConfig {
|
||||
@@ -153,4 +154,27 @@ impl <C: Clone> super::ConfigProvider<C> for CubeConfig {
|
||||
fn ids(&self) -> Vec<u32> {
|
||||
self.cubes.values().map(|cube| cube.id).collect()
|
||||
}
|
||||
|
||||
fn regen_config(&self) -> Typed<C> {
|
||||
let regen_data: crate::data::auto_regen::AutoRegenHealthConfig = self.battle.regen.clone().into();
|
||||
regen_data.as_transmissible()
|
||||
}
|
||||
|
||||
fn after_battle_vote_config(&self) -> Typed<C> {
|
||||
let mut vote_data = Vec::with_capacity(self.battle.votes.len()); // probably len() == 2
|
||||
for (key, val) in self.battle.votes.iter() {
|
||||
let key_data: crate::data::voting::Vote = key.to_owned().into();
|
||||
let mut val_data = Vec::with_capacity(val.len());
|
||||
for item in val {
|
||||
let vote_data: crate::data::voting::VoteThresholdData = item.to_owned().into();
|
||||
val_data.push(vote_data.as_transmissible());
|
||||
}
|
||||
vote_data.push((Typed::Str(key_data.as_str().into()), Typed::ObjArr(val_data.into())));
|
||||
}
|
||||
Typed::Dict(Dict {
|
||||
key_ty: TypePrefix::Str,
|
||||
val_ty: TypePrefix::Any,
|
||||
items: vote_data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,6 @@ pub trait ConfigProvider<C> {
|
||||
fn weapon_upgrade_list(&self) -> Typed<C>;
|
||||
fn tech_tree_nodes(&self, unlocked_cubes: &std::collections::HashSet<u32>) -> Typed<C>;
|
||||
fn ids(&self) -> Vec<u32>;
|
||||
fn regen_config(&self) -> Typed<C>;
|
||||
fn after_battle_vote_config(&self) -> Typed<C>;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ pub struct CubeInfo {
|
||||
pub cpu: u32,
|
||||
#[serde(default = "default_1")]
|
||||
pub health: u32,
|
||||
#[serde(default = "default_1_0")]
|
||||
#[serde(default)]
|
||||
pub health_boost: f32,
|
||||
#[serde(default)]
|
||||
pub grey_out_in_tutorial: bool,
|
||||
@@ -59,10 +59,6 @@ fn default_1() -> u32 {
|
||||
1
|
||||
}
|
||||
|
||||
fn default_1_0() -> f32 {
|
||||
1.0
|
||||
}
|
||||
|
||||
fn default_63() -> u32 {
|
||||
63
|
||||
}
|
||||
@@ -113,8 +109,8 @@ impl <C: Clone> std::convert::Into<crate::data::cube_list::CubeInfo<C>> for Cube
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Debug, Default)]
|
||||
pub enum VisibilityMode {
|
||||
Mothership,
|
||||
#[default]
|
||||
Mothership,
|
||||
All,
|
||||
Tutorial,
|
||||
None,
|
||||
|
||||
@@ -16,3 +16,6 @@ pub use weapon::{WeaponData, WeaponUpgradeInfo};
|
||||
|
||||
mod tech_tree;
|
||||
pub use tech_tree::TechTreeData;
|
||||
|
||||
mod combat;
|
||||
pub use combat::BattleConfig;
|
||||
|
||||
@@ -11,6 +11,7 @@ pub struct MovementCategoryData {
|
||||
pub max_hover_height: Option<f32>,
|
||||
pub light_machine_mass: Option<f32>,
|
||||
pub heavy_machine_mass: Option<f32>,
|
||||
#[serde(flatten)]
|
||||
pub specifics: MovementCategorySpecificData,
|
||||
}
|
||||
|
||||
@@ -31,6 +32,7 @@ impl MovementCategoryData {
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||
#[serde(tag = "movement_enum_variant")]
|
||||
pub enum MovementCategorySpecificData {
|
||||
#[default]
|
||||
Wheel,
|
||||
@@ -44,6 +46,7 @@ pub enum MovementCategorySpecificData {
|
||||
SprinterLeg(MechLegCategoryData), // same as mech leg
|
||||
TankTrack,
|
||||
Rotor(RotorCategoryData),
|
||||
Ski,
|
||||
}
|
||||
|
||||
impl std::convert::Into<crate::data::movement_list::MovementCategorySpecificData> for MovementCategorySpecificData {
|
||||
@@ -60,6 +63,7 @@ impl std::convert::Into<crate::data::movement_list::MovementCategorySpecificData
|
||||
Self::SprinterLeg(x) => crate::data::movement_list::MovementCategorySpecificData::SprinterLeg(x.into()),
|
||||
Self::TankTrack => crate::data::movement_list::MovementCategorySpecificData::TankTrack,
|
||||
Self::Rotor(x) => crate::data::movement_list::MovementCategorySpecificData::Rotor(x.into()),
|
||||
Self::Ski => crate::data::movement_list::MovementCategorySpecificData::Ski,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,6 +127,7 @@ pub struct MovementData {
|
||||
pub max_carry_mass: Option<f32>,
|
||||
pub horizontal_top_speed: Option<f32>,
|
||||
pub vertical_top_speed: Option<f32>,
|
||||
#[serde(flatten)]
|
||||
pub specifics: MovementSpecificData,
|
||||
}
|
||||
|
||||
@@ -139,6 +144,7 @@ impl std::convert::Into<crate::data::movement_list::MovementData> for MovementDa
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(tag = "movement_enum_variant")]
|
||||
pub enum MovementSpecificData {
|
||||
Wheel(WheelData),
|
||||
Hover(HoverData),
|
||||
@@ -151,6 +157,7 @@ pub enum MovementSpecificData {
|
||||
SprinterLeg(MechLegData), // same as mech leg
|
||||
TankTrack(TankTrackData),
|
||||
Rotor(RotorData),
|
||||
Ski,
|
||||
}
|
||||
|
||||
impl std::convert::Into<crate::data::movement_list::MovementSpecificData> for MovementSpecificData {
|
||||
@@ -167,6 +174,7 @@ impl std::convert::Into<crate::data::movement_list::MovementSpecificData> for Mo
|
||||
Self::SprinterLeg(x) => crate::data::movement_list::MovementSpecificData::SprinterLeg(x.into()),
|
||||
Self::TankTrack(x) => crate::data::movement_list::MovementSpecificData::TankTrack(x.into()),
|
||||
Self::Rotor(x) => crate::data::movement_list::MovementSpecificData::Rotor(x.into()),
|
||||
Self::Ski=> crate::data::movement_list::MovementSpecificData::Ski,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +213,7 @@ impl std::convert::Into<crate::data::movement_list::WheelData> for WheelData {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
|
||||
pub struct HoverData {
|
||||
pub max_hover_height_light: f32,
|
||||
pub max_hover_height_heaver: f32,
|
||||
pub max_hover_height_heavy: f32,
|
||||
pub height_change_speed_light: f32,
|
||||
pub height_change_speed_heavy: f32,
|
||||
pub turn_torque_light: f32,
|
||||
@@ -222,7 +230,7 @@ impl std::convert::Into<crate::data::movement_list::HoverData> for HoverData {
|
||||
fn into(self) -> crate::data::movement_list::HoverData {
|
||||
crate::data::movement_list::HoverData {
|
||||
max_hover_height_light: self.max_hover_height_light,
|
||||
max_hover_height_heaver: self.max_hover_height_heaver,
|
||||
max_hover_height_heavy: self.max_hover_height_heavy,
|
||||
height_change_speed_light: self.height_change_speed_light,
|
||||
height_change_speed_heavy: self.height_change_speed_heavy,
|
||||
turn_torque_light: self.turn_torque_light,
|
||||
@@ -360,8 +368,8 @@ pub struct MechLegData {
|
||||
pub turn_acceleration_heavy: f32,
|
||||
pub legacy_turn_acceleration_light: f32,
|
||||
pub legacy_turn_acceleration_heavy: f32,
|
||||
pub long_jump_speec_scale_light: f32,
|
||||
pub long_jump_speec_scale_heavy: f32,
|
||||
pub long_jump_speed_scale_light: f32,
|
||||
pub long_jump_speed_scale_heavy: f32,
|
||||
pub max_lateral_force_light: f32,
|
||||
pub max_lateral_force_heavy: f32,
|
||||
pub max_damping_force_light: f32,
|
||||
@@ -379,8 +387,8 @@ impl std::convert::Into<crate::data::movement_list::MechLegData> for MechLegData
|
||||
turn_acceleration_heavy: self.turn_acceleration_heavy,
|
||||
legacy_turn_acceleration_light: self.legacy_turn_acceleration_light,
|
||||
legacy_turn_acceleration_heavy: self.legacy_turn_acceleration_heavy,
|
||||
long_jump_speec_scale_light: self.long_jump_speec_scale_light,
|
||||
long_jump_speec_scale_heavy: self.long_jump_speec_scale_heavy,
|
||||
long_jump_speed_scale_light: self.long_jump_speed_scale_light,
|
||||
long_jump_speed_scale_heavy: self.long_jump_speed_scale_heavy,
|
||||
max_lateral_force_light: self.max_lateral_force_light,
|
||||
max_lateral_force_heavy: self.max_lateral_force_heavy,
|
||||
max_damping_force_light: self.max_damping_force_light,
|
||||
|
||||
@@ -142,10 +142,10 @@ impl <C: Clone> super::User<C> for UserData {
|
||||
data: polariton::operation::Typed::Bytes(slot.robot_data.into()),
|
||||
colour_data: polariton::operation::Typed::Bytes(slot.colour_data.into()),
|
||||
cube_count: polariton::operation::Typed::Int(slot.cubes as _),
|
||||
weapon_order: polariton::operation::Typed::IntArr(vec![0].into()), // TODO
|
||||
weapon_order: polariton::operation::Typed::IntArr(slot.weapon_order.clone().into()),
|
||||
movement_categories: polariton::operation::Typed::IntArr(slot.movement_categories.into_iter().map(|cat| {
|
||||
let cat: crate::data::weapon_list::ItemCategory = cat.into();
|
||||
cat as i32
|
||||
cat.but_bigger()
|
||||
}).collect::<Vec<_>>().into()),
|
||||
control_type: polariton::operation::Typed::Int(control_ty as _),
|
||||
control_options: control_options.as_transmissible(),
|
||||
@@ -169,12 +169,34 @@ impl <C: Clone> super::User<C> for UserData {
|
||||
existing_data.robot_data = vehicle.robot_data;
|
||||
existing_data.colour_data = vehicle.colour_data;
|
||||
log::debug!("weapon order: {:?}", vehicle.weapon_order);
|
||||
existing_data.weapon_order = vehicle.weapon_order;
|
||||
self.save_garage(&existing_data).map_err(|e| {
|
||||
log::error!("Failed to save vehicle {}: {}", id, e);
|
||||
DATABASE_ERR
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn signup_date(&self) -> i64 {
|
||||
match self.root.metadata() {
|
||||
Ok(meta) => {
|
||||
match meta.created() {
|
||||
Ok(created) => {
|
||||
match created.duration_since(std::time::SystemTime::UNIX_EPOCH) {
|
||||
Ok(dur) => {
|
||||
return super::since_windows_epoch(dur.as_secs() as i64);
|
||||
},
|
||||
Err(e) => log::error!("could not get duration since unix epoch of {}: {}", self.root.display(), e),
|
||||
}
|
||||
},
|
||||
Err(e) => log::error!("could not read creation time of {}: {}", self.root.display(), e),
|
||||
}
|
||||
},
|
||||
Err(e) => log::error!("could not retrieve metadata of {}: {}", self.root.display(), e),
|
||||
}
|
||||
super::since_windows_epoch(0)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
|
||||
@@ -60,7 +60,7 @@ fn default_garage_slots() -> Vec<crate::persist::GarageSlot> {
|
||||
control_options: crate::persist::GarageControls { vertical_strafing: false, sideways_driving: false, tracks_turn_on_spot: false, },
|
||||
mastery_level: 1,
|
||||
bay_skin_id: "RC_MothershipSkin_Neptune_01".to_owned(), // TODO get the rest of the names
|
||||
weapon_order: vec![0],
|
||||
weapon_order: vec![],
|
||||
robot_data: vec![0; 4],
|
||||
colour_data: vec![0; 4],
|
||||
}
|
||||
|
||||
@@ -24,3 +24,11 @@ fn __must_impl<T: UserProvider<()>>() {}
|
||||
fn __test_impl() {
|
||||
__must_impl::<UserImpl>();
|
||||
}
|
||||
|
||||
pub fn since_windows_epoch(since_unix_epoch: i64) -> i64 {
|
||||
use chrono::TimeZone;
|
||||
let windows_epoch = chrono::Utc.from_utc_datetime(&chrono::NaiveDateTime::parse_from_str("1601-01-01 00:00:00", "%Y-%m-%d %H:%M:%S").unwrap());
|
||||
let time_in = chrono::DateTime::<chrono::Utc>::from_timestamp(since_unix_epoch, 0).unwrap();
|
||||
//let time_in = chrono::Utc.from_utc_datetime(&chrono::NaiveDateTime::from_timestamp(since_unix_epoch, 0));
|
||||
time_in.signed_duration_since(windows_epoch).num_milliseconds() * 10_000
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ pub trait User<C> {
|
||||
fn all_slots_by_id(&self) -> UserSlots<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;
|
||||
}
|
||||
|
||||
pub struct UserSlots<C> {
|
||||
|
||||
Reference in New Issue
Block a user