use polariton::operation::Typed; pub trait ConfigProvider { fn cube_list(&self) -> Typed; fn movement_list(&self) -> Typed; fn weapon_list(&self) -> Typed; fn weapon_upgrade_list(&self) -> Typed; fn weapon_keys(&self) -> Typed; fn tech_tree_nodes(&self, unlocked_cubes: &std::collections::HashSet) -> Typed; fn ids(&self) -> Vec; fn regen_config(&self) -> Typed; fn after_battle_vote_config(&self) -> Typed; fn game_mode_config(&self) -> Typed; fn campaigns_parameters(&self) -> Typed; fn campaign_waves(&self) -> Typed; fn campaign_version(&self) -> Typed; fn campaign_details(&self) -> CompleteCampaignProvider; fn client_config(&self) -> Typed; fn login_messages(&self) -> DevMessageProvider; fn public_channels(&self) -> Typed; fn server_config(&self) -> ServerConfig; fn garage_upgrades(&self) -> GarageUpgrades; } pub struct CompleteCampaignProvider { map: std::collections::HashMap>, } impl CompleteCampaignProvider { pub fn new(map: std::collections::HashMap>) -> Self { Self { map } } pub fn get(&self, id: &str, difficulty: &i32) -> Result, i16> { if let Some(campaign) = self.map.get(id) { if let Some(details) = campaign.get(difficulty) { Ok(details.as_transmissible()) } else { log::warn!("Couldn't find difficulty {} in campaign `{}`", difficulty, id); Err(crate::data::error_codes::WebServicesError::DatabaseError as i16) } } else { log::warn!("Couldn't find campaign {} (ignoring difficulty {})", id, difficulty); Err(crate::data::error_codes::WebServicesError::DatabaseError as i16) } } } pub struct DevMessageProvider { messages: Vec>, } impl DevMessageProvider { pub fn new(messages: Vec<(String, i32)>) -> Self { Self { messages: messages.into_iter().map(|(msg, time)| { let bytes: Vec = msg.as_bytes().into(); TypedDevMessage { message: Typed::Bytes(bytes.into()), display_time: Typed::Int(time), } } ).collect(), } } pub fn get(&self, index: usize) -> TypedDevMessage { // TODO maybe make this less obtuse -- it works for random, but isn't really obvious for anything else if self.messages.is_empty() { TypedDevMessage { message: Typed::Bytes(Vec::default().into()), display_time: Typed::Int(-1), } } else if self.messages.len() == 1 { self.messages[0].clone() } else { let actual_index = index % self.messages.len(); // guarantees index is within allowed range of messages self.messages[actual_index].clone() } } } #[derive(Clone, Debug)] pub struct TypedDevMessage { pub message: Typed, pub display_time: Typed, } pub struct ServerConfig { pub database: String, } #[derive(Clone, Debug)] pub struct GarageUpgrades { pub increments: Vec, } #[derive(Clone, Debug)] pub struct GarageUpgradeIncrement { pub cpu: u32, pub cost: u32, } impl GarageUpgrades { pub fn slot_upgrades(&self) -> Typed { Typed::HashMap(vec![ (Typed::Str("cpuIncreaseCost".into()), Typed::Dict(polariton::operation::Dict { key_ty: polariton::serdes::TypePrefix::Int, // int val_ty: polariton::serdes::TypePrefix::Int, // int // (CPU limit, upgrade cost) items: self.increments.iter().map(|inc| (Typed::Int(inc.cpu as _), Typed::Int(inc.cost as _))).collect(), })) ].into()) } }