diff --git a/src/bot.rs b/src/bot.rs index 86959eb..cccd1e7 100644 --- a/src/bot.rs +++ b/src/bot.rs @@ -16,10 +16,7 @@ use veloren_common::{ clock::Clock, comp::{ invite::InviteKind, - item::{ - modular, ItemBase, ItemDef, ItemDefinitionId, ItemDefinitionIdOwned, ItemDesc, - ItemI18n, MaterialStatManifest, - }, + item::{ItemDefinitionId, ItemDesc, ItemI18n, MaterialStatManifest}, slot::InvSlotId, tool::AbilityMap, ChatType, ControllerInputs, Item, Ori, Pos, @@ -33,7 +30,7 @@ use veloren_common::{ }; use veloren_common_net::sync::WorldSyncExt; -use crate::PriceList; +use crate::config::PriceList; const COINS: &str = "common.items.utility.coins"; const COINS_ID: ItemDefinitionId = ItemDefinitionId::Simple(Cow::Borrowed(COINS)); diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..fa2d12b --- /dev/null +++ b/src/config.rs @@ -0,0 +1,162 @@ +use hashbrown::HashMap; +use serde::{de::Visitor, Deserialize}; +use veloren_common::comp::item::{ItemDefinitionIdOwned, Material}; + +#[derive(Deserialize)] +pub struct Config { + pub game_server: Option, + pub auth_server: Option, + pub position: Option<[f32; 3]>, + pub orientation: Option, + pub announcement: Option, + pub buy_prices: PriceList, + pub sell_prices: PriceList, +} + +#[derive(Deserialize)] +pub struct Secrets { + pub username: String, + pub password: String, + pub character: String, + pub admins: Vec, +} + +pub struct PriceList { + pub simple: HashMap, + pub modular: Vec, +} + +impl<'de> Deserialize<'de> for PriceList { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_map(PriceListVisitor) + } +} + +pub struct PriceListVisitor; + +impl<'de> Visitor<'de> for PriceListVisitor { + type Value = PriceList; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a map with simple and/or modular keys") + } + + fn visit_map(self, mut map: A) -> Result + where + A: serde::de::MapAccess<'de>, + { + let mut simple = None; + let mut modular = None; + + while let Some(key) = map.next_key::()? { + match key.as_str() { + "simple" => { + let simple_prices_with_item_string = + map.next_value::>()?; + let simple_prices_with_item_id = simple_prices_with_item_string + .into_iter() + .map(|(mut key, value)| { + key.insert_str(0, "common.items."); + + (ItemDefinitionIdOwned::Simple(key), value) + }) + .collect(); + + simple = Some(simple_prices_with_item_id); + } + "modular" => { + modular = Some(map.next_value()?); + } + _ => { + return Err(serde::de::Error::unknown_field( + &key, + &["simple", "modular"], + )); + } + } + } + + Ok(PriceList { + simple: simple.ok_or_else(|| serde::de::Error::missing_field("simple"))?, + modular: modular.ok_or_else(|| serde::de::Error::missing_field("modular"))?, + }) + } +} + +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct ModularItemPrice { + pub material: Material, + pub primary: ItemDefinitionIdOwned, + pub secondary: ItemDefinitionIdOwned, + pub price: u32, +} + +impl<'de> Deserialize<'de> for ModularItemPrice { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_map(ModularPriceVisitor) + } +} + +struct ModularPriceVisitor; + +impl<'de> Visitor<'de> for ModularPriceVisitor { + type Value = ModularItemPrice; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a map with material, primary, secondary and price keys") + } + + fn visit_map(self, mut map: A) -> Result + where + A: serde::de::MapAccess<'de>, + { + let mut material = None; + let mut primary = None; + let mut secondary = None; + let mut price = None; + + while let Some(key) = map.next_key::()? { + match key.as_str() { + "material" => { + material = Some(map.next_value()?); + } + "primary" => { + let mut primary_string = map.next_value::()?; + + primary_string.insert_str(0, "common.items.modular.weapon.primary."); + + primary = Some(ItemDefinitionIdOwned::Simple(primary_string)); + } + "secondary" => { + let mut secondary_string = map.next_value::()?; + + secondary_string.insert_str(0, "common.items.modular.weapon.secondary."); + + secondary = Some(ItemDefinitionIdOwned::Simple(secondary_string)); + } + "price" => { + price = Some(map.next_value()?); + } + _ => { + return Err(serde::de::Error::unknown_field( + &key, + &["material", "primary", "secondary", "price"], + )); + } + } + } + + Ok(ModularItemPrice { + material: material.ok_or_else(|| serde::de::Error::missing_field("material"))?, + primary: primary.ok_or_else(|| serde::de::Error::missing_field("primary"))?, + secondary: secondary.ok_or_else(|| serde::de::Error::missing_field("secondary"))?, + price: price.ok_or_else(|| serde::de::Error::missing_field("price"))?, + }) + } +} diff --git a/src/main.rs b/src/main.rs index 0e14bbc..ef82600 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,172 +1,12 @@ #![feature(duration_constructors)] mod bot; +mod config; -use std::{borrow::Cow, env::var, fs::read_to_string, str::FromStr}; +use std::{env::var, fs::read_to_string}; use bot::Bot; -use hashbrown::HashMap; -use serde::{de::Visitor, Deserialize}; -use veloren_common::comp::item::{ItemDefinitionId, ItemDefinitionIdOwned, Material}; - -pub struct PriceList { - pub simple: HashMap, - pub modular: Vec, -} - -impl<'de> Deserialize<'de> for PriceList { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_map(PriceListVisitor) - } -} - -pub struct PriceListVisitor; - -impl<'de> Visitor<'de> for PriceListVisitor { - type Value = PriceList; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a map with simple and/or modular keys") - } - - fn visit_map(self, mut map: A) -> Result - where - A: serde::de::MapAccess<'de>, - { - let mut simple = None; - let mut modular = None; - - while let Some(key) = map.next_key::()? { - match key.as_str() { - "simple" => { - let simple_prices_with_item_string = - map.next_value::>()?; - let simple_prices_with_item_id = simple_prices_with_item_string - .into_iter() - .map(|(mut key, value)| { - key.insert_str(0, "common.items."); - - (ItemDefinitionIdOwned::Simple(key), value) - }) - .collect(); - - simple = Some(simple_prices_with_item_id); - } - "modular" => { - modular = Some(map.next_value()?); - } - _ => { - return Err(serde::de::Error::unknown_field( - &key, - &["simple", "modular"], - )); - } - } - } - - Ok(PriceList { - simple: simple.ok_or_else(|| serde::de::Error::missing_field("simple"))?, - modular: modular.ok_or_else(|| serde::de::Error::missing_field("modular"))?, - }) - } -} - -#[derive(Debug, PartialEq, Eq, Hash)] -pub struct ModularItemPrice { - pub material: Material, - pub primary: ItemDefinitionIdOwned, - pub secondary: ItemDefinitionIdOwned, - pub price: u32, -} - -impl<'de> Deserialize<'de> for ModularItemPrice { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_map(ModularPriceVisitor) - } -} - -struct ModularPriceVisitor; - -impl<'de> Visitor<'de> for ModularPriceVisitor { - type Value = ModularItemPrice; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a map with material, primary, secondary and price keys") - } - - fn visit_map(self, mut map: A) -> Result - where - A: serde::de::MapAccess<'de>, - { - let mut material = None; - let mut primary = None; - let mut secondary = None; - let mut price = None; - - while let Some(key) = map.next_key::()? { - match key.as_str() { - "material" => { - material = Some(map.next_value()?); - } - "primary" => { - let mut primary_string = map.next_value::()?; - - primary_string.insert_str(0, "common.items.modular.weapon.primary."); - - primary = Some(ItemDefinitionIdOwned::Simple(primary_string)); - } - "secondary" => { - let mut secondary_string = map.next_value::()?; - - secondary_string.insert_str(0, "common.items.modular.weapon.secondary."); - - secondary = Some(ItemDefinitionIdOwned::Simple(secondary_string)); - } - "price" => { - price = Some(map.next_value()?); - } - _ => { - return Err(serde::de::Error::unknown_field( - &key, - &["material", "primary", "secondary", "price"], - )); - } - } - } - - Ok(ModularItemPrice { - material: material.ok_or_else(|| serde::de::Error::missing_field("material"))?, - primary: primary.ok_or_else(|| serde::de::Error::missing_field("primary"))?, - secondary: secondary.ok_or_else(|| serde::de::Error::missing_field("secondary"))?, - price: price.ok_or_else(|| serde::de::Error::missing_field("price"))?, - }) - } -} - -#[derive(Deserialize)] -struct Config { - pub game_server: Option, - pub auth_server: Option, - pub position: Option<[f32; 3]>, - pub orientation: Option, - pub announcement: Option, - pub buy_prices: PriceList, - pub sell_prices: PriceList, -} - -#[derive(Deserialize)] -pub struct Secrets { - pub username: String, - pub password: String, - pub character: String, - pub admins: Vec, -} +use config::{Config, Secrets}; fn main() { env_logger::init();