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:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1774,6 +1774,7 @@ name = "rc_services_room"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chrono",
|
||||
"clap",
|
||||
"env_logger",
|
||||
"hex",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,5 +11,6 @@ pub fn handler() -> OperationsHandler<crate::UserTy> {
|
||||
.without_state(chat_ignores::ignores_provider())
|
||||
.without_state(pending_sanctions::pending_sanctions_checker())
|
||||
.without_state(all_joined_channels::all_channels_provider())
|
||||
.without_state(polariton_server::operations::Ack::<12, _>::default())
|
||||
//.without_state(polariton_server::operations::Ack::<00000, _>::default())
|
||||
}
|
||||
|
||||
@@ -15,3 +15,4 @@ base64 = "0.22"
|
||||
hex = "0.4"
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
chrono = "0.4"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
RUST_BACKTRACE=1 RUST_LOG=debug cargo run
|
||||
RUST_BACKTRACE=1 RUST_LOG=debug cargo run #&> ../data/rc_services_room.log
|
||||
|
||||
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> {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
import re
|
||||
|
||||
# weapon required data
|
||||
WEAPONS = {
|
||||
@@ -203,6 +205,16 @@ def guess_type(category: str) -> str:
|
||||
else:
|
||||
return "NotAFunctionalItem"
|
||||
|
||||
TIERS = [
|
||||
"NoTier",
|
||||
"T0",
|
||||
"T1",
|
||||
"T2",
|
||||
"T3",
|
||||
"T4",
|
||||
"T5",
|
||||
]
|
||||
|
||||
def guess_tier(name: str, sprite: str) -> str:
|
||||
if guess_category(name, sprite) == "NotAFunctionalItem" and "medium" in name.lower(): # Medium cube variants
|
||||
return "NoTier"
|
||||
@@ -288,19 +300,134 @@ def is_variant_guess(name: str, sprite: str) -> bool:
|
||||
return True
|
||||
return False
|
||||
|
||||
def main():
|
||||
print(sys.argv)
|
||||
filename_in = sys.argv[1]
|
||||
with open(filename_in) as f:
|
||||
FIELD_NAME_EXCEPTIONS = {
|
||||
"verticalTopSpeed": "max_vertical_velocity",
|
||||
}
|
||||
|
||||
def rename_field(original: str) -> str:
|
||||
if original in FIELD_NAME_EXCEPTIONS:
|
||||
return FIELD_NAME_EXCEPTIONS[original]
|
||||
else:
|
||||
return camel_to_snake_case(original)
|
||||
|
||||
SEEN_MOVEMENTS = {}
|
||||
|
||||
SEEN_WEAPONS = {}
|
||||
|
||||
EXCLUDED_FIELDS = [
|
||||
"T0",
|
||||
"T1",
|
||||
"T2",
|
||||
"T3",
|
||||
"T4",
|
||||
"T5",
|
||||
]
|
||||
|
||||
def apply_entry_overrides(entry: dict, cubes_data: dict, weapons_data: dict, movement_data: dict):
|
||||
if cubes_data is not None:
|
||||
if entry["hexId"] in cubes_data:
|
||||
cube_data = cubes_data[entry["hexId"]]
|
||||
entry["info"]["description"] = cube_data["Description"]
|
||||
entry["info"]["health"] = cube_data["health"]
|
||||
entry["info"]["cpu"] = cube_data["cpuRating"]
|
||||
entry["info"]["visibility"] = cube_data["buildVisibility"]
|
||||
entry["info"]["ranking"] = cube_data["robotRanking"]
|
||||
if "ItemSize" in cube_data:
|
||||
entry["info"]["size"] = cube_data["ItemSize"]
|
||||
if "ItemType" in cube_data:
|
||||
entry["info"]["type"] = cube_data["ItemType"]
|
||||
if "ItemCategory" in cube_data:
|
||||
entry["info"]["category"] = cube_data["ItemCategory"]
|
||||
if "PlacementFaces" in cube_data:
|
||||
entry["info"]["placements"] = cube_data["PlacementFaces"]
|
||||
if movement_data is not None and not entry["isVariant"]:
|
||||
if entry["info"]["category"] in movement_data["Movements"]:
|
||||
if entry["info"]["size"] in movement_data["Movements"][entry["info"]["category"]]:
|
||||
if entry["info"]["category"] not in SEEN_MOVEMENTS:
|
||||
SEEN_MOVEMENTS[entry["info"]["category"]] = dict()
|
||||
SEEN_MOVEMENTS[entry["info"]["category"]][entry["info"]["size"]] = True
|
||||
specific_data = movement_data["Movements"][entry["info"]["category"]][entry["info"]["size"]]
|
||||
if "movement" not in entry:
|
||||
entry["movement"] = dict()
|
||||
for (key, val) in specific_data.items():
|
||||
entry["movement"][rename_field(key)] = specific_data[key]
|
||||
entry["movement"]["movement_enum_variant"] = entry["info"]["category"]
|
||||
if weapons_data is not None and not entry["isVariant"]:
|
||||
weapon_key = entry["info"]["size"] + "_" + entry["info"]["category"]
|
||||
if weapon_key in weapons_data:
|
||||
if weapon_key in SEEN_WEAPONS:
|
||||
print("WARN: Already seen weapon key", weapon_key)
|
||||
SEEN_WEAPONS[weapon_key] = True
|
||||
if "weapon" not in entry:
|
||||
entry["weapon"] = dict()
|
||||
for (key, val) in weapons_data[weapon_key].items():
|
||||
entry["weapon"][rename_field(key)] = val
|
||||
|
||||
def apply_global_overrides(conf: dict, cubes_data: dict, weapons_data: dict, movement_data: dict):
|
||||
if movement_data is not None:
|
||||
if "movement" not in conf:
|
||||
conf["movement"] = dict()
|
||||
for (category, cat_setting) in movement_data["Movements"].items():
|
||||
if category not in conf["movement"]:
|
||||
conf["movement"][category] = dict()
|
||||
for (field, setting) in cat_setting.items():
|
||||
if field not in EXCLUDED_FIELDS:
|
||||
conf["movement"][category][rename_field(field)] = setting
|
||||
conf["movement"][category]["movement_enum_variant"] = category
|
||||
|
||||
def load_or_none(file_json):
|
||||
if file_json is None:
|
||||
return None
|
||||
else:
|
||||
with open(file_json) as f:
|
||||
return json.load(f)
|
||||
|
||||
CAMEL_TO_SNAKE_PATTERN = re.compile(r'(?<!^)(?=[A-Z])')
|
||||
|
||||
def camel_to_snake_case(s: str) -> str:
|
||||
return CAMEL_TO_SNAKE_PATTERN.sub('_', s).lower()
|
||||
|
||||
def main(asset_in, cubes=None, weapons=None, movement=None):
|
||||
cubes_data = load_or_none(cubes)
|
||||
weapons_data = load_or_none(weapons)
|
||||
movement_data = load_or_none(movement)
|
||||
with open(asset_in) as f:
|
||||
cubes_asset = json.load(f)
|
||||
|
||||
name = cubes_asset["0 MonoBehaviour Base"]["1 string m_Name"]
|
||||
print(f"found name (expected to be empty): `{name}`")
|
||||
cubes = cubes_asset["0 MonoBehaviour Base"]["0 CubeTypeData cubeTypes"]["0 Array Array"]
|
||||
print(f"found {len(cubes)} cubes to process")
|
||||
cubes_out = {
|
||||
conf_out = {
|
||||
"cubes": dict(),
|
||||
"movement": dict(),
|
||||
"lerp_value": 10.0,
|
||||
"lerp_value": 0.1,
|
||||
"battle": {
|
||||
"regen": {
|
||||
"wait_for_heal_s": 5.0,
|
||||
"wait_full_heal_s": 5.0,
|
||||
"sound_start_s": 2.5,
|
||||
"auto_heal": True,
|
||||
},
|
||||
"votes": {
|
||||
"BestPlayed": [
|
||||
{
|
||||
"name": "Best Played",
|
||||
"localised_name": "strBestPlayed",
|
||||
"color": "0000ff",
|
||||
"votes_required": 1,
|
||||
}
|
||||
],
|
||||
"BestLooking": [
|
||||
{
|
||||
"name": "Best Looking",
|
||||
"localised_name": "strBestLooking",
|
||||
"color": "ff0000",
|
||||
"votes_required": 2,
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
last_tech_tree_id = 0
|
||||
tech_tree_index = 0
|
||||
@@ -346,6 +473,7 @@ def main():
|
||||
"nameStrKey": cube["1 string nameStrKey"],
|
||||
"mirrorCubeId": cube["0 PersistentCubeData cubeData"]["1 string mirrorCubeId"],
|
||||
"hexId": str(cube["1 string itemCode"]),
|
||||
"isVariant": is_variant_guess(cube["1 string nameStrKey"], cube["1 string spriteName"]),
|
||||
}
|
||||
if "protonium" in name.lower():
|
||||
new_entry["info"]["protonium"] = True
|
||||
@@ -364,7 +492,7 @@ def main():
|
||||
else:
|
||||
new_entry["info"]["description"] += " (" + str(cube["0 unsigned int itemCodeValue"]) + "_10|" + str(cube["1 string itemCode"]) + "_16)"
|
||||
|
||||
is_original = not is_variant_guess(cube["1 string nameStrKey"], cube["1 string spriteName"])
|
||||
is_original = not new_entry["isVariant"]
|
||||
# weapons
|
||||
if new_entry["info"]["type"] == "Weapon":
|
||||
if is_original and "module" not in new_entry["info"]["category"].lower(): # ignore variants and modules
|
||||
@@ -410,11 +538,36 @@ def main():
|
||||
}
|
||||
tech_tree_specials_index += 1
|
||||
|
||||
# overrides
|
||||
apply_entry_overrides(new_entry, cubes_data, weapons_data, movement_data)
|
||||
|
||||
print(f"processed cube {i} into {new_entry}")
|
||||
cubes_out["cubes"][new_key] = new_entry
|
||||
with open("../assets/robocraft/cubes.json", "w") as f:
|
||||
json.dump(cubes_out, f, indent=4)
|
||||
conf_out["cubes"][new_key] = new_entry
|
||||
# more overrides
|
||||
apply_global_overrides(conf_out, cubes_data, weapons_data, movement_data)
|
||||
with open("../assets/robocraft/config.json", "w") as f:
|
||||
json.dump(conf_out, f, indent=4)
|
||||
print(f"processed {len(cubes)} cubes")
|
||||
if movement_data is not None:
|
||||
for category in CATEGORIES[1:13]:
|
||||
if category not in SEEN_MOVEMENTS:
|
||||
print("Missed movement category", category)
|
||||
else:
|
||||
if len(SEEN_MOVEMENTS[category]) != len(TIERS) - 1:
|
||||
print("Only found", len(SEEN_MOVEMENTS[category]), "of", len(TIERS) - 1, "tiers for movement category", category)
|
||||
'''for tier in TIERS[1:]:
|
||||
if tier not in SEEN_MOVEMENTS[category] or SEEN_MOVEMENTS[category][tier] == False:
|
||||
print("Missed movement tier", tier, "in category", category)'''
|
||||
if weapons_data is not None:
|
||||
if len(weapons_data) != len(SEEN_WEAPONS):
|
||||
print("Only found", len(SEEN_WEAPONS), "of", len(weapons_data), "weapon entries in reference")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("asset_json")
|
||||
parser.add_argument("--cubes")
|
||||
parser.add_argument("--weapons")
|
||||
parser.add_argument("--movement")
|
||||
args = parser.parse_args()
|
||||
main(args.asset_json, cubes=args.cubes, weapons=args.weapons, movement=args.movement)
|
||||
|
||||
Reference in New Issue
Block a user