tf_demo_parser/demo/parser/
handler.rs1use 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}