1use serde::Serialize;
2use std::fmt::Debug;
3
4#[doc(hidden)]
6#[macro_export]
7macro_rules! val {
8 ($x:expr) => {
9 match $x {
10 Some(x) => x,
11 None => bail!("{:?} is None @ {}, line: {}", stringify!($x), file!(), line!()),
12 }
13 };
14}
15
16#[derive(Debug, Serialize, Default)]
18pub struct Record {
19 pub parser: String,
20 pub md5: Option<String>,
21 pub filename: String,
22 pub filesize: usize,
23 pub lastmod: u128,
25 pub guid: Option<String>,
26 pub verlog: Option<u32>,
27 pub ver: Option<Version>,
28 pub verraw: Option<String>,
29 pub versave: Option<f32>,
31 pub versave2: Option<u32>,
32 pub verscenario: Option<f32>,
33 pub include_ai: Option<bool>,
34 pub speed_raw: Option<u32>,
35 pub speed: Option<String>,
36 pub recorder: Option<u16>,
37 pub totalplayers: Option<u8>,
39 pub mapsize_raw: Option<u32>,
40 pub mapsize: Option<String>,
41 pub revealmap_raw: Option<i32>,
42 pub revealmap: Option<String>,
43 pub mapx: Option<i32>,
44 pub mapy: Option<i32>,
45 pub fogofwar: Option<bool>,
46 pub instantbuild: Option<bool>,
47 pub enablecheats: Option<bool>,
48 pub restoretime: Option<u32>,
49 pub ismultiplayer: Option<bool>,
50 pub isconquest: Option<bool>,
51 pub relics2win: Option<i32>,
52 pub explored2win: Option<i32>,
53 pub anyorall: Option<bool>,
54 pub victorytype_raw: Option<i32>,
55 pub victorytype: Option<String>,
56 pub score2win: Option<i32>,
57 pub time2win_raw: Option<i32>,
58 pub time2win: Option<String>,
59 #[serde(skip)]
60 pub scenariofilename_raw: Option<Vec<u8>>,
61 pub scenariofilename: Option<String>,
62 #[serde(skip)]
63 pub instructions_raw: Option<Vec<u8>>,
64 pub instructions: Option<String>,
65 pub duration: u32,
66 pub chat: Vec<Chat>,
67 pub mapid: Option<u32>,
68 pub mapname: Option<String>,
69 pub difficulty_raw: Option<i32>,
70 pub difficulty: Option<String>,
71 pub lockteams: Option<bool>,
72 pub poplimit: Option<u32>,
73 pub gametype_raw: Option<u8>,
74 pub gametype: Option<String>,
75 pub lockdiplomacy: Option<bool>,
76 pub haswinner: bool,
77 pub matchup: Option<Vec<usize>>,
78 pub teams: Vec<Vec<i32>>,
79 pub players: [Player; 9],
80 #[serde(skip)]
82 pub debug: DebugInfo,
83}
84
85#[derive(Debug, Serialize, Default)]
87pub struct Player {
88 pub slot: usize,
89 pub index: Option<i32>,
90 pub playertype: Option<i32>,
91 #[serde(skip)]
92 pub name_raw: Option<Vec<u8>>,
93 pub name: Option<String>,
94 pub teamid: Option<u8>,
95 pub ismainop: Option<bool>,
96 pub initx: Option<f32>,
97 pub inity: Option<f32>,
98 pub civ_raw: Option<u8>,
99 pub civ: Option<String>,
100 pub colorid: Option<u8>,
101 pub disconnected: Option<bool>,
102 pub resigned: Option<u32>,
103 pub feudaltime: Option<u32>,
104 pub castletime: Option<u32>,
105 pub imperialtime: Option<u32>,
106 pub initage_raw: Option<f32>,
107 pub initage: Option<String>,
108 pub initfood: Option<f32>,
109 pub initwood: Option<f32>,
110 pub initstone: Option<f32>,
111 pub initgold: Option<f32>,
112 pub initpop: Option<f32>,
113 pub initcivilian: Option<f32>,
114 pub initmilitary: Option<f32>,
115 pub modversion: Option<f32>,
117 pub winner: Option<bool>,
119}
120
121impl Player {
122 pub fn new(slot: usize) -> Self {
123 Player { slot, ..Default::default() }
124 }
125
126 pub fn isvalid(&self) -> bool {
127 self.playertype.is_some_and(|x| (2..=5).contains(&x))
128 }
129}
130
131#[derive(Debug, Serialize)]
133pub struct Chat {
134 pub time: Option<u32>,
135 pub player: Option<u8>,
137 #[serde(skip)]
138 pub content_raw: Option<Vec<u8>>,
139 pub content: Option<String>,
140}
141
142#[derive(Debug, Default)]
144pub struct DebugInfo {
145 pub currentpos_header: usize,
146 pub currentpos_body: usize,
147 pub aipos: usize,
148 pub initpos: usize,
149 pub triggerpos: usize,
150 pub triggersign: f64,
151 pub settingspos: usize,
152 pub disabledtechspos: usize,
153 pub victorypos: usize,
154 pub scenariopos: usize,
155 pub mappos: Option<usize>,
156 pub playerinitpos_by_idx: [Option<usize>; 9],
157 pub earlymovecount: usize,
158 pub earlymovecmd: Vec<[u8; 19]>,
159 pub earlymovetime: Vec<u32>,
160}
161
162#[derive(Debug, PartialEq, Serialize)]
164pub enum Version {
165 AoKTrial,
166 AoK,
167 AoCTrial,
168 AoC,
169 AoC10a,
170 AoC10c,
171 UP12,
172 UP13,
173 UP14,
174 UP14RC1,
175 UP14RC2,
176 UP15,
177 AoFE21,
178 HD,
179 DE,
180 MCP,
181 Unknown,
182}
183
184impl Record {
185 pub fn new(filename: String, filesize: usize, lastmod: u128) -> Self {
186 Record {
187 parser: format!(
188 "mgx-rs {}-{}",
189 env!("CARGO_PKG_VERSION"),
190 if cfg!(debug_assertions) { "debug" } else { "release" }
191 ),
192 filename,
193 filesize,
194 lastmod,
195 players: [
196 Player::new(0),
197 Player::new(1),
198 Player::new(2),
199 Player::new(3),
200 Player::new(4),
201 Player::new(5),
202 Player::new(6),
203 Player::new(7),
204 Player::new(8),
205 ],
206 debug: DebugInfo {
207 triggersign: 1.6, ..Default::default()
209 },
210 ..Default::default()
211 }
212 }
213}