1use std::collections::{BTreeMap, BTreeSet};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 items::{
7 ArmorSlot, DamageType, GatheringToolsType, Rarity, Restrictions, WeaponType, WeightClass,
8 },
9 misc::colors::ColorId,
10 BulkEndpoint, Endpoint, EndpointWithId,
11};
12
13pub type SkinId = u32;
14
15#[derive(Clone, PartialEq, Eq, PartialOrd, Debug, Serialize, Deserialize)]
16#[cfg_attr(test, serde(deny_unknown_fields))]
17pub enum SkinType {
18 Armor,
19 Back,
20 Gathering,
21 Weapon,
22}
23
24#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Serialize, Deserialize)]
25#[cfg_attr(test, serde(deny_unknown_fields))]
26pub enum Flags {
27 ShowInWardrobe,
29 NoCost,
31 HideIfLocked,
33 OverrideRarity,
35}
36
37#[derive(Clone, PartialEq, Eq, PartialOrd, Debug, Serialize, Deserialize)]
38#[serde(rename_all = "lowercase")]
39#[cfg_attr(test, serde(deny_unknown_fields))]
40pub enum Material {
41 Cloth,
42 Leather,
43 Metal,
44}
45
46#[derive(Clone, PartialEq, Eq, PartialOrd, Debug, Serialize, Deserialize)]
47#[cfg_attr(test, serde(deny_unknown_fields))]
48pub struct DyeSlot {
49 pub color_id: ColorId,
50 pub material: Material,
51}
52
53#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Serialize, Deserialize)]
54#[cfg_attr(test, serde(deny_unknown_fields))]
55pub enum RaceGender {
56 AsuraMale,
57 AsuraFemale,
58 CharrMale,
59 CharrFemale,
60 HumanMale,
61 HumanFemale,
62 NornMale,
63 NornFemale,
64 SylvariMale,
65 SylvariFemale,
66}
67
68#[derive(Clone, PartialEq, Eq, PartialOrd, Debug, Serialize, Deserialize)]
69#[cfg_attr(test, serde(deny_unknown_fields))]
70pub struct DyeSlots {
71 pub default: Vec<Option<DyeSlot>>,
72 pub overrides: BTreeMap<RaceGender, Vec<Option<DyeSlot>>>,
73}
74
75#[derive(Clone, PartialEq, PartialOrd, Debug, Serialize, Deserialize)]
76#[cfg_attr(test, serde(deny_unknown_fields))]
77pub struct ArmorDetails {
78 #[serde(rename = "type")]
79 pub _type: ArmorSlot,
80 pub weight_class: WeightClass,
81 pub dye_slots: Option<DyeSlots>,
82}
83
84#[derive(Clone, PartialEq, PartialOrd, Debug, Serialize, Deserialize)]
85#[cfg_attr(test, serde(deny_unknown_fields))]
86pub struct GatheringToolsDetails {
87 #[serde(rename = "type")]
88 pub _type: GatheringToolsType,
89}
90
91#[derive(Clone, PartialEq, PartialOrd, Debug, Serialize, Deserialize)]
92#[cfg_attr(test, serde(deny_unknown_fields))]
93pub struct WeaponDetails {
94 #[serde(rename = "type")]
95 pub _type: WeaponType,
96 pub damage_type: DamageType,
97}
98
99#[derive(Clone, PartialEq, PartialOrd, Debug, Serialize, Deserialize)]
100#[serde(tag = "type", content = "details")]
101#[cfg_attr(test, serde(deny_unknown_fields))]
102pub enum Details {
103 Armor(ArmorDetails),
104 Back,
105 Gathering(GatheringToolsDetails),
106 Weapon(WeaponDetails),
107}
108
109impl From<Details> for SkinType {
110 fn from(d: Details) -> Self {
111 match d {
112 Details::Armor(_) => SkinType::Armor,
113 Details::Back => SkinType::Back,
114 Details::Gathering(_) => SkinType::Gathering,
115 Details::Weapon(_) => SkinType::Weapon,
116 }
117 }
118}
119
120#[derive(Clone, PartialEq, PartialOrd, Debug, Serialize, Deserialize)]
121#[cfg_attr(test, serde(deny_unknown_fields))]
122pub struct Skin {
123 pub id: SkinId,
124 pub name: String,
125 pub icon: Option<String>,
126 pub description: Option<String>,
127 pub rarity: Rarity,
128 pub flags: BTreeSet<Flags>,
129 pub restrictions: BTreeSet<Restrictions>,
130 #[serde(flatten)]
131 pub details: Details,
132}
133
134impl EndpointWithId for Skin {
135 type IdType = SkinId;
136}
137
138impl Endpoint for Skin {
139 const AUTHENTICATED: bool = false;
140 const LOCALE: bool = true;
141 const URL: &'static str = "v2/skins";
142 const VERSION: &'static str = "2023-03-20T19:00:00.000Z";
143}
144
145impl BulkEndpoint for Skin {
146 const ALL: bool = false;
147
148 fn id(&self) -> &Self::IdType {
149 &self.id
150 }
151}