mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 18:24:05 +02:00
strongly typed sendpropdefinition
This commit is contained in:
parent
1258827b54
commit
df9a6a138e
10 changed files with 384 additions and 206 deletions
|
|
@ -14,7 +14,7 @@ use tf_demo_parser::demo::message::Message;
|
||||||
use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTableName};
|
use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTableName};
|
||||||
use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
|
use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
|
||||||
use tf_demo_parser::demo::parser::MessageHandler;
|
use tf_demo_parser::demo::parser::MessageHandler;
|
||||||
use tf_demo_parser::demo::sendprop::SendPropDefinition;
|
use tf_demo_parser::demo::sendprop::RawSendPropDefinition;
|
||||||
use tf_demo_parser::{Demo, DemoParser, MatchState, MessageType, MessageTypeAnalyser, ParserState};
|
use tf_demo_parser::{Demo, DemoParser, MatchState, MessageType, MessageTypeAnalyser, ParserState};
|
||||||
|
|
||||||
struct AllMessages;
|
struct AllMessages;
|
||||||
|
|
|
||||||
|
|
@ -14,48 +14,48 @@ use tf_demo_parser::demo::message::Message;
|
||||||
use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTableName};
|
use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTableName};
|
||||||
use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
|
use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
|
||||||
use tf_demo_parser::demo::parser::MessageHandler;
|
use tf_demo_parser::demo::parser::MessageHandler;
|
||||||
use tf_demo_parser::demo::sendprop::SendPropDefinition;
|
use tf_demo_parser::demo::sendprop::RawSendPropDefinition;
|
||||||
use tf_demo_parser::{Demo, DemoParser, MatchState, MessageType, MessageTypeAnalyser, ParserState};
|
use tf_demo_parser::{Demo, DemoParser, MatchState, MessageType, MessageTypeAnalyser, ParserState};
|
||||||
|
|
||||||
pub struct SendPropAnalyser;
|
pub struct SendPropAnalyser;
|
||||||
|
|
||||||
impl MessageHandler for SendPropAnalyser {
|
// impl MessageHandler for SendPropAnalyser {
|
||||||
type Output = Vec<ParseSendTable>;
|
// type Output = Vec<ParseSendTable>;
|
||||||
|
//
|
||||||
fn does_handle(message_type: MessageType) -> bool {
|
// fn does_handle(message_type: MessageType) -> bool {
|
||||||
false
|
// false
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fn into_output(self, state: &ParserState) -> Self::Output {
|
// fn into_output(self, state: &ParserState) -> Self::Output {
|
||||||
state
|
// state
|
||||||
.send_tables
|
// .send_tables
|
||||||
.iter()
|
// .iter()
|
||||||
.map(|v| ParseSendTable {
|
// .map(|v| ParseSendTable {
|
||||||
name: v.name.clone(),
|
// name: v.name.clone(),
|
||||||
props: v.props.clone(),
|
// props: v.props.clone(),
|
||||||
needs_decoder: v.needs_decoder,
|
// needs_decoder: v.needs_decoder,
|
||||||
})
|
// })
|
||||||
.collect()
|
// .collect()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fn flatten_bench(input_file: &str, b: &mut Bencher) {
|
// fn flatten_bench(input_file: &str, b: &mut Bencher) {
|
||||||
let file = fs::read(input_file).expect("Unable to read file");
|
// let file = fs::read(input_file).expect("Unable to read file");
|
||||||
let demo = Demo::new(&file);
|
// let demo = Demo::new(&file);
|
||||||
let stream = demo.get_stream();
|
// let stream = demo.get_stream();
|
||||||
let (_, send_tables) = DemoParser::new_with_analyser(stream.clone(), SendPropAnalyser)
|
// let (_, send_tables) = DemoParser::new_with_analyser(stream.clone(), SendPropAnalyser)
|
||||||
.parse()
|
// .parse()
|
||||||
.unwrap();
|
// .unwrap();
|
||||||
b.iter(|| {
|
// b.iter(|| {
|
||||||
let flat: Vec<_> = send_tables
|
// let flat: Vec<_> = send_tables
|
||||||
.iter()
|
// .iter()
|
||||||
.map(|table| table.flatten_props(&send_tables))
|
// .map(|table| table.flatten_props(&send_tables))
|
||||||
.collect();
|
// .collect();
|
||||||
test::black_box(flat);
|
// test::black_box(flat);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[bench]
|
// #[bench]
|
||||||
fn sendprop_test_gully(b: &mut Bencher) {
|
// fn sendprop_test_gully(b: &mut Bencher) {
|
||||||
flatten_bench("data/gully.dem", b);
|
// flatten_bench("data/gully.dem", b);
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
use crate::demo::message::stringtable::log_base2;
|
use crate::demo::message::stringtable::log_base2;
|
||||||
use crate::demo::packet::datatable::{ClassId, SendTable};
|
use crate::demo::packet::datatable::{ClassId, SendTable};
|
||||||
use crate::demo::parser::ParseBitSkip;
|
use crate::demo::parser::ParseBitSkip;
|
||||||
use crate::demo::sendprop::{SendProp, SendPropDefinition, SendPropValue};
|
use crate::demo::sendprop::{SendProp, SendPropIdentifier, SendPropValue};
|
||||||
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, ReadResult, Result, Stream};
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
@ -13,7 +13,6 @@ use std::cmp::min;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hint::unreachable_unchecked;
|
use std::hint::unreachable_unchecked;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
|
|
@ -70,15 +69,15 @@ impl fmt::Display for PacketEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketEntity {
|
impl PacketEntity {
|
||||||
fn get_prop_by_definition(&mut self, definition: &SendPropDefinition) -> Option<&mut SendProp> {
|
fn get_prop_by_identifier(&mut self, identifier: &SendPropIdentifier) -> Option<&mut SendProp> {
|
||||||
self.props
|
self.props
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|prop| prop.definition.index == definition.index)
|
.find(|prop| prop.identifier.index == identifier.index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_update(&mut self, props: Vec<SendProp>) {
|
pub fn apply_update(&mut self, props: Vec<SendProp>) {
|
||||||
for prop in props {
|
for prop in props {
|
||||||
match self.get_prop_by_definition(&prop.definition) {
|
match self.get_prop_by_identifier(&prop.identifier) {
|
||||||
Some(existing_prop) => existing_prop.value = prop.value,
|
Some(existing_prop) => existing_prop.value = prop.value,
|
||||||
None => self.props.push(prop),
|
None => self.props.push(prop),
|
||||||
}
|
}
|
||||||
|
|
@ -87,8 +86,8 @@ impl PacketEntity {
|
||||||
|
|
||||||
pub fn get_prop_by_name(&self, table_name: &str, name: &str) -> Option<&SendProp> {
|
pub fn get_prop_by_name(&self, table_name: &str, name: &str) -> Option<&SendProp> {
|
||||||
self.props.iter().find(|prop| {
|
self.props.iter().find(|prop| {
|
||||||
prop.definition.owner_table.as_str() == table_name
|
prop.identifier.owner_table.as_str() == table_name
|
||||||
&& prop.definition.name.as_str() == name
|
&& prop.identifier.name.as_str() == name
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -252,7 +251,7 @@ impl PacketEntitiesMessage {
|
||||||
Some(definition) => {
|
Some(definition) => {
|
||||||
let value = SendPropValue::parse(stream, definition)?;
|
let value = SendPropValue::parse(stream, definition)?;
|
||||||
props.push(SendProp {
|
props.push(SendProp {
|
||||||
definition: Rc::clone(definition),
|
identifier: definition.identifier(),
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ use bitbuffer::BitRead;
|
||||||
|
|
||||||
use crate::demo::parser::MalformedSendPropDefinitionError;
|
use crate::demo::parser::MalformedSendPropDefinitionError;
|
||||||
use crate::demo::sendprop::{
|
use crate::demo::sendprop::{
|
||||||
SendPropDefinition, SendPropDefinitionIndex, SendPropFlag, SendPropName, SendPropType,
|
RawSendPropDefinition, SendPropDefinition, SendPropDefinitionIndex, SendPropFlag, SendPropName,
|
||||||
|
SendPropType,
|
||||||
};
|
};
|
||||||
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
use crate::{Parse, ParseError, ParserState, Result, Stream};
|
||||||
use parse_display::{Display, FromStr};
|
use parse_display::{Display, FromStr};
|
||||||
|
|
@ -50,7 +51,18 @@ pub struct ServerClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
BitRead, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Clone, Display, PartialOrd, Ord,
|
BitRead,
|
||||||
|
PartialEq,
|
||||||
|
Eq,
|
||||||
|
Hash,
|
||||||
|
Debug,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
Clone,
|
||||||
|
Display,
|
||||||
|
PartialOrd,
|
||||||
|
Ord,
|
||||||
|
Default,
|
||||||
)]
|
)]
|
||||||
pub struct SendTableName(Rc<String>);
|
pub struct SendTableName(Rc<String>);
|
||||||
|
|
||||||
|
|
@ -69,7 +81,7 @@ impl From<String> for SendTableName {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ParseSendTable {
|
pub struct ParseSendTable {
|
||||||
pub name: SendTableName,
|
pub name: SendTableName,
|
||||||
pub props: Vec<Rc<SendPropDefinition>>,
|
pub props: Vec<Rc<RawSendPropDefinition>>,
|
||||||
pub needs_decoder: bool,
|
pub needs_decoder: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,8 +97,8 @@ impl ParseSendTable {
|
||||||
|
|
||||||
for prop_index in 0..prop_count {
|
for prop_index in 0..prop_count {
|
||||||
let definition_index = SendPropDefinitionIndex::new(table_index, prop_index);
|
let definition_index = SendPropDefinitionIndex::new(table_index, prop_index);
|
||||||
let prop: SendPropDefinition =
|
let prop: RawSendPropDefinition =
|
||||||
SendPropDefinition::read(stream, name.clone(), definition_index)?;
|
RawSendPropDefinition::read(stream, name.clone(), definition_index)?;
|
||||||
if prop.flags.contains(SendPropFlag::InsideArray) {
|
if prop.flags.contains(SendPropFlag::InsideArray) {
|
||||||
if array_element_prop.is_some() || prop.flags.contains(SendPropFlag::ChangesOften) {
|
if array_element_prop.is_some() || prop.flags.contains(SendPropFlag::ChangesOften) {
|
||||||
return Err(MalformedSendPropDefinitionError::ArrayChangesOften.into());
|
return Err(MalformedSendPropDefinitionError::ArrayChangesOften.into());
|
||||||
|
|
@ -112,7 +124,7 @@ impl ParseSendTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParseSendTable {
|
impl ParseSendTable {
|
||||||
pub fn flatten_props(&self, tables: &[ParseSendTable]) -> Vec<Rc<SendPropDefinition>> {
|
pub fn flatten_props(&self, tables: &[ParseSendTable]) -> Vec<Rc<RawSendPropDefinition>> {
|
||||||
let mut flat = Vec::with_capacity(32);
|
let mut flat = Vec::with_capacity(32);
|
||||||
self.get_all_props(tables, &self.get_excludes(tables), &mut flat);
|
self.get_all_props(tables, &self.get_excludes(tables), &mut flat);
|
||||||
|
|
||||||
|
|
@ -137,7 +149,7 @@ impl ParseSendTable {
|
||||||
if let Some(exclude_table) = prop.get_exclude_table() {
|
if let Some(exclude_table) = prop.get_exclude_table() {
|
||||||
excludes.push(Exclude {
|
excludes.push(Exclude {
|
||||||
table: exclude_table,
|
table: exclude_table,
|
||||||
prop: &prop.name,
|
prop: &prop.identifier.name,
|
||||||
})
|
})
|
||||||
} else if let Some(table) = prop.get_data_table(tables) {
|
} else if let Some(table) = prop.get_data_table(tables) {
|
||||||
excludes.extend_from_slice(&table.get_excludes(tables));
|
excludes.extend_from_slice(&table.get_excludes(tables));
|
||||||
|
|
@ -152,7 +164,7 @@ impl ParseSendTable {
|
||||||
&self,
|
&self,
|
||||||
tables: &[ParseSendTable],
|
tables: &[ParseSendTable],
|
||||||
excludes: &[Exclude],
|
excludes: &[Exclude],
|
||||||
props: &mut Vec<Rc<SendPropDefinition>>,
|
props: &mut Vec<Rc<RawSendPropDefinition>>,
|
||||||
) {
|
) {
|
||||||
let mut local_props = Vec::new();
|
let mut local_props = Vec::new();
|
||||||
|
|
||||||
|
|
@ -164,8 +176,8 @@ impl ParseSendTable {
|
||||||
&self,
|
&self,
|
||||||
tables: &[ParseSendTable],
|
tables: &[ParseSendTable],
|
||||||
excludes: &[Exclude],
|
excludes: &[Exclude],
|
||||||
local_props: &mut Vec<Rc<SendPropDefinition>>,
|
local_props: &mut Vec<Rc<RawSendPropDefinition>>,
|
||||||
props: &mut Vec<Rc<SendPropDefinition>>,
|
props: &mut Vec<Rc<RawSendPropDefinition>>,
|
||||||
) {
|
) {
|
||||||
self.props
|
self.props
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -192,17 +204,16 @@ struct Exclude<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Exclude<'a> {
|
impl<'a> Exclude<'a> {
|
||||||
pub fn matches(&self, prop: &SendPropDefinition) -> bool {
|
pub fn matches(&self, prop: &RawSendPropDefinition) -> bool {
|
||||||
self.table == &prop.owner_table && *self.prop == prop.name
|
self.table == &prop.identifier.owner_table && *self.prop == prop.identifier.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SendTable {
|
pub struct SendTable {
|
||||||
pub name: SendTableName,
|
pub name: SendTableName,
|
||||||
pub props: Vec<Rc<SendPropDefinition>>,
|
|
||||||
pub needs_decoder: bool,
|
pub needs_decoder: bool,
|
||||||
pub flattened_props: Vec<Rc<SendPropDefinition>>,
|
pub flattened_props: Vec<SendPropDefinition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,7 @@ impl GameStateAnalyser {
|
||||||
|
|
||||||
pub fn handle_player_resource(&mut self, entity: &PacketEntity) {
|
pub fn handle_player_resource(&mut self, entity: &PacketEntity) {
|
||||||
for prop in &entity.props {
|
for prop in &entity.props {
|
||||||
if let Ok(player_id) = u32::from_str(prop.definition.name.as_str()) {
|
if let Ok(player_id) = u32::from_str(prop.identifier.name.as_str()) {
|
||||||
let entity_id = EntityId::from(player_id);
|
let entity_id = EntityId::from(player_id);
|
||||||
if let Some(player) = self
|
if let Some(player) = self
|
||||||
.state
|
.state
|
||||||
|
|
@ -214,7 +214,7 @@ impl GameStateAnalyser {
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|player| player.entity == entity_id)
|
.find(|player| player.entity == entity_id)
|
||||||
{
|
{
|
||||||
match prop.definition.owner_table.as_str() {
|
match prop.identifier.owner_table.as_str() {
|
||||||
"m_iTeam" => {
|
"m_iTeam" => {
|
||||||
player.team = Team::new(i64::try_from(&prop.value).unwrap_or_default())
|
player.team = Team::new(i64::try_from(&prop.value).unwrap_or_default())
|
||||||
}
|
}
|
||||||
|
|
@ -237,8 +237,8 @@ impl GameStateAnalyser {
|
||||||
let player = self.state.get_or_create_player(entity.entity_index);
|
let player = self.state.get_or_create_player(entity.entity_index);
|
||||||
|
|
||||||
for prop in &entity.props {
|
for prop in &entity.props {
|
||||||
match prop.definition.owner_table.as_str() {
|
match prop.identifier.owner_table.as_str() {
|
||||||
"DT_BasePlayer" => match prop.definition.name.as_str() {
|
"DT_BasePlayer" => match prop.identifier.name.as_str() {
|
||||||
"m_iHealth" => {
|
"m_iHealth" => {
|
||||||
player.health = i64::try_from(&prop.value).unwrap_or_default() as u16
|
player.health = i64::try_from(&prop.value).unwrap_or_default() as u16
|
||||||
}
|
}
|
||||||
|
|
@ -252,7 +252,7 @@ impl GameStateAnalyser {
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
"DT_TFLocalPlayerExclusive" | "DT_TFNonLocalPlayerExclusive" => {
|
"DT_TFLocalPlayerExclusive" | "DT_TFNonLocalPlayerExclusive" => {
|
||||||
match prop.definition.name.as_str() {
|
match prop.identifier.name.as_str() {
|
||||||
"m_vecOrigin" => {
|
"m_vecOrigin" => {
|
||||||
let pos_xy = VectorXY::try_from(&prop.value).unwrap_or_default();
|
let pos_xy = VectorXY::try_from(&prop.value).unwrap_or_default();
|
||||||
player.position.x = pos_xy.x;
|
player.position.x = pos_xy.x;
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ impl<'a, T: MessageHandler> DemoHandler<'a, T> {
|
||||||
pub fn handle_packet(&mut self, packet: Packet<'a>) -> Result<()> {
|
pub fn handle_packet(&mut self, packet: Packet<'a>) -> Result<()> {
|
||||||
match packet {
|
match packet {
|
||||||
Packet::DataTables(packet) => {
|
Packet::DataTables(packet) => {
|
||||||
self.handle_data_table(packet.tables, packet.server_classes);
|
self.handle_data_table(packet.tables, packet.server_classes)?;
|
||||||
}
|
}
|
||||||
Packet::StringTables(packet) => {
|
Packet::StringTables(packet) => {
|
||||||
for table in packet.tables.into_iter() {
|
for table in packet.tables.into_iter() {
|
||||||
|
|
@ -127,11 +127,11 @@ impl<'a, T: MessageHandler> DemoHandler<'a, T> {
|
||||||
&mut self,
|
&mut self,
|
||||||
send_tables: Vec<ParseSendTable>,
|
send_tables: Vec<ParseSendTable>,
|
||||||
server_classes: Vec<ServerClass>,
|
server_classes: Vec<ServerClass>,
|
||||||
) {
|
) -> Result<()> {
|
||||||
self.analyser
|
self.analyser
|
||||||
.handle_data_tables(&send_tables, &server_classes);
|
.handle_data_tables(&send_tables, &server_classes);
|
||||||
self.state_handler
|
self.state_handler
|
||||||
.handle_data_table(send_tables, server_classes);
|
.handle_data_table(send_tables, server_classes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_message(&mut self, message: Message<'a>) {
|
fn handle_message(&mut self, message: Message<'a>) {
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,11 @@ use crate::demo::packet::datatable::{
|
||||||
};
|
};
|
||||||
use crate::demo::packet::stringtable::StringTableEntry;
|
use crate::demo::packet::stringtable::StringTableEntry;
|
||||||
|
|
||||||
use crate::demo::sendprop::SendProp;
|
use crate::demo::sendprop::{SendProp, SendPropDefinition};
|
||||||
use crate::nullhasher::NullHasherBuilder;
|
use crate::nullhasher::NullHasherBuilder;
|
||||||
use crate::{Result, Stream};
|
use crate::{Result, Stream};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct DemoMeta {
|
pub struct DemoMeta {
|
||||||
|
|
@ -100,7 +101,7 @@ impl<'a> ParserState {
|
||||||
&mut self,
|
&mut self,
|
||||||
parse_tables: Vec<ParseSendTable>,
|
parse_tables: Vec<ParseSendTable>,
|
||||||
server_classes: Vec<ServerClass>,
|
server_classes: Vec<ServerClass>,
|
||||||
) {
|
) -> Result<()> {
|
||||||
if self.handle_entities {
|
if self.handle_entities {
|
||||||
let flat_props: Vec<_> = parse_tables
|
let flat_props: Vec<_> = parse_tables
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -111,17 +112,19 @@ impl<'a> ParserState {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(flat_props.into_iter())
|
.zip(flat_props.into_iter())
|
||||||
.map(|(parse_table, flat)| {
|
.map(|(parse_table, flat)| {
|
||||||
(
|
Ok((
|
||||||
parse_table.name.clone(),
|
parse_table.name.clone(),
|
||||||
SendTable {
|
SendTable {
|
||||||
name: parse_table.name,
|
name: parse_table.name,
|
||||||
props: parse_table.props,
|
|
||||||
needs_decoder: parse_table.needs_decoder,
|
needs_decoder: parse_table.needs_decoder,
|
||||||
flattened_props: flat,
|
flattened_props: flat
|
||||||
|
.into_iter()
|
||||||
|
.map(|raw| SendPropDefinition::try_from(raw.as_ref()))
|
||||||
|
.collect::<std::result::Result<Vec<_>, _>>()?,
|
||||||
},
|
},
|
||||||
)
|
))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect::<Result<_>>()?;
|
||||||
|
|
||||||
self.server_classes = server_classes;
|
self.server_classes = server_classes;
|
||||||
|
|
||||||
|
|
@ -133,6 +136,8 @@ impl<'a> ParserState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_string_table_meta(&mut self, table: StringTableMeta) {
|
pub fn handle_string_table_meta(&mut self, table: StringTableMeta) {
|
||||||
|
|
|
||||||
|
|
@ -40,34 +40,32 @@ impl From<String> for SendPropName {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SendPropDefinition {
|
pub struct RawSendPropDefinition {
|
||||||
pub prop_type: SendPropType,
|
pub prop_type: SendPropType,
|
||||||
pub name: SendPropName,
|
pub identifier: Rc<SendPropIdentifier>,
|
||||||
pub flags: SendPropFlags,
|
pub flags: SendPropFlags,
|
||||||
pub table_name: Option<SendTableName>,
|
pub table_name: Option<SendTableName>,
|
||||||
pub owner_table: SendTableName,
|
|
||||||
pub low_value: Option<f32>,
|
pub low_value: Option<f32>,
|
||||||
pub high_value: Option<f32>,
|
pub high_value: Option<f32>,
|
||||||
pub bit_count: Option<u32>,
|
pub bit_count: Option<u32>,
|
||||||
pub element_count: Option<u16>,
|
pub element_count: Option<u16>,
|
||||||
pub array_property: Option<Box<SendPropDefinition>>,
|
pub array_property: Option<Box<RawSendPropDefinition>>,
|
||||||
pub index: SendPropDefinitionIndex,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for SendPropDefinition {
|
impl PartialEq for RawSendPropDefinition {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.index == other.index
|
self.identifier.index == other.identifier.index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SendPropDefinition {
|
impl fmt::Display for RawSendPropDefinition {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self.prop_type {
|
match self.prop_type {
|
||||||
SendPropType::Vector | SendPropType::VectorXY => write!(
|
SendPropType::Vector | SendPropType::VectorXY => write!(
|
||||||
f,
|
f,
|
||||||
"{}::{}({})(flags: {}, low: {}, high: {}, bits: {})",
|
"{}::{}({})(flags: {}, low: {}, high: {}, bits: {})",
|
||||||
self.owner_table,
|
self.identifier.owner_table,
|
||||||
self.name,
|
self.identifier.name,
|
||||||
self.prop_type,
|
self.prop_type,
|
||||||
self.flags,
|
self.flags,
|
||||||
self.low_value.unwrap_or_default(),
|
self.low_value.unwrap_or_default(),
|
||||||
|
|
@ -77,8 +75,8 @@ impl fmt::Display for SendPropDefinition {
|
||||||
SendPropType::Float => write!(
|
SendPropType::Float => write!(
|
||||||
f,
|
f,
|
||||||
"{}::{}({})(flags: {}, low: {}, high: {}, bits: {})",
|
"{}::{}({})(flags: {}, low: {}, high: {}, bits: {})",
|
||||||
self.owner_table,
|
self.identifier.owner_table,
|
||||||
self.name,
|
self.identifier.name,
|
||||||
self.prop_type,
|
self.prop_type,
|
||||||
self.flags,
|
self.flags,
|
||||||
self.low_value.unwrap_or_default(),
|
self.low_value.unwrap_or_default(),
|
||||||
|
|
@ -88,47 +86,55 @@ impl fmt::Display for SendPropDefinition {
|
||||||
SendPropType::Int => write!(
|
SendPropType::Int => write!(
|
||||||
f,
|
f,
|
||||||
"{}::{}({})(flags: {}, bits: {})",
|
"{}::{}({})(flags: {}, bits: {})",
|
||||||
self.owner_table,
|
self.identifier.owner_table,
|
||||||
self.name,
|
self.identifier.name,
|
||||||
self.prop_type,
|
self.prop_type,
|
||||||
self.flags,
|
self.flags,
|
||||||
self.bit_count.unwrap_or(32)
|
self.bit_count.unwrap_or(32)
|
||||||
),
|
),
|
||||||
SendPropType::String => {
|
SendPropType::String => {
|
||||||
write!(f, "{}::{}({})", self.owner_table, self.name, self.prop_type)
|
write!(
|
||||||
|
f,
|
||||||
|
"{}::{}({})",
|
||||||
|
self.identifier.owner_table, self.identifier.name, self.prop_type
|
||||||
|
)
|
||||||
}
|
}
|
||||||
SendPropType::Array => match &self.array_property {
|
SendPropType::Array => match &self.array_property {
|
||||||
Some(array_prop) => write!(
|
Some(array_prop) => write!(
|
||||||
f,
|
f,
|
||||||
"{}::{}([{}({})] * {})",
|
"{}::{}([{}({})] * {})",
|
||||||
self.owner_table,
|
self.identifier.owner_table,
|
||||||
self.name,
|
self.identifier.name,
|
||||||
array_prop.prop_type,
|
array_prop.prop_type,
|
||||||
array_prop.flags,
|
array_prop.flags,
|
||||||
self.element_count.unwrap_or_default(),
|
self.element_count.unwrap_or_default(),
|
||||||
),
|
),
|
||||||
None => write!(f, "{}(Malformed array)", self.name),
|
None => write!(f, "{}(Malformed array)", self.identifier.name),
|
||||||
},
|
},
|
||||||
SendPropType::DataTable => match &self.table_name {
|
SendPropType::DataTable => match &self.table_name {
|
||||||
Some(sub_table) => write!(
|
Some(sub_table) => write!(
|
||||||
f,
|
f,
|
||||||
"{}::{}(DataTable = {})",
|
"{}::{}(DataTable = {})",
|
||||||
self.owner_table, self.name, sub_table
|
self.identifier.owner_table, self.identifier.name, sub_table
|
||||||
),
|
),
|
||||||
None => write!(f, "{}(Malformed DataTable)", self.name),
|
None => write!(f, "{}(Malformed DataTable)", self.identifier.name),
|
||||||
},
|
},
|
||||||
SendPropType::NumSendPropTypes => {
|
SendPropType::NumSendPropTypes => {
|
||||||
write!(f, "{}::{}(NumSendPropTypes)", self.owner_table, self.name)
|
write!(
|
||||||
|
f,
|
||||||
|
"{}::{}(NumSendPropTypes)",
|
||||||
|
self.identifier.owner_table, self.identifier.name
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SendPropDefinition {
|
impl RawSendPropDefinition {
|
||||||
pub fn with_array_property(self, array_property: Self) -> Self {
|
pub fn with_array_property(self, array_property: Self) -> Self {
|
||||||
SendPropDefinition {
|
RawSendPropDefinition {
|
||||||
prop_type: self.prop_type,
|
prop_type: self.prop_type,
|
||||||
name: self.name,
|
identifier: self.identifier,
|
||||||
flags: self.flags,
|
flags: self.flags,
|
||||||
table_name: self.table_name,
|
table_name: self.table_name,
|
||||||
low_value: self.low_value,
|
low_value: self.low_value,
|
||||||
|
|
@ -136,8 +142,6 @@ impl SendPropDefinition {
|
||||||
bit_count: self.bit_count,
|
bit_count: self.bit_count,
|
||||||
element_count: self.element_count,
|
element_count: self.element_count,
|
||||||
array_property: Some(Box::new(array_property)),
|
array_property: Some(Box::new(array_property)),
|
||||||
owner_table: self.owner_table,
|
|
||||||
index: self.index,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,9 +191,13 @@ impl SendPropDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(SendPropDefinition {
|
Ok(RawSendPropDefinition {
|
||||||
prop_type,
|
prop_type,
|
||||||
|
identifier: Rc::new(SendPropIdentifier {
|
||||||
|
index,
|
||||||
name,
|
name,
|
||||||
|
owner_table,
|
||||||
|
}),
|
||||||
flags,
|
flags,
|
||||||
table_name,
|
table_name,
|
||||||
low_value,
|
low_value,
|
||||||
|
|
@ -197,8 +205,6 @@ impl SendPropDefinition {
|
||||||
bit_count,
|
bit_count,
|
||||||
element_count,
|
element_count,
|
||||||
array_property: None,
|
array_property: None,
|
||||||
owner_table,
|
|
||||||
index,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,6 +310,173 @@ impl BitRead<'_, LittleEndian> for SendPropFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum FloatDefinition {
|
||||||
|
Coord,
|
||||||
|
CoordMP,
|
||||||
|
CoordMPLowPrecision,
|
||||||
|
CoordMPIntegral,
|
||||||
|
FloatNoScale,
|
||||||
|
NormalVarFloat,
|
||||||
|
Scaled { bit_count: u8, high: f32, low: f32 },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FloatDefinition {
|
||||||
|
pub fn new(
|
||||||
|
flags: SendPropFlags,
|
||||||
|
bit_count: Option<u32>,
|
||||||
|
high: Option<f32>,
|
||||||
|
low: Option<f32>,
|
||||||
|
) -> std::result::Result<Self, MalformedSendPropDefinitionError> {
|
||||||
|
if flags.contains(SendPropFlag::Coord) {
|
||||||
|
Ok(FloatDefinition::Coord)
|
||||||
|
} else if flags.contains(SendPropFlag::CoordMP) {
|
||||||
|
Ok(FloatDefinition::CoordMP)
|
||||||
|
} else if flags.contains(SendPropFlag::CoordMPLowPrecision) {
|
||||||
|
Ok(FloatDefinition::CoordMPLowPrecision)
|
||||||
|
} else if flags.contains(SendPropFlag::CoordMPIntegral) {
|
||||||
|
Ok(FloatDefinition::CoordMPIntegral)
|
||||||
|
} else if flags.contains(SendPropFlag::NoScale) {
|
||||||
|
Ok(FloatDefinition::FloatNoScale)
|
||||||
|
} else if flags.contains(SendPropFlag::NormalVarInt) {
|
||||||
|
Ok(FloatDefinition::NormalVarFloat)
|
||||||
|
} else if let (Some(bit_count), Some(high), Some(low)) = (bit_count, high, low) {
|
||||||
|
Ok(FloatDefinition::Scaled {
|
||||||
|
bit_count: bit_count as u8,
|
||||||
|
high,
|
||||||
|
low,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err(MalformedSendPropDefinitionError::UnsizedFloat)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum SendPropDefinition {
|
||||||
|
NormalVarInt {
|
||||||
|
identifier: Rc<SendPropIdentifier>,
|
||||||
|
unsigned: bool,
|
||||||
|
},
|
||||||
|
UnsignedInt {
|
||||||
|
identifier: Rc<SendPropIdentifier>,
|
||||||
|
bit_count: u8,
|
||||||
|
},
|
||||||
|
Int {
|
||||||
|
identifier: Rc<SendPropIdentifier>,
|
||||||
|
bit_count: u8,
|
||||||
|
},
|
||||||
|
Float {
|
||||||
|
identifier: Rc<SendPropIdentifier>,
|
||||||
|
definition: FloatDefinition,
|
||||||
|
},
|
||||||
|
String {
|
||||||
|
identifier: Rc<SendPropIdentifier>,
|
||||||
|
},
|
||||||
|
Vector {
|
||||||
|
identifier: Rc<SendPropIdentifier>,
|
||||||
|
definition: FloatDefinition,
|
||||||
|
},
|
||||||
|
VectorXY {
|
||||||
|
identifier: Rc<SendPropIdentifier>,
|
||||||
|
definition: FloatDefinition,
|
||||||
|
},
|
||||||
|
Array {
|
||||||
|
identifier: Rc<SendPropIdentifier>,
|
||||||
|
inner_definition: Box<SendPropDefinition>,
|
||||||
|
count_bit_count: u16,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SendPropDefinition {
|
||||||
|
pub fn identifier(&self) -> Rc<SendPropIdentifier> {
|
||||||
|
match self {
|
||||||
|
SendPropDefinition::NormalVarInt { identifier, .. } => identifier.clone(),
|
||||||
|
SendPropDefinition::UnsignedInt { identifier, .. } => identifier.clone(),
|
||||||
|
SendPropDefinition::Int { identifier, .. } => identifier.clone(),
|
||||||
|
SendPropDefinition::Float { identifier, .. } => identifier.clone(),
|
||||||
|
SendPropDefinition::String { identifier, .. } => identifier.clone(),
|
||||||
|
SendPropDefinition::Vector { identifier, .. } => identifier.clone(),
|
||||||
|
SendPropDefinition::VectorXY { identifier, .. } => identifier.clone(),
|
||||||
|
SendPropDefinition::Array { identifier, .. } => identifier.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&RawSendPropDefinition> for SendPropDefinition {
|
||||||
|
type Error = MalformedSendPropDefinitionError;
|
||||||
|
|
||||||
|
fn try_from(definition: &RawSendPropDefinition) -> std::result::Result<Self, Self::Error> {
|
||||||
|
let identifier = definition.identifier.clone();
|
||||||
|
match definition.prop_type {
|
||||||
|
SendPropType::Int => {
|
||||||
|
if definition.flags.contains(SendPropFlag::NormalVarInt) {
|
||||||
|
Ok(SendPropDefinition::NormalVarInt {
|
||||||
|
identifier,
|
||||||
|
unsigned: definition.flags.contains(SendPropFlag::Unsigned),
|
||||||
|
})
|
||||||
|
} else if definition.flags.contains(SendPropFlag::Unsigned) {
|
||||||
|
Ok(SendPropDefinition::UnsignedInt {
|
||||||
|
identifier,
|
||||||
|
bit_count: definition.bit_count.unwrap_or(32) as u8,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(SendPropDefinition::Int {
|
||||||
|
identifier,
|
||||||
|
bit_count: definition.bit_count.unwrap_or(32) as u8,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SendPropType::Float => Ok(SendPropDefinition::Float {
|
||||||
|
identifier,
|
||||||
|
definition: FloatDefinition::new(
|
||||||
|
definition.flags,
|
||||||
|
definition.bit_count,
|
||||||
|
definition.high_value,
|
||||||
|
definition.low_value,
|
||||||
|
)?,
|
||||||
|
}),
|
||||||
|
SendPropType::String => Ok(SendPropDefinition::String { identifier }),
|
||||||
|
SendPropType::Vector => Ok(SendPropDefinition::Vector {
|
||||||
|
identifier,
|
||||||
|
definition: FloatDefinition::new(
|
||||||
|
definition.flags,
|
||||||
|
definition.bit_count,
|
||||||
|
definition.high_value,
|
||||||
|
definition.low_value,
|
||||||
|
)?,
|
||||||
|
}),
|
||||||
|
SendPropType::VectorXY => Ok(SendPropDefinition::VectorXY {
|
||||||
|
identifier,
|
||||||
|
definition: FloatDefinition::new(
|
||||||
|
definition.flags,
|
||||||
|
definition.bit_count,
|
||||||
|
definition.high_value,
|
||||||
|
definition.low_value,
|
||||||
|
)?,
|
||||||
|
}),
|
||||||
|
SendPropType::Array => {
|
||||||
|
let count_bit_count = log_base2(
|
||||||
|
definition
|
||||||
|
.element_count
|
||||||
|
.ok_or(MalformedSendPropDefinitionError::UnsizedArray)?,
|
||||||
|
) as u16
|
||||||
|
+ 1;
|
||||||
|
let child_definition = definition
|
||||||
|
.array_property
|
||||||
|
.as_deref()
|
||||||
|
.ok_or(MalformedSendPropDefinitionError::UntypedArray)?;
|
||||||
|
Ok(SendPropDefinition::Array {
|
||||||
|
identifier,
|
||||||
|
inner_definition: Box::new(SendPropDefinition::try_from(child_definition)?),
|
||||||
|
count_bit_count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Err(MalformedSendPropDefinitionError::InvalidPropType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum SendPropValue {
|
pub enum SendPropValue {
|
||||||
|
|
@ -385,108 +558,90 @@ impl fmt::Display for SendPropValue {
|
||||||
|
|
||||||
impl SendPropValue {
|
impl SendPropValue {
|
||||||
pub fn parse(stream: &mut Stream, definition: &SendPropDefinition) -> Result<Self> {
|
pub fn parse(stream: &mut Stream, definition: &SendPropDefinition) -> Result<Self> {
|
||||||
match definition.prop_type {
|
match definition {
|
||||||
SendPropType::Int => Self::read_int(stream, definition).map(SendPropValue::from),
|
SendPropDefinition::NormalVarInt { unsigned, .. } => read_var_int(stream, !*unsigned)
|
||||||
SendPropType::Float => Self::read_float(stream, definition).map(SendPropValue::from),
|
|
||||||
SendPropType::String => Self::read_string(stream, definition).map(SendPropValue::from),
|
|
||||||
SendPropType::Vector => Self::read_vector(stream, definition).map(SendPropValue::from),
|
|
||||||
SendPropType::VectorXY => {
|
|
||||||
Self::read_vector_xy(stream, definition).map(SendPropValue::from)
|
|
||||||
}
|
|
||||||
SendPropType::Array => Self::read_array(stream, definition).map(SendPropValue::from),
|
|
||||||
_ => Err(MalformedSendPropDefinitionError::InvalidPropType.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_int(stream: &mut Stream, definition: &SendPropDefinition) -> Result<i64> {
|
|
||||||
if definition.flags.contains(SendPropFlag::NormalVarInt) {
|
|
||||||
read_var_int(stream, !definition.flags.contains(SendPropFlag::Unsigned))
|
|
||||||
.map_err(ParseError::from)
|
.map_err(ParseError::from)
|
||||||
.map(|int| int as i64)
|
.map(|int| int as i64)
|
||||||
} else if definition.flags.contains(SendPropFlag::Unsigned) {
|
.map(SendPropValue::from),
|
||||||
let unsigned: u32 = stream.read_sized(definition.bit_count.unwrap_or(32) as usize)?;
|
SendPropDefinition::UnsignedInt { bit_count, .. } => {
|
||||||
Ok(unsigned as i64)
|
Ok((stream.read_sized::<u32>(*bit_count as usize)? as i64).into())
|
||||||
} else {
|
}
|
||||||
stream
|
SendPropDefinition::Int { bit_count, .. } => stream
|
||||||
.read_int(definition.bit_count.unwrap_or(32) as usize)
|
.read_int::<i32>((*bit_count) as usize)
|
||||||
.map_err(ParseError::from)
|
.map_err(ParseError::from)
|
||||||
|
.map(SendPropValue::from),
|
||||||
|
SendPropDefinition::Float {
|
||||||
|
definition: float_definition,
|
||||||
|
..
|
||||||
|
} => Self::read_float(stream, float_definition).map(SendPropValue::from),
|
||||||
|
SendPropDefinition::String { .. } => {
|
||||||
|
let length = stream.read_int(9)?;
|
||||||
|
stream
|
||||||
|
.read_sized::<String>(length)
|
||||||
|
.map_err(ParseError::from)
|
||||||
|
.map(SendPropValue::from)
|
||||||
}
|
}
|
||||||
|
SendPropDefinition::Vector {
|
||||||
|
definition: float_definition,
|
||||||
|
..
|
||||||
|
} => Ok(Vector {
|
||||||
|
x: Self::read_float(stream, float_definition)?,
|
||||||
|
y: Self::read_float(stream, float_definition)?,
|
||||||
|
z: Self::read_float(stream, float_definition)?,
|
||||||
}
|
}
|
||||||
|
.into()),
|
||||||
fn read_array(
|
SendPropDefinition::VectorXY {
|
||||||
stream: &mut Stream,
|
definition: float_definition,
|
||||||
definition: &SendPropDefinition,
|
..
|
||||||
) -> Result<Vec<SendPropValue>> {
|
} => Ok(VectorXY {
|
||||||
let num_bits = log_base2(
|
x: Self::read_float(stream, float_definition)?,
|
||||||
definition
|
y: Self::read_float(stream, float_definition)?,
|
||||||
.element_count
|
}
|
||||||
.ok_or(MalformedSendPropDefinitionError::UnsizedArray)?,
|
.into()),
|
||||||
) + 1;
|
SendPropDefinition::Array {
|
||||||
|
count_bit_count,
|
||||||
let count = stream.read_int(num_bits as usize)?;
|
inner_definition,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let count = stream.read_int(*count_bit_count as usize)?;
|
||||||
let mut values = Vec::with_capacity(min(count, 128));
|
let mut values = Vec::with_capacity(min(count, 128));
|
||||||
|
|
||||||
let child_definition = definition
|
|
||||||
.array_property
|
|
||||||
.as_ref()
|
|
||||||
.ok_or(MalformedSendPropDefinitionError::UntypedArray)?;
|
|
||||||
|
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
values.push(Self::parse(stream, child_definition)?);
|
values.push(Self::parse(stream, inner_definition)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(values)
|
Ok(values.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_string(stream: &mut Stream, _definition: &SendPropDefinition) -> Result<String> {
|
fn read_float(stream: &mut Stream, definition: &FloatDefinition) -> Result<f32> {
|
||||||
let length = stream.read_int(9)?;
|
match definition {
|
||||||
stream.read_sized(length).map_err(ParseError::from)
|
FloatDefinition::Coord => read_bit_coord(stream).map_err(ParseError::from),
|
||||||
}
|
FloatDefinition::CoordMP => {
|
||||||
|
|
||||||
fn read_vector(stream: &mut Stream, definition: &SendPropDefinition) -> Result<Vector> {
|
|
||||||
Ok(Vector {
|
|
||||||
x: Self::read_float(stream, definition)?,
|
|
||||||
y: Self::read_float(stream, definition)?,
|
|
||||||
z: Self::read_float(stream, definition)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_vector_xy(stream: &mut Stream, definition: &SendPropDefinition) -> Result<VectorXY> {
|
|
||||||
Ok(VectorXY {
|
|
||||||
x: Self::read_float(stream, definition)?,
|
|
||||||
y: Self::read_float(stream, definition)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_float(stream: &mut Stream, definition: &SendPropDefinition) -> Result<f32> {
|
|
||||||
if definition.flags.contains(SendPropFlag::Coord) {
|
|
||||||
read_bit_coord(stream).map_err(ParseError::from)
|
|
||||||
} else if definition.flags.contains(SendPropFlag::CoordMP) {
|
|
||||||
read_bit_coord_mp(stream, false, false).map_err(ParseError::from)
|
read_bit_coord_mp(stream, false, false).map_err(ParseError::from)
|
||||||
} else if definition.flags.contains(SendPropFlag::CoordMPLowPrecision) {
|
}
|
||||||
|
FloatDefinition::CoordMPLowPrecision => {
|
||||||
read_bit_coord_mp(stream, false, true).map_err(ParseError::from)
|
read_bit_coord_mp(stream, false, true).map_err(ParseError::from)
|
||||||
} else if definition.flags.contains(SendPropFlag::CoordMPIntegral) {
|
}
|
||||||
|
FloatDefinition::CoordMPIntegral => {
|
||||||
read_bit_coord_mp(stream, true, false).map_err(ParseError::from)
|
read_bit_coord_mp(stream, true, false).map_err(ParseError::from)
|
||||||
} else if definition.flags.contains(SendPropFlag::NoScale) {
|
}
|
||||||
stream.read().map_err(ParseError::from)
|
FloatDefinition::FloatNoScale => stream.read().map_err(ParseError::from),
|
||||||
} else if definition.flags.contains(SendPropFlag::NormalVarInt) {
|
FloatDefinition::NormalVarFloat => read_bit_normal(stream).map_err(ParseError::from),
|
||||||
read_bit_normal(stream).map_err(ParseError::from)
|
FloatDefinition::Scaled {
|
||||||
} else {
|
bit_count,
|
||||||
let bit_count = definition
|
low,
|
||||||
.bit_count
|
high,
|
||||||
.ok_or(MalformedSendPropDefinitionError::UnsizedFloat)?;
|
} => {
|
||||||
let high = definition
|
let raw: u32 = stream.read_int(*bit_count as usize)?;
|
||||||
.high_value
|
|
||||||
.ok_or(MalformedSendPropDefinitionError::UnsizedFloat)?;
|
|
||||||
let low = definition
|
|
||||||
.low_value
|
|
||||||
.ok_or(MalformedSendPropDefinitionError::UnsizedFloat)?;
|
|
||||||
let raw: u32 = stream.read_int(bit_count as usize)?;
|
|
||||||
// is this -1 correct?, it is consistent with the js version but seems weird
|
// is this -1 correct?, it is consistent with the js version but seems weird
|
||||||
let percentage = (raw as f32) / ((1i32.wrapping_shl(bit_count)) as f32 - 1.0);
|
let percentage =
|
||||||
|
(raw as f32) / ((1i32.wrapping_shl(*bit_count as u32)) as f32 - 1.0);
|
||||||
Ok(low + ((high - low) * percentage))
|
Ok(low + ((high - low) * percentage))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i32> for SendPropValue {
|
impl From<i32> for SendPropValue {
|
||||||
|
|
@ -601,10 +756,18 @@ impl SendPropDefinitionIndex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Display)]
|
||||||
|
#[display("{owner_table}::{name}")]
|
||||||
|
pub struct SendPropIdentifier {
|
||||||
|
pub index: SendPropDefinitionIndex,
|
||||||
|
pub name: SendPropName,
|
||||||
|
pub owner_table: SendTableName,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Display)]
|
#[derive(Debug, Clone, Display)]
|
||||||
#[display("{definition.owner_table}::{definition.name} = {value}")]
|
#[display("{identifier} = {value}")]
|
||||||
pub struct SendProp {
|
pub struct SendProp {
|
||||||
pub definition: Rc<SendPropDefinition>,
|
pub identifier: Rc<SendPropIdentifier>,
|
||||||
pub value: SendPropValue,
|
pub value: SendPropValue,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ impl EntityDump {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|prop| {
|
.map(|prop| {
|
||||||
(
|
(
|
||||||
format!("{}.{}", prop.definition.owner_table, prop.definition.name),
|
format!("{}.{}", prop.identifier.owner_table, prop.identifier.name),
|
||||||
prop.value,
|
prop.value,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ fn flatten_test(input_file: &str, snapshot_file: &str) {
|
||||||
table
|
table
|
||||||
.flatten_props(&send_tables)
|
.flatten_props(&send_tables)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|prop| format!("{}.{}", prop.owner_table, prop.name))
|
.map(|prop| format!("{}.{}", prop.identifier.owner_table, prop.identifier.name))
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue