mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 10:14:06 +02:00
skip messages we dont care about
This commit is contained in:
parent
b9a92be010
commit
128bf1ceb2
17 changed files with 237 additions and 71 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
use bitstream_reader::{BitRead, LittleEndian, BitSkip};
|
||||||
|
|
||||||
use crate::demo::sendprop::read_bit_coord;
|
use crate::demo::sendprop::read_bit_coord;
|
||||||
use crate::demo::vector::Vector;
|
use crate::demo::vector::Vector;
|
||||||
|
|
@ -44,3 +44,5 @@ impl BitRead<LittleEndian> for BSPDecalMessage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for BSPDecalMessage{}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
use bitstream_reader::{BitRead, BitReadSized, LittleEndian, BitSkip};
|
||||||
|
|
||||||
use crate::demo::message::stringtable::log_base2;
|
use crate::demo::message::stringtable::log_base2;
|
||||||
use crate::{ReadResult, Stream};
|
use crate::{ReadResult, Stream};
|
||||||
|
|
@ -40,3 +40,5 @@ impl BitRead<LittleEndian> for ClassInfoMessage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for ClassInfoMessage{}
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
use bitstream_reader::{BitRead, LittleEndian, BitSkip};
|
||||||
|
|
||||||
use crate::demo::gameevent_gen::GameEventType;
|
use crate::demo::gameevent_gen::GameEventType;
|
||||||
use crate::demo::gamevent::{
|
use crate::demo::gamevent::{
|
||||||
GameEvent, GameEventDefinition, GameEventEntry, GameEventValue, GameEventValueType,
|
GameEvent, GameEventDefinition, GameEventEntry, GameEventValue, GameEventValueType,
|
||||||
RawGameEvent,
|
RawGameEvent,
|
||||||
};
|
};
|
||||||
use crate::{Parse, ParserState, ReadResult, Result, Stream};
|
use crate::{Parse, ParserState, ReadResult, Result, Stream, ParseError};
|
||||||
|
use crate::demo::parser::ParseBitSkip;
|
||||||
|
|
||||||
fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<GameEventValue> {
|
fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<GameEventValue> {
|
||||||
Ok(match definition.kind {
|
Ok(match definition.kind {
|
||||||
|
|
@ -52,6 +53,13 @@ impl Parse for GameEventMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParseBitSkip for GameEventMessage {
|
||||||
|
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
||||||
|
let length: u16 = stream.read_sized(11)?;
|
||||||
|
stream.skip_bits(length as usize).map_err(ParseError::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct GameEventTypeId(u16);
|
pub struct GameEventTypeId(u16);
|
||||||
|
|
||||||
|
|
@ -102,3 +110,5 @@ impl BitRead<LittleEndian> for GameEventListMessage {
|
||||||
Ok(GameEventListMessage { event_list })
|
Ok(GameEventListMessage { event_list })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for GameEventListMessage{}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::Stream;
|
use crate::Stream;
|
||||||
/// Messages that consists only of primitives and string and can be derived
|
/// Messages that consists only of primitives and string and can be derived
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
use bitstream_reader::{BitRead, LittleEndian, BitSize, BitSkip};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, Debug)]
|
||||||
|
|
@ -10,7 +10,9 @@ pub struct FileMessage {
|
||||||
pub requested: bool,
|
pub requested: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
impl BitSkip<LittleEndian> for FileMessage{}
|
||||||
|
|
||||||
|
#[derive(BitRead, BitSize, Debug)]
|
||||||
pub struct NetTickMessage {
|
pub struct NetTickMessage {
|
||||||
pub tick: u32,
|
pub tick: u32,
|
||||||
pub frame_time: u16,
|
pub frame_time: u16,
|
||||||
|
|
@ -22,7 +24,9 @@ pub struct StringCmdMessage {
|
||||||
pub command: String,
|
pub command: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
impl BitSkip<LittleEndian> for StringCmdMessage{}
|
||||||
|
|
||||||
|
#[derive(BitRead, BitSize, Debug)]
|
||||||
pub struct SigOnStateMessage {
|
pub struct SigOnStateMessage {
|
||||||
pub state: u8,
|
pub state: u8,
|
||||||
pub count: u32,
|
pub count: u32,
|
||||||
|
|
@ -33,6 +37,8 @@ pub struct PrintMessage {
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for PrintMessage{}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, Debug)]
|
||||||
pub struct ServerInfoMessage {
|
pub struct ServerInfoMessage {
|
||||||
pub version: u16,
|
pub version: u16,
|
||||||
|
|
@ -54,18 +60,20 @@ pub struct ServerInfoMessage {
|
||||||
pub replay: bool,
|
pub replay: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
impl BitSkip<LittleEndian> for ServerInfoMessage{}
|
||||||
|
|
||||||
|
#[derive(BitRead, BitSize, Debug)]
|
||||||
pub struct SetPauseMessage {
|
pub struct SetPauseMessage {
|
||||||
pub pause: bool,
|
pub pause: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitSize, Debug)]
|
||||||
pub struct SetViewMessage {
|
pub struct SetViewMessage {
|
||||||
#[size = 11]
|
#[size = 11]
|
||||||
pub index: u16,
|
pub index: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, BitSize, Debug)]
|
||||||
pub struct FixAngleMessage {
|
pub struct FixAngleMessage {
|
||||||
pub relative: bool,
|
pub relative: bool,
|
||||||
pub x: u16,
|
pub x: u16,
|
||||||
|
|
@ -86,7 +94,9 @@ pub struct EntityMessage {
|
||||||
pub data: Stream,
|
pub data: Stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
impl BitSkip<LittleEndian> for EntityMessage{}
|
||||||
|
|
||||||
|
#[derive(BitRead, BitSize, Debug)]
|
||||||
pub struct PreFetchMessage {
|
pub struct PreFetchMessage {
|
||||||
#[size = 14]
|
#[size = 14]
|
||||||
pub index: u16,
|
pub index: u16,
|
||||||
|
|
@ -101,12 +111,16 @@ pub struct MenuMessage {
|
||||||
pub index: Stream,
|
pub index: Stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for MenuMessage{}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, Debug)]
|
||||||
pub struct GetCvarValueMessage {
|
pub struct GetCvarValueMessage {
|
||||||
pub cookie: u32,
|
pub cookie: u32,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for GetCvarValueMessage{}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, Debug)]
|
||||||
#[endianness = "LittleEndian"]
|
#[endianness = "LittleEndian"]
|
||||||
pub struct CmdKeyValuesMessage {
|
pub struct CmdKeyValuesMessage {
|
||||||
|
|
@ -115,8 +129,12 @@ pub struct CmdKeyValuesMessage {
|
||||||
pub data: Stream,
|
pub data: Stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for CmdKeyValuesMessage{}
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, Debug)]
|
||||||
pub struct SetConVarMessage {
|
pub struct SetConVarMessage {
|
||||||
#[size_bits = 8]
|
#[size_bits = 8]
|
||||||
vars: HashMap<String, String>,
|
vars: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for SetConVarMessage{}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use num_traits::FromPrimitive;
|
||||||
|
|
||||||
pub use generated::*;
|
pub use generated::*;
|
||||||
|
|
||||||
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
use crate::demo::message::bspdecal::*;
|
use crate::demo::message::bspdecal::*;
|
||||||
use crate::demo::message::classinfo::*;
|
use crate::demo::message::classinfo::*;
|
||||||
use crate::demo::message::gameevent::*;
|
use crate::demo::message::gameevent::*;
|
||||||
|
|
@ -11,7 +12,7 @@ use crate::demo::message::stringtable::*;
|
||||||
use crate::demo::message::tempentities::*;
|
use crate::demo::message::tempentities::*;
|
||||||
use crate::demo::message::usermessage::*;
|
use crate::demo::message::usermessage::*;
|
||||||
use crate::demo::message::voice::*;
|
use crate::demo::message::voice::*;
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::demo::parser::ParseBitSkip;
|
||||||
|
|
||||||
pub mod bspdecal;
|
pub mod bspdecal;
|
||||||
pub mod classinfo;
|
pub mod classinfo;
|
||||||
|
|
@ -23,7 +24,7 @@ pub mod tempentities;
|
||||||
pub mod usermessage;
|
pub mod usermessage;
|
||||||
pub mod voice;
|
pub mod voice;
|
||||||
|
|
||||||
#[derive(Primitive, Debug, Clone, Copy)]
|
#[derive(Primitive, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum MessageType {
|
pub enum MessageType {
|
||||||
Empty = 0,
|
Empty = 0,
|
||||||
File = 2,
|
File = 2,
|
||||||
|
|
@ -98,6 +99,45 @@ pub enum Message {
|
||||||
impl Parse for Message {
|
impl Parse for Message {
|
||||||
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
|
fn parse(stream: &mut Stream, state: &ParserState) -> Result<Self> {
|
||||||
let message_type = MessageType::parse(stream, state)?;
|
let message_type = MessageType::parse(stream, state)?;
|
||||||
|
Self::from_type(message_type, stream, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Message {
|
||||||
|
pub fn get_message_type(&self) -> MessageType {
|
||||||
|
match self {
|
||||||
|
Message::Empty => MessageType::Empty,
|
||||||
|
Message::File(_) => MessageType::File,
|
||||||
|
Message::NetTick(_) => MessageType::NetTick,
|
||||||
|
Message::StringCmd(_) => MessageType::StringCmd,
|
||||||
|
Message::SetConVar(_) => MessageType::SetConVar,
|
||||||
|
Message::SigOnState(_) => MessageType::SigOnState,
|
||||||
|
Message::Print(_) => MessageType::Print,
|
||||||
|
Message::ServerInfo(_) => MessageType::ServerInfo,
|
||||||
|
Message::ClassInfo(_) => MessageType::ClassInfo,
|
||||||
|
Message::SetPause(_) => MessageType::SetPause,
|
||||||
|
Message::CreateStringTable(_) => MessageType::CreateStringTable,
|
||||||
|
Message::UpdateStringTable(_) => MessageType::UpdateStringTable,
|
||||||
|
Message::VoiceInit(_) => MessageType::VoiceInit,
|
||||||
|
Message::VoiceData(_) => MessageType::VoiceData,
|
||||||
|
Message::ParseSounds(_) => MessageType::ParseSounds,
|
||||||
|
Message::SetView(_) => MessageType::SetView,
|
||||||
|
Message::FixAngle(_) => MessageType::FixAngle,
|
||||||
|
Message::BspDecal(_) => MessageType::BspDecal,
|
||||||
|
Message::UserMessage(_) => MessageType::UserMessage,
|
||||||
|
Message::EntityMessage(_) => MessageType::EntityMessage,
|
||||||
|
Message::GameEvent(_) => MessageType::GameEvent,
|
||||||
|
Message::PacketEntities(_) => MessageType::PacketEntities,
|
||||||
|
Message::TempEntities(_) => MessageType::TempEntities,
|
||||||
|
Message::PreFetch(_) => MessageType::PreFetch,
|
||||||
|
Message::Menu(_) => MessageType::Menu,
|
||||||
|
Message::GameEventList(_) => MessageType::GameEventList,
|
||||||
|
Message::GetCvarValue(_) => MessageType::GetCvarValue,
|
||||||
|
Message::CmdKeyValues(_) => MessageType::CmdKeyValues,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_type(message_type: MessageType, stream: &mut Stream, state: &ParserState) -> Result<Self> {
|
||||||
Ok(match message_type {
|
Ok(match message_type {
|
||||||
MessageType::Empty => Message::Empty,
|
MessageType::Empty => Message::Empty,
|
||||||
MessageType::File => Message::File(FileMessage::parse(stream, state)?),
|
MessageType::File => Message::File(FileMessage::parse(stream, state)?),
|
||||||
|
|
@ -151,39 +191,37 @@ impl Parse for Message {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Message {
|
pub fn skip_type(message_type: MessageType, stream: &mut Stream) -> Result<()> {
|
||||||
pub fn get_message_type(&self) -> MessageType {
|
match message_type {
|
||||||
match self {
|
MessageType::Empty => Ok(()),
|
||||||
Message::Empty => MessageType::Empty,
|
MessageType::File => FileMessage::parse_skip(stream),
|
||||||
Message::File(_) => MessageType::File,
|
MessageType::NetTick => NetTickMessage::parse_skip(stream),
|
||||||
Message::NetTick(_) => MessageType::NetTick,
|
MessageType::StringCmd => StringCmdMessage::parse_skip(stream),
|
||||||
Message::StringCmd(_) => MessageType::StringCmd,
|
MessageType::SetConVar => SetConVarMessage::parse_skip(stream),
|
||||||
Message::SetConVar(_) => MessageType::SetConVar,
|
MessageType::SigOnState => SigOnStateMessage::parse_skip(stream),
|
||||||
Message::SigOnState(_) => MessageType::SigOnState,
|
MessageType::Print => PrintMessage::parse_skip(stream),
|
||||||
Message::Print(_) => MessageType::Print,
|
MessageType::ServerInfo => ServerInfoMessage::parse_skip(stream),
|
||||||
Message::ServerInfo(_) => MessageType::ServerInfo,
|
MessageType::ClassInfo => ClassInfoMessage::parse_skip(stream),
|
||||||
Message::ClassInfo(_) => MessageType::ClassInfo,
|
MessageType::SetPause => SetPauseMessage::parse_skip(stream),
|
||||||
Message::SetPause(_) => MessageType::SetPause,
|
MessageType::CreateStringTable => CreateStringTableMessage::parse_skip(stream),
|
||||||
Message::CreateStringTable(_) => MessageType::CreateStringTable,
|
MessageType::UpdateStringTable => UpdateStringTableMessage::parse_skip(stream),
|
||||||
Message::UpdateStringTable(_) => MessageType::UpdateStringTable,
|
MessageType::VoiceInit => VoiceInitMessage::parse_skip(stream),
|
||||||
Message::VoiceInit(_) => MessageType::VoiceInit,
|
MessageType::VoiceData => VoiceDataMessage::parse_skip(stream),
|
||||||
Message::VoiceData(_) => MessageType::VoiceData,
|
MessageType::ParseSounds => ParseSoundsMessage::parse_skip(stream),
|
||||||
Message::ParseSounds(_) => MessageType::ParseSounds,
|
MessageType::SetView => SetViewMessage::parse_skip(stream),
|
||||||
Message::SetView(_) => MessageType::SetView,
|
MessageType::FixAngle => FixAngleMessage::parse_skip(stream),
|
||||||
Message::FixAngle(_) => MessageType::FixAngle,
|
MessageType::BspDecal => BSPDecalMessage::parse_skip(stream),
|
||||||
Message::BspDecal(_) => MessageType::BspDecal,
|
MessageType::UserMessage => UserMessage::parse_skip(stream),
|
||||||
Message::UserMessage(_) => MessageType::UserMessage,
|
MessageType::EntityMessage => EntityMessage::parse_skip(stream),
|
||||||
Message::EntityMessage(_) => MessageType::EntityMessage,
|
MessageType::GameEvent => GameEventMessage::parse_skip(stream),
|
||||||
Message::GameEvent(_) => MessageType::GameEvent,
|
MessageType::PacketEntities => PacketEntitiesMessage::parse_skip(stream),
|
||||||
Message::PacketEntities(_) => MessageType::PacketEntities,
|
MessageType::TempEntities => TempEntitiesMessage::parse_skip(stream),
|
||||||
Message::TempEntities(_) => MessageType::TempEntities,
|
MessageType::PreFetch => PreFetchMessage::parse_skip(stream),
|
||||||
Message::PreFetch(_) => MessageType::PreFetch,
|
MessageType::Menu => MenuMessage::parse_skip(stream),
|
||||||
Message::Menu(_) => MessageType::Menu,
|
MessageType::GameEventList => GameEventListMessage::parse_skip(stream),
|
||||||
Message::GameEventList(_) => MessageType::GameEventList,
|
MessageType::GetCvarValue => GetCvarValueMessage::parse_skip(stream),
|
||||||
Message::GetCvarValue(_) => MessageType::GetCvarValue,
|
MessageType::CmdKeyValues => CmdKeyValuesMessage::parse_skip(stream),
|
||||||
Message::CmdKeyValues(_) => MessageType::CmdKeyValues,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
use bitstream_reader::BitRead;
|
use bitstream_reader::BitRead;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::{Parse, ParserState, Result, Stream, ParseError};
|
||||||
use crate::demo::packet::datatable::ServerClass;
|
use crate::demo::packet::datatable::ServerClass;
|
||||||
use crate::demo::sendprop::SendProp;
|
use crate::demo::sendprop::SendProp;
|
||||||
use crate::{Parse, ParserState, Result, Stream};
|
use crate::demo::parser::ParseBitSkip;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize)]
|
||||||
pub struct EntityId(u32);
|
pub struct EntityId(u32);
|
||||||
|
|
@ -66,3 +67,15 @@ impl Parse for PacketEntitiesMessage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParseBitSkip for PacketEntitiesMessage {
|
||||||
|
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
||||||
|
let _: u16 = stream.read_sized(11)?;
|
||||||
|
let _: Option<u32> = stream.read()?;
|
||||||
|
let _: u8 = stream.read_sized(1)?;
|
||||||
|
let _: u16 = stream.read_sized(11)?;
|
||||||
|
let length: u32 = stream.read_sized(20)?;
|
||||||
|
let _: bool = stream.read()?;
|
||||||
|
stream.skip_bits(length as usize).map_err(ParseError::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ use bitstream_reader::{BitBuffer, BitStream, LittleEndian};
|
||||||
use num_traits::{PrimInt, Unsigned};
|
use num_traits::{PrimInt, Unsigned};
|
||||||
use snap::Decoder;
|
use snap::Decoder;
|
||||||
|
|
||||||
|
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
use crate::demo::packet::stringtable::{
|
use crate::demo::packet::stringtable::{
|
||||||
ExtraData, FixedUserdataSize, StringTable, StringTableEntry,
|
ExtraData, FixedUserdataSize, StringTable, StringTableEntry,
|
||||||
};
|
};
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::demo::parser::ParseBitSkip;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CreateStringTableMessage {
|
pub struct CreateStringTableMessage {
|
||||||
|
|
@ -33,13 +34,13 @@ impl Parse for CreateStringTableMessage {
|
||||||
let max_entries: u16 = stream.read()?;
|
let max_entries: u16 = stream.read()?;
|
||||||
let encode_bits = log_base2(max_entries);
|
let encode_bits = log_base2(max_entries);
|
||||||
let entity_count: u16 = stream.read_sized(encode_bits as usize + 1)?;
|
let entity_count: u16 = stream.read_sized(encode_bits as usize + 1)?;
|
||||||
let bit_count = read_var_int(stream)?;
|
let length = read_var_int(stream)?;
|
||||||
|
|
||||||
let fixed_userdata_size = stream.read()?;
|
let fixed_userdata_size = stream.read()?;
|
||||||
|
|
||||||
let compressed = stream.read()?;
|
let compressed = stream.read()?;
|
||||||
|
|
||||||
let mut table_data = stream.read_bits(bit_count as usize)?;
|
let mut table_data = stream.read_bits(length as usize)?;
|
||||||
|
|
||||||
if compressed {
|
if compressed {
|
||||||
let decompressed_size: u32 = table_data.read()?;
|
let decompressed_size: u32 = table_data.read()?;
|
||||||
|
|
@ -88,6 +89,23 @@ impl Parse for CreateStringTableMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParseBitSkip for CreateStringTableMessage {
|
||||||
|
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
||||||
|
let _: String = stream.read()?;
|
||||||
|
let max_entries: u16 = stream.read()?;
|
||||||
|
let encode_bits = log_base2(max_entries);
|
||||||
|
let _: u16 = stream.read_sized(encode_bits as usize + 1)?;
|
||||||
|
let length = read_var_int(stream)?;
|
||||||
|
|
||||||
|
let _: Option<FixedUserdataSize> = stream.read()?;
|
||||||
|
|
||||||
|
let _: bool = stream.read()?;
|
||||||
|
|
||||||
|
stream.skip_bits(length as usize).map_err(ParseError::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct UpdateStringTableMessage {
|
pub struct UpdateStringTableMessage {
|
||||||
pub entries: Vec<(u16, StringTableEntry)>,
|
pub entries: Vec<(u16, StringTableEntry)>,
|
||||||
|
|
@ -99,9 +117,9 @@ impl Parse for UpdateStringTableMessage {
|
||||||
let table_id = stream.read_sized(5)?;
|
let table_id = stream.read_sized(5)?;
|
||||||
|
|
||||||
let changed: u16 = if stream.read()? { stream.read()? } else { 1 };
|
let changed: u16 = if stream.read()? { stream.read()? } else { 1 };
|
||||||
let len = stream.read_int(20)?;
|
let length: u32 = stream.read_int(20)?;
|
||||||
|
|
||||||
let mut data = stream.read_bits(len)?;
|
let mut data = stream.read_bits(length as usize)?;
|
||||||
|
|
||||||
let entries = match state.string_tables.get(table_id as usize) {
|
let entries = match state.string_tables.get(table_id as usize) {
|
||||||
Some(table) => parse_string_table_update(&mut data, table, changed),
|
Some(table) => parse_string_table_update(&mut data, table, changed),
|
||||||
|
|
@ -112,6 +130,16 @@ impl Parse for UpdateStringTableMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParseBitSkip for UpdateStringTableMessage {
|
||||||
|
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
||||||
|
let _: u8 = stream.read_sized(5)?;
|
||||||
|
|
||||||
|
let _: u16 = if stream.read()? { stream.read()? } else { 1 };
|
||||||
|
let length: u32 = stream.read_int(20)?;
|
||||||
|
stream.skip_bits(length as usize).map_err(ParseError::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_string_table_update(
|
fn parse_string_table_update(
|
||||||
stream: &mut Stream,
|
stream: &mut Stream,
|
||||||
table_meta: &StringTableMeta,
|
table_meta: &StringTableMeta,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{Parse, ParserState, Result, Stream};
|
use crate::{Parse, ParserState, Result, Stream, ParseError};
|
||||||
|
|
||||||
use super::packetentities::PacketEntity;
|
use super::packetentities::PacketEntity;
|
||||||
use super::stringtable::read_var_int;
|
use super::stringtable::read_var_int;
|
||||||
|
use crate::demo::parser::ParseBitSkip;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TempEntitiesMessage {
|
pub struct TempEntitiesMessage {
|
||||||
|
|
@ -19,3 +20,11 @@ impl Parse for TempEntitiesMessage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParseBitSkip for TempEntitiesMessage {
|
||||||
|
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
||||||
|
let _: u8 = stream.read()?;
|
||||||
|
let length = read_var_int(stream)?;
|
||||||
|
stream.skip_bits(length as usize).map_err(ParseError::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
use bitstream_reader::{BitRead, BitSkip, LittleEndian};
|
||||||
use enum_primitive_derive::Primitive;
|
use enum_primitive_derive::Primitive;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
use crate::{ReadResult, Stream, Result, ParseError};
|
||||||
|
use crate::demo::parser::ParseBitSkip;
|
||||||
|
|
||||||
#[derive(Primitive, Clone, Copy, Debug)]
|
#[derive(Primitive, Clone, Copy, Debug)]
|
||||||
pub enum UserMessageType {
|
pub enum UserMessageType {
|
||||||
|
|
@ -98,6 +99,15 @@ impl BitRead<LittleEndian> for UserMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParseBitSkip for UserMessage {
|
||||||
|
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
||||||
|
let _ = stream.skip_bits(8)?;
|
||||||
|
let length:u32 = stream.read_int(11)?;
|
||||||
|
stream.skip_bits(length as usize).map_err(ParseError::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub enum ChatMessageKind {
|
pub enum ChatMessageKind {
|
||||||
#[serde(rename = "TF_Chat_All")]
|
#[serde(rename = "TF_Chat_All")]
|
||||||
|
|
@ -146,7 +156,7 @@ impl BitRead<LittleEndian> for SayText2Message {
|
||||||
if first == 7 {
|
if first == 7 {
|
||||||
let _color = stream.read_string(Some(6))?;
|
let _color = stream.read_string(Some(6))?;
|
||||||
} else {
|
} else {
|
||||||
let _ = stream.skip(8)?;
|
let _ = stream.skip_bits(8)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let text: String = stream.read()?;
|
let text: String = stream.read()?;
|
||||||
|
|
@ -169,7 +179,7 @@ impl BitRead<LittleEndian> for SayText2Message {
|
||||||
let kind = stream.read()?;
|
let kind = stream.read()?;
|
||||||
let from = stream.read()?;
|
let from = stream.read()?;
|
||||||
let text = stream.read()?;
|
let text = stream.read()?;
|
||||||
let _ = stream.skip(16)?;
|
let _ = stream.skip_bits(16)?;
|
||||||
(kind, from, text)
|
(kind, from, text)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
use bitstream_reader::{BitRead, LittleEndian, BitSkip};
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
use crate::{ReadResult, Stream};
|
||||||
|
|
||||||
|
|
@ -30,6 +30,8 @@ impl BitRead<LittleEndian> for VoiceInitMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for VoiceInitMessage{}
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone)]
|
#[derive(BitRead, Debug, Clone)]
|
||||||
#[endianness = "LittleEndian"]
|
#[endianness = "LittleEndian"]
|
||||||
pub struct VoiceDataMessage {
|
pub struct VoiceDataMessage {
|
||||||
|
|
@ -40,6 +42,8 @@ pub struct VoiceDataMessage {
|
||||||
data: Stream,
|
data: Stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for VoiceDataMessage{}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ParseSoundsMessage {
|
pub struct ParseSoundsMessage {
|
||||||
pub reliable: bool,
|
pub reliable: bool,
|
||||||
|
|
@ -67,3 +71,5 @@ impl BitRead<LittleEndian> for ParseSoundsMessage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BitSkip<LittleEndian> for ParseSoundsMessage{}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitstream_reader::{BitRead, LazyBitReadSized, LittleEndian};
|
use bitstream_reader::{BitRead, LittleEndian};
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
use crate::{ReadResult, Stream};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use bitstream_reader::{BitRead, BitSize, LazyBitRead, LittleEndian};
|
use bitstream_reader::{BitRead, BitSize, LazyBitRead, LittleEndian};
|
||||||
|
|
||||||
use crate::demo::message::Message;
|
|
||||||
use crate::demo::vector::Vector;
|
|
||||||
use crate::{Parse, ParserState, ReadResult, Result, Stream};
|
use crate::{Parse, ParserState, ReadResult, Result, Stream};
|
||||||
|
use crate::demo::message::{Message, MessageType};
|
||||||
|
use crate::demo::vector::Vector;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MessagePacket {
|
pub struct MessagePacket {
|
||||||
|
|
@ -57,10 +57,13 @@ impl Parse for MessagePacket {
|
||||||
|
|
||||||
let mut messages: Vec<Message> = Vec::with_capacity(25);
|
let mut messages: Vec<Message> = Vec::with_capacity(25);
|
||||||
while packet_data.bits_left() > 6 {
|
while packet_data.bits_left() > 6 {
|
||||||
let message = Message::parse(&mut packet_data, state)?;
|
let message_type = MessageType::parse(&mut packet_data, state)?;
|
||||||
match message {
|
|
||||||
Message::Empty => {}
|
if state.parse_message_types.contains(&message_type) {
|
||||||
_ => messages.push(message),
|
let message = Message::from_type(message_type, &mut packet_data, state)?;
|
||||||
|
messages.push(message);
|
||||||
|
} else {
|
||||||
|
let _ = Message::skip_type(message_type, &mut packet_data)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ impl BitRead<LittleEndian> for UserCmdPacket {
|
||||||
let tick = stream.read()?;
|
let tick = stream.read()?;
|
||||||
let sequence_out = stream.read()?;
|
let sequence_out = stream.read()?;
|
||||||
let len: u32 = stream.read()?;
|
let len: u32 = stream.read()?;
|
||||||
let _ = stream.skip(len as usize * 8)?;
|
let _ = stream.skip_bits(len as usize * 8)?;
|
||||||
// TODO parse the packet data
|
// TODO parse the packet data
|
||||||
Ok(UserCmdPacket { tick, sequence_out })
|
Ok(UserCmdPacket { tick, sequence_out })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,10 @@ impl Analyser {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_message_types(&self) -> Vec<MessageType> {
|
||||||
|
vec![MessageType::GameEvent, MessageType::UserMessage]
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_user_message(&mut self, message: UserMessage, tick: u32) {
|
fn handle_user_message(&mut self, message: UserMessage, tick: u32) {
|
||||||
match message {
|
match message {
|
||||||
UserMessage::SayText2(message) => match message.kind {
|
UserMessage::SayText2(message) => match message.kind {
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,15 @@ pub struct DemoHandler {
|
||||||
|
|
||||||
impl DemoHandler {
|
impl DemoHandler {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
let mut state = ParserState::new();
|
||||||
|
let analyser = Analyser::new();
|
||||||
|
state.parse_message_types.extend(analyser.get_message_types());
|
||||||
|
|
||||||
DemoHandler {
|
DemoHandler {
|
||||||
tick: 0,
|
tick: 0,
|
||||||
string_table_names: Vec::new(),
|
string_table_names: Vec::new(),
|
||||||
analyser: Analyser::new(),
|
analyser,
|
||||||
state_handler: ParserState::new(),
|
state_handler: state,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use bitstream_reader::{BitRead, LittleEndian, ReadError};
|
use bitstream_reader::{BitRead, BitSkip, LittleEndian, ReadError};
|
||||||
|
|
||||||
use crate::demo::gamevent::{GameEventValue, GameEventValueType};
|
use crate::demo::gamevent::{GameEventValue, GameEventValueType};
|
||||||
use crate::demo::header::Header;
|
use crate::demo::header::Header;
|
||||||
|
|
@ -74,6 +74,17 @@ impl<T: BitRead<LittleEndian>> Parse for T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ParseBitSkip {
|
||||||
|
fn parse_skip(stream: &mut Stream) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: BitSkip<LittleEndian>> ParseBitSkip for T {
|
||||||
|
#[inline(always)]
|
||||||
|
fn parse_skip(stream: &mut Stream) -> Result<()> {
|
||||||
|
Self::skip(stream).map_err(ParseError::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DemoParser {
|
pub struct DemoParser {
|
||||||
stream: Stream,
|
stream: Stream,
|
||||||
handler: DemoHandler,
|
handler: DemoHandler,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::demo::gamevent::GameEventDefinition;
|
use crate::demo::gamevent::GameEventDefinition;
|
||||||
|
use crate::demo::message::{Message, MessageType};
|
||||||
use crate::demo::message::gameevent::GameEventTypeId;
|
use crate::demo::message::gameevent::GameEventTypeId;
|
||||||
use crate::demo::message::packetentities::EntityId;
|
use crate::demo::message::packetentities::EntityId;
|
||||||
use crate::demo::message::stringtable::StringTableMeta;
|
use crate::demo::message::stringtable::StringTableMeta;
|
||||||
use crate::demo::message::{Message, MessageType};
|
|
||||||
use crate::demo::packet::datatable::{SendTable, ServerClass};
|
use crate::demo::packet::datatable::{SendTable, ServerClass};
|
||||||
use crate::demo::packet::stringtable::StringTableEntry;
|
use crate::demo::packet::stringtable::StringTableEntry;
|
||||||
use crate::demo::parser::handler::{MessageHandler, StringTableEntryHandler};
|
use crate::demo::parser::handler::{MessageHandler, StringTableEntryHandler};
|
||||||
|
|
@ -28,6 +28,7 @@ pub struct ParserState {
|
||||||
pub server_classes: Vec<ServerClass>,
|
pub server_classes: Vec<ServerClass>,
|
||||||
pub instance_baselines: [HashMap<EntityId, Vec<SendProp>>; 2],
|
pub instance_baselines: [HashMap<EntityId, Vec<SendProp>>; 2],
|
||||||
pub demo_meta: DemoMeta,
|
pub demo_meta: DemoMeta,
|
||||||
|
pub parse_message_types: Vec<MessageType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StaticBaseline {
|
pub struct StaticBaseline {
|
||||||
|
|
@ -48,7 +49,14 @@ impl StaticBaseline {
|
||||||
|
|
||||||
impl ParserState {
|
impl ParserState {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
ParserState::default()
|
let mut state = ParserState::default();
|
||||||
|
state.parse_message_types.extend_from_slice(&[
|
||||||
|
MessageType::ServerInfo,
|
||||||
|
MessageType::GameEventList,
|
||||||
|
MessageType::CreateStringTable,
|
||||||
|
MessageType::UpdateStringTable
|
||||||
|
]);
|
||||||
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_data_table(
|
pub fn handle_data_table(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue