source_demo_tool/
demo_file.rs

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
15//use kdam::{tqdm, BarExt};
16
17use 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        // read header
53        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        // read sign on data
59        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        // parse sign on data
67        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        // index frames
83
84        // we'll index frames on the main thread, while worker threads parse the frames
85        //    main thread: index frames and send to worker threads, receive completed work
86        // worker threads: parse frames and send results back to main thread
87
88        // setup data channel
89        let (tx_to_workers, rx_from_main) = async_channel::unbounded();
90        let (tx_to_main, rx_from_workers) = async_channel::unbounded();
91
92        // build and spawn worker threads
93        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        // receive frames (out of order)
139        loop {
140            match rx.recv_blocking() {
141                Ok(frame) => {
142                    frames.push(frame?);
143                    //pb.update(1);
144                },
145                Err(_) => break
146            };
147        }
148
149        // order frames and return
150        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            // parse and send data
191            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                                    // find the game event listing
302                                    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}