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	pub bastion: Option<BastionType>,
58	/// The heights of the 4 zero-cyclable end towers
59	#[serde(default)]
60	pub end_towers: Option<[u8; 4]>,
61	#[serde(default)]
62	#[cfg(feature = "variations")]
63	pub variations: Box<[Variation]>,
64	#[cfg(not(feature = "variations"))]
65	pub variations: Box<[Box<str>]>,
66}
67impl MatchSeedInfo {
68	/// Id of the seed (not the seed itself)
69	pub fn id(&self) -> Option<&str> {
70		self.id.as_ref().map(AsRef::as_ref)
71	}
72	#[cfg(not(feature = "variations"))]
73	pub fn variations(&self) -> &[Box<str>] {
74		self.variations.as_ref()
75	}
76	#[cfg(feature = "variations")]
77	pub fn variations(&self) -> &[Variation] {
78		self.variations.as_ref()
79	}
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize_repr, Serialize_repr)]
83#[repr(u8)]
84pub enum MatchType {
85	Causal = 1,
86	Ranked = 2,
87	Private = 3,
88	Event = 4,
89}
90
91#[cfg_attr(feature = "serialize", derive(Serialize))]
92#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
93#[serde(rename_all = "camelCase")]
94pub struct MatchOutcome {
95	#[serde(rename = "uuid")]
96	pub winner_uuid: Option<Uuid>,
97	pub time: Time,
98}
99
100/// Match leaderboard ranking
101#[cfg_attr(feature = "serialize", derive(Serialize))]
102#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
103#[serde(rename_all = "camelCase")]
104pub struct MatchRank {
105	pub season: Option<Rank>,
106	pub all_time: Option<Rank>,
107}
108
109/// Match contestant's elo update
110#[cfg_attr(feature = "serialize", derive(Serialize))]
111#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
112#[serde(rename_all = "camelCase")]
113pub struct MatchEloUpdate {
114	#[serde(rename = "uuid")]
115	pub player_uuid: Uuid,
116	pub change: Option<EloChange>,
117	#[serde(rename = "eloRate")]
118	pub elo: Option<Elo>,
119}
120
121/// Seed type (overworld)
122#[cfg_attr(feature = "serialize", derive(Serialize))]
123#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
124#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
125pub enum OverworldType {
126	Village,
127	BuriedTreasure,
128	Shipwreck,
129	RuinedPortal,
130	DesertTemple,
131}
132
133/// Bastion type
134#[cfg_attr(feature = "serialize", derive(Serialize))]
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
136#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
137pub enum BastionType {
138	Housing,
139	Treasure,
140	Bridge,
141	Stables,
142}
143
144/// Match completion info
145#[cfg_attr(feature = "serialize", derive(Serialize))]
146#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
147#[serde(rename_all = "camelCase")]
148pub struct MatchCompletion {
149	#[serde(rename = "uuid")]
150	pub player_uuid: Uuid,
151	pub time: Time,
152}
153
154/// Match timeline event
155#[cfg_attr(feature = "serialize", derive(Serialize))]
156#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
157#[serde(rename_all = "camelCase")]
158pub struct MatchTimelineEvent {
159	#[serde(rename = "uuid")]
160	pub player_uuid: Uuid,
161	pub time: Time,
162	#[serde(rename = "type")]
163	pub id: Box<str>,
164}
165impl MatchTimelineEvent {
166	pub fn id(&self) -> &str {
167		&self.id
168	}
169}
170
171/// Match info
172#[cfg_attr(feature = "serialize", derive(Serialize))]
173#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
174#[serde(rename_all = "camelCase")]
175pub struct MatchInfo {
176	pub id: MatchId,
177	#[serde(rename = "type")]
178	pub kind: MatchType,
179	pub season: Season,
180	pub category: Option<MatchCategory>,
181	#[serde(with = "ts_seconds")]
182	pub date: DateTime<Utc>,
183	pub players: Box<[UserProfile]>,
184	pub spectators: Box<[UserProfile]>,
185	pub seed: Option<MatchSeedInfo>,
186	pub result: MatchOutcome,
187	pub forfeited: bool,
188	pub decayed: bool,
189	pub rank: MatchRank,
190	#[serde(rename = "changes")]
191	pub elo_updates: Box<[MatchEloUpdate]>,
192}
193impl MatchInfo {
194	/// Users participating in the match
195	pub fn players(&self) -> &[UserProfile] {
196		&self.players
197	}
198	/// Users spectating the match
199	pub fn spectators(&self) -> &[UserProfile] {
200		&self.spectators
201	}
202	// The updates to the participants' ELOs
203	pub fn elo_updates(&self) -> &[MatchEloUpdate] {
204		&self.elo_updates
205	}
206}
207
208/// Advanced (full) match info
209#[cfg_attr(feature = "serialize", derive(Serialize))]
210#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
211#[serde(rename_all = "camelCase")]
212pub struct AdvancedMatchInfo {
213	/// The base info about the match
214	#[serde(flatten)]
215	info: MatchInfo,
216	/// Which players completed the match
217	completions: Box<[MatchCompletion]>,
218	#[serde(rename = "timelines")]
219	/// Advancements and other events that happened during the match
220	timeline_events: Box<[MatchTimelineEvent]>,
221	#[serde(rename = "replayExist")]
222	replay_exists: bool,
223}
224impl AdvancedMatchInfo {
225	/// The completions info of the match
226	pub fn completions(&self) -> &[MatchCompletion] {
227		&self.completions
228	}
229	/// The events (achievements) timeline
230	pub fn timeline_events(&self) -> &[MatchTimelineEvent] {
231		&self.timeline_events
232	}
233}