pub use super::gameevent_gen::{GameEvent, GameEventType}; use crate::demo::data::MaybeUtf8String; use crate::demo::message::gameevent::GameEventTypeId; use crate::{GameEventError, Result, Stream}; use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian}; use parse_display::Display; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GameEventDefinition { pub id: GameEventTypeId, pub event_type: GameEventType, pub entries: Vec, } impl PartialEq for GameEventDefinition { fn eq(&self, other: &Self) -> bool { self.id.eq(&other.id) } } impl Eq for GameEventDefinition {} impl PartialOrd for GameEventDefinition { fn partial_cmp(&self, other: &Self) -> Option { Some(self.id.cmp(&other.id)) } } impl Ord for GameEventDefinition { fn cmp(&self, other: &Self) -> Ordering { self.id.cmp(&other.id) } } #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct GameEventEntry { pub name: String, pub kind: GameEventValueType, } #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[derive(BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Display, Serialize, Deserialize)] #[discriminant_bits = 3] pub enum GameEventValueType { None = 0, String = 1, Float = 2, Long = 3, Short = 4, Byte = 5, Boolean = 6, Local = 7, } #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum GameEventValue { String(MaybeUtf8String), Float(f32), Long(u32), Short(u16), Byte(u8), Boolean(bool), Local, } fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result { Ok(match definition.kind { GameEventValueType::String => GameEventValue::String(stream.read()?), GameEventValueType::Float => GameEventValue::Float(stream.read()?), GameEventValueType::Long => GameEventValue::Long(stream.read()?), GameEventValueType::Short => GameEventValue::Short(stream.read()?), GameEventValueType::Byte => GameEventValue::Byte(stream.read()?), GameEventValueType::Boolean => GameEventValue::Boolean(stream.read()?), GameEventValueType::Local => GameEventValue::Local, GameEventValueType::None => return Err(GameEventError::NoneValue.into()), }) } impl BitWrite for GameEventValue { fn write(&self, stream: &mut BitWriteStream) -> bitbuffer::Result<()> { match self { GameEventValue::String(value) => value.write(stream), GameEventValue::Float(value) => value.write(stream), GameEventValue::Long(value) => value.write(stream), GameEventValue::Short(value) => value.write(stream), GameEventValue::Byte(value) => value.write(stream), GameEventValue::Boolean(value) => value.write(stream), GameEventValue::Local => Ok(()), } } } impl GameEventValue { pub fn get_type(&self) -> GameEventValueType { match self { GameEventValue::String(_) => GameEventValueType::String, GameEventValue::Float(_) => GameEventValueType::Float, GameEventValue::Long(_) => GameEventValueType::Long, GameEventValue::Short(_) => GameEventValueType::Short, GameEventValue::Byte(_) => GameEventValueType::Byte, GameEventValue::Boolean(_) => GameEventValueType::Boolean, GameEventValue::Local => GameEventValueType::Local, } } } pub trait EventValue: Sized { fn value_type() -> GameEventValueType; } impl EventValue for String { fn value_type() -> GameEventValueType { GameEventValueType::String } } impl EventValue for MaybeUtf8String { fn value_type() -> GameEventValueType { GameEventValueType::String } } impl EventValue for f32 { fn value_type() -> GameEventValueType { GameEventValueType::Float } } impl EventValue for u32 { fn value_type() -> GameEventValueType { GameEventValueType::Long } } impl EventValue for u16 { fn value_type() -> GameEventValueType { GameEventValueType::Short } } impl EventValue for u8 { fn value_type() -> GameEventValueType { GameEventValueType::Byte } } impl EventValue for bool { fn value_type() -> GameEventValueType { GameEventValueType::Boolean } } impl EventValue for () { fn value_type() -> GameEventValueType { GameEventValueType::Local } } #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)] pub struct RawGameEvent { pub event_type: GameEventType, pub values: Vec, } impl RawGameEvent { pub fn read(stream: &mut Stream, definition: &GameEventDefinition) -> Result { let mut values: Vec = Vec::with_capacity(definition.entries.len()); for entry in &definition.entries { values.push(read_event_value(stream, entry)?); } Ok(RawGameEvent { event_type: definition.event_type.clone(), values, }) } } impl BitWrite for RawGameEvent { fn write(&self, stream: &mut BitWriteStream) -> bitbuffer::Result<()> { for value in self.values.iter() { value.write(stream)?; } Ok(()) } } pub trait FromRawGameEvent: Sized { fn from_raw_event(values: Vec) -> Result; } impl FromRawGameEvent for Box { fn from_raw_event(values: Vec) -> Result { Ok(Box::new(T::from_raw_event(values)?)) } }