gw2lib_model/maps/continents/
floors.rs

1use std::{
2    collections::HashMap,
3    fmt::{Display, Formatter},
4};
5
6use serde::{Deserialize, Serialize};
7use serde_tuple::{Deserialize_tuple, Serialize_tuple};
8
9use crate::{
10    maps::{
11        continents::{ContinentId, Dimensions},
12        MapId,
13    },
14    Endpoint, EndpointWithId,
15};
16
17pub type FloorId = i16;
18pub type RegionId = u8;
19pub type MasteryPointId = u16;
20pub type PointOfInterestId = u16;
21pub type GodShrineId = u8;
22pub type TaskId = u16;
23pub type SectorId = u16;
24
25#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)]
26pub struct ContinentFloorId {
27    pub continent: ContinentId,
28    pub floor: FloorId,
29}
30
31impl From<(ContinentId, FloorId)> for ContinentFloorId {
32    fn from(value: (ContinentId, FloorId)) -> Self {
33        Self {
34            continent: value.0,
35            floor: value.1,
36        }
37    }
38}
39
40impl Display for ContinentFloorId {
41    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
42        write!(f, "{}/floors/{}", self.continent, self.floor)
43    }
44}
45
46#[derive(Clone, Debug, PartialOrd, PartialEq, Serialize_tuple, Deserialize_tuple)]
47#[cfg_attr(test, serde(deny_unknown_fields))]
48pub struct Coordinates {
49    pub x: f32,
50    pub y: f32,
51}
52
53#[derive(Clone, Debug, PartialOrd, PartialEq, Serialize_tuple, Deserialize_tuple)]
54#[cfg_attr(test, serde(deny_unknown_fields))]
55pub struct ContinentRectangle {
56    pub top_left: Coordinates,
57    pub bottom_right: Coordinates,
58}
59
60#[derive(Clone, Debug, PartialOrd, PartialEq, Serialize_tuple, Deserialize_tuple)]
61#[cfg_attr(test, serde(deny_unknown_fields))]
62pub struct MapRectangle {
63    pub bottom_left: Coordinates,
64    pub top_right: Coordinates,
65}
66
67#[derive(Clone, PartialEq, Eq, PartialOrd, Debug, Serialize, Deserialize)]
68#[serde(rename_all = "lowercase")]
69#[cfg_attr(test, serde(deny_unknown_fields))]
70pub enum PointOfInterestType {
71    Landmark,
72    Waypoint,
73    Vista,
74    Unlock,
75}
76
77#[derive(Clone, Debug, Serialize, Deserialize)]
78#[cfg_attr(test, serde(deny_unknown_fields))]
79pub struct PointOfInterest {
80    /// The POI id.
81    pub id: PointOfInterestId,
82    /// The POI name, if any.
83    pub name: Option<String>,
84    /// The POI type.
85    #[serde(rename = "type")]
86    pub _type: PointOfInterestType,
87    /// The floor of this POI.
88    pub floor: FloorId,
89    /// The POI coordinates.
90    pub coord: Coordinates,
91    /// The POI chat link.
92    pub chat_link: String,
93    /// For [`Unlock`](PointOfInterestType::Unlock) type, provides the render
94    /// service url for the POI's icon.
95    pub icon: Option<String>,
96}
97
98#[derive(Clone, Debug, Serialize, Deserialize)]
99#[cfg_attr(test, serde(deny_unknown_fields))]
100pub struct GodShrine {
101    /// The shrine id.
102    pub id: GodShrineId,
103    /// The shrine name when not contested.
104    pub name: String,
105    /// The shrine name when contested.
106    pub name_contested: String,
107    /// The shrine coordinates.
108    pub coord: Coordinates,
109    /// The associated waypoint id.
110    pub poi_id: PointOfInterestId,
111    /// The render service url for the shrine's icon when not contested.
112    pub icon: String,
113    /// The render service url for the shrine's icon when contested.
114    pub icon_contested: String,
115}
116
117#[derive(Clone, Debug, Serialize, Deserialize)]
118#[cfg_attr(test, serde(deny_unknown_fields))]
119pub struct Task {
120    /// The task id.
121    pub id: TaskId,
122    /// The objective or name of the task.
123    pub objective: String,
124    /// The level of the task.
125    pub level: u8,
126    /// The coordinates of the task.
127    pub coord: Coordinates,
128    /// A list of coordinates marking the boundary of the task.
129    pub bounds: Vec<Coordinates>,
130    /// The task chat link (provides an invalid link if attempting to display
131    /// in-game).
132    pub chat_link: String,
133}
134
135#[derive(Clone, Debug, Serialize, Deserialize)]
136#[cfg_attr(test, serde(deny_unknown_fields))]
137pub struct SkillChallenge {
138    /// The hero challenge id, if any.
139    ///
140    /// It is formed of two numbers separated by a dash. The first number
141    /// represents the expansion (0 for Core Tyria, 1 for Heart of Thorns
142    /// and 2 for Path of Fire), and therefore could be used to change the
143    /// hero challenge map marker icon. If the first number and dash prefix is
144    /// removed from the string, the second number is no longer unique among
145    /// other hero challenges.
146    pub id: Option<String>,
147    /// The coordinates of this hero challenge.
148    pub coord: Coordinates,
149}
150
151#[derive(Clone, Debug, Serialize, Deserialize)]
152#[cfg_attr(test, serde(deny_unknown_fields))]
153pub struct Sector {
154    /// The sector id.
155    pub id: SectorId,
156    /// The name of the sector, if any.
157    pub name: Option<String>,
158    /// The level of the sector.
159    pub level: u8,
160    /// The coordinates of the sector (this is usually the center position).
161    pub coord: Coordinates,
162    /// A list of coordinates marking the boundary of the sector.
163    pub bounds: Vec<Coordinates>,
164    /// The sector chat link (provides an invalid link if attempting to display
165    /// in-game).
166    pub chat_link: String,
167}
168
169#[derive(Clone, Debug, Serialize, Deserialize)]
170#[cfg_attr(test, serde(deny_unknown_fields))]
171pub struct Adventure {
172    /// The adventure UUID.
173    pub id: String,
174    /// The name of the adventure.
175    pub name: String,
176    /// The description of the adventure.
177    pub description: String,
178    /// The coordinates of the start of the adventure.
179    pub coord: Coordinates,
180}
181
182#[derive(Clone, PartialEq, Eq, PartialOrd, Debug, Serialize, Deserialize)]
183#[cfg_attr(test, serde(deny_unknown_fields))]
184pub enum MasteryPointRegion {
185    /// Core Tyria, in red.
186    Tyria,
187    /// Heart of Thorns, in green.
188    Maguuma,
189    /// Path of Fire, in purple
190    Desert,
191    /// Living World Season 5, in blue.
192    Tundra,
193    /// End of Dragons
194    Jade,
195    /// Secrets of the Obscure
196    Sky,
197    /// Janthir Wilds
198    #[serde(alias = "Unknown")]
199    Janthir,
200}
201
202#[derive(Clone, Debug, Serialize, Deserialize)]
203#[cfg_attr(test, serde(deny_unknown_fields))]
204pub struct MasteryPoint {
205    /// The mastery point id.
206    pub id: MasteryPointId,
207    /// The type of mastery.
208    pub region: MasteryPointRegion,
209    /// The coordinates of the start of the adventure.
210    pub coord: Coordinates,
211}
212
213#[derive(Clone, Debug, Serialize, Deserialize)]
214#[cfg_attr(test, serde(deny_unknown_fields))]
215pub struct Map {
216    /// The map id.
217    pub id: MapId,
218    /// The map name.
219    pub name: String,
220    /// The minimum level on this map.
221    pub min_level: u8,
222    /// The maximum level on this map.
223    pub max_level: u8,
224    /// The default floor of the map.
225    pub default_floor: FloorId,
226    /// The coordinates of the map label.
227    pub label_coord: Option<Coordinates>,
228    /// The dimensions of the map.
229    pub map_rect: MapRectangle,
230    /// The dimensions of the map within the continent coordinate system.
231    pub continent_rect: ContinentRectangle,
232    /// The list of points of interest (landmarks, waypoints, vistas, etc) of
233    /// the map.
234    pub points_of_interest: HashMap<PointOfInterestId, PointOfInterest>,
235    pub god_shrines: Option<Vec<GodShrine>>,
236    /// The list of renown hearts of the map.
237    pub tasks: HashMap<TaskId, Task>,
238    /// The list of hero challenges of the map.
239    pub skill_challenges: Vec<SkillChallenge>,
240    /// The list of areas of the map.
241    pub sectors: HashMap<SectorId, Sector>,
242    /// The list of adventures of the map.
243    pub adventures: Vec<Adventure>,
244    /// The list of mastery points of the map.
245    pub mastery_points: Vec<MasteryPoint>,
246}
247
248#[derive(Clone, Debug, Serialize, Deserialize)]
249#[cfg_attr(test, serde(deny_unknown_fields))]
250pub struct Region {
251    /// The region id.
252    pub id: RegionId,
253    /// The region name.
254    pub name: String,
255    ///  The coordinates of the region label.
256    pub label_coord: Coordinates,
257    /// The dimensions of the region in the continent.
258    pub continent_rect: ContinentRectangle,
259    /// The list of maps in this region.
260    pub maps: HashMap<MapId, Map>,
261}
262
263#[derive(Clone, Debug, Serialize, Deserialize)]
264#[cfg_attr(test, serde(deny_unknown_fields))]
265pub struct Floor {
266    pub id: FloorId,
267    /// The dimensions of the texture.
268    pub texture_dims: Dimensions,
269    /// If present, it represents a rectangle of downloadable textures. Every
270    /// tile coordinate outside this rectangle is not available on the tile
271    /// server.
272    pub clamped_view: Option<ContinentRectangle>,
273    /// The list of regions in on this floor.
274    pub regions: HashMap<RegionId, Region>,
275}
276
277impl EndpointWithId for Floor {
278    type IdType = ContinentFloorId;
279
280    fn format_id(id: &Self::IdType) -> String {
281        id.to_string()
282    }
283}
284
285impl Endpoint for Floor {
286    const AUTHENTICATED: bool = false;
287    const LOCALE: bool = true;
288    const URL: &'static str = "v2/continents";
289    const VERSION: &'static str = "2023-03-31T00:00:00.000Z";
290}