mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
format
This commit is contained in:
parent
8183ac5b65
commit
f2650dc32f
19 changed files with 3614 additions and 2210 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
||||||
|
use bitstream_reader::BitRead;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use bitstream_reader::{BitRead};
|
|
||||||
|
|
||||||
use crate::{ParseError, Result};
|
use crate::{ParseError, Result};
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@ impl FromGameEventValue for String {
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(ParseError::InvalidGameEvent {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
value,
|
value,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +65,7 @@ impl FromGameEventValue for f32 {
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(ParseError::InvalidGameEvent {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
value,
|
value,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +77,7 @@ impl FromGameEventValue for u32 {
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(ParseError::InvalidGameEvent {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
value,
|
value,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +89,7 @@ impl FromGameEventValue for u16 {
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(ParseError::InvalidGameEvent {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
value,
|
value,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +101,7 @@ impl FromGameEventValue for u8 {
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(ParseError::InvalidGameEvent {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
value,
|
value,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,7 +113,7 @@ impl FromGameEventValue for bool {
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(ParseError::InvalidGameEvent {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
value,
|
value,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -125,7 +125,7 @@ impl FromGameEventValue for () {
|
||||||
_ => Err(ParseError::InvalidGameEvent {
|
_ => Err(ParseError::InvalidGameEvent {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
value,
|
value,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
|
||||||
use crate::demo::sendprop::read_bit_coord;
|
use crate::demo::sendprop::read_bit_coord;
|
||||||
use crate::demo::vector::Vector;
|
use crate::demo::vector::Vector;
|
||||||
|
use crate::{ReadResult, Stream};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BSPDecalMessage {
|
pub struct BSPDecalMessage {
|
||||||
|
|
@ -44,4 +44,3 @@ impl BitRead<LittleEndian> for BSPDecalMessage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
|
||||||
use crate::demo::message::stringtable::log_base2;
|
use crate::demo::message::stringtable::log_base2;
|
||||||
|
use crate::{ReadResult, Stream};
|
||||||
|
|
||||||
#[derive(BitReadSized, Debug)]
|
#[derive(BitReadSized, Debug)]
|
||||||
pub struct ClassInfoEntry {
|
pub struct ClassInfoEntry {
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,12 @@ use std::iter::FromIterator;
|
||||||
|
|
||||||
use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
||||||
|
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
|
||||||
use crate::demo::gameevent_gen::GameEventType;
|
use crate::demo::gameevent_gen::GameEventType;
|
||||||
use crate::demo::gamevent::{GameEvent, GameEventDefinition, GameEventEntry, GameEventValue, GameEventValueType, RawGameEvent};
|
use crate::demo::gamevent::{
|
||||||
|
GameEvent, GameEventDefinition, GameEventEntry, GameEventValue, GameEventValueType,
|
||||||
|
RawGameEvent,
|
||||||
|
};
|
||||||
|
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
|
|
||||||
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 {
|
||||||
|
|
@ -16,13 +19,13 @@ fn read_event_value(stream: &mut Stream, definition: &GameEventEntry) -> Result<
|
||||||
GameEventValueType::Byte => GameEventValue::Byte(stream.read()?),
|
GameEventValueType::Byte => GameEventValue::Byte(stream.read()?),
|
||||||
GameEventValueType::Boolean => GameEventValue::Boolean(stream.read()?),
|
GameEventValueType::Boolean => GameEventValue::Boolean(stream.read()?),
|
||||||
GameEventValueType::Local => GameEventValue::Local,
|
GameEventValueType::Local => GameEventValue::Local,
|
||||||
GameEventValueType::None => unreachable!()
|
GameEventValueType::None => unreachable!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GameEventMessage {
|
pub struct GameEventMessage {
|
||||||
pub event: GameEvent
|
pub event: GameEvent,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for GameEventMessage {
|
impl Parse for GameEventMessage {
|
||||||
|
|
@ -37,17 +40,12 @@ impl Parse for GameEventMessage {
|
||||||
values.push(read_event_value(&mut data, &entry)?);
|
values.push(read_event_value(&mut data, &entry)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
RawGameEvent {
|
RawGameEvent { event_type, values }
|
||||||
event_type,
|
|
||||||
values,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None => unreachable!()
|
None => unreachable!(),
|
||||||
};
|
};
|
||||||
let event = GameEvent::from_raw_event(raw_event)?;
|
let event = GameEvent::from_raw_event(raw_event)?;
|
||||||
Ok(GameEventMessage {
|
Ok(GameEventMessage { event })
|
||||||
event
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,12 +84,8 @@ impl BitRead<LittleEndian> for GameEventListMessage {
|
||||||
let length: u32 = stream.read_sized(20)?;
|
let length: u32 = stream.read_sized(20)?;
|
||||||
let mut data = stream.read_bits(length as usize)?;
|
let mut data = stream.read_bits(length as usize)?;
|
||||||
let event_list_vec: Vec<GameEventDefinition> = data.read_sized(count as usize)?;
|
let event_list_vec: Vec<GameEventDefinition> = data.read_sized(count as usize)?;
|
||||||
let event_list = HashMap::from_iter(
|
let event_list = HashMap::from_iter(event_list_vec.into_iter().map(|def| (def.id, def)));
|
||||||
event_list_vec.into_iter().map(|def| (def.id, def))
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(GameEventListMessage {
|
Ok(GameEventListMessage { event_list })
|
||||||
event_list
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
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, BitStream, LittleEndian};
|
use bitstream_reader::{BitRead, BitStream, LittleEndian};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use crate::Stream;
|
|
||||||
|
|
||||||
#[derive(BitRead, Debug)]
|
#[derive(BitRead, Debug)]
|
||||||
pub struct FileMessage {
|
pub struct FileMessage {
|
||||||
|
|
@ -77,11 +77,11 @@ pub struct FixAngleMessage {
|
||||||
#[endianness = "LittleEndian"]
|
#[endianness = "LittleEndian"]
|
||||||
pub struct EntityMessage {
|
pub struct EntityMessage {
|
||||||
#[size = 11]
|
#[size = 11]
|
||||||
pub index: u16,
|
pub index: u16,
|
||||||
#[size = 9]
|
#[size = 9]
|
||||||
pub class_id: u16,
|
pub class_id: u16,
|
||||||
#[size = 11]
|
#[size = 11]
|
||||||
pub length: u16,
|
pub length: u16,
|
||||||
#[size = "length * 8"]
|
#[size = "length * 8"]
|
||||||
pub data: Stream,
|
pub data: Stream,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ use num_traits::FromPrimitive;
|
||||||
|
|
||||||
pub use generated::*;
|
pub use generated::*;
|
||||||
|
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream, ReadResult};
|
|
||||||
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::*;
|
||||||
|
|
@ -13,17 +12,18 @@ 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, ReadResult, Result, Stream};
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
use bitstream_reader::{BitRead, LittleEndian};
|
||||||
|
|
||||||
pub mod classinfo;
|
|
||||||
pub mod generated;
|
|
||||||
pub mod stringtable;
|
|
||||||
pub mod voice;
|
|
||||||
pub mod bspdecal;
|
pub mod bspdecal;
|
||||||
pub mod usermessage;
|
pub mod classinfo;
|
||||||
pub mod gameevent;
|
pub mod gameevent;
|
||||||
|
pub mod generated;
|
||||||
pub mod packetentities;
|
pub mod packetentities;
|
||||||
|
pub mod stringtable;
|
||||||
pub mod tempentities;
|
pub mod tempentities;
|
||||||
|
pub mod usermessage;
|
||||||
|
pub mod voice;
|
||||||
|
|
||||||
#[derive(Primitive, Debug, Clone, Copy)]
|
#[derive(Primitive, Debug, Clone, Copy)]
|
||||||
pub enum MessageType {
|
pub enum MessageType {
|
||||||
|
|
@ -106,29 +106,51 @@ impl Parse for Message {
|
||||||
MessageType::NetTick => Message::NetTick(NetTickMessage::parse(stream, state)?),
|
MessageType::NetTick => Message::NetTick(NetTickMessage::parse(stream, state)?),
|
||||||
MessageType::StringCmd => Message::StringCmd(StringCmdMessage::parse(stream, state)?),
|
MessageType::StringCmd => Message::StringCmd(StringCmdMessage::parse(stream, state)?),
|
||||||
MessageType::SetConVar => Message::SetConVar(SetConVarMessage::parse(stream, state)?),
|
MessageType::SetConVar => Message::SetConVar(SetConVarMessage::parse(stream, state)?),
|
||||||
MessageType::SigOnState => Message::SigOnState(SigOnStateMessage::parse(stream, state)?),
|
MessageType::SigOnState => {
|
||||||
|
Message::SigOnState(SigOnStateMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
MessageType::Print => Message::Print(PrintMessage::parse(stream, state)?),
|
MessageType::Print => Message::Print(PrintMessage::parse(stream, state)?),
|
||||||
MessageType::ServerInfo => Message::ServerInfo(ServerInfoMessage::parse(stream, state)?),
|
MessageType::ServerInfo => {
|
||||||
|
Message::ServerInfo(ServerInfoMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
MessageType::ClassInfo => Message::ClassInfo(ClassInfoMessage::parse(stream, state)?),
|
MessageType::ClassInfo => Message::ClassInfo(ClassInfoMessage::parse(stream, state)?),
|
||||||
MessageType::SetPause => Message::SetPause(SetPauseMessage::parse(stream, state)?),
|
MessageType::SetPause => Message::SetPause(SetPauseMessage::parse(stream, state)?),
|
||||||
MessageType::CreateStringTable => Message::CreateStringTable(CreateStringTableMessage::parse(stream, state)?),
|
MessageType::CreateStringTable => {
|
||||||
MessageType::UpdateStringTable => Message::UpdateStringTable(UpdateStringTableMessage::parse(stream, state)?),
|
Message::CreateStringTable(CreateStringTableMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
|
MessageType::UpdateStringTable => {
|
||||||
|
Message::UpdateStringTable(UpdateStringTableMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
MessageType::VoiceInit => Message::VoiceInit(VoiceInitMessage::parse(stream, state)?),
|
MessageType::VoiceInit => Message::VoiceInit(VoiceInitMessage::parse(stream, state)?),
|
||||||
MessageType::VoiceData => Message::VoiceData(VoiceDataMessage::parse(stream, state)?),
|
MessageType::VoiceData => Message::VoiceData(VoiceDataMessage::parse(stream, state)?),
|
||||||
MessageType::ParseSounds => Message::ParseSounds(ParseSoundsMessage::parse(stream, state)?),
|
MessageType::ParseSounds => {
|
||||||
|
Message::ParseSounds(ParseSoundsMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
MessageType::SetView => Message::SetView(SetViewMessage::parse(stream, state)?),
|
MessageType::SetView => Message::SetView(SetViewMessage::parse(stream, state)?),
|
||||||
MessageType::FixAngle => Message::FixAngle(FixAngleMessage::parse(stream, state)?),
|
MessageType::FixAngle => Message::FixAngle(FixAngleMessage::parse(stream, state)?),
|
||||||
MessageType::BspDecal => Message::BspDecal(BSPDecalMessage::parse(stream, state)?),
|
MessageType::BspDecal => Message::BspDecal(BSPDecalMessage::parse(stream, state)?),
|
||||||
MessageType::UserMessage => Message::UserMessage(UserMessage::parse(stream, state)?),
|
MessageType::UserMessage => Message::UserMessage(UserMessage::parse(stream, state)?),
|
||||||
MessageType::EntityMessage => Message::EntityMessage(EntityMessage::parse(stream, state)?),
|
MessageType::EntityMessage => {
|
||||||
|
Message::EntityMessage(EntityMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
MessageType::GameEvent => Message::GameEvent(GameEventMessage::parse(stream, state)?),
|
MessageType::GameEvent => Message::GameEvent(GameEventMessage::parse(stream, state)?),
|
||||||
MessageType::PacketEntities => Message::PacketEntities(PacketEntitiesMessage::parse(stream, state)?),
|
MessageType::PacketEntities => {
|
||||||
MessageType::TempEntities => Message::TempEntities(TempEntitiesMessage::parse(stream, state)?),
|
Message::PacketEntities(PacketEntitiesMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
|
MessageType::TempEntities => {
|
||||||
|
Message::TempEntities(TempEntitiesMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
MessageType::PreFetch => Message::PreFetch(PreFetchMessage::parse(stream, state)?),
|
MessageType::PreFetch => Message::PreFetch(PreFetchMessage::parse(stream, state)?),
|
||||||
MessageType::Menu => Message::Menu(MenuMessage::parse(stream, state)?),
|
MessageType::Menu => Message::Menu(MenuMessage::parse(stream, state)?),
|
||||||
MessageType::GameEventList => Message::GameEventList(GameEventListMessage::parse(stream, state)?),
|
MessageType::GameEventList => {
|
||||||
MessageType::GetCvarValue => Message::GetCvarValue(GetCvarValueMessage::parse(stream, state)?),
|
Message::GameEventList(GameEventListMessage::parse(stream, state)?)
|
||||||
MessageType::CmdKeyValues => Message::CmdKeyValues(CmdKeyValuesMessage::parse(stream, state)?),
|
}
|
||||||
|
MessageType::GetCvarValue => {
|
||||||
|
Message::GetCvarValue(GetCvarValueMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
|
MessageType::CmdKeyValues => {
|
||||||
|
Message::CmdKeyValues(CmdKeyValuesMessage::parse(stream, state)?)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
||||||
|
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
|
||||||
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, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct EntityId(u32);
|
pub struct EntityId(u32);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use arraydeque::{ArrayDeque, Wrapping};
|
use arraydeque::{ArrayDeque, Wrapping};
|
||||||
use bitstream_reader::{BitRead, BitReadSized, BitStream, LittleEndian, BitBuffer};
|
use bitstream_reader::{BitBuffer, BitRead, BitReadSized, BitStream, LittleEndian};
|
||||||
use snap::Decoder;
|
use snap::Decoder;
|
||||||
|
|
||||||
|
use crate::demo::packet::stringtable::{
|
||||||
|
ExtraData, FixedUserdataSize, StringTable, StringTableEntry,
|
||||||
|
};
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
use crate::demo::packet::stringtable::{ExtraData, FixedUserdataSize, StringTable, StringTableEntry};
|
|
||||||
use num_traits::{PrimInt, Unsigned};
|
use num_traits::{PrimInt, Unsigned};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -55,12 +57,14 @@ impl Parse for CreateStringTableMessage {
|
||||||
let compressed_data = table_data.read_bytes(compressed_size as usize - 4)?;
|
let compressed_data = table_data.read_bytes(compressed_size as usize - 4)?;
|
||||||
|
|
||||||
let mut decoder = Decoder::new();
|
let mut decoder = Decoder::new();
|
||||||
let decompressed_data = decoder.decompress_vec(&compressed_data).map_err(ParseError::from)?;
|
let decompressed_data = decoder
|
||||||
|
.decompress_vec(&compressed_data)
|
||||||
|
.map_err(ParseError::from)?;
|
||||||
|
|
||||||
if decompressed_data.len() != decompressed_size as usize {
|
if decompressed_data.len() != decompressed_size as usize {
|
||||||
return Err(ParseError::UnexpectedDecompressedSize {
|
return Err(ParseError::UnexpectedDecompressedSize {
|
||||||
expected: decompressed_size,
|
expected: decompressed_size,
|
||||||
size: decompressed_data.len() as u32
|
size: decompressed_data.len() as u32,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,7 +77,8 @@ impl Parse for CreateStringTableMessage {
|
||||||
fixed_userdata_size,
|
fixed_userdata_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
let entries = parse_string_table_entries(&mut table_data, &table_meta, entity_count, &Vec::new())?;
|
let entries =
|
||||||
|
parse_string_table_entries(&mut table_data, &table_meta, entity_count, &Vec::new())?;
|
||||||
let mut entries: Vec<(u16, StringTableEntry)> = entries.into_iter().collect();
|
let mut entries: Vec<(u16, StringTableEntry)> = entries.into_iter().collect();
|
||||||
|
|
||||||
// verify that there are no holes in our indexes
|
// verify that there are no holes in our indexes
|
||||||
|
|
@ -93,9 +98,7 @@ impl Parse for CreateStringTableMessage {
|
||||||
compressed,
|
compressed,
|
||||||
name,
|
name,
|
||||||
};
|
};
|
||||||
Ok(CreateStringTableMessage {
|
Ok(CreateStringTableMessage { table })
|
||||||
table
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,14 +118,16 @@ impl Parse for UpdateStringTableMessage {
|
||||||
let mut data = stream.read_bits(len)?;
|
let mut data = stream.read_bits(len)?;
|
||||||
|
|
||||||
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_entries(&mut data, &table.get_table_meta(), changed, &table.entries),
|
Some(table) => parse_string_table_entries(
|
||||||
None => return Err(ParseError::StringTableNotFound(table_id))
|
&mut data,
|
||||||
|
&table.get_table_meta(),
|
||||||
|
changed,
|
||||||
|
&table.entries,
|
||||||
|
),
|
||||||
|
None => return Err(ParseError::StringTableNotFound(table_id)),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
Ok(UpdateStringTableMessage {
|
Ok(UpdateStringTableMessage { table_id, entries })
|
||||||
table_id,
|
|
||||||
entries,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,17 +152,22 @@ fn parse_string_table_entries(
|
||||||
|
|
||||||
last_entry = index as i16;
|
last_entry = index as i16;
|
||||||
|
|
||||||
let value = if stream.read()? { // set value
|
let value = if stream.read()? {
|
||||||
if stream.read()? { // reuse from history
|
// set value
|
||||||
|
if stream.read()? {
|
||||||
|
// reuse from history
|
||||||
let index: u16 = stream.read_sized(5)?;
|
let index: u16 = stream.read_sized(5)?;
|
||||||
let bytes_to_copy: u32 = stream.read_sized(5)?;
|
let bytes_to_copy: u32 = stream.read_sized(5)?;
|
||||||
let rest_of_string: String = stream.read()?;
|
let rest_of_string: String = stream.read()?;
|
||||||
|
|
||||||
Some(match history.get(index as usize) {
|
Some(match history.get(index as usize) {
|
||||||
Some(text) => String::from_utf8({
|
Some(text) => String::from_utf8({
|
||||||
text.bytes().take(bytes_to_copy as usize).chain(rest_of_string.bytes()).collect()
|
text.bytes()
|
||||||
|
.take(bytes_to_copy as usize)
|
||||||
|
.chain(rest_of_string.bytes())
|
||||||
|
.collect()
|
||||||
})?,
|
})?,
|
||||||
None => rest_of_string // best guess, happens in some pov demos but only for unimportant tables it seems
|
None => rest_of_string, // best guess, happens in some pov demos but only for unimportant tables it seems
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Some(stream.read()?)
|
Some(stream.read()?)
|
||||||
|
|
@ -176,7 +186,8 @@ fn parse_string_table_entries(
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}.map(|stream| ExtraData {
|
}
|
||||||
|
.map(|stream| ExtraData {
|
||||||
len: stream.bit_len() as u16 / 8,
|
len: stream.bit_len() as u16 / 8,
|
||||||
data: stream,
|
data: stream,
|
||||||
});
|
});
|
||||||
|
|
@ -193,7 +204,7 @@ fn parse_string_table_entries(
|
||||||
None => StringTableEntry {
|
None => StringTableEntry {
|
||||||
text: value.unwrap_or_default(),
|
text: value.unwrap_or_default(),
|
||||||
extra_data: user_data,
|
extra_data: user_data,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
// optimize: any way to get rid of the clone here?
|
// optimize: any way to get rid of the clone here?
|
||||||
// `entries` always outlives `history` without reallocation
|
// `entries` always outlives `history` without reallocation
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use super::stringtable::read_var_int;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TempEntitiesMessage {
|
pub struct TempEntitiesMessage {
|
||||||
pub entities: Vec<PacketEntity>
|
pub entities: Vec<PacketEntity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for TempEntitiesMessage {
|
impl Parse for TempEntitiesMessage {
|
||||||
|
|
@ -17,7 +17,7 @@ impl Parse for TempEntitiesMessage {
|
||||||
let data = stream.read_bits(length as usize)?;
|
let data = stream.read_bits(length as usize)?;
|
||||||
|
|
||||||
Ok(TempEntitiesMessage {
|
Ok(TempEntitiesMessage {
|
||||||
entities: Vec::new()
|
entities: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,8 +2,8 @@ use bitstream_reader::{BitRead, BitReadSized, LittleEndian};
|
||||||
use enum_primitive_derive::Primitive;
|
use enum_primitive_derive::Primitive;
|
||||||
use num_traits::{FromPrimitive, ToPrimitive};
|
use num_traits::{FromPrimitive, ToPrimitive};
|
||||||
|
|
||||||
use crate::{ReadResult, Stream};
|
|
||||||
use crate::demo::message::usermessage::UserMessage::SayText2;
|
use crate::demo::message::usermessage::UserMessage::SayText2;
|
||||||
|
use crate::{ReadResult, Stream};
|
||||||
|
|
||||||
#[derive(Primitive, Clone, Copy, Debug)]
|
#[derive(Primitive, Clone, Copy, Debug)]
|
||||||
pub enum UserMessageType {
|
pub enum UserMessageType {
|
||||||
|
|
@ -81,8 +81,8 @@ pub enum UserMessage {
|
||||||
|
|
||||||
impl BitRead<LittleEndian> for UserMessage {
|
impl BitRead<LittleEndian> for UserMessage {
|
||||||
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
||||||
let message_type = UserMessageType::from_u8(stream.read()?)
|
let message_type =
|
||||||
.unwrap_or(UserMessageType::Unknown);
|
UserMessageType::from_u8(stream.read()?).unwrap_or(UserMessageType::Unknown);
|
||||||
let length = stream.read_int(11)?;
|
let length = stream.read_int(11)?;
|
||||||
let mut data = stream.read_bits(length)?;
|
let mut data = stream.read_bits(length)?;
|
||||||
let message = match message_type {
|
let message = match message_type {
|
||||||
|
|
@ -113,7 +113,7 @@ impl BitRead<LittleEndian> for SayText2Kind {
|
||||||
"TF_Chat_Team" => SayText2Kind::ChatTeam,
|
"TF_Chat_Team" => SayText2Kind::ChatTeam,
|
||||||
"TF_Chat_AllDead" => SayText2Kind::ChatAllDead,
|
"TF_Chat_AllDead" => SayText2Kind::ChatAllDead,
|
||||||
"#TF_Name_Change" => SayText2Kind::NameChange,
|
"#TF_Name_Change" => SayText2Kind::NameChange,
|
||||||
_ => SayText2Kind::ChatAll
|
_ => SayText2Kind::ChatAll,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -144,7 +144,9 @@ impl BitRead<LittleEndian> for SayText2Message {
|
||||||
// grave talk is in the format '*DEAD* \u0003$from\u0001: $text'b
|
// grave talk is in the format '*DEAD* \u0003$from\u0001: $text'b
|
||||||
let start = text.find(char::from(3)).unwrap_or(0);
|
let start = text.find(char::from(3)).unwrap_or(0);
|
||||||
let end = text.find(char::from(1)).unwrap_or(0);
|
let end = text.find(char::from(1)).unwrap_or(0);
|
||||||
let from: String = String::from_utf8(text.bytes().skip(start + 1).take(end - start - 1).collect())?;
|
let from: String = String::from_utf8(
|
||||||
|
text.bytes().skip(start + 1).take(end - start - 1).collect(),
|
||||||
|
)?;
|
||||||
let text: String = String::from_utf8(text.bytes().skip(end + 5).collect())?;
|
let text: String = String::from_utf8(text.bytes().skip(end + 5).collect())?;
|
||||||
let kind = SayText2Kind::ChatAllDead;
|
let kind = SayText2Kind::ChatAllDead;
|
||||||
(kind, from, text)
|
(kind, from, text)
|
||||||
|
|
@ -162,11 +164,14 @@ impl BitRead<LittleEndian> for SayText2Message {
|
||||||
};
|
};
|
||||||
|
|
||||||
// cleanup color codes
|
// cleanup color codes
|
||||||
let mut text = text
|
let mut text = text.replace(char::from(1), "").replace(char::from(3), "");
|
||||||
.replace(char::from(1), "")
|
|
||||||
.replace(char::from(3), "");
|
|
||||||
while let Some(pos) = text.find(char::from(7)) {
|
while let Some(pos) = text.find(char::from(7)) {
|
||||||
text = String::from_utf8(text.bytes().take(pos).chain(text.bytes().skip(pos + 7)).collect())?;
|
text = String::from_utf8(
|
||||||
|
text.bytes()
|
||||||
|
.take(pos)
|
||||||
|
.chain(text.bytes().skip(pos + 7))
|
||||||
|
.collect(),
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(SayText2Message {
|
Ok(SayText2Message {
|
||||||
|
|
@ -198,12 +203,12 @@ pub struct TextMessage {
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone)]
|
#[derive(BitRead, Debug, Clone)]
|
||||||
pub struct ResetHudMessage {
|
pub struct ResetHudMessage {
|
||||||
pub data: u8
|
pub data: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone)]
|
#[derive(BitRead, Debug, Clone)]
|
||||||
pub struct TrainMessage {
|
pub struct TrainMessage {
|
||||||
pub data: u8
|
pub data: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, Debug, Clone)]
|
#[derive(BitRead, Debug, Clone)]
|
||||||
|
|
@ -223,13 +228,13 @@ pub struct ShakeMessage {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct UnknownUserMessage {
|
pub struct UnknownUserMessage {
|
||||||
data: Stream
|
data: Stream,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitRead<LittleEndian> for UnknownUserMessage {
|
impl BitRead<LittleEndian> for UnknownUserMessage {
|
||||||
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
||||||
Ok(UnknownUserMessage {
|
Ok(UnknownUserMessage {
|
||||||
data: stream.read_bits(stream.bits_left())?
|
data: stream.read_bits(stream.bits_left())?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +52,11 @@ impl BitRead<LittleEndian> for ParseSoundsMessage {
|
||||||
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
fn read(stream: &mut Stream) -> ReadResult<Self> {
|
||||||
let reliable = stream.read()?;
|
let reliable = stream.read()?;
|
||||||
let num = if reliable { 1u8 } else { stream.read()? };
|
let num = if reliable { 1u8 } else { stream.read()? };
|
||||||
let length = if reliable { stream.read_sized::<u16>(8)? } else { stream.read()? };
|
let length = if reliable {
|
||||||
|
stream.read_sized::<u16>(8)?
|
||||||
|
} else {
|
||||||
|
stream.read()?
|
||||||
|
};
|
||||||
let data = stream.read_sized(length as usize)?;
|
let data = stream.read_sized(length as usize)?;
|
||||||
|
|
||||||
Ok(ParseSoundsMessage {
|
Ok(ParseSoundsMessage {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use bitstream_reader::{BitBuffer, BitStream, LittleEndian};
|
use bitstream_reader::{BitBuffer, BitStream, LittleEndian};
|
||||||
|
|
||||||
pub mod gamevent;
|
|
||||||
pub mod gameevent_gen;
|
pub mod gameevent_gen;
|
||||||
|
pub mod gamevent;
|
||||||
pub mod header;
|
pub mod header;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod packet;
|
pub mod packet;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
|
||||||
use crate::demo::message::Message;
|
use crate::demo::message::Message;
|
||||||
use crate::demo::vector::Vector;
|
use crate::demo::vector::Vector;
|
||||||
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MessagePacket {
|
pub struct MessagePacket {
|
||||||
|
|
@ -36,7 +36,7 @@ impl Parse for MessagePacket {
|
||||||
let message = Message::parse(&mut packet_data, state)?;
|
let message = Message::parse(&mut packet_data, state)?;
|
||||||
match message {
|
match message {
|
||||||
Message::Empty => {}
|
Message::Empty => {}
|
||||||
_ => messages.push(message)
|
_ => messages.push(message),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ use std::fmt;
|
||||||
|
|
||||||
use bitstream_reader::{BitRead, LittleEndian};
|
use bitstream_reader::{BitRead, LittleEndian};
|
||||||
|
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
|
||||||
use crate::demo::message::stringtable::StringTableMeta;
|
use crate::demo::message::stringtable::StringTableMeta;
|
||||||
use crate::demo::sendprop::SendPropFlag::Exclude;
|
use crate::demo::sendprop::SendPropFlag::Exclude;
|
||||||
|
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
|
|
||||||
#[derive(BitRead, Clone, Copy, Debug)]
|
#[derive(BitRead, Clone, Copy, Debug)]
|
||||||
pub struct FixedUserdataSize {
|
pub struct FixedUserdataSize {
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,7 @@ pub enum ParseError {
|
||||||
/// A unknown game event type was read
|
/// A unknown game event type was read
|
||||||
UnknownGameEvent(String),
|
UnknownGameEvent(String),
|
||||||
/// A read game event doesn't contain the expected values
|
/// A read game event doesn't contain the expected values
|
||||||
InvalidGameEvent {
|
InvalidGameEvent { name: String, value: GameEventValue },
|
||||||
name: String,
|
|
||||||
value: GameEventValue,
|
|
||||||
},
|
|
||||||
/// Unexpected type of compressed data
|
/// Unexpected type of compressed data
|
||||||
UnexpectedCompressionType(String),
|
UnexpectedCompressionType(String),
|
||||||
/// Error while decompressing SNAP compressed string table
|
/// Error while decompressing SNAP compressed string table
|
||||||
|
|
@ -43,8 +40,8 @@ pub enum ParseError {
|
||||||
/// Expected decompressed size
|
/// Expected decompressed size
|
||||||
expected: u32,
|
expected: u32,
|
||||||
/// Actual decompressed size
|
/// Actual decompressed size
|
||||||
size: u32
|
size: u32,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ReadError> for ParseError {
|
impl From<ReadError> for ParseError {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::demo::gameevent_gen::GameEventType;
|
use crate::demo::gameevent_gen::GameEventType;
|
||||||
use crate::demo::gamevent::GameEventDefinition;
|
use crate::demo::gamevent::GameEventDefinition;
|
||||||
use crate::demo::message::Message;
|
|
||||||
use crate::demo::message::packetentities::EntityId;
|
use crate::demo::message::packetentities::EntityId;
|
||||||
|
use crate::demo::message::Message;
|
||||||
use crate::demo::packet::datatable::{SendTable, ServerClass};
|
use crate::demo::packet::datatable::{SendTable, ServerClass};
|
||||||
use crate::demo::packet::Packet;
|
|
||||||
use crate::demo::packet::stringtable::{StringTable, StringTableEntry};
|
use crate::demo::packet::stringtable::{StringTable, StringTableEntry};
|
||||||
|
use crate::demo::packet::Packet;
|
||||||
use crate::demo::sendprop::SendProp;
|
use crate::demo::sendprop::SendProp;
|
||||||
use crate::Stream;
|
use crate::Stream;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,11 @@ pub fn read_bit_coord(stream: &mut Stream) -> ReadResult<f32> {
|
||||||
|
|
||||||
Ok(if has_int || has_frac {
|
Ok(if has_int || has_frac {
|
||||||
let sign = if stream.read()? { -1f32 } else { 1f32 };
|
let sign = if stream.read()? { -1f32 } else { 1f32 };
|
||||||
let int_val: u16 = if has_int { stream.read_sized::<u16>(14)? + 1 } else { 0 };
|
let int_val: u16 = if has_int {
|
||||||
|
stream.read_sized::<u16>(14)? + 1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
let frac_val: u8 = if has_frac { stream.read_sized(5)? } else { 0 };
|
let frac_val: u8 = if has_frac { stream.read_sized(5)? } else { 0 };
|
||||||
let value = int_val as f32 + (frac_val as f32 * (1f32 / 32f32));
|
let value = int_val as f32 + (frac_val as f32 * (1f32 / 32f32));
|
||||||
value * sign
|
value * sign
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue