2025-03-15 11:03:35 -04:00
|
|
|
use polariton::operation::Typed;
|
|
|
|
|
|
2025-05-17 23:06:07 -04:00
|
|
|
#[async_trait::async_trait]
|
2025-03-30 17:54:06 -04:00
|
|
|
pub trait ConfigProvider<C: Clone> {
|
2025-03-15 11:03:35 -04:00
|
|
|
fn cube_list(&self) -> Typed<C>;
|
|
|
|
|
fn movement_list(&self) -> Typed<C>;
|
|
|
|
|
fn weapon_list(&self) -> Typed<C>;
|
|
|
|
|
fn weapon_upgrade_list(&self) -> Typed<C>;
|
2025-03-29 22:08:08 -04:00
|
|
|
fn weapon_keys(&self) -> Typed<C>;
|
2025-03-15 11:03:35 -04:00
|
|
|
fn tech_tree_nodes(&self, unlocked_cubes: &std::collections::HashSet<u32>) -> Typed<C>;
|
|
|
|
|
fn ids(&self) -> Vec<u32>;
|
2025-03-15 17:21:18 -04:00
|
|
|
fn regen_config(&self) -> Typed<C>;
|
|
|
|
|
fn after_battle_vote_config(&self) -> Typed<C>;
|
2025-03-18 16:47:11 -04:00
|
|
|
fn game_mode_config(&self) -> Typed<C>;
|
2025-03-29 22:08:08 -04:00
|
|
|
fn campaigns_parameters(&self) -> Typed<C>;
|
|
|
|
|
fn campaign_waves(&self) -> Typed<C>;
|
|
|
|
|
fn campaign_version(&self) -> Typed<C>;
|
|
|
|
|
fn campaign_details(&self) -> CompleteCampaignProvider;
|
2025-03-30 17:54:06 -04:00
|
|
|
fn client_config(&self) -> Typed<C>;
|
|
|
|
|
fn login_messages(&self) -> DevMessageProvider<C>;
|
2025-04-14 21:17:41 -04:00
|
|
|
fn public_channels(&self) -> Typed<C>;
|
2025-05-07 20:23:22 -04:00
|
|
|
fn server_config(&self) -> ServerConfig;
|
2025-05-11 12:09:23 -04:00
|
|
|
fn garage_upgrades(&self) -> GarageUpgrades;
|
2025-05-17 23:06:07 -04:00
|
|
|
async fn factory(&self) -> Result<crate::factory::Factory, Box<dyn std::error::Error + 'static>>;
|
2025-05-18 20:33:29 -04:00
|
|
|
fn cubes(&self) -> &'_ std::collections::HashMap<String, crate::persist::Cube>;
|
2025-05-23 16:46:12 -04:00
|
|
|
fn chat_system_config(&self) -> ChatSystemConfig;
|
2025-03-29 22:08:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct CompleteCampaignProvider {
|
|
|
|
|
map: std::collections::HashMap<String, std::collections::HashMap<i32, crate::data::campaign::CampaignWavesDifficultyData>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl CompleteCampaignProvider {
|
|
|
|
|
pub fn new(map: std::collections::HashMap<String, std::collections::HashMap<i32, crate::data::campaign::CampaignWavesDifficultyData>>) -> Self {
|
|
|
|
|
Self { map }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get<C>(&self, id: &str, difficulty: &i32) -> Result<Typed<C>, 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)
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-03-15 11:03:35 -04:00
|
|
|
}
|
2025-03-30 17:54:06 -04:00
|
|
|
|
|
|
|
|
pub struct DevMessageProvider<C: Clone> {
|
|
|
|
|
messages: Vec<TypedDevMessage<C>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl <C: Clone> DevMessageProvider<C> {
|
|
|
|
|
pub fn new(messages: Vec<(String, i32)>) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
messages: messages.into_iter().map(|(msg, time)| {
|
|
|
|
|
let bytes: Vec<u8> = msg.as_bytes().into();
|
|
|
|
|
TypedDevMessage {
|
|
|
|
|
message: Typed::Bytes(bytes.into()),
|
|
|
|
|
display_time: Typed::Int(time),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
).collect(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get(&self, index: usize) -> TypedDevMessage<C> {
|
|
|
|
|
// TODO maybe make this less obtuse -- it works for random, but isn't really obvious for anything else
|
|
|
|
|
if self.messages.is_empty() {
|
2025-05-18 22:23:33 -04:00
|
|
|
self.get_empty()
|
2025-03-30 17:54:06 -04:00
|
|
|
} 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()
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-18 22:23:33 -04:00
|
|
|
|
|
|
|
|
pub fn get_empty(&self) -> TypedDevMessage<C> {
|
|
|
|
|
TypedDevMessage {
|
|
|
|
|
message: Typed::Bytes(Vec::default().into()),
|
|
|
|
|
display_time: Typed::Int(-1),
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-03-30 17:54:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct TypedDevMessage<C> {
|
|
|
|
|
pub message: Typed<C>,
|
|
|
|
|
pub display_time: Typed<C>,
|
|
|
|
|
}
|
2025-05-07 20:23:22 -04:00
|
|
|
|
|
|
|
|
pub struct ServerConfig {
|
|
|
|
|
pub database: String,
|
2025-05-12 20:56:24 -04:00
|
|
|
pub auto_signup: bool,
|
2025-05-07 20:23:22 -04:00
|
|
|
}
|
2025-05-11 12:09:23 -04:00
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct GarageUpgrades {
|
|
|
|
|
pub increments: Vec<GarageUpgradeIncrement>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct GarageUpgradeIncrement {
|
|
|
|
|
pub cpu: u32,
|
|
|
|
|
pub cost: u32,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl GarageUpgrades {
|
|
|
|
|
pub fn slot_upgrades<C>(&self) -> Typed<C> {
|
|
|
|
|
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())
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-23 16:46:12 -04:00
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
pub struct ChatSystemConfig {
|
|
|
|
|
pub command_channel: String,
|
|
|
|
|
pub commands: Vec<crate::persist::ChatCommand>,
|
|
|
|
|
}
|