tf_demo_parser/demo/message/
bspdecal.rs

1use crate::demo::sendprop::{read_bit_coord, write_bit_coord};
2use crate::demo::vector::Vector;
3use crate::{ReadResult, Stream};
4use bitbuffer::{BitRead, BitWrite, BitWriteSized, BitWriteStream, LittleEndian};
5use serde::{Deserialize, Serialize};
6
7#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct BSPDecalMessage {
10    pub position: Vector,
11    pub texture_index: u16,
12    pub ent_index: u16,
13    pub model_index: u16,
14    pub low_priority: bool,
15}
16
17impl BitRead<'_, LittleEndian> for BSPDecalMessage {
18    fn read(stream: &mut Stream) -> ReadResult<Self> {
19        let position = {
20            let (has_x, has_y, has_z) = stream.read()?;
21
22            Vector {
23                x: if has_x { read_bit_coord(stream)? } else { 0f32 },
24                y: if has_y { read_bit_coord(stream)? } else { 0f32 },
25                z: if has_z { read_bit_coord(stream)? } else { 0f32 },
26            }
27        };
28
29        let texture_index = stream.read_sized(9)?;
30        let (ent_index, model_index): (u16, u16) = if stream.read()? {
31            (stream.read_sized(11)?, stream.read_sized(13)?)
32        } else {
33            (0, 0)
34        };
35        let low_priority = stream.read()?;
36
37        Ok(BSPDecalMessage {
38            position,
39            texture_index,
40            ent_index,
41            model_index,
42            low_priority,
43        })
44    }
45}
46
47impl BitWrite<LittleEndian> for BSPDecalMessage {
48    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> ReadResult<()> {
49        let has_x = self.position.x != 0.0;
50        let has_y = self.position.y != 0.0;
51        let has_z = self.position.z != 0.0;
52        (has_x, has_y, has_z).write(stream)?;
53
54        if has_x {
55            write_bit_coord(self.position.x, stream)?;
56        }
57        if has_y {
58            write_bit_coord(self.position.y, stream)?;
59        }
60        if has_z {
61            write_bit_coord(self.position.z, stream)?;
62        }
63        self.texture_index.write_sized(stream, 9)?;
64        if self.ent_index != 0 || self.model_index != 0 {
65            true.write(stream)?;
66            self.ent_index.write_sized(stream, 11)?;
67            self.model_index.write_sized(stream, 13)?;
68        } else {
69            false.write(stream)?;
70        }
71        self.low_priority.write(stream)?;
72
73        Ok(())
74    }
75}
76
77#[test]
78fn test_decal_roundtrip() {
79    crate::test_roundtrip_write(BSPDecalMessage {
80        position: Vector::default(),
81        texture_index: 0,
82        ent_index: 0,
83        model_index: 0,
84        low_priority: false,
85    });
86    crate::test_roundtrip_write(BSPDecalMessage {
87        position: Vector {
88            x: 1.0,
89            y: 0.5,
90            z: 0.0,
91        },
92        texture_index: 12,
93        ent_index: 15,
94        model_index: 2,
95        low_priority: true,
96    });
97}