Skip to main content

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