mirror of
https://codeberg.org/demostf/parser.git
synced 2026-06-03 10:14:06 +02:00
save sendtables by classid
since we only really need to get them by classid
This commit is contained in:
parent
91e5b82f2f
commit
bf65dffb13
8 changed files with 83 additions and 78 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,3 +4,4 @@
|
||||||
*.svg
|
*.svg
|
||||||
*.data*
|
*.data*
|
||||||
*.iml
|
*.iml
|
||||||
|
*.bench
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ impl MessageHandler for SendPropAnalyser {
|
||||||
state
|
state
|
||||||
.send_tables
|
.send_tables
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_k, v)| ParseSendTable {
|
.map(|(_, v)| ParseSendTable {
|
||||||
name: v.name,
|
name: v.name,
|
||||||
props: v.props,
|
props: v.props,
|
||||||
needs_decoder: v.needs_decoder,
|
needs_decoder: v.needs_decoder,
|
||||||
|
|
|
||||||
|
|
@ -105,40 +105,32 @@ pub struct PacketEntitiesMessage {
|
||||||
pub updated_base_line: bool,
|
pub updated_base_line: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_send_table<'a>(state: &'a ParserState, table: &SendTableName) -> Result<&'a SendTable> {
|
fn get_send_table(state: &ParserState, class: ClassId) -> Result<&SendTable> {
|
||||||
state
|
state
|
||||||
.send_tables
|
.send_tables
|
||||||
.get(table)
|
.get(&class)
|
||||||
.ok_or_else(|| MalformedDemoError::UnknownSendTable(table.clone()).into())
|
.ok_or_else(|| MalformedDemoError::UnknownServerClass(class).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_entity_for_update(
|
fn get_entity_for_update(
|
||||||
state: &ParserState,
|
state: &ParserState,
|
||||||
entity_index: EntityId,
|
entity_index: EntityId,
|
||||||
pvs: PVS,
|
pvs: PVS,
|
||||||
) -> Result<(PacketEntity, &ServerClass)> {
|
) -> Result<PacketEntity> {
|
||||||
let class_id = *state
|
let class_id = *state
|
||||||
.entity_classes
|
.entity_classes
|
||||||
.get(&entity_index)
|
.get(&entity_index)
|
||||||
.ok_or_else(|| MalformedDemoError::UnknownEntity(entity_index))?;
|
.ok_or_else(|| MalformedDemoError::UnknownEntity(entity_index))?;
|
||||||
|
|
||||||
let server_class = state
|
Ok(PacketEntity {
|
||||||
.server_classes
|
server_class: class_id,
|
||||||
.get(usize::from(class_id))
|
entity_index,
|
||||||
.ok_or_else(|| MalformedDemoError::UnknownServerClass(class_id.into()))?;
|
props: Vec::new(),
|
||||||
|
in_pvs: false,
|
||||||
Ok((
|
pvs,
|
||||||
PacketEntity {
|
serial_number: 0,
|
||||||
server_class: class_id,
|
delay: None,
|
||||||
entity_index,
|
})
|
||||||
props: Vec::new(),
|
|
||||||
in_pvs: false,
|
|
||||||
pvs,
|
|
||||||
serial_number: 0,
|
|
||||||
delay: None,
|
|
||||||
},
|
|
||||||
server_class,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for PacketEntitiesMessage {
|
impl Parse for PacketEntitiesMessage {
|
||||||
|
|
@ -163,23 +155,23 @@ impl Parse for PacketEntitiesMessage {
|
||||||
|
|
||||||
let pvs = data.read()?;
|
let pvs = data.read()?;
|
||||||
if pvs == PVS::Enter {
|
if pvs == PVS::Enter {
|
||||||
let (mut entity, server_class) =
|
let mut entity =
|
||||||
Self::read_enter(&mut data, entity_index, state, base_line as usize)?;
|
Self::read_enter(&mut data, entity_index, state, base_line as usize)?;
|
||||||
let send_table = get_send_table(state, &server_class.data_table)?;
|
let send_table = get_send_table(state, entity.server_class)?;
|
||||||
let updated_props = Self::read_update(&mut data, send_table)?;
|
let updated_props = Self::read_update(&mut data, send_table)?;
|
||||||
entity.apply_update(updated_props);
|
entity.apply_update(updated_props);
|
||||||
|
|
||||||
entities.push(entity);
|
entities.push(entity);
|
||||||
} else if pvs == PVS::Preserve {
|
} else if pvs == PVS::Preserve {
|
||||||
let (mut entity, server_class) = get_entity_for_update(state, entity_index, pvs)?;
|
let mut entity = get_entity_for_update(state, entity_index, pvs)?;
|
||||||
let send_table = get_send_table(state, &server_class.data_table)?;
|
let send_table = get_send_table(state, entity.server_class)?;
|
||||||
|
|
||||||
let updated_props = Self::read_update(&mut data, send_table)?;
|
let updated_props = Self::read_update(&mut data, send_table)?;
|
||||||
entity.props = updated_props;
|
entity.props = updated_props;
|
||||||
|
|
||||||
entities.push(entity);
|
entities.push(entity);
|
||||||
} else if state.entity_classes.contains_key(&entity_index) {
|
} else if state.entity_classes.contains_key(&entity_index) {
|
||||||
let (entity, server_class) = get_entity_for_update(state, entity_index, pvs)?;
|
let entity = get_entity_for_update(state, entity_index, pvs)?;
|
||||||
entities.push(entity);
|
entities.push(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -202,47 +194,38 @@ impl Parse for PacketEntitiesMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PacketEntitiesMessage {
|
impl PacketEntitiesMessage {
|
||||||
fn read_enter<'a>(
|
fn read_enter(
|
||||||
stream: &mut Stream,
|
stream: &mut Stream,
|
||||||
entity_index: EntityId,
|
entity_index: EntityId,
|
||||||
state: &'a ParserState,
|
state: &ParserState,
|
||||||
baseline_index: usize,
|
baseline_index: usize,
|
||||||
) -> Result<(PacketEntity, &'a ServerClass)> {
|
) -> Result<PacketEntity> {
|
||||||
let bits = log_base2(state.server_classes.len()) + 1;
|
let bits = log_base2(state.server_classes.len()) + 1;
|
||||||
let class_index = stream.read_sized::<u16>(bits as usize)? as usize;
|
let class_index: ClassId = stream.read_sized::<u16>(bits as usize)?.into();
|
||||||
let server_class = state
|
|
||||||
.server_classes
|
|
||||||
.get(class_index)
|
|
||||||
.ok_or_else(|| ParseError::from(MalformedDemoError::UnknownServerClass(class_index)))?;
|
|
||||||
|
|
||||||
let serial = stream.read_sized(10)?;
|
let serial = stream.read_sized(10)?;
|
||||||
let send_table = state
|
let send_table = state
|
||||||
.send_tables
|
.send_tables
|
||||||
.get(&server_class.data_table)
|
.get(&class_index)
|
||||||
.ok_or_else(|| MalformedDemoError::UnknownSendTable(server_class.data_table.clone()))?;
|
.ok_or_else(|| MalformedDemoError::UnknownServerClass(class_index))?;
|
||||||
|
|
||||||
let props = match state.instance_baselines[baseline_index].get(&entity_index) {
|
let props = match state.instance_baselines[baseline_index].get(&entity_index) {
|
||||||
Some(baseline) => baseline.clone(),
|
Some(baseline) => baseline.clone(),
|
||||||
None => match state.static_baselines.get(&server_class.id) {
|
None => match state.static_baselines.get(&class_index) {
|
||||||
Some(static_baseline) => {
|
Some(static_baseline) => state.get_static_baseline(class_index, send_table)?,
|
||||||
state.get_static_baseline((class_index as u16).into(), send_table)?
|
|
||||||
}
|
|
||||||
None => Vec::new(),
|
None => Vec::new(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((
|
Ok(PacketEntity {
|
||||||
PacketEntity {
|
server_class: class_index,
|
||||||
server_class: server_class.id,
|
entity_index,
|
||||||
entity_index,
|
props,
|
||||||
props,
|
in_pvs: true,
|
||||||
in_pvs: true,
|
pvs: PVS::Enter,
|
||||||
pvs: PVS::Enter,
|
serial_number: serial,
|
||||||
serial_number: serial,
|
delay: None,
|
||||||
delay: None,
|
})
|
||||||
},
|
|
||||||
server_class,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_update(stream: &mut Stream, send_table: &SendTable) -> Result<Vec<SendProp>> {
|
pub fn read_update(stream: &mut Stream, send_table: &SendTable) -> Result<Vec<SendProp>> {
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,9 @@ pub struct ServerClass {
|
||||||
pub data_table: SendTableName,
|
pub data_table: SendTableName,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Clone, Display)]
|
#[derive(
|
||||||
|
BitRead, PartialEq, Eq, Hash, Debug, Serialize, Deserialize, Clone, Display, PartialOrd, Ord,
|
||||||
|
)]
|
||||||
pub struct SendTableName(Rc<String>);
|
pub struct SendTableName(Rc<String>);
|
||||||
|
|
||||||
impl From<String> for SendTableName {
|
impl From<String> for SendTableName {
|
||||||
|
|
@ -190,7 +192,7 @@ impl<'a> Exclude<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SendTable {
|
pub struct SendTable {
|
||||||
pub name: SendTableName,
|
pub name: SendTableName,
|
||||||
pub props: Vec<Rc<SendPropDefinition>>,
|
pub props: Vec<Rc<SendPropDefinition>>,
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@ pub trait MessageHandler {
|
||||||
|
|
||||||
fn does_handle(message_type: MessageType) -> bool;
|
fn does_handle(message_type: MessageType) -> bool;
|
||||||
|
|
||||||
fn handle_message(&mut self, message: Message, tick: u32);
|
fn handle_message(&mut self, message: Message, tick: u32) {}
|
||||||
|
|
||||||
fn handle_string_entry(&mut self, table: &String, index: usize, entries: &StringTableEntry);
|
fn handle_string_entry(&mut self, table: &String, index: usize, entries: &StringTableEntry) {}
|
||||||
|
|
||||||
|
fn handle_data_tables(&mut self, tables: &[SendTable]) {}
|
||||||
|
|
||||||
fn get_output(self, state: ParserState) -> Self::Output;
|
fn get_output(self, state: ParserState) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
@ -98,6 +100,7 @@ impl<T: MessageHandler> DemoHandler<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_data_table(&mut self, send_tables: Vec<SendTable>, server_classes: Vec<ServerClass>) {
|
fn handle_data_table(&mut self, send_tables: Vec<SendTable>, server_classes: Vec<ServerClass>) {
|
||||||
|
self.analyser.handle_data_tables(&send_tables);
|
||||||
self.state_handler
|
self.state_handler
|
||||||
.handle_data_table(send_tables, server_classes);
|
.handle_data_table(send_tables, server_classes);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ pub use self::messagetypeanalyser::MessageTypeAnalyser;
|
||||||
use crate::demo::gamevent::{GameEventValue, GameEventValueType};
|
use crate::demo::gamevent::{GameEventValue, GameEventValueType};
|
||||||
use crate::demo::header::Header;
|
use crate::demo::header::Header;
|
||||||
use crate::demo::message::packetentities::EntityId;
|
use crate::demo::message::packetentities::EntityId;
|
||||||
use crate::demo::packet::datatable::SendTableName;
|
use crate::demo::packet::datatable::{ClassId, SendTableName};
|
||||||
use crate::demo::packet::Packet;
|
use crate::demo::packet::Packet;
|
||||||
use crate::demo::parser::analyser::Analyser;
|
use crate::demo::parser::analyser::Analyser;
|
||||||
pub use crate::demo::parser::analyser::MatchState;
|
pub use crate::demo::parser::analyser::MatchState;
|
||||||
|
|
@ -81,7 +81,7 @@ pub enum MalformedDemoError {
|
||||||
found_type: GameEventValueType,
|
found_type: GameEventValueType,
|
||||||
},
|
},
|
||||||
#[error(display = "An entity with an unknown server class({}) was read", _0)]
|
#[error(display = "An entity with an unknown server class({}) was read", _0)]
|
||||||
UnknownServerClass(usize),
|
UnknownServerClass(ClassId),
|
||||||
#[error(display = "Unknown send table: {}", _0)]
|
#[error(display = "Unknown send table: {}", _0)]
|
||||||
UnknownSendTable(SendTableName),
|
UnknownSendTable(SendTableName),
|
||||||
#[error(
|
#[error(
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ pub struct ParserState {
|
||||||
pub event_definitions: Vec<GameEventDefinition>,
|
pub event_definitions: Vec<GameEventDefinition>,
|
||||||
pub string_tables: Vec<StringTableMeta>,
|
pub string_tables: Vec<StringTableMeta>,
|
||||||
pub entity_classes: HashMap<EntityId, ClassId>,
|
pub entity_classes: HashMap<EntityId, ClassId>,
|
||||||
pub send_tables: HashMap<SendTableName, SendTable>,
|
pub send_tables: HashMap<ClassId, SendTable>,
|
||||||
pub server_classes: Vec<ServerClass>,
|
pub server_classes: Vec<ServerClass>,
|
||||||
pub instance_baselines: [HashMap<EntityId, Vec<SendProp>>; 2],
|
pub instance_baselines: [HashMap<EntityId, Vec<SendProp>>; 2],
|
||||||
pub demo_meta: DemoMeta,
|
pub demo_meta: DemoMeta,
|
||||||
|
|
@ -90,10 +90,20 @@ impl ParserState {
|
||||||
send_tables: Vec<SendTable>,
|
send_tables: Vec<SendTable>,
|
||||||
server_classes: Vec<ServerClass>,
|
server_classes: Vec<ServerClass>,
|
||||||
) {
|
) {
|
||||||
for table in send_tables {
|
let mut send_tables: HashMap<SendTableName, SendTable> = send_tables
|
||||||
self.send_tables.insert(table.name.clone(), table);
|
.into_iter()
|
||||||
|
.map(|table| (table.name.clone(), table))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
self.server_classes = server_classes;
|
||||||
|
|
||||||
|
self.send_tables.reserve(self.server_classes.len());
|
||||||
|
|
||||||
|
for class in self.server_classes.iter() {
|
||||||
|
if let Some(table) = send_tables.remove(&class.data_table) {
|
||||||
|
self.send_tables.insert(class.id, table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.server_classes = server_classes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_string_table_meta(&mut self, table: StringTableMeta) {
|
pub fn handle_string_table_meta(&mut self, table: StringTableMeta) {
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,21 @@ use std::fs;
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use tf_demo_parser::demo::message::Message;
|
use tf_demo_parser::demo::message::Message;
|
||||||
use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTableName};
|
use tf_demo_parser::demo::packet::datatable::{ParseSendTable, SendTable, 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::SendPropDefinition;
|
||||||
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 {
|
||||||
|
tables: Vec<ParseSendTable>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SendPropAnalyser {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
SendPropAnalyser { tables: Vec::new() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MessageHandler for SendPropAnalyser {
|
impl MessageHandler for SendPropAnalyser {
|
||||||
type Output = Vec<ParseSendTable>;
|
type Output = Vec<ParseSendTable>;
|
||||||
|
|
@ -22,28 +30,27 @@ impl MessageHandler for SendPropAnalyser {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_message(&mut self, message: Message, tick: u32) {}
|
fn handle_data_tables(&mut self, tables: &[SendTable]) {
|
||||||
|
self.tables = tables
|
||||||
fn handle_string_entry(&mut self, table: &String, _index: usize, entry: &StringTableEntry) {}
|
.iter()
|
||||||
|
.map(|v| ParseSendTable {
|
||||||
fn get_output(self, state: ParserState) -> Self::Output {
|
name: v.name.clone(),
|
||||||
state
|
props: v.props.clone(),
|
||||||
.send_tables
|
|
||||||
.into_iter()
|
|
||||||
.map(|(_k, v)| ParseSendTable {
|
|
||||||
name: v.name,
|
|
||||||
props: v.props,
|
|
||||||
needs_decoder: v.needs_decoder,
|
needs_decoder: v.needs_decoder,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_output(self, state: ParserState) -> Self::Output {
|
||||||
|
self.tables
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flatten_test(input_file: &str, snapshot_file: &str) {
|
fn flatten_test(input_file: &str, snapshot_file: &str) {
|
||||||
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 (_, send_tables) =
|
let (_, send_tables) =
|
||||||
DemoParser::parse_with_analyser(demo.get_stream(), SendPropAnalyser).unwrap();
|
DemoParser::parse_with_analyser(demo.get_stream(), SendPropAnalyser::new()).unwrap();
|
||||||
let flat_props: HashMap<SendTableName, Vec<String>> = send_tables
|
let flat_props: HashMap<SendTableName, Vec<String>> = send_tables
|
||||||
.iter()
|
.iter()
|
||||||
.map(|table| {
|
.map(|table| {
|
||||||
|
|
@ -70,7 +77,6 @@ fn flatten_test(input_file: &str, snapshot_file: &str) {
|
||||||
|
|
||||||
assert_eq!(expected_tables, actual_tables);
|
assert_eq!(expected_tables, actual_tables);
|
||||||
for table in expected_tables {
|
for table in expected_tables {
|
||||||
dbg!(table);
|
|
||||||
assert_eq!(expected[table], flat_props[table]);
|
assert_eq!(expected[table], flat_props[table]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue