tf_demo_parser/demo/message/
tempentities.rs

1use super::stringtable::read_var_int;
2use crate::demo::message::packetentities::PacketEntitiesMessage;
3use crate::demo::message::stringtable::{encode_var_int_fixed, log_base2};
4use crate::demo::packet::datatable::ClassId;
5use crate::demo::parser::{Encode, ParseBitSkip};
6use crate::demo::sendprop::SendProp;
7use crate::Result;
8use crate::{Parse, ParseError, ParserState, Stream};
9use bitbuffer::{BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
10use serde::{Deserialize, Serialize};
11
12#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
13#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
14pub struct TempEntitiesMessage {
15    pub events: Vec<EventInfo>,
16}
17
18#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
19#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
20pub struct EventInfo {
21    pub class_id: ClassId,
22    pub fire_delay: f32,
23    pub reliable: bool,
24    pub props: Vec<SendProp>,
25}
26
27impl Parse<'_> for TempEntitiesMessage {
28    fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
29        let count: u8 = stream.read()?;
30        let length = if state.protocol_version > 23 {
31            read_var_int(stream)?
32        } else {
33            stream.read_sized(17)?
34        };
35        let data = stream.read_bits(length as usize)?;
36        let mut stream = data.clone();
37        let stream = &mut stream;
38
39        let (count, reliable) = if count == 0 {
40            (1, true)
41        } else {
42            (count, false)
43        };
44
45        let mut events: Vec<EventInfo> = Vec::with_capacity(count as usize);
46
47        for _ in 0..count {
48            let delay = if stream.read()? {
49                let raw: u8 = stream.read()?;
50                raw as f32 / 100.0
51            } else {
52                0.0
53            };
54
55            let class_id = if stream.read()? {
56                let bits = log_base2(state.server_classes.len()) + 1;
57                (stream.read_sized::<u16>(bits as usize)?.saturating_sub(1)).into()
58            } else {
59                let last = events.last().ok_or(ParseError::InvalidDemo(
60                    "temp entity update without previous",
61                ))?;
62
63                last.class_id
64            };
65            let send_table = state
66                .send_tables
67                .get(usize::from(class_id))
68                .ok_or(ParseError::UnknownServerClass(class_id))?;
69
70            let mut props = Vec::new();
71            PacketEntitiesMessage::read_update(stream, send_table, &mut props, 0u32.into())?;
72
73            events.push(EventInfo {
74                class_id,
75                fire_delay: delay,
76                reliable,
77                props,
78            });
79        }
80
81        Ok(TempEntitiesMessage { events })
82    }
83}
84
85impl ParseBitSkip<'_> for TempEntitiesMessage {
86    fn parse_skip(stream: &mut Stream, state: &ParserState) -> Result<()> {
87        let _: u8 = stream.read()?;
88        let length = if state.protocol_version > 23 {
89            read_var_int(stream)?
90        } else {
91            stream.read_sized(17)?
92        };
93        stream.skip_bits(length as usize)?;
94        Ok(())
95    }
96}
97
98impl Encode for TempEntitiesMessage {
99    fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
100        let count = match (self.events.len(), self.events.first()) {
101            (1, Some(event)) if event.reliable => 0,
102            (1, _) => 1,
103            (len, _) => len as u8,
104        };
105        count.write(stream)?;
106
107        stream.reserve_int::<ParseError, _>(40, |stream| {
108            let start = stream.bit_len();
109            let mut last_class_id = u16::MAX.into();
110
111            for event in self.events.iter() {
112                if event.fire_delay > 0.0 {
113                    true.write(stream)?;
114                    ((event.fire_delay * 100.0) as u8).write(stream)?;
115                } else {
116                    false.write(stream)?;
117                }
118
119                if event.class_id != last_class_id {
120                    true.write(stream)?;
121                    let bits = log_base2(state.server_classes.len()) + 1;
122                    let id: u16 = event.class_id.into();
123                    (id + 1).write_sized(stream, bits as usize)?;
124                } else {
125                    false.write(stream)?;
126                }
127                last_class_id = event.class_id;
128
129                let send_table = state
130                    .send_tables
131                    .get(usize::from(event.class_id))
132                    .ok_or(ParseError::UnknownServerClass(event.class_id))?;
133                PacketEntitiesMessage::write_update(&event.props, stream, send_table, 0u32.into())?;
134            }
135            let end = stream.bit_len();
136            Ok(encode_var_int_fixed((end - start) as u32))
137        })?;
138        Ok(())
139    }
140}