mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-05 02:54:10 +02:00
packet parsers
This commit is contained in:
parent
4ac2a3cfc6
commit
b41bb56822
19 changed files with 626 additions and 64 deletions
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue