1pub mod frame;
2pub mod header;
3pub mod packet;
4
5use std:: {
6 fs::File,
7 vec::Vec,
8 io::{Read, Seek, SeekFrom},
9 thread, path::PathBuf,
10};
11
12use async_channel::{self, Receiver, Sender};
13use buf_redux::BufReader;
14
15use self::{
18 frame::{ Frame, FrameIndex, DataTablesData, Command, },
19 header::DemoHeader,
20 packet::netmessage::{
21 NetMessage,
22 GameEventListData,
23 ServerInfoData,
24 UserMessageData,
25 },
26 packet::usermessage::{
27 UserMessage,
28 }
29};
30
31#[derive(Debug, Clone)]
32pub struct DemoFile {
33 pub path: PathBuf,
34 pub header: DemoHeader,
35 pub frames: Vec<frame::Frame>,
36 pub sign_on_frames: Vec<Frame>,
37 pub last_index_error: Option<String>,
38}
39
40impl DemoFile {
41 pub fn open(filepath: &PathBuf) -> Result<Self, String> {
42 let file = match File::open(filepath) {
43 Ok(file) => file,
44 Err(e) => match e.kind() {
45 std::io::ErrorKind::NotFound => return Err(format!("file '{}' not found", filepath.to_str().unwrap())),
46 _ => return Err(String::from("an unexpected file error occured"))
47 }
48 };
49
50 let mut reader = BufReader::new(file);
51
52 let header = match DemoHeader::from_readable(&mut reader) {
54 Ok(h) => h,
55 Err(e) => return Err(format!("couldn't parse header: {e}"))
56 };
57
58 let mut sign_on_data: Vec<u8> = Vec::new();
60 sign_on_data.resize(header.sign_on_length.try_into().unwrap(), 0);
61 match reader.read_exact(sign_on_data.as_mut_slice()) {
62 Ok(()) => {},
63 Err(_) => return Err(String::from("couldn't read sign_on_data"))
64 }
65
66 let mut sod_reader = BufReader::with_capacity(sign_on_data.len(), sign_on_data.as_slice());
68 sod_reader.read_into_buf().unwrap();
69 let mut sign_on_frames = Vec::new();
70
71 while sod_reader.buf_len() > 0 {
72 let frame_index = match FrameIndex::from_readable(&mut sod_reader) {
73 Ok(fi) => fi,
74 Err(e) => return Err(format!(
75 "invalid or corrupt sign_on_data: {:?}", e
76 ))
77 };
78
79 sign_on_frames.push(Frame::from_frame_index(frame_index)?);
80 }
81
82 let (tx_to_workers, rx_from_main) = async_channel::unbounded();
90 let (tx_to_main, rx_from_workers) = async_channel::unbounded();
91
92 let core_count: usize = thread::available_parallelism()
94 .expect("couldn't get available cores")
95 .into();
96
97 let mut worker_threads = Vec::new();
98 for i in 0..core_count {
99 let rx = rx_from_main.clone();
100 let tx = tx_to_main.clone();
101 match thread::Builder::new()
102 .name(format!("frame parser thread {i}"))
103 .spawn(move || Self::worker_thread_receive_parse_and_send(rx, tx)) {
104 Ok(h) => worker_threads.push(h),
105 Err(e) => return Err(format!("couldn't spawn frame worker thread[{i}]: {e}"))
106 };
107 }
108 drop(tx_to_main);
109 drop(rx_from_main);
110
111 let last_index_error = Self::index_and_send_frames(reader, &tx_to_workers)?;
112 drop(tx_to_workers);
113
114 let frames = match Self::receive_parsed_frames(&rx_from_workers){
115 Ok(f) => f,
116 Err(e) => return Err(e.into())
117 };
118 drop(rx_from_workers);
119
120 for join_handle in worker_threads {
121 join_handle.join().unwrap();
122 }
123
124 Ok(
125 DemoFile {
126 frames,
127 header,
128 sign_on_frames,
129 last_index_error,
130 path: filepath.clone(),
131 }
132 )
133 }
134
135 fn receive_parsed_frames(rx: &Receiver<Result<Frame, &'static str>>) -> Result<Vec<Frame>, &'static str> {
136 let mut frames = Vec::new();
137
138 loop {
140 match rx.recv_blocking() {
141 Ok(frame) => {
142 frames.push(frame?);
143 },
145 Err(_) => break
146 };
147 }
148
149 frames.sort_unstable_by_key(|f| f.tick);
151 Ok(frames)
152 }
153
154 fn index_and_send_frames(mut reader: impl Read + Seek, tx: &Sender<FrameIndex>) -> Result<Option<String>, String> {
155 let current_location = reader.stream_position().unwrap();
156 let file_length = match reader.seek(SeekFrom::End(0)) {
157 Ok(n) => n,
158 Err(_) => return Err(String::from("couldn't get eof"))
159 };
160 reader.seek(SeekFrom::Start(current_location)).unwrap();
161
162 loop {
163 let file_position = reader.stream_position().unwrap();
164
165 if file_position >= file_length {
166 if file_position != file_length {
167 return Err(String::from("bad frame index read"))
168 }
169 return Ok(None)
170 }
171
172 let frame_index = match FrameIndex::from_readable(&mut reader) {
173 Ok(fi) => fi,
174 Err(e) => return Ok(Some(format!("error occured parsing frame index: {:?}", e)))
175 };
176
177 if let Err(e) = tx.send_blocking(frame_index) {
178 return Err(format!("error occured sending frame index: {e}"))
179 }
180 }
181 }
182
183 fn worker_thread_receive_parse_and_send(rx: Receiver<FrameIndex>, tx: Sender<Result<Frame, &'static str>>) {
184 loop {
185 let frame_index = match rx.recv_blocking() {
186 Ok(f) => f,
187 Err(_) => return
188 };
189
190 let frame = frame::Frame::from_frame_index(frame_index);
192 tx.send_blocking(frame).unwrap()
193 }
194 }
195
196 pub fn get_data_tables(self: &Self) -> Vec<&DataTablesData> {
197 let mut dtables = Vec::new();
198 for f in &self.sign_on_frames {
199 match &f.command {
200 Command::DataTables(dt) => dtables.push(dt),
201 _ => {}
202 }
203 }
204 for f in &self.frames {
205 match &f.command {
206 Command::DataTables(dt) => dtables.push(dt),
207 _ => {}
208 }
209 }
210 dtables
211 }
212
213 pub fn get_server_info(self: &Self) -> Option<&ServerInfoData> {
214 for f in &self.sign_on_frames {
215 match &f.command {
216 Command::SignOn(pd) => {
217 for msg in &pd.network_messages {
218 if let Some(nmsg) = &msg.message {
219 match nmsg {
220 NetMessage::ServerInfo(si) => return Some(si),
221 _ => continue
222 }
223 }
224 }
225 },
226 _ => continue
227 }
228 }
229 for f in &self.frames {
230 match &f.command {
231 Command::SignOn(pd) => {
232 for msg in &pd.network_messages {
233 if let Some(nmsg) = &msg.message {
234 match nmsg {
235 NetMessage::ServerInfo(si) => return Some(si),
236 _ => continue
237 }
238 }
239 }
240 },
241 _ => continue
242 }
243 }
244 None
245 }
246
247 pub fn get_game_event_list(self: &Self) -> Option<&GameEventListData> {
248 for f in &self.sign_on_frames {
249 match &f.command {
250 Command::SignOn(pd) => {
251 for msg in &pd.network_messages {
252 if let Some(nmsg) = &msg.message {
253 match nmsg {
254 NetMessage::GameEventList(gel) => return Some(gel),
255 _ => continue
256 }
257 }
258 }
259 },
260 _ => continue
261 }
262 }
263 for f in &self.frames {
264 match &f.command {
265 Command::SignOn(pd) => {
266 for msg in &pd.network_messages {
267 if let Some(nmsg) = &msg.message {
268 match nmsg {
269 NetMessage::GameEventList(gel) => return Some(gel),
270 _ => continue
271 }
272 }
273 }
274 },
275 _ => continue
276 }
277 }
278 None
279 }
280
281 pub fn get_full_game_events(self: &Self) -> Vec<FullGameEvent> {
282 let mut events = Vec::new();
283
284 let game_event_list = match self.get_game_event_list() {
285 Some(gel) => gel,
286 None => return events
287 };
288
289 for frame_index in 0..self.frames.len() {
290 let f = &self.frames[frame_index];
291 match &f.command {
292 Command::Packet(pd) => {
293 for message_index in 0..pd.network_messages.len() {
294 let msg = &pd.network_messages[message_index];
295 if let Some(nmsg) = &msg.message {
296 match &nmsg {
297 NetMessage::GameEvent(ge) => {
298 let event_id = ge.event_id.unwrap();
299 let mut event_listing = None;
300
301 for listing in &game_event_list.Descriptors {
303 if event_id == listing.event_id.unwrap() {
304 event_listing = Some(listing);
305 break;
306 }
307 }
308
309 let event_listing = event_listing.unwrap();
310 assert_eq!(event_listing.DescriptorKeys.len(), ge.GameEventKeys.len());
311
312 let mut event_keys = Vec::new();
313 for i in 0..ge.GameEventKeys.len() {
314 let listing = &event_listing.DescriptorKeys[i];
315 let ev = &ge.GameEventKeys[i];
316 assert_eq!(listing.key_type.unwrap(), ev.val_type.unwrap());
317
318 let key_type: FullGameEventKeyType = listing.key_type.unwrap().try_into().unwrap();
319 let key_name = listing.key_name.as_ref().unwrap().clone();
320
321 let mut val_string = None;
322 let mut val_float = None;
323 let mut val_int = None;
324 let mut val_bool = None;
325
326 match key_type {
327 FullGameEventKeyType::String => val_string = ev.val_string.clone(),
328 FullGameEventKeyType::Float => val_float = ev.val_float.clone(),
329 FullGameEventKeyType::Long => val_int = ev.val_long.clone(),
330 FullGameEventKeyType::Byte => val_int = ev.val_byte.clone(),
331 FullGameEventKeyType::Short => val_int = ev.val_short.clone(),
332 FullGameEventKeyType::Bool => val_bool = Some(*ev.val_bool.as_ref().unwrap() > 0)
333 }
334
335 event_keys.push(FullGameEventKey{
336 key_name,
337 key_type,
338 val_string,
339 val_float,
340 val_int,
341 val_bool
342 });
343 }
344 let event_name = event_listing.name.as_ref().unwrap().clone();
345 let event_tick = f.tick;
346 events.push( FullGameEvent {
347 event_id,
348 event_name,
349 event_keys,
350 event_tick,
351 frame_index,
352 message_index,
353 })
354 },
355 _ => continue
356 }
357 };
358 }
359 },
360 _ => continue
361 }
362 }
363
364 events
365 }
366
367
368 fn get_all_user_message_data(self: &Self) -> Vec<(usize, usize, i32, &UserMessageData)> {
369 let mut user_message_data = Vec::new();
370
371 for it in 0..self.frames.len() {
372 let f = &self.frames[it];
373 let tick = f.tick;
374 if let Command::Packet(pd) = &f.command {
375 for jt in 0..pd.network_messages.len() {
376 let nmsg = &pd.network_messages[jt];
377 let msg = nmsg.message.as_ref().unwrap();
378 match msg {
379 NetMessage::UserMessage(umd) => {
380 user_message_data.push((it, jt, tick, umd));
381 },
382 _ => continue
383 }
384 }
385 }
386 }
387
388 user_message_data
389 }
390
391 pub fn get_user_messages(self: &Self) -> Vec<ParsedUserMessage> {
392 let mut user_messages = Vec::new();
393
394 let all_user_message_data = self.get_all_user_message_data();
395
396 for msg in all_user_message_data {
397 let data = msg.3.msg_data.as_ref().unwrap();
398 let mut reader = BufReader::with_capacity(data.len(), data.as_slice());
399 reader.read_into_buf().unwrap();
400
401 match UserMessage::parse_from_id_and_bufredux_reader(msg.3.msg_type.unwrap(), &mut reader) {
402 Ok((inner_msg, warns)) => user_messages.push( ParsedUserMessage {
403 frame_index: msg.0,
404 message_index: msg.1,
405 tick: msg.2,
406 message_return: packet::MessageParseReturn {
407 message: Some(inner_msg),
408 warnings: Some(warns),
409 err: None,
410 }
411 }),
412 Err(e) => user_messages.push( ParsedUserMessage {
413 frame_index: msg.0,
414 message_index: msg.1,
415 tick: msg.2,
416 message_return: packet::MessageParseReturn {
417 message: None,
418 warnings: None,
419 err: Some(e)
420 }
421 })
422 }
423 }
424
425 user_messages
426 }
427}
428
429#[derive(Debug, Clone)]
430pub struct ParsedUserMessage {
431 pub frame_index: usize,
432 pub message_index: usize,
433 pub message_return: packet::MessageParseReturn<UserMessage>,
434 pub tick: i32,
435}
436
437#[derive(Debug, Clone)]
438pub struct FullGameEvent {
439 pub event_name: String,
440 pub event_id: u64,
441 pub event_tick: i32,
442 pub event_keys: Vec<FullGameEventKey>,
443 pub frame_index: usize,
444 pub message_index: usize,
445}
446
447#[derive(Debug, Clone)]
448pub struct FullGameEventKey {
449 pub key_name: String,
450 pub key_type: FullGameEventKeyType,
451 pub val_string: Option<String>,
452 pub val_float: Option<f32>,
453 pub val_int: Option<u64>,
454 pub val_bool: Option<bool>
455}
456
457#[derive(Debug, Clone)]
458pub enum FullGameEventKeyType {
459 String,
460 Float,
461 Long,
462 Short,
463 Byte,
464 Bool
465}
466
467impl TryFrom<u64> for FullGameEventKeyType {
468 type Error = &'static str;
469 fn try_from(value: u64) -> Result<Self, Self::Error> {
470 match value {
471 1 => Ok(FullGameEventKeyType::String),
472 2 => Ok(FullGameEventKeyType::Float),
473 3 => Ok(FullGameEventKeyType::Long),
474 4 => Ok(FullGameEventKeyType::Short),
475 5 => Ok(FullGameEventKeyType::Byte),
476 6 => Ok(FullGameEventKeyType::Bool),
477 _ => Err("unknown key type")
478 }
479 }
480}