tf_demo_parser/demo/
gamevent.rs

1pub use super::gameevent_gen::{GameEvent, GameEventType};
2use crate::demo::data::MaybeUtf8String;
3use crate::demo::message::gameevent::GameEventTypeId;
4use crate::{GameEventError, Result, Stream};
5use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
6use parse_display::Display;
7use serde::{Deserialize, Serialize};
8use std::cmp::Ordering;
9
10#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct GameEventDefinition {
13    pub id: GameEventTypeId,
14    pub event_type: GameEventType,
15    pub entries: Vec<GameEventEntry>,
16}
17
18impl PartialEq<GameEventDefinition> for GameEventDefinition {
19    fn eq(&self, other: &Self) -> bool {
20        self.id.eq(&other.id)
21    }
22}
23
24impl Eq for GameEventDefinition {}
25
26impl PartialOrd for GameEventDefinition {
27    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
28        Some(self.id.cmp(&other.id))
29    }
30}
31
32impl Ord for GameEventDefinition {
33    fn cmp(&self, other: &Self) -> Ordering {
34        self.id.cmp(&other.id)
35    }
36}
37
38#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
39#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
40pub struct GameEventEntry {
41    pub name: String,
42    pub kind: GameEventValueType,
43}
44
45#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
46#[derive(BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Display, Serialize, Deserialize)]
47#[discriminant_bits = 3]
48pub enum GameEventValueType {
49    None = 0,
50    String = 1,
51    Float = 2,
52    Long = 3,
53    Short = 4,
54    Byte = 5,
55    Boolean = 6,
56    Local = 7,
57}
58
59#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
60#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
61pub enum GameEventValue {
62    String(MaybeUtf8String),
63    Float(f32),
64    Long(u32),
65    Short(u16),
66    Byte(u8),
67    Boolean(bool),
68    Local,
69}
70
71fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<GameEventValue> {
72    Ok(match definition.kind {
73        GameEventValueType::String => GameEventValue::String(stream.read()?),
74        GameEventValueType::Float => GameEventValue::Float(stream.read()?),
75        GameEventValueType::Long => GameEventValue::Long(stream.read()?),
76        GameEventValueType::Short => GameEventValue::Short(stream.read()?),
77        GameEventValueType::Byte => GameEventValue::Byte(stream.read()?),
78        GameEventValueType::Boolean => GameEventValue::Boolean(stream.read()?),
79        GameEventValueType::Local => GameEventValue::Local,
80        GameEventValueType::None => return Err(GameEventError::NoneValue.into()),
81    })
82}
83
84impl BitWrite<LittleEndian> for GameEventValue {
85    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> bitbuffer::Result<()> {
86        match self {
87            GameEventValue::String(value) => value.write(stream),
88            GameEventValue::Float(value) => value.write(stream),
89            GameEventValue::Long(value) => value.write(stream),
90            GameEventValue::Short(value) => value.write(stream),
91            GameEventValue::Byte(value) => value.write(stream),
92            GameEventValue::Boolean(value) => value.write(stream),
93            GameEventValue::Local => Ok(()),
94        }
95    }
96}
97
98impl GameEventValue {
99    pub fn get_type(&self) -> GameEventValueType {
100        match self {
101            GameEventValue::String(_) => GameEventValueType::String,
102            GameEventValue::Float(_) => GameEventValueType::Float,
103            GameEventValue::Long(_) => GameEventValueType::Long,
104            GameEventValue::Short(_) => GameEventValueType::Short,
105            GameEventValue::Byte(_) => GameEventValueType::Byte,
106            GameEventValue::Boolean(_) => GameEventValueType::Boolean,
107            GameEventValue::Local => GameEventValueType::Local,
108        }
109    }
110}
111
112pub trait EventValue: Sized {
113    fn value_type() -> GameEventValueType;
114}
115
116impl EventValue for String {
117    fn value_type() -> GameEventValueType {
118        GameEventValueType::String
119    }
120}
121
122impl EventValue for MaybeUtf8String {
123    fn value_type() -> GameEventValueType {
124        GameEventValueType::String
125    }
126}
127
128impl EventValue for f32 {
129    fn value_type() -> GameEventValueType {
130        GameEventValueType::Float
131    }
132}
133
134impl EventValue for u32 {
135    fn value_type() -> GameEventValueType {
136        GameEventValueType::Long
137    }
138}
139
140impl EventValue for u16 {
141    fn value_type() -> GameEventValueType {
142        GameEventValueType::Short
143    }
144}
145
146impl EventValue for u8 {
147    fn value_type() -> GameEventValueType {
148        GameEventValueType::Byte
149    }
150}
151
152impl EventValue for bool {
153    fn value_type() -> GameEventValueType {
154        GameEventValueType::Boolean
155    }
156}
157
158impl EventValue for () {
159    fn value_type() -> GameEventValueType {
160        GameEventValueType::Local
161    }
162}
163
164#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
165#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
166pub struct RawGameEvent {
167    pub event_type: GameEventType,
168    pub values: Vec<GameEventValue>,
169}
170
171impl RawGameEvent {
172    pub fn read(stream: &mut Stream, definition: &GameEventDefinition) -> Result<Self> {
173        let mut values: Vec<GameEventValue> = Vec::with_capacity(definition.entries.len());
174        for entry in &definition.entries {
175            values.push(read_event_value(stream, entry)?);
176        }
177
178        Ok(RawGameEvent {
179            event_type: definition.event_type.clone(),
180            values,
181        })
182    }
183}
184
185impl BitWrite<LittleEndian> for RawGameEvent {
186    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> bitbuffer::Result<()> {
187        for value in self.values.iter() {
188            value.write(stream)?;
189        }
190        Ok(())
191    }
192}
193
194pub trait FromRawGameEvent: Sized {
195    fn from_raw_event(values: Vec<GameEventValue>) -> Result<Self>;
196}
197
198impl<T: FromRawGameEvent> FromRawGameEvent for Box<T> {
199    fn from_raw_event(values: Vec<GameEventValue>) -> Result<Self> {
200        Ok(Box::new(T::from_raw_event(values)?))
201    }
202}