source_demo_tool/demo_file/
frame.rs1use std::io::Read;
2
3use crate:: {
4 demo_file::packet::{
5 netmessage::{ NetMessage, SendTableData },
6 PacketData, PacketIndex,
7 },
8 event_data::EventData,
9 parse_tools::{ parse_cstr, parse_i32, parse_u8, parse_u16, parse_u32, },
10};
11
12use source_demo_tool_impl_proc_macros::event;
13
14use buf_redux::BufReader;
15
16#[derive(Debug, Clone)]
17pub struct Frame {
18 pub command: Command,
19 pub tick: i32,
20 pub player_slot: u8,
21}
22
23impl Frame {
24 pub fn from_frame_index(frame_index: FrameIndex) -> Result<Self, &'static str> {
25 let command = frame_index.command_index.try_into()?;
26 let tick = frame_index.tick;
27 let player_slot = frame_index.player_slot;
28
29 Ok(Self {
30 command,
31 tick,
32 player_slot,
33 })
34 }
35}
36
37pub struct FrameIndex {
38 pub command_index: CommandIndex,
39 pub tick: i32,
40 pub player_slot: u8,
41}
42
43impl FrameIndex {
44 pub fn from_readable(mut reader: impl Read) -> Result<Self, EventData> {
45 let command_num = match parse_u8(&mut reader) {
46 Ok(n) => n,
47 Err(_e) => return Err(event!{"couldn't parse command"})
48 };
49
50 let tick = match parse_i32(&mut reader) {
51 Ok(n) => n,
52 Err(_e) => return Err(event!{"couldn't parse tick"})
53 };
54
55 let player_slot = match parse_u8(&mut reader) {
56 Ok(n) => n,
57 Err(_e) => return Err(event!{"couldn't parse player slot"})
58 };
59
60 let command_index = match CommandIndex::from_u8_and_reader(command_num, &mut reader) {
61 Ok(ci) => ci,
62 Err(e) => return Err(e)
63 };
64
65 Ok( Self {
66 command_index,
67 tick,
68 player_slot,
69 })
70 }
71}
72
73#[derive(Debug, Clone)]
74pub enum Command {
75 SignOn(PacketData),
76 Packet(PacketData),
77 SyncTick,
78 DataTables(DataTablesData),
81 Stop,
82 }
84
85impl TryFrom<CommandIndex> for Command {
86 type Error = &'static str;
87 fn try_from(value: CommandIndex) -> Result<Self, Self::Error> {
88 match value {
89 CommandIndex::Packet(pi) => Ok(Command::Packet(PacketData::from_packet_index(pi))),
90 CommandIndex::SignOn(pi) => Ok(Command::SignOn(PacketData::from_packet_index(pi))),
91 CommandIndex::SyncTick => Ok(Command::SyncTick),
92 CommandIndex::DataTables(dti) => Ok(Command::DataTables(DataTablesData::from_data_tables_index(dti)?)),
93 CommandIndex::Stop => Ok(Command::Stop),
94 }
95 }
96}
97
98impl Command {
99 pub fn as_u8(&self) -> u8 {
100 match self {
101 Command::SignOn(_) => command_id::SIGN_ON,
102 Command::Packet(_) => command_id::PACKET,
103 Command::SyncTick => command_id::SYNC_TICK,
104 Command::DataTables(_) => command_id::DATA_TABLES,
107 Command::Stop => command_id::STOP,
108 }
110 }
111
112 pub fn get_command_str(&self) -> &str {
113 match self {
114 Command::SignOn(_) => "SignOn",
115 Command::Packet(_) => "Packet",
116 Command::SyncTick => "SyncTick",
117 Command::DataTables(_) => "DataTables",
120 Command::Stop => "Stop",
121 }
122 }
123}
124
125pub struct DataTablesIndex {
126 pub data: Vec<u8>
127}
128
129impl DataTablesIndex {
130 pub fn from_readable(mut reader: impl Read) -> Result<Self, String> {
131 let data_len = match parse_u32(&mut reader) {
132 Ok(n) => n,
133 Err(e) => return Err(format!{"parsing data_len: {}", e})
134 };
135
136 let mut data = Vec::new();
137 data.resize(data_len.try_into().unwrap(), 0);
138 reader.read_exact(data.as_mut_slice()).unwrap();
139
140 Ok(Self { data })
141 }
142}
143
144#[derive(Debug, Clone)]
145pub struct DataTablesData {
146 pub send_tables: Vec<SendTableData>,
147 pub class_descriptions: Vec<DataTablesClassDescription>,
148}
149
150#[derive(Debug, Clone)]
151pub struct DataTablesClassDescription {
152 pub class_id: u16,
153 pub network_name: String,
154 pub table_name: String,
155}
156
157impl DataTablesData {
158 pub fn from_data_tables_index(dti: DataTablesIndex) -> Result<Self, &'static str> {
159 let mut data_reader = BufReader::with_capacity
160 (dti.data.len(), dti.data.as_slice());
161
162 data_reader.read_into_buf().unwrap();
163
164 let mut send_tables = Vec::new();
166 while data_reader.buf_len() > 0 {
167 let net_result = NetMessage::parse_from_bufredux_reader(&mut data_reader);
168
169 let mut message = None;
170 if let Ok((msg, _warn)) = net_result {
171 message = Some(msg);
172 }
173
174 if message.is_none() {
175 return Err("couldn't parse SendTable message")
176 }
177
178 let mut is_end = false;
179 if let NetMessage::SendTable(st) = message.unwrap() {
180 if st.is_end.is_some() {
181 is_end = st.is_end.unwrap() > 0;
182 }
183 send_tables.push(st);
184 } else {
185 return Err("expected SendTable messages only")
186 }
187
188 if is_end { break;
190 }
191 }
192
193 let mut class_descriptions = Vec::new();
195 {
196 let class_count = parse_u16(&mut data_reader)?;
197
198 while data_reader.buf_len() > 0 {
199 let class_id = parse_u16(&mut data_reader)?;
200 let network_name = parse_cstr(&mut data_reader)?;
201 let table_name = parse_cstr(&mut data_reader)?;
202
203 class_descriptions.push(DataTablesClassDescription { class_id, network_name, table_name });
204 }
205
206 if class_descriptions.len() != class_count as usize {
207 return Err("too little or too many class descriptions were received")
208 }
209 }
210
211 Ok(Self { send_tables, class_descriptions })
212 }
213}
214
215pub enum CommandIndex {
216 SignOn(PacketIndex),
217 Packet(PacketIndex),
218 SyncTick,
219 DataTables(DataTablesIndex),
220 Stop,
221}
222
223impl CommandIndex {
224 pub fn from_u8_and_reader(num: u8, mut reader: impl Read) -> Result<Self, EventData> {
225 match num {
226 command_id::SIGN_ON => Ok(
227 Self::SignOn(match PacketIndex::from_readable(&mut reader) {
228 Ok(soi) => soi,
229 Err(e) => {
230 let mut ev = event!{""};
231 ev.details = format!("SignOnIndex parse error: {}", e);
232 return Err(ev)
233 }
234 })
235 ),
236 command_id::PACKET => Ok(
237 Self::Packet(match PacketIndex::from_readable(&mut reader) {
238 Ok(pi) => pi,
239 Err(e) => {
240 let mut ev = event!{""};
241 ev.details = format!("PacketIndex parse error: {}", e);
242 return Err(ev)
243 }
244 })
245 ),
246 command_id::SYNC_TICK => Ok(Self::SyncTick),
247 command_id::DATA_TABLES => Ok(
248 Self::DataTables(match DataTablesIndex::from_readable(&mut reader) {
249 Ok(dti) => dti,
250 Err(e) => {
251 let mut ev = event!{""};
252 ev.details = format!("DataTablesIndex parse error: {}", e);
253 return Err(ev)
254 }
255 })
256 ),
257 command_id::STOP => Ok(Self::Stop),
258 _ => {
259 let mut ev = event!{""};
260 ev.details = format!{"unsupported command number: {}", num};
261 return Err(ev)
262 }
263 }
264 }
265}
266
267mod command_id {
268 pub const SIGN_ON: u8 = 1;
269 pub const PACKET: u8 = 2;
270 pub const SYNC_TICK: u8 = 3;
271 pub const DATA_TABLES: u8 = 6;
274 pub const STOP: u8 = 7;
275 }