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 GameEventDefinition {
19    pub fn get_entry(&self, name: &str) -> Option<&GameEventEntry> {
20        self.entries.iter().find(|entry| entry.name == name)
21    }
22}
23
24impl PartialEq<GameEventDefinition> for GameEventDefinition {
25    fn eq(&self, other: &Self) -> bool {
26        self.id.eq(&other.id)
27    }
28}
29
30impl Eq for GameEventDefinition {}
31
32impl PartialOrd for GameEventDefinition {
33    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
34        Some(self.id.cmp(&other.id))
35    }
36}
37
38impl Ord for GameEventDefinition {
39    fn cmp(&self, other: &Self) -> Ordering {
40        self.id.cmp(&other.id)
41    }
42}
43
44#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
46pub struct GameEventEntry {
47    pub name: String,
48    pub kind: GameEventValueType,
49}
50
51#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
52#[derive(BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Display, Serialize, Deserialize)]
53#[discriminant_bits = 3]
54pub enum GameEventValueType {
55    None = 0,
56    String = 1,
57    Float = 2,
58    Long = 3,
59    Short = 4,
60    Byte = 5,
61    Boolean = 6,
62    Local = 7,
63}
64
65impl GameEventValueType {
66    pub fn default_value(&self) -> GameEventValue {
67        match self {
68            GameEventValueType::None => GameEventValue::Local,
69            GameEventValueType::String => GameEventValue::String(Default::default()),
70            GameEventValueType::Float => GameEventValue::Float(Default::default()),
71            GameEventValueType::Long => GameEventValue::Long(Default::default()),
72            GameEventValueType::Short => GameEventValue::Short(Default::default()),
73            GameEventValueType::Byte => GameEventValue::Byte(Default::default()),
74            GameEventValueType::Boolean => GameEventValue::Boolean(Default::default()),
75            GameEventValueType::Local => GameEventValue::Local,
76        }
77    }
78}
79
80#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
81#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
82pub enum GameEventValue {
83    String(MaybeUtf8String),
84    Float(f32),
85    Long(u32),
86    Short(u16),
87    Byte(u8),
88    Boolean(bool),
89    Local,
90}
91
92impl From<MaybeUtf8String> for GameEventValue {
93    fn from(value: MaybeUtf8String) -> Self {
94        GameEventValue::String(value)
95    }
96}
97
98impl From<f32> for GameEventValue {
99    fn from(value: f32) -> Self {
100        GameEventValue::Float(value)
101    }
102}
103
104impl From<u32> for GameEventValue {
105    fn from(value: u32) -> Self {
106        GameEventValue::Long(value)
107    }
108}
109
110impl From<u16> for GameEventValue {
111    fn from(value: u16) -> Self {
112        GameEventValue::Short(value)
113    }
114}
115
116impl From<u8> for GameEventValue {
117    fn from(value: u8) -> Self {
118        GameEventValue::Byte(value)
119    }
120}
121
122impl From<bool> for GameEventValue {
123    fn from(value: bool) -> Self {
124        GameEventValue::Boolean(value)
125    }
126}
127
128fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<GameEventValue> {
129    Ok(match definition.kind {
130        GameEventValueType::String => GameEventValue::String(stream.read()?),
131        GameEventValueType::Float => GameEventValue::Float(stream.read()?),
132        GameEventValueType::Long => GameEventValue::Long(stream.read()?),
133        GameEventValueType::Short => GameEventValue::Short(stream.read()?),
134        GameEventValueType::Byte => GameEventValue::Byte(stream.read()?),
135        GameEventValueType::Boolean => GameEventValue::Boolean(stream.read()?),
136        GameEventValueType::Local => GameEventValue::Local,
137        GameEventValueType::None => return Err(GameEventError::NoneValue.into()),
138    })
139}
140
141impl BitWrite<LittleEndian> for GameEventValue {
142    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> bitbuffer::Result<()> {
143        match self {
144            GameEventValue::String(value) => value.write(stream),
145            GameEventValue::Float(value) => value.write(stream),
146            GameEventValue::Long(value) => value.write(stream),
147            GameEventValue::Short(value) => value.write(stream),
148            GameEventValue::Byte(value) => value.write(stream),
149            GameEventValue::Boolean(value) => value.write(stream),
150            GameEventValue::Local => Ok(()),
151        }
152    }
153}
154
155impl GameEventValue {
156    pub fn get_type(&self) -> GameEventValueType {
157        match self {
158            GameEventValue::String(_) => GameEventValueType::String,
159            GameEventValue::Float(_) => GameEventValueType::Float,
160            GameEventValue::Long(_) => GameEventValueType::Long,
161            GameEventValue::Short(_) => GameEventValueType::Short,
162            GameEventValue::Byte(_) => GameEventValueType::Byte,
163            GameEventValue::Boolean(_) => GameEventValueType::Boolean,
164            GameEventValue::Local => GameEventValueType::Local,
165        }
166    }
167}
168
169pub trait EventValue: Sized {
170    fn value_type() -> GameEventValueType;
171}
172
173impl EventValue for String {
174    fn value_type() -> GameEventValueType {
175        GameEventValueType::String
176    }
177}
178
179impl EventValue for MaybeUtf8String {
180    fn value_type() -> GameEventValueType {
181        GameEventValueType::String
182    }
183}
184
185impl EventValue for f32 {
186    fn value_type() -> GameEventValueType {
187        GameEventValueType::Float
188    }
189}
190
191impl EventValue for u32 {
192    fn value_type() -> GameEventValueType {
193        GameEventValueType::Long
194    }
195}
196
197impl EventValue for u16 {
198    fn value_type() -> GameEventValueType {
199        GameEventValueType::Short
200    }
201}
202
203impl EventValue for u8 {
204    fn value_type() -> GameEventValueType {
205        GameEventValueType::Byte
206    }
207}
208
209impl EventValue for bool {
210    fn value_type() -> GameEventValueType {
211        GameEventValueType::Boolean
212    }
213}
214
215impl EventValue for () {
216    fn value_type() -> GameEventValueType {
217        GameEventValueType::Local
218    }
219}
220
221#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
222#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
223pub struct RawGameEvent {
224    pub event_type: GameEventType,
225    pub values: Vec<GameEventValue>,
226}
227
228impl RawGameEvent {
229    pub fn read(stream: &mut Stream, definition: &GameEventDefinition) -> Result<Self> {
230        let mut values: Vec<GameEventValue> = Vec::with_capacity(definition.entries.len());
231        for entry in &definition.entries {
232            values.push(read_event_value(stream, entry)?);
233        }
234
235        Ok(RawGameEvent {
236            event_type: definition.event_type.clone(),
237            values,
238        })
239    }
240}
241
242impl BitWrite<LittleEndian> for RawGameEvent {
243    fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> bitbuffer::Result<()> {
244        for value in self.values.iter() {
245            value.write(stream)?;
246        }
247        Ok(())
248    }
249}
250
251pub trait FromRawGameEvent: Sized {
252    fn from_raw_event(values: Vec<GameEventValue>) -> Result<Self>;
253}
254
255impl<T: FromRawGameEvent> FromRawGameEvent for Box<T> {
256    fn from_raw_event(values: Vec<GameEventValue>) -> Result<Self> {
257        Ok(Box::new(T::from_raw_event(values)?))
258    }
259}