Change the way entity data is stored
This commit is contained in:
@@ -12,5 +12,5 @@ fn main() {
|
|||||||
println!("Header: {:?}", output.header);
|
println!("Header: {:?}", output.header);
|
||||||
println!("Players: {:?}", output.player_info);
|
println!("Players: {:?}", output.player_info);
|
||||||
println!("Events: {:?}", output.events.len());
|
println!("Events: {:?}", output.events.len());
|
||||||
println!("Entities: {:?}", output.entity_states.len());
|
println!("Entity-Ticks: {:?}", output.entity_states.ticks.len());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ fn main() {
|
|||||||
println!("Header: {:?}", output.header);
|
println!("Header: {:?}", output.header);
|
||||||
println!("Players: {:?}", output.player_info);
|
println!("Players: {:?}", output.player_info);
|
||||||
println!("Events: {:?}", output.events.len());
|
println!("Events: {:?}", output.events.len());
|
||||||
println!("Entities: {:?}", output.entity_states.len());
|
println!("Entity-Ticks: {:?}", output.entity_states.ticks.len());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ use crate::csgo_proto;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum DemoEvent {
|
pub enum DemoEvent {
|
||||||
GameEvent(crate::game_event::GameEvent),
|
GameEvent(Box<crate::game_event::GameEvent>),
|
||||||
ServerInfo(csgo_proto::CsvcMsgServerInfo),
|
ServerInfo(Box<csgo_proto::CsvcMsgServerInfo>),
|
||||||
Tick(csgo_proto::CnetMsgTick),
|
Tick(Box<csgo_proto::CnetMsgTick>),
|
||||||
RankUpdate(csgo_proto::CcsUsrMsgServerRankUpdate),
|
RankUpdate(Box<csgo_proto::CcsUsrMsgServerRankUpdate>),
|
||||||
RankReveal(csgo_proto::CcsUsrMsgServerRankRevealAll),
|
RankReveal(Box<csgo_proto::CcsUsrMsgServerRankRevealAll>),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,13 +51,46 @@ pub struct Entity {
|
|||||||
pub cls: u32,
|
pub cls: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct EntityTickList {
|
||||||
|
pub ticks: Vec<EntityTickStates>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<entities::EntityState>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FirstPassOutput {
|
pub struct FirstPassOutput {
|
||||||
pub header: crate::csgo_proto::CDemoFileHeader,
|
pub header: crate::csgo_proto::CDemoFileHeader,
|
||||||
pub info: crate::csgo_proto::CDemoFileInfo,
|
pub info: crate::csgo_proto::CDemoFileInfo,
|
||||||
pub events: Vec<DemoEvent>,
|
pub events: Vec<DemoEvent>,
|
||||||
pub player_info: std::collections::HashMap<UserId, Player>,
|
pub player_info: std::collections::HashMap<UserId, Player>,
|
||||||
pub entity_states: Vec<entities::EntityState>,
|
pub entity_states: EntityTickList,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -104,7 +137,9 @@ where
|
|||||||
|
|
||||||
let mut baselines = std::collections::HashMap::new();
|
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();
|
let mut buffer = Vec::new();
|
||||||
for frame in frames.into_iter() {
|
for frame in frames.into_iter() {
|
||||||
@@ -135,6 +170,7 @@ where
|
|||||||
&mut baselines,
|
&mut baselines,
|
||||||
&prop_controller,
|
&prop_controller,
|
||||||
&mut entity_states,
|
&mut entity_states,
|
||||||
|
&mut current_tick,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
DemoCommand::FullPacket => {
|
DemoCommand::FullPacket => {
|
||||||
@@ -152,6 +188,7 @@ where
|
|||||||
&mut baselines,
|
&mut baselines,
|
||||||
&prop_controller,
|
&prop_controller,
|
||||||
&mut entity_states,
|
&mut entity_states,
|
||||||
|
&mut current_tick,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,7 +287,8 @@ fn inner_parse_packet(
|
|||||||
qf_mapper: &mut decoder::QfMapper,
|
qf_mapper: &mut decoder::QfMapper,
|
||||||
baselines: &mut std::collections::HashMap<u32, Vec<u8>>,
|
baselines: &mut std::collections::HashMap<u32, Vec<u8>>,
|
||||||
prop_controller: &propcontroller::PropController,
|
prop_controller: &propcontroller::PropController,
|
||||||
entity_states: &mut Vec<entities::EntityState>,
|
entity_states: &mut EntityTickList,
|
||||||
|
current_tick: &mut u32,
|
||||||
) -> Result<(), FirstPassError> {
|
) -> Result<(), FirstPassError> {
|
||||||
let mut bitreader = crate::bitreader::Bitreader::new(raw.data());
|
let mut bitreader = crate::bitreader::Bitreader::new(raw.data());
|
||||||
|
|
||||||
@@ -288,7 +326,7 @@ fn inner_parse_packet(
|
|||||||
let raw: crate::csgo_proto::CsvcMsgServerInfo =
|
let raw: crate::csgo_proto::CsvcMsgServerInfo =
|
||||||
prost::Message::decode(msg_bytes.as_slice())?;
|
prost::Message::decode(msg_bytes.as_slice())?;
|
||||||
|
|
||||||
events.push(DemoEvent::ServerInfo(raw));
|
events.push(DemoEvent::ServerInfo(Box::new(raw)));
|
||||||
}
|
}
|
||||||
crate::netmessagetypes::NetmessageType::net_SignonState => {
|
crate::netmessagetypes::NetmessageType::net_SignonState => {
|
||||||
let raw: crate::csgo_proto::CnetMsgSignonState =
|
let raw: crate::csgo_proto::CnetMsgSignonState =
|
||||||
@@ -299,7 +337,13 @@ fn inner_parse_packet(
|
|||||||
let raw: crate::csgo_proto::CnetMsgTick =
|
let raw: crate::csgo_proto::CnetMsgTick =
|
||||||
prost::Message::decode(msg_bytes.as_slice())?;
|
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::net_SetConVar => {}
|
||||||
crate::netmessagetypes::NetmessageType::svc_ClassInfo => {}
|
crate::netmessagetypes::NetmessageType::svc_ClassInfo => {}
|
||||||
@@ -345,7 +389,7 @@ fn inner_parse_packet(
|
|||||||
prop_controller,
|
prop_controller,
|
||||||
)?;
|
)?;
|
||||||
if let Some(state) = state {
|
if let Some(state) = state {
|
||||||
entity_states.push(state);
|
entity_states.add_state(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0b00 => {
|
0b00 => {
|
||||||
@@ -362,7 +406,7 @@ fn inner_parse_packet(
|
|||||||
prop_controller,
|
prop_controller,
|
||||||
)?;
|
)?;
|
||||||
if let Some(state) = state {
|
if let Some(state) = state {
|
||||||
entity_states.push(state);
|
entity_states.add_state(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unknown => {
|
unknown => {
|
||||||
@@ -388,7 +432,7 @@ fn inner_parse_packet(
|
|||||||
Some(parser) => {
|
Some(parser) => {
|
||||||
let parsed = parser.parse(keys.as_slice(), raw.clone())?;
|
let parsed = parser.parse(keys.as_slice(), raw.clone())?;
|
||||||
|
|
||||||
events.push(DemoEvent::GameEvent(parsed));
|
events.push(DemoEvent::GameEvent(Box::new(parsed)));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
println!("No parser for {:?}", name);
|
println!("No parser for {:?}", name);
|
||||||
@@ -406,13 +450,13 @@ fn inner_parse_packet(
|
|||||||
let raw: crate::csgo_proto::CcsUsrMsgServerRankUpdate =
|
let raw: crate::csgo_proto::CcsUsrMsgServerRankUpdate =
|
||||||
prost::Message::decode(msg_bytes.as_slice())?;
|
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 => {
|
crate::netmessagetypes::NetmessageType::CS_UM_ServerRankRevealAll => {
|
||||||
let raw: crate::csgo_proto::CcsUsrMsgServerRankRevealAll =
|
let raw: crate::csgo_proto::CcsUsrMsgServerRankRevealAll =
|
||||||
prost::Message::decode(msg_bytes.as_slice())?;
|
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_WeaponSound => {}
|
||||||
crate::netmessagetypes::NetmessageType::CS_UM_RadioText => {}
|
crate::netmessagetypes::NetmessageType::CS_UM_RadioText => {}
|
||||||
@@ -440,8 +484,8 @@ fn inner_parse_packet(
|
|||||||
crate::netmessagetypes::NetmessageType::net_SpawnGroup_Load => {}
|
crate::netmessagetypes::NetmessageType::net_SpawnGroup_Load => {}
|
||||||
crate::netmessagetypes::NetmessageType::CS_UM_MatchEndConditions => {}
|
crate::netmessagetypes::NetmessageType::CS_UM_MatchEndConditions => {}
|
||||||
crate::netmessagetypes::NetmessageType::TE_Explosion => {}
|
crate::netmessagetypes::NetmessageType::TE_Explosion => {}
|
||||||
unknown => {
|
_unknown => {
|
||||||
dbg!(unknown);
|
// dbg!(unknown);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,8 +268,8 @@ impl<'b> crate::bitreader::Bitreader<'b> {
|
|||||||
|
|
||||||
pub fn decode_vector_noscale(&mut self) -> Result<[f32; 3], super::FirstPassError> {
|
pub fn decode_vector_noscale(&mut self) -> Result<[f32; 3], super::FirstPassError> {
|
||||||
let mut v = [0.0; 3];
|
let mut v = [0.0; 3];
|
||||||
for idx in 0..3 {
|
for item in v.iter_mut() {
|
||||||
v[idx] = self.decode_noscale()?;
|
*item = self.decode_noscale()?;
|
||||||
}
|
}
|
||||||
Ok(v)
|
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> {
|
pub fn decode_vector_float_coord(&mut self) -> Result<[f32; 3], super::FirstPassError> {
|
||||||
let mut v = [0.0; 3];
|
let mut v = [0.0; 3];
|
||||||
for idx in 0..3 {
|
for item in v.iter_mut() {
|
||||||
v[idx] = self.decode_float_coord()?;
|
*item = self.decode_float_coord()?;
|
||||||
}
|
}
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,12 +54,11 @@ impl QuantalizedFloat {
|
|||||||
self.high_low_mul = 0.0;
|
self.high_low_mul = 0.0;
|
||||||
let range = self.high - self.low;
|
let range = self.high - self.low;
|
||||||
|
|
||||||
let high: u32;
|
let high: u32 = if self.bit_count == 32 {
|
||||||
if self.bit_count == 32 {
|
0xFFFFFFFE
|
||||||
high = 0xFFFFFFFE;
|
|
||||||
} else {
|
} else {
|
||||||
high = (1 << self.bit_count) - 1;
|
(1 << self.bit_count) - 1
|
||||||
}
|
};
|
||||||
|
|
||||||
let mut high_mul: f32;
|
let mut high_mul: f32;
|
||||||
// Xd?
|
// Xd?
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ impl PropController {
|
|||||||
self.traverse_fields(&mut serializer.fields, serializer.name.clone(), Vec::new())
|
self.traverse_fields(&mut serializer.fields, serializer.name.clone(), Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traverse_fields(&mut self, fields: &mut Vec<Field>, ser_name: String, path_og: Vec<i32>) {
|
fn traverse_fields(&mut self, fields: &mut [Field], ser_name: String, path_og: Vec<i32>) {
|
||||||
for (idx, f) in fields.iter_mut().enumerate() {
|
for (idx, f) in fields.iter_mut().enumerate() {
|
||||||
let mut path = path_og.clone();
|
let mut path = path_og.clone();
|
||||||
path.push(idx as i32);
|
path.push(idx as i32);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ fn mirage_1() {
|
|||||||
assert_eq!("de_mirage", output.header.map_name());
|
assert_eq!("de_mirage", output.header.map_name());
|
||||||
|
|
||||||
for event in output.events.iter() {
|
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!(
|
assert!(
|
||||||
death.remaining.is_empty(),
|
death.remaining.is_empty(),
|
||||||
"Remaining for PlayerDeath: {:?}",
|
"Remaining for PlayerDeath: {:?}",
|
||||||
|
|||||||
Reference in New Issue
Block a user