mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
packet parsers
This commit is contained in:
parent
4ac2a3cfc6
commit
b41bb56822
19 changed files with 626 additions and 64 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{ParseError, Parse, Result, Stream, ParserState};
|
||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||
//use crate::test::test_parse;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
|
@ -59,4 +59,4 @@ impl<'a> Parse<'a> for Header {
|
|||
// },
|
||||
// 0,
|
||||
// );
|
||||
//}
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ use rentals::OwnedBuffer;
|
|||
|
||||
pub mod gamevent;
|
||||
pub mod header;
|
||||
pub mod packet;
|
||||
pub mod parser;
|
||||
pub mod sendprop;
|
||||
pub mod vector;
|
||||
pub mod parser;
|
||||
pub mod packet;
|
||||
|
||||
pub type Buffer<'a> = BitBuffer<'a, LittleEndian, NonPadded>;
|
||||
pub type Stream<'a> = BitStream<'a, LittleEndian, NonPadded>;
|
||||
|
|
|
|||
|
|
@ -20,4 +20,4 @@ impl<'a> Parse<'a> for ConsoleCmdPacket {
|
|||
let len = stream.read(32)?;
|
||||
stream.skip(len).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
91
src/demo/packet/datatable.rs
Normal file
91
src/demo/packet/datatable.rs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||
use crate::demo::sendprop::{SendPropDefinition, SendPropFlag, SendPropType};
|
||||
|
||||
pub struct ServerClass {
|
||||
id: u32,
|
||||
name: String,
|
||||
data_table: String,
|
||||
}
|
||||
|
||||
pub struct SendTable {
|
||||
name: String,
|
||||
props: Vec<SendPropDefinition>,
|
||||
needs_decoder: bool,
|
||||
flattened_props: Option<Vec<SendPropDefinition>>,
|
||||
}
|
||||
|
||||
pub struct DataTablePacket {
|
||||
tick: u32,
|
||||
tables: Vec<SendTable>,
|
||||
server_classes: Vec<ServerClass>,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for DataTablePacket {
|
||||
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
|
||||
let tick = stream.read(32)?;
|
||||
let _len = stream.read::<u32>(32)?;
|
||||
|
||||
let mut tables = vec![];
|
||||
while stream.read_bool()? {
|
||||
let needs_decoder = stream.read_bool()?;
|
||||
let name = stream.read_string(None)?;
|
||||
let prop_count = stream.read(10)?;
|
||||
|
||||
let mut array_element_prop = None;
|
||||
let mut props = Vec::with_capacity(prop_count);
|
||||
|
||||
for i in 0..prop_count {
|
||||
let prop: SendPropDefinition = SendPropDefinition::parse(stream, state, name.clone())?;
|
||||
if prop.flags.contains(SendPropFlag::InsideArray) {
|
||||
if array_element_prop.is_some() || prop.flags.contains(SendPropFlag::ChangesOften) {
|
||||
return Err(ParseError::InvalidSendPropArray);
|
||||
}
|
||||
array_element_prop = Some(prop);
|
||||
} else if let Some(array_element) = array_element_prop {
|
||||
if prop.prop_type == SendPropType::Array {
|
||||
return Err(ParseError::InvalidSendPropArray);
|
||||
}
|
||||
array_element_prop = None;
|
||||
props.push(prop.with_array_property(array_element));
|
||||
} else {
|
||||
props.push(prop);
|
||||
}
|
||||
}
|
||||
|
||||
let table = SendTable {
|
||||
name,
|
||||
flattened_props: None,
|
||||
needs_decoder,
|
||||
props,
|
||||
};
|
||||
tables.push(table);
|
||||
}
|
||||
|
||||
// TODO linked tables?
|
||||
|
||||
let server_class_count = stream.read(16)?;
|
||||
let mut server_classes = Vec::with_capacity(server_class_count);
|
||||
for i in 0..server_class_count {
|
||||
let id = stream.read(16)?;
|
||||
let name = stream.read_string(None)?;
|
||||
let data_table = stream.read_string(None)?;
|
||||
server_classes.push(ServerClass {
|
||||
id,
|
||||
name,
|
||||
data_table,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(DataTablePacket {
|
||||
tick,
|
||||
tables,
|
||||
server_classes,
|
||||
})
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
let _ = stream.skip(32)?;
|
||||
let len = stream.read(32)?;
|
||||
stream.skip(len).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
59
src/demo/packet/message.rs
Normal file
59
src/demo/packet/message.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||
use crate::demo::vector::Vector;
|
||||
|
||||
pub struct Message;
|
||||
|
||||
pub struct MessagePacket {
|
||||
tick: u32,
|
||||
messages: Vec<Message>,
|
||||
view_origin: (Vector, Vector),
|
||||
view_angles: (Vector, Vector),
|
||||
local_view_angles: (Vector, Vector),
|
||||
sequence_in: u32,
|
||||
sequence_out: u32,
|
||||
flags: u32, // TODO
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for MessagePacket {
|
||||
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
|
||||
let tick = stream.read(32)?;
|
||||
let flags = stream.read(32)?;
|
||||
|
||||
let view_origin_1 = Vector::parse(stream, state)?;
|
||||
let view_angle_1 = Vector::parse(stream, state)?;
|
||||
let local_view_angle_1 = Vector::parse(stream, state)?;
|
||||
let view_origin = (Vector::parse(stream, state)?, view_origin_1);
|
||||
let view_angles = (Vector::parse(stream, state)?, view_angle_1);
|
||||
let local_view_angles = (Vector::parse(stream, state)?, local_view_angle_1);
|
||||
|
||||
let sequence_in = stream.read(32)?;
|
||||
let sequence_out = stream.read(32)?;
|
||||
let length: usize = stream.read(32)?;
|
||||
let _ = stream.skip(length).map_err(ParseError::from);
|
||||
|
||||
let mut messages = vec![];
|
||||
|
||||
Ok(MessagePacket {
|
||||
tick,
|
||||
messages,
|
||||
view_origin,
|
||||
view_angles,
|
||||
local_view_angles,
|
||||
sequence_in,
|
||||
sequence_out,
|
||||
flags,
|
||||
})
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
let _ = stream.skip(32 * 2)?;
|
||||
|
||||
for i in 0..6 {
|
||||
Vector::skip(stream)?;
|
||||
}
|
||||
|
||||
let _ = stream.skip(32 * 2)?;
|
||||
let length: usize = stream.read(32)?;
|
||||
stream.skip(length).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,39 @@
|
|||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||
use enum_primitive_derive::Primitive;
|
||||
use num_traits::FromPrimitive;
|
||||
use self::stop::Stop;
|
||||
|
||||
mod stop;
|
||||
mod synctick;
|
||||
mod consolecmd;
|
||||
mod usercmd;
|
||||
mod stringtable;
|
||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||
|
||||
pub enum Packet {
|
||||
Stop(Stop)
|
||||
use self::consolecmd::ConsoleCmdPacket;
|
||||
use self::datatable::DataTablePacket;
|
||||
use self::message::MessagePacket;
|
||||
use self::stop::StopPacket;
|
||||
use self::stringtable::StringTablePacket;
|
||||
use self::synctick::SyncTickPacket;
|
||||
use self::usercmd::UserCmdPacket;
|
||||
|
||||
pub mod consolecmd;
|
||||
pub mod stop;
|
||||
pub mod stringtable;
|
||||
pub mod synctick;
|
||||
pub mod usercmd;
|
||||
pub mod datatable;
|
||||
pub mod message;
|
||||
|
||||
pub enum Packet<'a> {
|
||||
Sigon(MessagePacket),
|
||||
Message(MessagePacket),
|
||||
SyncTick(SyncTickPacket),
|
||||
ConsoleCmd(ConsoleCmdPacket),
|
||||
UserCmd(UserCmdPacket),
|
||||
DataTables(DataTablePacket),
|
||||
Stop(StopPacket),
|
||||
StringTables(StringTablePacket<'a>),
|
||||
}
|
||||
|
||||
#[derive(Primitive)]
|
||||
pub enum PacketType {
|
||||
Sigon = 1,
|
||||
Packet = 2,
|
||||
Message = 2,
|
||||
SyncTick = 3,
|
||||
ConsoleCmd = 4,
|
||||
UserCmd = 5,
|
||||
|
|
@ -24,23 +42,44 @@ pub enum PacketType {
|
|||
StringTables = 8,
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
fn read_type(stream: &mut Stream) -> Result<PacketType> {
|
||||
impl Parse<'_> for PacketType {
|
||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||
let raw = stream.read(8)?;
|
||||
let packet_type: Option<PacketType> = PacketType::from_u8(raw);
|
||||
packet_type.ok_or(ParseError::InvalidPacketType(raw))
|
||||
let prop_type: Option<PacketType> = PacketType::from_u8(raw);
|
||||
prop_type.ok_or(ParseError::InvalidPacketType(raw))
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
stream.skip(8).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
|
||||
//impl Parse for Packet {
|
||||
// fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||
// let packet_type = Packet::read_type(stream);
|
||||
// match packet_type {
|
||||
// Sigon => {}
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn skip(stream: &mut Stream) -> Result<()> {
|
||||
// Ok(())
|
||||
// }
|
||||
//}
|
||||
impl<'a> Parse<'a> for Packet<'a> {
|
||||
fn parse(stream: &mut Stream<'a>, state: &ParserState<'a>) -> Result<Self> {
|
||||
let packet_type = PacketType::parse(stream, state)?;
|
||||
Ok(match packet_type {
|
||||
PacketType::Sigon => Packet::Sigon(MessagePacket::parse(stream, state)?),
|
||||
PacketType::Message => Packet::Message(MessagePacket::parse(stream, state)?),
|
||||
PacketType::SyncTick => Packet::SyncTick(SyncTickPacket::parse(stream, state)?),
|
||||
PacketType::ConsoleCmd => Packet::ConsoleCmd(ConsoleCmdPacket::parse(stream, state)?),
|
||||
PacketType::UserCmd => Packet::UserCmd(UserCmdPacket::parse(stream, state)?),
|
||||
PacketType::DataTables => Packet::DataTables(DataTablePacket::parse(stream, state)?),
|
||||
PacketType::Stop => Packet::Stop(StopPacket::parse(stream, state)?),
|
||||
PacketType::StringTables => Packet::StringTables(StringTablePacket::parse(stream, state)?),
|
||||
})
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
let packet_type = PacketType::parse(stream, &ParserState::new(&stream))?;
|
||||
match packet_type {
|
||||
PacketType::Sigon => MessagePacket::skip(stream),
|
||||
PacketType::Message => MessagePacket::skip(stream),
|
||||
PacketType::SyncTick => SyncTickPacket::skip(stream),
|
||||
PacketType::ConsoleCmd => ConsoleCmdPacket::skip(stream),
|
||||
PacketType::UserCmd => UserCmdPacket::skip(stream),
|
||||
PacketType::DataTables => DataTablePacket::skip(stream),
|
||||
PacketType::Stop => StopPacket::skip(stream),
|
||||
PacketType::StringTables => StringTablePacket::skip(stream),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use crate::{Parse, ParserState, Result, Stream};
|
||||
|
||||
pub struct Stop;
|
||||
pub struct StopPacket;
|
||||
|
||||
impl<'a> Parse<'a> for Stop {
|
||||
impl<'a> Parse<'a> for StopPacket {
|
||||
fn parse(_stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||
Ok(Stop)
|
||||
Ok(StopPacket)
|
||||
}
|
||||
|
||||
fn skip(_stream: &mut Stream) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,10 +56,7 @@ impl<'a> StringTableEntry<'a> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
Ok(StringTableEntry {
|
||||
text,
|
||||
extra_data,
|
||||
})
|
||||
Ok(StringTableEntry { text, extra_data })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,10 +74,7 @@ impl<'a> Parse<'a> for StringTablePacket<'a> {
|
|||
for _ in 0..count {
|
||||
tables.push(StringTable::parse(stream)?);
|
||||
}
|
||||
Ok(StringTablePacket {
|
||||
tick,
|
||||
tables,
|
||||
})
|
||||
Ok(StringTablePacket { tick, tables })
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
|
|
@ -88,4 +82,4 @@ impl<'a> Parse<'a> for StringTablePacket<'a> {
|
|||
let length = stream.read(32)?;
|
||||
stream.skip(length).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||
|
||||
pub struct SyncTickPacket {
|
||||
tick: u32
|
||||
tick: u32,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for SyncTickPacket {
|
||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||
Ok(SyncTickPacket {
|
||||
tick: stream.read(32)?
|
||||
tick: stream.read(32)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
stream.skip(32).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::{Parse, ParseError, ParserState, Result, Stream};
|
|||
pub struct UserCmdPacket {
|
||||
tick: u32,
|
||||
command: String,
|
||||
sequence_out: u32
|
||||
sequence_out: u32,
|
||||
}
|
||||
|
||||
impl<'a> Parse<'a> for UserCmdPacket {
|
||||
|
|
@ -23,4 +23,4 @@ impl<'a> Parse<'a> for UserCmdPacket {
|
|||
let len = stream.read(32)?;
|
||||
stream.skip(len).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use bitstream_reader::ReadError;
|
||||
pub use crate::demo::parser::state::ParserState;
|
||||
use crate::Stream;
|
||||
use bitstream_reader::ReadError;
|
||||
|
||||
mod state;
|
||||
|
||||
|
|
@ -11,6 +11,10 @@ pub enum ParseError {
|
|||
ReadError(ReadError),
|
||||
/// Packet identifier is invalid
|
||||
InvalidPacketType(u8),
|
||||
/// SendProp type is invalid
|
||||
InvalidSendPropType(u8),
|
||||
/// Invalid structure found while creating array SendProp
|
||||
InvalidSendPropArray,
|
||||
}
|
||||
|
||||
impl From<ReadError> for ParseError {
|
||||
|
|
@ -26,7 +30,6 @@ pub trait Parse<'a>: Sized {
|
|||
fn skip(stream: &mut Stream) -> Result<()>;
|
||||
}
|
||||
|
||||
|
||||
pub struct DemoParser<'a> {
|
||||
stream: Stream<'a>,
|
||||
state: ParserState<'a>,
|
||||
|
|
@ -56,4 +59,4 @@ impl<'a> DemoParser<'a> {
|
|||
self.stream.set_pos(pos)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::demo::gamevent::GameEventDefinition;
|
||||
use crate::demo::sendprop::SendProp;
|
||||
use std::collections::HashMap;
|
||||
use crate::Stream;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct ParserState<'a> {
|
||||
pub version: u32,
|
||||
|
|
@ -23,4 +23,4 @@ impl<'a> ParserState<'a> {
|
|||
event_definitions: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,203 @@
|
|||
use enum_primitive_derive::Primitive;
|
||||
use enumflags2::BitFlags;
|
||||
use enumflags2_derive::EnumFlags;
|
||||
use num_traits::cast::FromPrimitive;
|
||||
|
||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||
|
||||
use super::packet::datatable::SendTable;
|
||||
use super::vector::{Vector, VectorXY};
|
||||
|
||||
pub struct SendPropDefinition {}
|
||||
pub struct SendPropDefinition {
|
||||
pub prop_type: SendPropType,
|
||||
pub name: String,
|
||||
pub flags: BitFlags<SendPropFlag>,
|
||||
pub exclude_dt_name: Option<String>,
|
||||
pub low_value: Option<f32>,
|
||||
pub high_value: Option<f32>,
|
||||
pub bit_count: Option<u32>,
|
||||
pub original_bit_count: Option<u32>,
|
||||
pub table: Option<SendTable>,
|
||||
pub element_count: Option<u16>,
|
||||
pub array_property: Option<Box<SendPropDefinition>>,
|
||||
pub owner_table_name: String,
|
||||
}
|
||||
|
||||
impl SendPropDefinition {
|
||||
pub fn parse<'a>(stream: &mut Stream<'a>, state: &ParserState<'a>, owner_table_name: String) -> Result<Self> {
|
||||
let prop_type = SendPropType::parse(stream, state)?;
|
||||
let name = stream.read_string(None)?;
|
||||
let flags = BitFlags::<SendPropFlag>::parse(stream, state)?;
|
||||
let mut exclude_dt_name = None;
|
||||
let mut element_count = None;
|
||||
let mut low_value = None;
|
||||
let mut high_value = None;
|
||||
let mut bit_count = None;
|
||||
if prop_type == SendPropType::DataTable {
|
||||
exclude_dt_name = Some(stream.read_string(None)?);
|
||||
} else {
|
||||
if flags.contains(SendPropFlag::Exclude) {
|
||||
exclude_dt_name = Some(stream.read_string(None)?);
|
||||
} else if prop_type == SendPropType::Array {
|
||||
element_count = Some(stream.read(10)?);
|
||||
} else {
|
||||
low_value = Some(stream.read_float()?);
|
||||
high_value = Some(stream.read_float()?);
|
||||
bit_count = Some(stream.read(7)?);
|
||||
}
|
||||
}
|
||||
let original_bit_count = bit_count;
|
||||
|
||||
if flags.contains(SendPropFlag::NoScale) {
|
||||
if prop_type == SendPropType::Float {
|
||||
bit_count = Some(32);
|
||||
} else if prop_type == SendPropType::Vector && !flags.contains(SendPropFlag::NormalVarInt) {
|
||||
bit_count = Some(32 * 3);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(SendPropDefinition {
|
||||
prop_type,
|
||||
name,
|
||||
flags,
|
||||
exclude_dt_name,
|
||||
low_value,
|
||||
high_value,
|
||||
bit_count,
|
||||
original_bit_count,
|
||||
table: None,
|
||||
element_count,
|
||||
array_property: None,
|
||||
owner_table_name,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn with_array_property(self, array_property: Self) -> Self {
|
||||
SendPropDefinition {
|
||||
prop_type: self.prop_type,
|
||||
name: self.name,
|
||||
flags: self.flags,
|
||||
exclude_dt_name: self.exclude_dt_name,
|
||||
low_value: self.low_value,
|
||||
high_value: self.high_value,
|
||||
bit_count: self.bit_count,
|
||||
original_bit_count: self.original_bit_count,
|
||||
table: None,
|
||||
element_count: self.element_count,
|
||||
array_property: Some(Box::new(array_property)),
|
||||
owner_table_name: self.owner_table_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Primitive, Copy, Clone, PartialEq, Debug)]
|
||||
pub enum SendPropType {
|
||||
Int = 0,
|
||||
Float = 1,
|
||||
Vector = 2,
|
||||
VectorXY = 3,
|
||||
String = 4,
|
||||
Array = 5,
|
||||
DataTable = 6,
|
||||
NumSendPropTypes = 7,
|
||||
}
|
||||
|
||||
impl Parse<'_> for SendPropType {
|
||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||
let raw = stream.read(5)?;
|
||||
let prop_type: Option<SendPropType> = SendPropType::from_u8(raw);
|
||||
prop_type.ok_or(ParseError::InvalidSendPropType(raw))
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
stream.skip(5).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(EnumFlags, Copy, Clone, PartialEq, Debug)]
|
||||
#[repr(u16)]
|
||||
pub enum SendPropFlag {
|
||||
Unsigned = 1,
|
||||
//(1 << 0)
|
||||
// Unsigned integer data.
|
||||
Coord = 2,
|
||||
//(1 << 1)
|
||||
// If this is set, the float/vector is treated like a world coordinate.
|
||||
// Note that the bit count is ignored in this case.
|
||||
NoScale = 4,
|
||||
//(1 << 2)
|
||||
// For floating point, don't scale into range, just take value as is.
|
||||
RoundDown = 8,
|
||||
//(1 << 3)
|
||||
// For floating point, limit high value to range minus one bit unit
|
||||
RoundUp = 16,
|
||||
//(1 << 4)
|
||||
// For floating point, limit low value to range minus one bit unit
|
||||
// Normal = 32, // seems to be depricated
|
||||
//(1 << 5)
|
||||
// If this is set, the vector is treated like a normal (only valid for vectors)
|
||||
Exclude = 64,
|
||||
//(1 << 6)
|
||||
// This is an exclude prop (not excludED, but it points at another prop to be excluded).
|
||||
XYZE = 128,
|
||||
//(1 << 7)
|
||||
// Use XYZ/Exponent encoding for vectors.
|
||||
InsideArray = 256,
|
||||
//(1 << 8)
|
||||
// This tells us that the property is inside an array, so it shouldn't be put into the
|
||||
// flattened property list. Its array will point at it when it needs to.
|
||||
PropxyAlwaysYes = 512,
|
||||
//(1 << 9)
|
||||
// Set for datatable props using one of the default datatable proxies like
|
||||
// SendProxy_DataTableToDataTable that always send the data to all clients.
|
||||
ChangesOften = 1024,
|
||||
//(1 << 10)
|
||||
// this is an often changed field, moved to head of sendtable so it gets a small index
|
||||
IsVectorElement = 2048,
|
||||
//(1 << 11)
|
||||
// Set automatically if SPROP_VECTORELEM is used.
|
||||
Collapsible = 4096,
|
||||
//(1 << 12)
|
||||
// Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer
|
||||
// (ie: for all automatically-chained base classes).
|
||||
// In this case, it can get rid of this SendPropDataTable altogether and spare the
|
||||
// trouble of walking the hierarchy more than necessary.
|
||||
CoordMP = 8192,
|
||||
//(1 << 13)
|
||||
// Like SPROP_COORD, but special handling for multiplayer games
|
||||
CoordMPLowPercision = 16384,
|
||||
//(1 << 14)
|
||||
// Like SPROP_COORD, but special handling for multiplayer games
|
||||
// where the fractional component only gets a 3 bits instead of 5
|
||||
CoordMPIntegral = 32768,
|
||||
//(1 << 15)
|
||||
// SPROP_COORD_MP, but coordinates are rounded to integral boundaries
|
||||
// overloaded as both "Normal" and "VarInt"
|
||||
NormalVarInt = 32, //(1 << 5)
|
||||
}
|
||||
|
||||
impl Parse<'_> for BitFlags<SendPropFlag> {
|
||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||
let raw = stream.read(16)?;
|
||||
// since all 16 bits worth of flags are used there are no invalid flags
|
||||
Ok(BitFlags::from_bits_truncate(raw))
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
stream.skip(16).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum SendPropValue {
|
||||
Vector(Vector),
|
||||
VectorXY(VectorXY),
|
||||
Integer(i32),
|
||||
Float(f32),
|
||||
String(String),
|
||||
Array(Vec<SendPropType>),
|
||||
Array(Vec<SendPropValue>),
|
||||
}
|
||||
|
||||
pub struct SendProp {
|
||||
definition: SendPropDefinition,
|
||||
value: SendPropType,
|
||||
value: SendPropValue,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,39 @@
|
|||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||
|
||||
pub struct Vector {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub z: f32,
|
||||
}
|
||||
|
||||
impl Parse<'_> for Vector {
|
||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||
Ok(Vector {
|
||||
x: stream.read_float()?,
|
||||
y: stream.read_float()?,
|
||||
z: stream.read_float()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
stream.skip(32 * 3).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VectorXY {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl Parse<'_> for VectorXY {
|
||||
fn parse(stream: &mut Stream, _state: &ParserState) -> Result<Self> {
|
||||
Ok(VectorXY {
|
||||
x: stream.read_float()?,
|
||||
y: stream.read_float()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn skip(stream: &mut Stream) -> Result<()> {
|
||||
stream.skip(32 * 2).map_err(ParseError::from)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue