mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
make gameevent parsing more backwards compatible
This commit is contained in:
parent
8ff5e5e6df
commit
ab87b34de8
6 changed files with 16415 additions and 4409 deletions
|
|
@ -19,5 +19,8 @@ in
|
|||
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"schemars-0.8.16" = "sha256-mQR56Ym76gSRulZrThmZHHw2JfhEgYhWXabwaYmyMYs=";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,7 +225,9 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
|||
let span = Span::call_site();
|
||||
|
||||
let imports = quote!(
|
||||
use super::gamevent::{EventValue, GameEventDefinition, GameEventEntry, RawGameEvent};
|
||||
use super::gamevent::{
|
||||
EventValue, GameEventDefinition, GameEventEntry, RawGameEvent, GameEventValue,
|
||||
};
|
||||
use crate::demo::Stream;
|
||||
use crate::{ParseError, Result};
|
||||
use bitbuffer::{BitRead, LittleEndian, BitWrite, BitWriteStream};
|
||||
|
|
@ -241,32 +243,31 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
|||
quote!(pub #name: #ty,)
|
||||
});
|
||||
|
||||
let name = Ident::new(
|
||||
&format!("{}Event", get_event_name(event.event_type.as_str())),
|
||||
span,
|
||||
);
|
||||
let field_getters = event.entries.iter().map(|entry| {
|
||||
let raw_name = &entry.name;
|
||||
let name = get_entry_name(&entry.name);
|
||||
let ident = Ident::new(name.as_str(), span);
|
||||
|
||||
quote!(#raw_name => Ok(self.#ident.clone().into()))
|
||||
});
|
||||
|
||||
let event_name = get_event_name(event.event_type.as_str());
|
||||
let name = Ident::new(&format!("{event_name}Event"), span);
|
||||
|
||||
let entry_readers = event.entries.iter().map(|entry| {
|
||||
let raw_name = &entry.name;
|
||||
let name_str = get_entry_name(&entry.name);
|
||||
let name = Ident::new(&name_str, span);
|
||||
let ty = Ident::new(get_type_name(entry.kind), span);
|
||||
|
||||
quote!(
|
||||
#name: read_value::<#ty>(stream, iter.next(), #name_str)?,
|
||||
#name: read_value::<#ty>(stream, definition.get_entry(#raw_name), #name_str)?,
|
||||
)
|
||||
});
|
||||
|
||||
let definition_iter = if event.entries.len() > 0 {
|
||||
quote!(
|
||||
let mut iter = definition.entries.iter();
|
||||
)
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
|
||||
quote!(
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
#[derive(Debug, BitWrite, PartialEq, Serialize, Deserialize, Clone)]
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
pub struct #name {
|
||||
#(#fields)*
|
||||
}
|
||||
|
|
@ -274,12 +275,30 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
|||
impl #name {
|
||||
#[allow(unused_variables)]
|
||||
fn read(stream: &mut Stream, definition: &GameEventDefinition) -> Result<Self> {
|
||||
#definition_iter
|
||||
|
||||
Ok(#name {
|
||||
#(#entry_readers)*
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn get_field(&self, field: &str) -> Result<GameEventValue> {
|
||||
match field {
|
||||
#(#field_getters,)*
|
||||
_ => Err(ParseError::MissingGameEventValue {
|
||||
ty: #event_name,
|
||||
field: field.into(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn write(&self, stream: &mut BitWriteStream<LittleEndian>, definition: &GameEventDefinition) -> Result<()> {
|
||||
for entry in &definition.entries {
|
||||
let value = self.get_field(&entry.name).unwrap_or_else(|_| entry.kind.default_value());
|
||||
stream.write(&value)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
)
|
||||
});
|
||||
|
|
@ -353,7 +372,7 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
|||
let variant_name = Ident::new(&name, span);
|
||||
|
||||
quote!(
|
||||
GameEvent::#variant_name(event) => event.write(stream),
|
||||
GameEvent::#variant_name(event) => event.write(stream, definition),
|
||||
)
|
||||
});
|
||||
|
||||
|
|
@ -430,10 +449,10 @@ pub fn generate_game_events(demo: Demo) -> TokenStream {
|
|||
GameEventType::Unknown(_) => GameEvent::Unknown(RawGameEvent::read(stream, definition)?),
|
||||
})
|
||||
}
|
||||
pub fn write(&self, stream: &mut BitWriteStream<LittleEndian>) -> bitbuffer::Result<()> {
|
||||
pub fn write(&self, stream: &mut BitWriteStream<LittleEndian>, definition: &GameEventDefinition) -> Result<()> {
|
||||
match &self {
|
||||
#(#write_events)*
|
||||
GameEvent::Unknown(raw) => raw.write(stream),
|
||||
GameEvent::Unknown(raw) => Ok(raw.write(stream)?),
|
||||
}
|
||||
}
|
||||
pub fn event_type(&self) -> GameEventType {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -15,6 +15,12 @@ pub struct GameEventDefinition {
|
|||
pub entries: Vec<GameEventEntry>,
|
||||
}
|
||||
|
||||
impl GameEventDefinition {
|
||||
pub fn get_entry(&self, name: &str) -> Option<&GameEventEntry> {
|
||||
self.entries.iter().find(|entry| entry.name == name)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<GameEventDefinition> for GameEventDefinition {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id.eq(&other.id)
|
||||
|
|
@ -56,6 +62,21 @@ pub enum GameEventValueType {
|
|||
Local = 7,
|
||||
}
|
||||
|
||||
impl GameEventValueType {
|
||||
pub fn default_value(&self) -> GameEventValue {
|
||||
match self {
|
||||
GameEventValueType::None => GameEventValue::Local,
|
||||
GameEventValueType::String => GameEventValue::String(Default::default()),
|
||||
GameEventValueType::Float => GameEventValue::Float(Default::default()),
|
||||
GameEventValueType::Long => GameEventValue::Long(Default::default()),
|
||||
GameEventValueType::Short => GameEventValue::Short(Default::default()),
|
||||
GameEventValueType::Byte => GameEventValue::Byte(Default::default()),
|
||||
GameEventValueType::Boolean => GameEventValue::Boolean(Default::default()),
|
||||
GameEventValueType::Local => GameEventValue::Local,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum GameEventValue {
|
||||
|
|
@ -68,6 +89,42 @@ pub enum GameEventValue {
|
|||
Local,
|
||||
}
|
||||
|
||||
impl From<MaybeUtf8String> for GameEventValue {
|
||||
fn from(value: MaybeUtf8String) -> Self {
|
||||
GameEventValue::String(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for GameEventValue {
|
||||
fn from(value: f32) -> Self {
|
||||
GameEventValue::Float(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for GameEventValue {
|
||||
fn from(value: u32) -> Self {
|
||||
GameEventValue::Long(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u16> for GameEventValue {
|
||||
fn from(value: u16) -> Self {
|
||||
GameEventValue::Short(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for GameEventValue {
|
||||
fn from(value: u8) -> Self {
|
||||
GameEventValue::Byte(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for GameEventValue {
|
||||
fn from(value: bool) -> Self {
|
||||
GameEventValue::Boolean(value)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<GameEventValue> {
|
||||
Ok(match definition.kind {
|
||||
GameEventValueType::String => GameEventValue::String(stream.read()?),
|
||||
|
|
|
|||
|
|
@ -52,14 +52,17 @@ impl Parse<'_> for GameEventMessage {
|
|||
}
|
||||
|
||||
impl Encode for GameEventMessage {
|
||||
fn encode(
|
||||
&self,
|
||||
stream: &mut BitWriteStream<LittleEndian>,
|
||||
_state: &ParserState,
|
||||
) -> Result<()> {
|
||||
fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
|
||||
let definition = state
|
||||
.event_definitions
|
||||
.iter()
|
||||
.find(|def| def.event_type == self.event_type)
|
||||
.ok_or_else(|| {
|
||||
ParseError::MalformedGameEvent(GameEventError::UnknownType(self.event_type_id))
|
||||
})?;
|
||||
Ok(stream.reserve_length(11, |stream| {
|
||||
self.event_type_id.write(stream)?;
|
||||
self.event.write(stream)
|
||||
self.event.write(stream, definition)
|
||||
})?)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,12 @@ pub enum ParseError {
|
|||
name: &'static str,
|
||||
found_type: GameEventValueType,
|
||||
},
|
||||
#[error(
|
||||
display = "Game event of type {} does not contain a {} value",
|
||||
ty,
|
||||
field
|
||||
)]
|
||||
MissingGameEventValue { ty: &'static str, field: String },
|
||||
#[error(display = "An entity with an unknown server class({}) was read", _0)]
|
||||
UnknownServerClass(ClassId),
|
||||
#[error(display = "Unknown send table: {}", _0)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue