gw2lib_model/authenticated/
characters.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5// todo: remove this pub use on next breaking version
6pub use crate::game_mechanics::pets::PetId;
7use crate::{
8    game_mechanics::{skills::SkillId, specializations::SpecializationId, traits::TraitId},
9    items::{itemstats::StatsId, recipes::RecipeId, skins::SkinId, AttributeType, ItemId},
10    misc::{colors::ColorId, titles::TitleId},
11    pvp::amulets::AmuletId,
12    wvw::abilities::AbilityId,
13    BulkEndpoint, Endpoint, EndpointWithId, TimeStamp,
14};
15
16pub type Age = u64;
17pub type CharacterId = String;
18pub type BackStoryId = String;
19
20#[derive(Clone, Debug, Serialize, Deserialize)]
21#[cfg_attr(test, serde(deny_unknown_fields))]
22pub struct Backstory {
23    pub backstory: Vec<BackStoryId>,
24}
25
26#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
27#[cfg_attr(test, serde(deny_unknown_fields))]
28pub enum Race {
29    Asura,
30    Charr,
31    Human,
32    Norn,
33    Sylvari,
34}
35
36#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
37#[cfg_attr(test, serde(deny_unknown_fields))]
38pub enum Gender {
39    Male,
40    Female,
41}
42
43#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
44#[cfg_attr(test, serde(deny_unknown_fields))]
45pub enum Profession {
46    Elementalist,
47    Engineer,
48    Guardian,
49    Mesmer,
50    Necromancer,
51    Ranger,
52    Revenant,
53    Thief,
54    Warrior,
55}
56
57#[derive(Clone, Debug, Serialize, Deserialize)]
58#[cfg_attr(test, serde(deny_unknown_fields))]
59pub struct Core {
60    pub name: CharacterId,
61    pub race: Race,
62    pub gender: Gender,
63    pub profession: Profession,
64    pub level: u8,
65    pub guild: Option<String>,
66    pub age: Age,
67    pub created: TimeStamp,
68    pub last_modified: TimeStamp,
69    pub deaths: u32,
70    pub title: Option<TitleId>,
71}
72
73#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
74#[cfg_attr(test, serde(deny_unknown_fields))]
75pub enum Discipline {
76    Armorsmith,
77    Artificer,
78    Chef,
79    Huntsman,
80    Jeweler,
81    Leatherworker,
82    Scribe,
83    Tailor,
84    Weaponsmith,
85    Homesteader,
86}
87
88#[derive(Clone, Debug, Serialize, Deserialize)]
89#[cfg_attr(test, serde(deny_unknown_fields))]
90pub struct Craft {
91    pub discipline: Discipline,
92    pub rating: u16,
93    pub active: bool,
94}
95
96#[derive(Clone, Debug, Serialize, Deserialize)]
97#[cfg_attr(test, serde(deny_unknown_fields))]
98pub struct Crafting {
99    pub crafting: Vec<Craft>,
100}
101
102#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
103#[cfg_attr(test, serde(deny_unknown_fields))]
104pub enum Slot {
105    HelmAquatic,
106    Backpack,
107    Coat,
108    Boots,
109    Gloves,
110    Helm,
111    Leggings,
112    Shoulders,
113    Accessory1,
114    Accessory2,
115    Ring1,
116    Ring2,
117    Amulet,
118    WeaponAquaticA,
119    WeaponAquaticB,
120    WeaponA1,
121    WeaponA2,
122    WeaponB1,
123    WeaponB2,
124    Sickle,
125    Axe,
126    Pick,
127    FishingRod,
128    FishingBait,
129    FishingLure,
130    PowerCore,
131    SensoryArray,
132    ServiceChip,
133    Relic,
134}
135
136#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Eq)]
137#[cfg_attr(test, serde(deny_unknown_fields))]
138pub struct Stats {
139    pub id: StatsId,
140    pub attributes: HashMap<AttributeType, u16>,
141}
142
143#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Eq)]
144#[cfg_attr(test, serde(deny_unknown_fields))]
145pub enum Binding {
146    Character,
147    Account,
148}
149
150#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
151#[cfg_attr(test, serde(deny_unknown_fields))]
152pub enum Location {
153    Equipped,
154    Armory,
155    EquippedFromLegendaryArmory,
156    LegendaryArmory,
157}
158
159#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Eq)]
160#[cfg_attr(test, serde(deny_unknown_fields))]
161pub struct Equip {
162    pub id: ItemId,
163    pub slot: Option<Slot>,
164    /// only present in character.equipment
165    pub count: Option<usize>,
166    pub infusions: Option<Vec<ItemId>>,
167    pub upgrades: Option<Vec<ItemId>>,
168    pub skin: Option<SkinId>,
169    pub stats: Option<Stats>,
170    pub binding: Option<Binding>,
171    pub location: Location,
172    pub charges: Option<u16>,
173    pub bound_to: Option<String>,
174    pub dyes: Option<Vec<Option<ColorId>>>,
175    /// only present in character.equipment
176    pub tabs: Option<Vec<usize>>,
177}
178
179#[derive(Clone, Debug, Serialize, Deserialize)]
180#[cfg_attr(test, serde(deny_unknown_fields))]
181pub struct Equipment {
182    pub equipment: Vec<Equip>,
183}
184
185#[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Eq)]
186#[cfg_attr(test, serde(deny_unknown_fields))]
187pub struct InventoryItem {
188    pub id: ItemId,
189    pub count: u8,
190    pub charges: Option<u8>,
191    pub infusions: Option<Vec<ItemId>>,
192    pub upgrades: Option<Vec<ItemId>>,
193    pub upgrade_slot_indices: Option<Vec<usize>>,
194    pub skin: Option<SkinId>,
195    pub stats: Option<Stats>,
196    pub binding: Option<Binding>,
197    pub bound_to: Option<String>,
198    pub dyes: Option<Vec<ColorId>>,
199}
200
201#[derive(Clone, Debug, Serialize, Deserialize)]
202#[cfg_attr(test, serde(deny_unknown_fields))]
203pub struct InventoryBag {
204    pub id: ItemId,
205    pub size: u8,
206    pub inventory: Vec<Option<InventoryItem>>,
207}
208
209#[derive(Clone, Debug, Serialize, Deserialize)]
210#[cfg_attr(test, serde(deny_unknown_fields))]
211pub struct Inventory {
212    pub bags: Vec<Option<InventoryBag>>,
213}
214
215pub type Utilities = [Option<SkillId>; 3];
216
217#[derive(Clone, Debug, Serialize, Deserialize)]
218#[cfg_attr(test, serde(deny_unknown_fields))]
219pub struct Skillset {
220    pub heal: Option<SkillId>,
221    pub utilities: Utilities,
222    pub elite: Option<SkillId>,
223    // TODO: legends enum
224    pub legends: Option<Vec<String>>,
225}
226
227#[derive(Clone, Debug, Serialize, Deserialize)]
228#[cfg_attr(test, serde(deny_unknown_fields))]
229pub struct SkillDataSet {
230    pub pve: Skillset,
231    pub pvp: Skillset,
232    pub wvw: Skillset,
233}
234
235pub type TraitSet = [Option<TraitId>; 3];
236
237#[derive(Clone, Debug, Serialize, Deserialize)]
238#[cfg_attr(test, serde(deny_unknown_fields))]
239pub struct TraitLine {
240    pub id: Option<SpecializationId>,
241    pub traits: Option<TraitSet>,
242}
243
244pub type Specialization = [Option<TraitLine>; 3];
245
246#[derive(Clone, Debug, Serialize, Deserialize)]
247#[cfg_attr(test, serde(deny_unknown_fields))]
248pub struct SpecializationSet {
249    pub pve: Specialization,
250    pub pvp: Specialization,
251    pub wvw: Specialization,
252}
253
254#[derive(Clone, Debug, Serialize, Deserialize)]
255#[cfg_attr(test, serde(deny_unknown_fields))]
256pub struct TrainingSet {
257    // TODO: training id
258    pub id: u64,
259    pub spent: u16,
260    pub done: bool,
261}
262
263#[derive(Clone, Debug, Serialize, Deserialize)]
264#[cfg_attr(test, serde(deny_unknown_fields))]
265pub struct Training {
266    pub training: Vec<TrainingSet>,
267}
268
269#[derive(Clone, Debug, Serialize, Deserialize)]
270#[cfg_attr(test, serde(deny_unknown_fields))]
271pub struct Recipes {
272    pub recipes: Vec<RecipeId>,
273}
274
275#[derive(Clone, Debug, Serialize, Deserialize)]
276#[cfg_attr(test, serde(deny_unknown_fields))]
277pub struct WvwAbility {
278    pub id: AbilityId,
279    pub rank: u8,
280}
281
282#[derive(Clone, Debug, Serialize, Deserialize)]
283#[cfg_attr(test, serde(deny_unknown_fields))]
284pub struct EquipmentPvp {
285    pub amulet: Option<AmuletId>,
286    pub rune: Option<ItemId>,
287    pub sigils: (
288        Option<ItemId>,
289        Option<ItemId>,
290        Option<ItemId>,
291        Option<ItemId>,
292    ),
293}
294
295#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
296#[cfg_attr(test, serde(deny_unknown_fields))]
297pub enum Flags {
298    Beta,
299}
300
301#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
302#[cfg_attr(test, serde(deny_unknown_fields))]
303pub struct BuildPets {
304    pub terrestrial: [Option<PetId>; 2],
305    pub aquatic: [Option<PetId>; 2],
306}
307
308#[derive(Clone, Debug, Serialize, Deserialize)]
309#[cfg_attr(test, serde(deny_unknown_fields))]
310pub struct BuildLegends {
311    pub legends: LegendSlots,
312    pub aquatic_legends: LegendSlots,
313}
314
315pub type LegendId = String;
316pub type LegendSlots = [Option<LegendId>; 2];
317
318#[derive(Clone, Debug, Serialize, Deserialize)]
319#[cfg_attr(test, serde(deny_unknown_fields))]
320pub struct BuildTemplate {
321    pub name: Option<String>,
322    pub profession: Option<Profession>,
323    pub specializations: [TraitLine; 3],
324    pub skills: Skillset,
325    pub aquatic_skills: Skillset,
326    pub pets: Option<BuildPets>,
327    pub legends: Option<LegendSlots>,
328    pub aquatic_legends: Option<LegendSlots>,
329}
330
331#[derive(Clone, Debug, Serialize, Deserialize)]
332#[cfg_attr(test, serde(deny_unknown_fields))]
333pub struct BuildTab {
334    /// this index starts at 1
335    pub tab: usize,
336    pub is_active: bool,
337    pub build: BuildTemplate,
338}
339
340#[derive(Clone, Debug, Serialize, Deserialize)]
341#[cfg_attr(test, serde(deny_unknown_fields))]
342pub struct EquipmentTab {
343    /// this index starts at 1
344    pub tab: usize,
345    pub name: String,
346    pub is_active: bool,
347    pub equipment: Vec<Equip>,
348    pub equipment_pvp: Option<EquipmentPvp>,
349}
350
351#[derive(Clone, Debug, Serialize, Deserialize)]
352#[cfg_attr(test, serde(deny_unknown_fields))]
353pub struct Character {
354    pub backstory: Vec<BackStoryId>,
355    #[serde(flatten)]
356    pub core: Core,
357    pub crafting: Vec<Craft>,
358    #[serde(default)]
359    pub equipment: Vec<Equip>,
360    #[serde(default)]
361    pub bags: Vec<Option<InventoryBag>>,
362    #[serde(default)]
363    pub recipes: Vec<RecipeId>,
364    #[serde(default)]
365    pub training: Vec<TrainingSet>,
366    #[serde(default)]
367    pub build_tabs: Vec<BuildTab>,
368    pub build_tabs_unlocked: Option<usize>,
369    pub active_build_tab: Option<usize>,
370    #[serde(default)]
371    pub equipment_tabs: Vec<EquipmentTab>,
372    pub equipment_tabs_unlocked: Option<usize>,
373    pub active_equipment_tab: Option<usize>,
374    #[serde(default)]
375    pub wvw_abilities: Vec<WvwAbility>,
376    pub flags: Vec<Flags>,
377}
378
379impl EndpointWithId for Character {
380    type IdType = CharacterId;
381}
382
383impl Endpoint for Character {
384    const AUTHENTICATED: bool = true;
385    const LOCALE: bool = false;
386    const URL: &'static str = "v2/characters";
387    const VERSION: &'static str = "2022-06-14T00:00:00.000Z";
388}
389
390impl BulkEndpoint for Character {
391    const ALL: bool = true;
392
393    fn id(&self) -> &Self::IdType {
394        &self.core.name
395    }
396}
397
398impl EndpointWithId for Core {
399    type IdType = CharacterId;
400
401    fn format_url(id: &str) -> String {
402        format!("{}/{}/core", Self::URL, id)
403    }
404}
405
406impl Endpoint for Core {
407    const AUTHENTICATED: bool = true;
408    const LOCALE: bool = false;
409    const URL: &'static str = "v2/characters";
410    const VERSION: &'static str = "2022-06-14T00:00:00.000Z";
411}
412
413impl EndpointWithId for Backstory {
414    type IdType = CharacterId;
415
416    fn format_url(id: &str) -> String {
417        format!("{}/{}/backstory", Self::URL, id)
418    }
419}
420
421impl Endpoint for Backstory {
422    const AUTHENTICATED: bool = true;
423    const LOCALE: bool = false;
424    const URL: &'static str = "v2/characters";
425    const VERSION: &'static str = "2022-06-14T00:00:00.000Z";
426}
427
428impl EndpointWithId for Crafting {
429    type IdType = CharacterId;
430
431    fn format_url(id: &str) -> String {
432        format!("{}/{}/crafting", Self::URL, id)
433    }
434}
435
436impl Endpoint for Crafting {
437    const AUTHENTICATED: bool = true;
438    const LOCALE: bool = false;
439    const URL: &'static str = "v2/characters";
440    const VERSION: &'static str = "2022-06-14T00:00:00.000Z";
441}
442
443impl EndpointWithId for Equipment {
444    type IdType = CharacterId;
445
446    fn format_url(id: &str) -> String {
447        format!("{}/{}/equipment", Self::URL, id)
448    }
449}
450
451impl Endpoint for Equipment {
452    const AUTHENTICATED: bool = true;
453    const LOCALE: bool = false;
454    const URL: &'static str = "v2/characters";
455    const VERSION: &'static str = "2022-06-14T00:00:00.000Z";
456}
457
458impl EndpointWithId for Inventory {
459    type IdType = CharacterId;
460
461    fn format_url(id: &str) -> String {
462        format!("{}/{}/inventory", Self::URL, id)
463    }
464}
465
466impl Endpoint for Inventory {
467    const AUTHENTICATED: bool = true;
468    const LOCALE: bool = false;
469    const URL: &'static str = "v2/characters";
470    const VERSION: &'static str = "2022-06-14T00:00:00.000Z";
471}
472
473impl EndpointWithId for Recipes {
474    type IdType = CharacterId;
475
476    fn format_url(id: &str) -> String {
477        format!("{}/{}/recipes", Self::URL, id)
478    }
479}
480
481impl Endpoint for Recipes {
482    const AUTHENTICATED: bool = true;
483    const LOCALE: bool = false;
484    const URL: &'static str = "v2/characters";
485    const VERSION: &'static str = "2022-06-14T00:00:00.000Z";
486}
487
488impl EndpointWithId for Training {
489    type IdType = CharacterId;
490
491    fn format_url(id: &str) -> String {
492        format!("{}/{}/training", Self::URL, id)
493    }
494}
495
496impl Endpoint for Training {
497    const AUTHENTICATED: bool = true;
498    const LOCALE: bool = false;
499    const URL: &'static str = "v2/characters";
500    const VERSION: &'static str = "2022-06-14T00:00:00.000Z";
501}