tf_demo_parser/demo/parser/
handler.rs

1use crate::demo::message::{Message, MessageType};
2use crate::demo::packet::datatable::{ParseSendTable, ServerClass};
3use crate::demo::packet::stringtable::{StringTable, StringTableEntry};
4use crate::demo::packet::Packet;
5use crate::Result;
6
7use crate::demo::data::{DemoTick, ServerTick};
8use crate::demo::header::Header;
9use crate::demo::packet::message::MessagePacketMeta;
10use crate::ParserState;
11use std::borrow::Cow;
12
13pub trait MessageHandler {
14    type Output;
15
16    fn does_handle(message_type: MessageType) -> bool;
17
18    fn handle_header(&mut self, _header: &Header) {}
19
20    fn handle_message(&mut self, _message: &Message, _tick: DemoTick, _parser_state: &ParserState) {
21    }
22
23    fn handle_string_entry(
24        &mut self,
25        _table: &str,
26        _index: usize,
27        _entries: &StringTableEntry,
28        _parser_state: &ParserState,
29    ) {
30    }
31
32    fn handle_data_tables(
33        &mut self,
34        _tables: &[ParseSendTable],
35        _server_classes: &[ServerClass],
36        _parser_state: &ParserState,
37    ) {
38    }
39
40    fn handle_packet_meta(
41        &mut self,
42        _tick: DemoTick,
43        _meta: &MessagePacketMeta,
44        _parser_state: &ParserState,
45    ) {
46    }
47
48    fn into_output(self, state: &ParserState) -> Self::Output;
49}
50
51pub trait BorrowMessageHandler: MessageHandler {
52    fn borrow_output(&self, _state: &ParserState) -> &Self::Output;
53}
54
55pub struct NullHandler;
56
57impl MessageHandler for NullHandler {
58    type Output = ();
59
60    fn does_handle(_message_type: MessageType) -> bool {
61        false
62    }
63
64    fn into_output(self, _state: &ParserState) -> Self::Output {}
65}
66
67#[derive(Clone)]
68pub struct DemoHandler<'a, T: MessageHandler> {
69    pub server_tick: ServerTick,
70    pub demo_tick: DemoTick,
71    pub string_table_names: Vec<Cow<'a, str>>,
72    analyser: T,
73    pub state_handler: ParserState,
74}
75
76impl DemoHandler<'_, NullHandler> {
77    pub fn new() -> Self {
78        Self::parse_all_with_analyser(NullHandler)
79    }
80}
81
82impl Default for DemoHandler<'_, NullHandler> {
83    fn default() -> Self {
84        DemoHandler::new()
85    }
86}
87
88impl<'a, T: MessageHandler> DemoHandler<'a, T> {
89    pub fn with_analyser(analyser: T) -> Self {
90        let state_handler = ParserState::new(24, T::does_handle, false);
91
92        DemoHandler {
93            server_tick: ServerTick::default(),
94            demo_tick: DemoTick::default(),
95            string_table_names: Vec::new(),
96            analyser,
97            state_handler,
98        }
99    }
100    pub fn parse_all_with_analyser(analyser: T) -> Self {
101        let state_handler = ParserState::new(24, T::does_handle, true);
102
103        DemoHandler {
104            server_tick: ServerTick::default(),
105            demo_tick: DemoTick::default(),
106            string_table_names: Vec::new(),
107            analyser,
108            state_handler,
109        }
110    }
111
112    pub fn handle_header(&mut self, header: &Header) {
113        self.state_handler.protocol_version = header.protocol;
114        self.analyser.handle_header(header);
115    }
116
117    pub fn handle_packet(&mut self, packet: Packet<'a>) -> Result<()> {
118        match packet {
119            Packet::DataTables(packet) => {
120                self.handle_data_table(packet.tables, packet.server_classes)?;
121            }
122            Packet::StringTables(packet) => {
123                for table in packet.tables.into_iter() {
124                    self.handle_string_table(table)
125                }
126            }
127            Packet::Message(packet) | Packet::Signon(packet) => {
128                self.analyser
129                    .handle_packet_meta(packet.tick, &packet.meta, &self.state_handler);
130                for message in packet.messages {
131                    match message {
132                        Message::NetTick(message) => {
133                            self.server_tick = message.tick;
134                            self.handle_message(Message::NetTick(message), packet.tick)
135                        }
136                        Message::CreateStringTable(message) => {
137                            self.handle_string_table(message.table)
138                        }
139                        Message::UpdateStringTable(message) => {
140                            self.handle_table_update(message.table_id, message.entries)
141                        }
142                        Message::PacketEntities(msg) => {
143                            self.handle_message(Message::PacketEntities(msg), packet.tick)
144                        }
145                        message => self.handle_message(message, packet.tick),
146                    }
147                }
148            }
149            _ => {}
150        };
151        Ok(())
152    }
153
154    fn handle_string_table(&mut self, table: StringTable<'a>) {
155        self.state_handler
156            .handle_string_table_meta(table.get_table_meta());
157        for (entry_index, entry) in table.entries.into_iter() {
158            let entry_index = entry_index as usize;
159            self.state_handler
160                .handle_string_entry(&table.name, entry_index, &entry);
161            self.analyser.handle_string_entry(
162                &table.name,
163                entry_index,
164                &entry,
165                &self.state_handler,
166            );
167        }
168
169        self.string_table_names.push(table.name);
170    }
171
172    fn handle_table_update(&mut self, table_id: u8, entries: Vec<(u16, StringTableEntry<'a>)>) {
173        if let Some(table_name) = self.string_table_names.get(table_id as usize) {
174            for (index, entry) in entries {
175                let index = index as usize;
176                self.state_handler
177                    .handle_string_entry(table_name, index, &entry);
178                self.analyser
179                    .handle_string_entry(table_name, index, &entry, &self.state_handler);
180            }
181        }
182    }
183
184    fn handle_data_table(
185        &mut self,
186        send_tables: Vec<ParseSendTable>,
187        server_classes: Vec<ServerClass>,
188    ) -> Result<()> {
189        self.analyser
190            .handle_data_tables(&send_tables, &server_classes, &self.state_handler);
191        self.state_handler
192            .handle_data_table(&send_tables, server_classes)
193    }
194
195    pub fn handle_message(&mut self, message: Message<'a>, tick: DemoTick) {
196        let message_type = message.get_message_type();
197        if T::does_handle(message_type) {
198            self.analyser
199                .handle_message(&message, tick, &self.state_handler);
200        }
201        self.state_handler.handle_message(message, tick);
202    }
203
204    pub fn into_output(self) -> T::Output {
205        self.analyser.into_output(&self.state_handler)
206    }
207
208    pub fn get_parser_state(&self) -> &ParserState {
209        &self.state_handler
210    }
211}
212
213impl<T: MessageHandler + BorrowMessageHandler> DemoHandler<'_, T> {
214    pub fn borrow_output(&self) -> &T::Output {
215        self.analyser.borrow_output(&self.state_handler)
216    }
217}