mcsr_ranked_api/game/
mod.rs

1use chrono::DateTime;
2use chrono::{serde::ts_seconds, Utc};
3use serde::Deserialize;
4#[cfg(feature = "serialize")]
5use serde::Serialize;
6use serde_repr::{Deserialize_repr, Serialize_repr};
7use uuid::Uuid;
8
9use crate::types::Time;
10use crate::types::{Elo, EloChange, MatchId, Rank, Season};
11use crate::user::UserProfile;
12
13pub mod requests;
14#[cfg(test)]
15mod tests;
16pub mod versus;
17
18#[cfg_attr(feature = "serialize", derive(Serialize))]
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
20#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
21pub enum MatchCategory {
22	Any,
23	Custom,
24	High,
25	KillAllBosses,
26	KillWither,
27	KillElderGuardian,
28	AllAdvancements,
29	Half,
30	PoglootQuater,
31	HowDidWeGetHere,
32	HeroOfTheVillage,
33	Arbalistic,
34	CoverMeInDebris,
35	EnterNether,
36	EnterEnd,
37	AllSwords,
38	AllMinerals,
39	#[serde(rename = "FULL_IA_15_LVL")]
40	FullIa15Lvl,
41	AllWorkstations,
42	FullInv,
43	StackOfLimeWool,
44	AllPortals,
45	AllBlocks,
46	MineAChunk,
47}
48
49#[cfg_attr(feature = "serialize", derive(Serialize))]
50#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
51pub struct MatchSeedInfo {
52	/// Id of the seed (not the seed itself)
53	pub id: Option<Box<str>>,
54	pub overworld: Option<OverworldType>,
55	pub bastion: Option<BastionType>,
56	pub variations: Box<[Box<str>]>,
57}
58impl MatchSeedInfo {
59	/// Id of the seed (not the seed itself)
60	pub fn id(&self) -> Option<&str> {
61		self.id.as_ref().map(AsRef::as_ref)
62	}
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize_repr, Serialize_repr)]
66#[repr(u8)]
67pub enum MatchType {
68	Causal = 1,
69	Ranked = 2,
70	Private = 3,
71	Event = 4,
72}
73
74#[cfg_attr(feature = "serialize", derive(Serialize))]
75#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
76#[serde(rename_all = "camelCase")]
77pub struct MatchOutcome {
78	#[serde(rename = "uuid")]
79	pub winner_uuid: Option<Uuid>,
80	pub time: Time,
81}
82
83/// Match leaderboard ranking
84#[cfg_attr(feature = "serialize", derive(Serialize))]
85#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
86#[serde(rename_all = "camelCase")]
87pub struct MatchRank {
88	pub season: Option<Rank>,
89	pub all_time: Option<Rank>,
90}
91
92/// Match contestant's elo update
93#[cfg_attr(feature = "serialize", derive(Serialize))]
94#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
95#[serde(rename_all = "camelCase")]
96pub struct MatchEloUpdate {
97	#[serde(rename = "uuid")]
98	pub player_uuid: Uuid,
99	pub change: Option<EloChange>,
100	#[serde(rename = "eloRate")]
101	pub elo: Option<Elo>,
102}
103
104/// Seed type (overworld)
105#[cfg_attr(feature = "serialize", derive(Serialize))]
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
107#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
108pub enum OverworldType {
109	Village,
110	BuriedTreasure,
111	Shipwreck,
112	RuinedPortal,
113	DesertTemple,
114}
115
116/// Bastion type
117#[cfg_attr(feature = "serialize", derive(Serialize))]
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
119#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
120pub enum BastionType {
121	Housing,
122	Treasure,
123	Bridge,
124	Stables,
125}
126
127/// Match completion info
128#[cfg_attr(feature = "serialize", derive(Serialize))]
129#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
130#[serde(rename_all = "camelCase")]
131pub struct MatchCompletion {
132	#[serde(rename = "uuid")]
133	pub player_uuid: Uuid,
134	pub time: Time,
135}
136
137/// Match timeline event
138#[cfg_attr(feature = "serialize", derive(Serialize))]
139#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
140#[serde(rename_all = "camelCase")]
141pub struct MatchTimelineEvent {
142	#[serde(rename = "uuid")]
143	pub player_uuid: Uuid,
144	pub time: Time,
145	#[serde(rename = "type")]
146	pub id: Box<str>,
147}
148impl MatchTimelineEvent {
149	pub fn id(&self) -> &str {
150		&self.id
151	}
152}
153
154/// Match info
155#[cfg_attr(feature = "serialize", derive(Serialize))]
156#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
157#[serde(rename_all = "camelCase")]
158pub struct MatchInfo {
159	pub id: MatchId,
160	#[serde(rename = "type")]
161	pub kind: MatchType,
162	pub season: Season,
163	pub category: Option<MatchCategory>,
164	#[serde(with = "ts_seconds")]
165	pub date: DateTime<Utc>,
166	pub players: Box<[UserProfile]>,
167	pub spectators: Box<[UserProfile]>,
168	pub seed: Option<MatchSeedInfo>,
169	pub result: MatchOutcome,
170	pub forfeited: bool,
171	pub decayed: bool,
172	pub rank: MatchRank,
173	#[serde(rename = "changes")]
174	pub elo_updates: Box<[MatchEloUpdate]>,
175}
176impl MatchInfo {
177	/// Users participating in the match
178	pub fn players(&self) -> &[UserProfile] {
179		&self.players
180	}
181	/// Users spectating the match
182	pub fn spectators(&self) -> &[UserProfile] {
183		&self.spectators
184	}
185	// The updates to the participants' ELOs
186	pub fn elo_updates(&self) -> &[MatchEloUpdate] {
187		&self.elo_updates
188	}
189}
190
191/// Advanced (full) match info
192#[cfg_attr(feature = "serialize", derive(Serialize))]
193#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
194#[serde(rename_all = "camelCase")]
195pub struct AdvancedMatchInfo {
196	/// The base info about the match
197	#[serde(flatten)]
198	info: MatchInfo,
199	/// Which players completed the match
200	completions: Box<[MatchCompletion]>,
201	#[serde(rename = "timelines")]
202	/// Advancements and other events that happened during the match
203	timeline_events: Box<[MatchTimelineEvent]>,
204	#[serde(rename = "replayExist")]
205	replay_exists: bool,
206}
207impl AdvancedMatchInfo {
208	/// The completions info of the match
209	pub fn completions(&self) -> &[MatchCompletion] {
210		&self.completions
211	}
212	/// The events (achievements) timeline
213	pub fn timeline_events(&self) -> &[MatchTimelineEvent] {
214		&self.timeline_events
215	}
216}