From ff8d05b79ae347ceacfb20edf75f0f300bfb197e Mon Sep 17 00:00:00 2001 From: Lol3rrr Date: Sun, 22 Sep 2024 23:19:18 +0200 Subject: [PATCH] Change the way entity data is stored --- examples/ancient-entity.rs | 2 +- examples/ancient-noentity.rs | 2 +- src/packet.rs | 10 ++-- src/parser.rs | 68 +++++++++++++++++++++++----- src/parser/decoder.rs | 8 ++-- src/parser/decoder/quantizedfloat.rs | 9 ++-- src/parser/propcontroller.rs | 2 +- tests/parse.rs | 2 +- 8 files changed, 73 insertions(+), 30 deletions(-) diff --git a/examples/ancient-entity.rs b/examples/ancient-entity.rs index 3643033..9d11524 100644 --- a/examples/ancient-entity.rs +++ b/examples/ancient-entity.rs @@ -12,5 +12,5 @@ fn main() { println!("Header: {:?}", output.header); println!("Players: {:?}", output.player_info); println!("Events: {:?}", output.events.len()); - println!("Entities: {:?}", output.entity_states.len()); + println!("Entity-Ticks: {:?}", output.entity_states.ticks.len()); } diff --git a/examples/ancient-noentity.rs b/examples/ancient-noentity.rs index e9d404b..e4a8ad5 100644 --- a/examples/ancient-noentity.rs +++ b/examples/ancient-noentity.rs @@ -12,5 +12,5 @@ fn main() { println!("Header: {:?}", output.header); println!("Players: {:?}", output.player_info); println!("Events: {:?}", output.events.len()); - println!("Entities: {:?}", output.entity_states.len()); + println!("Entity-Ticks: {:?}", output.entity_states.ticks.len()); } diff --git a/src/packet.rs b/src/packet.rs index d732508..894dfd7 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -2,9 +2,9 @@ use crate::csgo_proto; #[derive(Debug)] pub enum DemoEvent { - GameEvent(crate::game_event::GameEvent), - ServerInfo(csgo_proto::CsvcMsgServerInfo), - Tick(csgo_proto::CnetMsgTick), - RankUpdate(csgo_proto::CcsUsrMsgServerRankUpdate), - RankReveal(csgo_proto::CcsUsrMsgServerRankRevealAll), + GameEvent(Box), + ServerInfo(Box), + Tick(Box), + RankUpdate(Box), + RankReveal(Box), } diff --git a/src/parser.rs b/src/parser.rs index 782c9f6..3aa5149 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -51,13 +51,46 @@ pub struct Entity { pub cls: u32, } +#[derive(Debug)] +pub struct EntityTickList { + pub ticks: Vec, +} + +impl EntityTickList { + pub fn new() -> Self { + Self { + ticks: vec![EntityTickStates { + tick: 0, + states: Vec::new() + }], + } + } + + fn new_tick(&mut self, n_tick: u32) { + self.ticks.push(EntityTickStates { + tick: n_tick, + states: Vec::new(), + }); + } + + fn add_state(&mut self, state: entities::EntityState) { + self.ticks.last_mut().expect("We start with at least 1 tick entry and never remove any, so we can always get the last element").states.push(state); + } +} + +#[derive(Debug)] +pub struct EntityTickStates { + pub tick: u32, + pub states: Vec, +} + #[derive(Debug)] pub struct FirstPassOutput { pub header: crate::csgo_proto::CDemoFileHeader, pub info: crate::csgo_proto::CDemoFileInfo, pub events: Vec, pub player_info: std::collections::HashMap, - pub entity_states: Vec, + pub entity_states: EntityTickList, } #[derive(Debug)] @@ -104,7 +137,9 @@ where let mut baselines = std::collections::HashMap::new(); - let mut entity_states = Vec::new(); + let mut entity_states = EntityTickList::new(); + + let mut current_tick = 0; let mut buffer = Vec::new(); for frame in frames.into_iter() { @@ -135,6 +170,7 @@ where &mut baselines, &prop_controller, &mut entity_states, + &mut current_tick, )?; } DemoCommand::FullPacket => { @@ -152,6 +188,7 @@ where &mut baselines, &prop_controller, &mut entity_states, + &mut current_tick, )?; } } @@ -250,7 +287,8 @@ fn inner_parse_packet( qf_mapper: &mut decoder::QfMapper, baselines: &mut std::collections::HashMap>, prop_controller: &propcontroller::PropController, - entity_states: &mut Vec, + entity_states: &mut EntityTickList, + current_tick: &mut u32, ) -> Result<(), FirstPassError> { let mut bitreader = crate::bitreader::Bitreader::new(raw.data()); @@ -288,7 +326,7 @@ fn inner_parse_packet( let raw: crate::csgo_proto::CsvcMsgServerInfo = prost::Message::decode(msg_bytes.as_slice())?; - events.push(DemoEvent::ServerInfo(raw)); + events.push(DemoEvent::ServerInfo(Box::new(raw))); } crate::netmessagetypes::NetmessageType::net_SignonState => { let raw: crate::csgo_proto::CnetMsgSignonState = @@ -299,7 +337,13 @@ fn inner_parse_packet( let raw: crate::csgo_proto::CnetMsgTick = prost::Message::decode(msg_bytes.as_slice())?; - events.push(DemoEvent::Tick(raw)); + assert!(*current_tick <= raw.tick(), "Current Tick {} <= Tick Packet {}", *current_tick, raw.tick()); + if raw.tick() > *current_tick { + *current_tick = raw.tick(); + entity_states.new_tick(*current_tick); + } + + events.push(DemoEvent::Tick(Box::new(raw))); } crate::netmessagetypes::NetmessageType::net_SetConVar => {} crate::netmessagetypes::NetmessageType::svc_ClassInfo => {} @@ -345,7 +389,7 @@ fn inner_parse_packet( prop_controller, )?; if let Some(state) = state { - entity_states.push(state); + entity_states.add_state(state); } } 0b00 => { @@ -362,7 +406,7 @@ fn inner_parse_packet( prop_controller, )?; if let Some(state) = state { - entity_states.push(state); + entity_states.add_state(state); } } unknown => { @@ -388,7 +432,7 @@ fn inner_parse_packet( Some(parser) => { let parsed = parser.parse(keys.as_slice(), raw.clone())?; - events.push(DemoEvent::GameEvent(parsed)); + events.push(DemoEvent::GameEvent(Box::new(parsed))); } None => { println!("No parser for {:?}", name); @@ -406,13 +450,13 @@ fn inner_parse_packet( let raw: crate::csgo_proto::CcsUsrMsgServerRankUpdate = prost::Message::decode(msg_bytes.as_slice())?; - events.push(DemoEvent::RankUpdate(raw)); + events.push(DemoEvent::RankUpdate(Box::new(raw))); } crate::netmessagetypes::NetmessageType::CS_UM_ServerRankRevealAll => { let raw: crate::csgo_proto::CcsUsrMsgServerRankRevealAll = prost::Message::decode(msg_bytes.as_slice())?; - events.push(DemoEvent::RankReveal(raw)); + events.push(DemoEvent::RankReveal(Box::new(raw))); } crate::netmessagetypes::NetmessageType::CS_UM_WeaponSound => {} crate::netmessagetypes::NetmessageType::CS_UM_RadioText => {} @@ -440,8 +484,8 @@ fn inner_parse_packet( crate::netmessagetypes::NetmessageType::net_SpawnGroup_Load => {} crate::netmessagetypes::NetmessageType::CS_UM_MatchEndConditions => {} crate::netmessagetypes::NetmessageType::TE_Explosion => {} - unknown => { - dbg!(unknown); + _unknown => { + // dbg!(unknown); } }; } diff --git a/src/parser/decoder.rs b/src/parser/decoder.rs index 8dd8167..73c4382 100644 --- a/src/parser/decoder.rs +++ b/src/parser/decoder.rs @@ -268,8 +268,8 @@ impl<'b> crate::bitreader::Bitreader<'b> { pub fn decode_vector_noscale(&mut self) -> Result<[f32; 3], super::FirstPassError> { let mut v = [0.0; 3]; - for idx in 0..3 { - v[idx] = self.decode_noscale()?; + for item in v.iter_mut() { + *item = self.decode_noscale()?; } Ok(v) } @@ -343,8 +343,8 @@ impl<'b> crate::bitreader::Bitreader<'b> { pub fn decode_vector_float_coord(&mut self) -> Result<[f32; 3], super::FirstPassError> { let mut v = [0.0; 3]; - for idx in 0..3 { - v[idx] = self.decode_float_coord()?; + for item in v.iter_mut() { + *item = self.decode_float_coord()?; } Ok(v) } diff --git a/src/parser/decoder/quantizedfloat.rs b/src/parser/decoder/quantizedfloat.rs index b8b8584..a5a9121 100644 --- a/src/parser/decoder/quantizedfloat.rs +++ b/src/parser/decoder/quantizedfloat.rs @@ -54,12 +54,11 @@ impl QuantalizedFloat { self.high_low_mul = 0.0; let range = self.high - self.low; - let high: u32; - if self.bit_count == 32 { - high = 0xFFFFFFFE; + let high: u32 = if self.bit_count == 32 { + 0xFFFFFFFE } else { - high = (1 << self.bit_count) - 1; - } + (1 << self.bit_count) - 1 + }; let mut high_mul: f32; // Xd? diff --git a/src/parser/propcontroller.rs b/src/parser/propcontroller.rs index 11c61d5..153f67a 100644 --- a/src/parser/propcontroller.rs +++ b/src/parser/propcontroller.rs @@ -114,7 +114,7 @@ impl PropController { self.traverse_fields(&mut serializer.fields, serializer.name.clone(), Vec::new()) } - fn traverse_fields(&mut self, fields: &mut Vec, ser_name: String, path_og: Vec) { + fn traverse_fields(&mut self, fields: &mut [Field], ser_name: String, path_og: Vec) { for (idx, f) in fields.iter_mut().enumerate() { let mut path = path_og.clone(); path.push(idx as i32); diff --git a/tests/parse.rs b/tests/parse.rs index b513459..05a5d78 100644 --- a/tests/parse.rs +++ b/tests/parse.rs @@ -18,7 +18,7 @@ fn mirage_1() { assert_eq!("de_mirage", output.header.map_name()); for event in output.events.iter() { - if let DemoEvent::GameEvent(gevent) = event { if let GameEvent::PlayerDeath(death) = gevent { + if let DemoEvent::GameEvent(gevent) = event { if let GameEvent::PlayerDeath(death) = gevent.as_ref() { assert!( death.remaining.is_empty(), "Remaining for PlayerDeath: {:?}",