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