source2_demo/parser/demo/writer/
run.rs1use super::*;
2use crate::parser::demo::DemoCommands;
3use crate::proto::{
4 CDemoClassInfo, CDemoFullPacket, CDemoPacket, CDemoSendTables, CDemoStringTables,
5 EDemoCommands, Message,
6};
7use crate::reader::{BitsReader, MessageReader};
8use std::io::{Seek, Write};
9
10impl<'a, R, W> DemoWriter<'a, R, W>
11where
12 R: BitsReader + MessageReader,
13 W: Write + Seek,
14{
15 pub fn run(&mut self) -> Result<(), ParserError> {
17 self.parser.reader.seek(0);
18 let header = self.parser.reader.read_bytes(16);
19 self.writer.write_all(&header)?;
20 self.bytes_written = header.len() as u64;
21
22 'messages: while let Some(message) = self.read_next_raw_message()? {
23 self.update_context_tick(message.tick);
24
25 let mut payload = None;
26 if self.has_rewriters(RewriteInterests::DEMO_MESSAGE) {
27 let mut decoded = Self::decode_raw_payload(&message)?;
28 let ctx = &self.parser.context;
29 for rewriter in self.rewriters.iter_mut().filter(|rewriter| {
30 rewriter
31 .interests()
32 .contains(RewriteInterests::DEMO_MESSAGE)
33 }) {
34 match rewriter.rewrite_demo_message(
35 ctx,
36 message.tick,
37 message.msg_type,
38 decoded.as_slice(),
39 )? {
40 MessageRewrite::Drop => continue 'messages,
41 MessageRewrite::Replace(bytes) => decoded = bytes,
42 MessageRewrite::Keep | MessageRewrite::Rewrite => {}
43 }
44 }
45 payload = Some(decoded);
46 }
47
48 match message.msg_type {
49 EDemoCommands::DemPacket | EDemoCommands::DemSignonPacket => {
50 if !self.needs_packet_scan() {
51 self.write_message_or_raw(&message, payload.as_deref())?;
52 continue;
53 }
54
55 let payload = Self::materialize_payload(&mut payload, &message)?;
56 let mut packet = CDemoPacket::decode(payload.as_slice())?;
57 let rewritten = self.rewrite_packet_data(
58 message.tick,
59 packet.data(),
60 self.needs_packet_state(),
61 )?;
62 packet.data = Some(rewritten);
63 let packet_bytes = packet.encode_to_vec();
64 self.write_demo_message_with_compression(
65 message.msg_type,
66 message.tick,
67 &packet_bytes,
68 message.compressed,
69 )?;
70 }
71 EDemoCommands::DemFullPacket => {
72 if !self.needs_packet_scan() && !self.needs_demo_string_table_scan() {
73 self.write_message_or_raw(&message, payload.as_deref())?;
74 continue;
75 }
76
77 let payload = Self::materialize_payload(&mut payload, &message)?;
78 let mut full = CDemoFullPacket::decode(payload.as_slice())?;
79 let should_process = self.parser.context.last_full_packet_tick == u32::MAX
80 || self.parser.skip_deltas;
81
82 if let Some(table) = full.string_table.take() {
83 if self.needs_demo_string_table_scan() {
84 if let Some(rewritten) =
85 self.rewrite_string_tables(message.tick, table)?
86 {
87 if should_process && self.needs_demo_string_table_state() {
88 self.parser.dem_string_tables(rewritten.clone())?;
89 }
90 full.string_table = Some(rewritten);
91 }
92 } else {
93 full.string_table = Some(table);
94 }
95 }
96
97 if let Some(packet) = full.packet.as_mut() {
98 if self.needs_packet_scan() {
99 let rewritten = self.rewrite_packet_data(
100 message.tick,
101 packet.data(),
102 should_process && self.needs_packet_state(),
103 )?;
104 packet.data = Some(rewritten);
105 }
106 }
107
108 self.parser.context.last_full_packet_tick = message.tick;
109 let full_bytes = full.encode_to_vec();
110 self.write_demo_message_with_compression(
111 message.msg_type,
112 message.tick,
113 &full_bytes,
114 message.compressed,
115 )?;
116 }
117 EDemoCommands::DemSendTables if self.needs_class_metadata() => {
118 let payload = Self::materialize_payload(&mut payload, &message)?;
119 let msg = CDemoSendTables::decode(payload.as_slice())?;
120 self.parser.dem_send_tables(msg)?;
121 self.write_demo_message_with_compression(
122 message.msg_type,
123 message.tick,
124 &payload,
125 message.compressed,
126 )?;
127 }
128 EDemoCommands::DemClassInfo if self.needs_class_metadata() => {
129 let payload = Self::materialize_payload(&mut payload, &message)?;
130 let msg = CDemoClassInfo::decode(payload.as_slice())?;
131 self.parser.dem_class_info(msg)?;
132 self.write_demo_message_with_compression(
133 message.msg_type,
134 message.tick,
135 &payload,
136 message.compressed,
137 )?;
138 }
139 EDemoCommands::DemStringTables => {
140 if !self.needs_demo_string_table_scan() {
141 self.write_message_or_raw(&message, payload.as_deref())?;
142 continue;
143 }
144
145 let payload = Self::materialize_payload(&mut payload, &message)?;
146 let mut msg = CDemoStringTables::decode(payload.as_slice())?;
147 let mut changed = false;
148 if self.rewrites_entity_fields() {
149 changed |= self.rewrite_instance_baselines(&mut msg)?;
150 }
151 changed |= self.rewrite_demo_string_table_entries(message.tick, &mut msg)?;
152 let mut out_payload: Option<Vec<u8>> = None;
153 let ctx = &self.parser.context;
154 for rewriter in self.rewriters.iter_mut().filter(|rewriter| {
155 rewriter
156 .interests()
157 .contains(RewriteInterests::DEMO_STRING_TABLES)
158 }) {
159 match rewriter.rewrite_demo_string_tables(ctx, message.tick, &mut msg)? {
160 MessageRewrite::Drop => continue 'messages,
161 MessageRewrite::Keep => {}
162 MessageRewrite::Rewrite => {
163 changed = false;
164 out_payload = Some(msg.encode_to_vec());
165 }
166 MessageRewrite::Replace(bytes) => {
167 msg = CDemoStringTables::decode(bytes.as_slice())?;
168 changed = false;
169 out_payload = Some(bytes);
170 }
171 }
172 }
173 let payload = out_payload.unwrap_or_else(|| {
174 if changed {
175 msg.encode_to_vec()
176 } else {
177 payload
178 }
179 });
180 if self.needs_demo_string_table_state() {
181 self.parser.dem_string_tables(msg)?;
182 }
183 self.write_demo_message_with_compression(
184 message.msg_type,
185 message.tick,
186 &payload,
187 message.compressed,
188 )?;
189 }
190 _ => {
191 self.write_message_or_raw(&message, payload.as_deref())?;
192 }
193 }
194 }
195
196 self.finalize_file_info_offset()?;
197 Ok(())
198 }
199
200 fn update_context_tick(&mut self, tick: u32) {
201 self.parser.context.previous_tick = self.parser.context.tick;
202 self.parser.context.tick = tick;
203 }
204}