use std::{borrow::Cow, str::FromStr};
use num_derive::FromPrimitive;
use parse_display::FromStr;
use serde::{
de::{Deserializer, Error as _, Unexpected},
Deserialize, Serialize, Serializer,
};
use serde_repr::{Deserialize_repr, Serialize_repr};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr, FromStr)]
#[repr(u8)]
#[display(style = "camelCase")]
pub enum StructureType {
Spawn = 0,
Extension = 1,
Road = 2,
Wall = 3,
Rampart = 4,
KeeperLair = 5,
Portal = 6,
Controller = 7,
Link = 8,
Storage = 9,
Tower = 10,
Observer = 11,
PowerBank = 12,
PowerSpawn = 13,
Extractor = 14,
Lab = 15,
Terminal = 16,
Container = 17,
Nuker = 18,
Factory = 19,
InvaderCore = 20,
}
impl StructureType {
#[inline]
pub fn construction_cost(self) -> Option<u32> {
use self::StructureType::*;
let cost = match self {
Spawn => 15_000,
Extension => 3_000,
Road => 300,
Wall => 1,
Rampart => 1,
Link => 5_000,
Storage => 30_000,
Tower => 5_000,
Observer => 8_000,
PowerSpawn => 100_000,
Extractor => 5_000,
Lab => 50_000,
Terminal => 100_000,
Container => 5_000,
Nuker => 100_000,
Factory => 100_000,
KeeperLair | PowerBank | Portal | Controller | InvaderCore => return None,
};
Some(cost)
}
#[inline]
pub fn initial_hits(self) -> Option<u32> {
use self::StructureType::*;
use super::numbers::*;
let hits = match self {
Spawn => SPAWN_HITS,
Extension => EXTENSION_HITS,
Road => ROAD_HITS,
Wall => WALL_HITS,
Rampart => RAMPART_HITS,
Link => LINK_HITS,
Storage => STORAGE_HITS,
Tower => TOWER_HITS,
Observer => OBSERVER_HITS,
PowerBank => POWER_BANK_HITS,
PowerSpawn => POWER_SPAWN_HITS,
Extractor => EXTENSION_HITS,
Lab => LAB_HITS,
Terminal => TOWER_HITS,
Container => CONTAINER_HITS,
Nuker => NUKER_HITS,
Factory => FACTORY_HITS,
InvaderCore => INVADER_CORE_HITS,
KeeperLair | Portal | Controller => return None,
};
Some(hits)
}
pub fn deserialize_from_str<'de, D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let s: Cow<'de, str> = Cow::deserialize(d)?;
Self::from_str(&s).map_err(|_| {
D::Error::invalid_value(Unexpected::Str(&s), &"a known STRUCTURE_* constant string")
})
}
}
js_deserializable!(StructureType);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr, FromStr)]
#[repr(u16)]
pub enum IntershardResourceType {
#[display("token")]
SubscriptionToken = 1001,
}
impl IntershardResourceType {
pub fn deserialize_from_str<'de, D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let s: Cow<'de, str> = Cow::deserialize(d)?;
Self::from_str(&s).map_err(|_| {
D::Error::invalid_value(
Unexpected::Str(&s),
&"a known constant string in INTERSHARD_RESOURCES",
)
})
}
}
js_deserializable!(IntershardResourceType);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr, FromStr)]
#[repr(u16)]
pub enum ResourceType {
#[display("energy")]
Energy = 1,
#[display("power")]
Power = 2,
#[display("H")]
Hydrogen = 3,
#[display("O")]
Oxygen = 4,
#[display("U")]
Utrium = 5,
#[display("L")]
Lemergium = 6,
#[display("K")]
Keanium = 7,
#[display("Z")]
Zynthium = 8,
#[display("X")]
Catalyst = 9,
#[display("G")]
Ghodium = 10,
#[display("OH")]
Hydroxide = 11,
#[display("ZK")]
ZynthiumKeanite = 12,
#[display("UL")]
UtriumLemergite = 13,
#[display("UH")]
UtriumHydride = 14,
#[display("UO")]
UtriumOxide = 15,
#[display("KH")]
KeaniumHydride = 16,
#[display("KO")]
KeaniumOxide = 17,
#[display("LH")]
LemergiumHydride = 18,
#[display("LO")]
LemergiumOxide = 19,
#[display("ZH")]
ZynthiumHydride = 20,
#[display("ZO")]
ZynthiumOxide = 21,
#[display("GH")]
GhodiumHydride = 22,
#[display("GO")]
GhodiumOxide = 23,
#[display("UH2O")]
UtriumAcid = 24,
#[display("UHO2")]
UtriumAlkalide = 25,
#[display("KH2O")]
KeaniumAcid = 26,
#[display("KHO2")]
KeaniumAlkalide = 27,
#[display("LH2O")]
LemergiumAcid = 28,
#[display("LHO2")]
LemergiumAlkalide = 29,
#[display("ZH2O")]
ZynthiumAcid = 30,
#[display("ZHO2")]
ZynthiumAlkalide = 31,
#[display("GH2O")]
GhodiumAcid = 32,
#[display("GHO2")]
GhodiumAlkalide = 33,
#[display("XUH2O")]
CatalyzedUtriumAcid = 34,
#[display("XUHO2")]
CatalyzedUtriumAlkalide = 35,
#[display("XKH2O")]
CatalyzedKeaniumAcid = 36,
#[display("XKHO2")]
CatalyzedKeaniumAlkalide = 37,
#[display("XLH2O")]
CatalyzedLemergiumAcid = 38,
#[display("XLHO2")]
CatalyzedLemergiumAlkalide = 39,
#[display("XZH2O")]
CatalyzedZynthiumAcid = 40,
#[display("XZHO2")]
CatalyzedZynthiumAlkalide = 41,
#[display("XGH2O")]
CatalyzedGhodiumAcid = 42,
#[display("XGHO2")]
CatalyzedGhodiumAlkalide = 43,
#[display("ops")]
Ops = 44,
#[display("silicon")]
Silicon = 45,
#[display("metal")]
Metal = 46,
#[display("biomass")]
Biomass = 47,
#[display("mist")]
Mist = 48,
#[display("utrium_bar")]
UtriumBar = 49,
#[display("lemergium_bar")]
LemergiumBar = 50,
#[display("zynthium_bar")]
ZynthiumBar = 51,
#[display("keanium_bar")]
KeaniumBar = 52,
#[display("ghodium_melt")]
GhodiumMelt = 53,
#[display("oxidant")]
Oxidant = 54,
#[display("reductant")]
Reductant = 55,
#[display("purifier")]
Purifier = 56,
#[display("battery")]
Battery = 57,
#[display("composite")]
Composite = 58,
#[display("crystal")]
Crystal = 59,
#[display("liquid")]
Liquid = 60,
#[display("wire")]
Wire = 61,
#[display("switch")]
Switch = 62,
#[display("transistor")]
Transistor = 63,
#[display("microchip")]
Microchip = 64,
#[display("circuit")]
Circuit = 65,
#[display("device")]
Device = 66,
#[display("cell")]
Cell = 67,
#[display("phlegm")]
Phlegm = 68,
#[display("tissue")]
Tissue = 69,
#[display("muscle")]
Muscle = 70,
#[display("organoid")]
Organoid = 71,
#[display("organism")]
Organism = 72,
#[display("alloy")]
Alloy = 73,
#[display("tube")]
Tube = 74,
#[display("fixtures")]
Fixtures = 75,
#[display("frame")]
Frame = 76,
#[display("hydraulics")]
Hydraulics = 77,
#[display("machine")]
Machine = 78,
#[display("condensate")]
Condensate = 79,
#[display("concentrate")]
Concentrate = 80,
#[display("extract")]
Extract = 81,
#[display("spirit")]
Spirit = 82,
#[display("emanation")]
Emanation = 83,
#[display("essence")]
Essence = 84,
}
#[derive(Copy, Clone, Debug)]
pub enum Boost {
Harvest(f64),
BuildAndRepair(f64),
Dismantle(f64),
UpgradeController(f64),
Attack(f64),
RangedAttack(f64),
Heal(f64),
Carry(f64),
Move(f64),
Tough(f64),
}
impl ResourceType {
#[inline]
pub fn boost(self) -> Option<Boost> {
use ResourceType::*;
let boost = match self {
UtriumHydride => Boost::Attack(2.0),
UtriumAcid => Boost::Attack(3.0),
CatalyzedUtriumAcid => Boost::Attack(4.0),
UtriumOxide => Boost::Harvest(3.0),
UtriumAlkalide => Boost::Harvest(5.0),
CatalyzedUtriumAlkalide => Boost::Harvest(7.0),
KeaniumHydride => Boost::Carry(2.0),
KeaniumAcid => Boost::Carry(3.0),
CatalyzedKeaniumAcid => Boost::Carry(4.0),
KeaniumOxide => Boost::RangedAttack(2.0),
KeaniumAlkalide => Boost::RangedAttack(4.0),
CatalyzedKeaniumAlkalide => Boost::RangedAttack(4.0),
LemergiumHydride => Boost::BuildAndRepair(1.5),
LemergiumAcid => Boost::BuildAndRepair(1.8),
CatalyzedLemergiumAcid => Boost::BuildAndRepair(2.0),
LemergiumOxide => Boost::Heal(2.0),
LemergiumAlkalide => Boost::Heal(3.0),
CatalyzedLemergiumAlkalide => Boost::Heal(4.0),
ZynthiumHydride => Boost::Dismantle(2.0),
ZynthiumAcid => Boost::Dismantle(3.0),
CatalyzedZynthiumAcid => Boost::Dismantle(4.0),
ZynthiumOxide => Boost::Move(2.0),
ZynthiumAlkalide => Boost::Move(3.0),
CatalyzedZynthiumAlkalide => Boost::Move(4.0),
GhodiumHydride => Boost::UpgradeController(1.5),
GhodiumAcid => Boost::UpgradeController(1.8),
CatalyzedGhodiumAcid => Boost::UpgradeController(2.0),
GhodiumOxide => Boost::Tough(0.7),
GhodiumAlkalide => Boost::Tough(0.5),
CatalyzedGhodiumAlkalide => Boost::Tough(0.3),
_ => return None,
};
Some(boost)
}
pub fn deserialize_from_str<'de, D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let s: Cow<'de, str> = Cow::deserialize(d)?;
Self::from_str(&s).map_err(|_| {
D::Error::invalid_value(
Unexpected::Str(&s),
&"a known constant string in RESOURCES_ALL",
)
})
}
}
js_deserializable!(ResourceType);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum MarketResourceType {
Resource(ResourceType),
IntershardResource(IntershardResourceType),
}
impl MarketResourceType {
pub fn deserialize_from_str<'de, D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let s: Cow<'de, str> = Cow::deserialize(d)?;
ResourceType::from_str(&s)
.map(|ty| MarketResourceType::Resource(ty))
.or(IntershardResourceType::from_str(&s)
.map(|ty| MarketResourceType::IntershardResource(ty)))
.map_err(|_| {
D::Error::invalid_value(
Unexpected::Str(&s),
&"a known constant string in RESOURCES_ALL or INTERSHARD_RESOURCES",
)
})
}
}
impl<'de> Deserialize<'de> for MarketResourceType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let resource = u16::deserialize(deserializer)?;
let resource_type = match resource {
1 => MarketResourceType::Resource(ResourceType::Energy),
2 => MarketResourceType::Resource(ResourceType::Power),
3 => MarketResourceType::Resource(ResourceType::Hydrogen),
4 => MarketResourceType::Resource(ResourceType::Oxygen),
5 => MarketResourceType::Resource(ResourceType::Utrium),
6 => MarketResourceType::Resource(ResourceType::Lemergium),
7 => MarketResourceType::Resource(ResourceType::Keanium),
8 => MarketResourceType::Resource(ResourceType::Zynthium),
9 => MarketResourceType::Resource(ResourceType::Catalyst),
10 => MarketResourceType::Resource(ResourceType::Ghodium),
11 => MarketResourceType::Resource(ResourceType::Hydroxide),
12 => MarketResourceType::Resource(ResourceType::ZynthiumKeanite),
13 => MarketResourceType::Resource(ResourceType::UtriumLemergite),
14 => MarketResourceType::Resource(ResourceType::UtriumHydride),
15 => MarketResourceType::Resource(ResourceType::UtriumOxide),
16 => MarketResourceType::Resource(ResourceType::KeaniumHydride),
17 => MarketResourceType::Resource(ResourceType::KeaniumOxide),
18 => MarketResourceType::Resource(ResourceType::LemergiumHydride),
19 => MarketResourceType::Resource(ResourceType::LemergiumOxide),
20 => MarketResourceType::Resource(ResourceType::ZynthiumHydride),
21 => MarketResourceType::Resource(ResourceType::ZynthiumOxide),
22 => MarketResourceType::Resource(ResourceType::GhodiumHydride),
23 => MarketResourceType::Resource(ResourceType::GhodiumOxide),
24 => MarketResourceType::Resource(ResourceType::UtriumAcid),
25 => MarketResourceType::Resource(ResourceType::UtriumAlkalide),
26 => MarketResourceType::Resource(ResourceType::KeaniumAcid),
27 => MarketResourceType::Resource(ResourceType::KeaniumAlkalide),
28 => MarketResourceType::Resource(ResourceType::LemergiumAcid),
29 => MarketResourceType::Resource(ResourceType::LemergiumAlkalide),
30 => MarketResourceType::Resource(ResourceType::ZynthiumAcid),
31 => MarketResourceType::Resource(ResourceType::ZynthiumAlkalide),
32 => MarketResourceType::Resource(ResourceType::GhodiumAcid),
33 => MarketResourceType::Resource(ResourceType::GhodiumAlkalide),
34 => MarketResourceType::Resource(ResourceType::CatalyzedUtriumAcid),
35 => MarketResourceType::Resource(ResourceType::CatalyzedUtriumAlkalide),
36 => MarketResourceType::Resource(ResourceType::CatalyzedKeaniumAcid),
37 => MarketResourceType::Resource(ResourceType::CatalyzedKeaniumAlkalide),
38 => MarketResourceType::Resource(ResourceType::CatalyzedLemergiumAcid),
39 => MarketResourceType::Resource(ResourceType::CatalyzedLemergiumAlkalide),
40 => MarketResourceType::Resource(ResourceType::CatalyzedZynthiumAcid),
41 => MarketResourceType::Resource(ResourceType::CatalyzedZynthiumAlkalide),
42 => MarketResourceType::Resource(ResourceType::CatalyzedGhodiumAcid),
43 => MarketResourceType::Resource(ResourceType::CatalyzedGhodiumAlkalide),
44 => MarketResourceType::Resource(ResourceType::Ops),
45 => MarketResourceType::Resource(ResourceType::Silicon),
46 => MarketResourceType::Resource(ResourceType::Metal),
47 => MarketResourceType::Resource(ResourceType::Biomass),
48 => MarketResourceType::Resource(ResourceType::Mist),
49 => MarketResourceType::Resource(ResourceType::UtriumBar),
50 => MarketResourceType::Resource(ResourceType::LemergiumBar),
51 => MarketResourceType::Resource(ResourceType::ZynthiumBar),
52 => MarketResourceType::Resource(ResourceType::KeaniumBar),
53 => MarketResourceType::Resource(ResourceType::GhodiumMelt),
54 => MarketResourceType::Resource(ResourceType::Oxidant),
55 => MarketResourceType::Resource(ResourceType::Reductant),
56 => MarketResourceType::Resource(ResourceType::Purifier),
57 => MarketResourceType::Resource(ResourceType::Battery),
58 => MarketResourceType::Resource(ResourceType::Composite),
59 => MarketResourceType::Resource(ResourceType::Crystal),
60 => MarketResourceType::Resource(ResourceType::Liquid),
61 => MarketResourceType::Resource(ResourceType::Wire),
62 => MarketResourceType::Resource(ResourceType::Switch),
63 => MarketResourceType::Resource(ResourceType::Transistor),
64 => MarketResourceType::Resource(ResourceType::Microchip),
65 => MarketResourceType::Resource(ResourceType::Circuit),
66 => MarketResourceType::Resource(ResourceType::Device),
67 => MarketResourceType::Resource(ResourceType::Cell),
68 => MarketResourceType::Resource(ResourceType::Phlegm),
69 => MarketResourceType::Resource(ResourceType::Tissue),
70 => MarketResourceType::Resource(ResourceType::Muscle),
71 => MarketResourceType::Resource(ResourceType::Organoid),
72 => MarketResourceType::Resource(ResourceType::Organism),
73 => MarketResourceType::Resource(ResourceType::Alloy),
74 => MarketResourceType::Resource(ResourceType::Tube),
75 => MarketResourceType::Resource(ResourceType::Fixtures),
76 => MarketResourceType::Resource(ResourceType::Frame),
77 => MarketResourceType::Resource(ResourceType::Hydraulics),
78 => MarketResourceType::Resource(ResourceType::Machine),
79 => MarketResourceType::Resource(ResourceType::Condensate),
80 => MarketResourceType::Resource(ResourceType::Concentrate),
81 => MarketResourceType::Resource(ResourceType::Extract),
82 => MarketResourceType::Resource(ResourceType::Spirit),
83 => MarketResourceType::Resource(ResourceType::Emanation),
84 => MarketResourceType::Resource(ResourceType::Essence),
1001 => {
MarketResourceType::IntershardResource(IntershardResourceType::SubscriptionToken)
}
_ => {
return Err(D::Error::invalid_value(
Unexpected::Unsigned(resource as u64),
&"a valid RESOURCES_ALL or INTERSHARD_RESOURCES type integer",
))
}
};
Ok(resource_type)
}
}
impl Serialize for MarketResourceType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
MarketResourceType::Resource(ty) => ty.serialize(serializer),
MarketResourceType::IntershardResource(ty) => ty.serialize(serializer),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr, FromStr)]
#[repr(u8)]
pub enum PowerCreepClass {
#[display("operator")]
Operator = 1,
}
js_deserializable!(PowerCreepClass);
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, FromPrimitive, Serialize_repr, Deserialize_repr,
)]
#[repr(u8)]
pub enum PowerType {
GenerateOps = 1,
OperateSpawn = 2,
OperateTower = 3,
OperateStorage = 4,
OperateLab = 5,
OperateExtension = 6,
OperateObserver = 7,
OperateTerminal = 8,
DisruptSpawn = 9,
DisruptTower = 10,
Shield = 12,
RegenSource = 13,
RegenMineral = 14,
DisruptTerminal = 15,
OperatePower = 16,
Fortify = 17,
OperateController = 18,
OperateFactory = 19,
}
js_deserializable!(PowerType);
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, FromPrimitive, Serialize_repr, Deserialize_repr,
)]
#[repr(u16)]
pub enum NaturalEffectType {
Invulnerability = 1001,
CollapseTimer = 1002,
}
js_deserializable!(NaturalEffectType);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum EffectType {
PowerEffect(PowerType),
NaturalEffect(NaturalEffectType),
}
impl<'de> Deserialize<'de> for EffectType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let effect = u16::deserialize(deserializer)?;
let effect_type = match effect {
1 => EffectType::PowerEffect(PowerType::GenerateOps),
2 => EffectType::PowerEffect(PowerType::OperateSpawn),
3 => EffectType::PowerEffect(PowerType::OperateTower),
4 => EffectType::PowerEffect(PowerType::OperateStorage),
5 => EffectType::PowerEffect(PowerType::OperateLab),
6 => EffectType::PowerEffect(PowerType::OperateExtension),
7 => EffectType::PowerEffect(PowerType::OperateObserver),
8 => EffectType::PowerEffect(PowerType::OperateTerminal),
9 => EffectType::PowerEffect(PowerType::DisruptSpawn),
10 => EffectType::PowerEffect(PowerType::DisruptTower),
12 => EffectType::PowerEffect(PowerType::Shield),
13 => EffectType::PowerEffect(PowerType::RegenSource),
14 => EffectType::PowerEffect(PowerType::RegenMineral),
15 => EffectType::PowerEffect(PowerType::DisruptTerminal),
16 => EffectType::PowerEffect(PowerType::OperatePower),
17 => EffectType::PowerEffect(PowerType::Fortify),
18 => EffectType::PowerEffect(PowerType::OperateController),
19 => EffectType::PowerEffect(PowerType::OperateFactory),
1001 => EffectType::NaturalEffect(NaturalEffectType::Invulnerability),
1002 => EffectType::NaturalEffect(NaturalEffectType::CollapseTimer),
_ => {
return Err(D::Error::invalid_value(
Unexpected::Unsigned(effect as u64),
&"a valid PWR_* or EFFECT_* type integer",
))
}
};
Ok(effect_type)
}
}