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}