diff --git a/Cargo.toml b/Cargo.toml index d6483f9..4e8fddb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ console_error_panic_hook = { version = "0.1.6", optional = true } # # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. wee_alloc = { version = "0.4.5", optional = true } +pretty_assertions = "1.2.1" [dev-dependencies] wasm-bindgen-test = "0.3.13" @@ -39,4 +40,4 @@ wasm-bindgen-test = "0.3.13" [profile.release] [profile.dev.package."*"] -opt-level = 3 \ No newline at end of file +opt-level = 3 diff --git a/src/entity.rs b/src/entity.rs index 114b536..605b462 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::iter::once; use std::mem::replace; use tf_demo_parser::demo::message::packetentities::{ - EntityId, PacketEntitiesMessage, PacketEntity, PVS, + EntityId, PacketEntitiesMessage, PacketEntity, UpdateType, }; use tf_demo_parser::ParserState; @@ -15,7 +15,7 @@ pub struct ActiveEntities { impl ActiveEntities { pub fn handle_message(&mut self, msg: &PacketEntitiesMessage, state: &ParserState) { for entity in &msg.entities { - if entity.pvs == PVS::Delete || entity.pvs == PVS::Leave { + if entity.update_type == UpdateType::Delete || entity.update_type == UpdateType::Leave { self.remove_entity(entity.entity_index); } else { self.handle_entity(entity, state); @@ -30,7 +30,7 @@ impl ActiveEntities { self.baselines.swap(0, 1); for entity in &msg.entities { - if entity.pvs == PVS::Enter { + if entity.update_type == UpdateType::Enter { self.baselines[new_index].insert(entity.entity_index, entity.clone()); } } @@ -48,8 +48,9 @@ impl ActiveEntities { .entry(entity.entity_index) .and_modify(|existing| { if existing.serial_number != entity.serial_number { + // todo: do baselines need to be cleanup up or updated here? *existing = entity.clone(); - existing.pvs = PVS::Enter; + existing.update_type = UpdateType::Enter; } else { assert_eq!( state.server_classes[usize::from(existing.server_class)], diff --git a/test_data/gully.dem b/test_data/gully.dem new file mode 100644 index 0000000..1c2d1d1 Binary files /dev/null and b/test_data/gully.dem differ diff --git a/tests/reparse.rs b/tests/reparse.rs new file mode 100644 index 0000000..2572960 --- /dev/null +++ b/tests/reparse.rs @@ -0,0 +1,114 @@ +use democutter::cut; +use pretty_assertions::assert_eq; +use std::fs; +use tf_demo_parser::demo::message::packetentities::EntityId; +use tf_demo_parser::demo::message::Message; +use tf_demo_parser::demo::packet::message::MessagePacketMeta; +use tf_demo_parser::demo::parser::gamestateanalyser::GameStateAnalyser; +use tf_demo_parser::demo::parser::handler::BorrowMessageHandler; +use tf_demo_parser::demo::parser::MessageHandler; +use tf_demo_parser::demo::sendprop::SendProp; +use tf_demo_parser::{Demo, DemoParser, MessageType, ParserState}; + +fn test_reparse_with_analyser( + f: F, +) { + let file = fs::read("test_data/gully.dem").unwrap(); + let output = cut(&file, 30000, 50000); + + let original = Demo::new(&file); + let cut = Demo::new(&output); + + let original_parser = DemoParser::new_with_analyser(original.get_stream(), A::default()); + let cut_parser = DemoParser::new_with_analyser(cut.get_stream(), A::default()); + + let mut original_ticks = original_parser.ticker().unwrap().1; + let mut cut_ticks = cut_parser.ticker().unwrap().1; + + while let Some(tick) = original_ticks.next().unwrap() { + if tick.tick > 30010 && tick.tick < 50000 { + break; + } + } + + while let Some(tick) = cut_ticks.next().unwrap() { + if tick.tick > 10 && tick.tick < 20000 { + break; + } + } + + original_ticks + .next() + .unwrap() + .expect("no more ticks in original"); + cut_ticks.next().unwrap().expect("no more ticks in cut"); + + while let (Some(original_tick), Some(cut_tick)) = + (original_ticks.next().unwrap(), cut_ticks.next().unwrap()) + { + assert_eq!(original_tick.tick, cut_tick.tick + 30000); + let original_state = &original_tick.state; + let cut_state = &cut_tick.state; + + f(original_state, cut_state); + } +} + +#[derive(Default)] +struct EntityDumper { + entities: Vec<(EntityId, Vec)>, +} + +impl MessageHandler for EntityDumper { + type Output = Vec<(EntityId, Vec)>; + + fn does_handle(message_type: MessageType) -> bool { + match message_type { + MessageType::PacketEntities => true, + _ => false, + } + } + + fn handle_message(&mut self, message: &Message, _tick: u32) { + match message { + Message::PacketEntities(entity_message) => { + for entity in &entity_message.entities { + self.entities + .push((entity.entity_index, entity.props().cloned().collect())); + } + } + _ => {} + } + } + + fn handle_packet_meta(&mut self, _tick: u32, _meta: &MessagePacketMeta) { + self.entities.clear(); + } + + fn into_output(self, _state: &ParserState) -> Self::Output { + self.entities + } +} + +impl BorrowMessageHandler for EntityDumper { + fn borrow_output(&self, _state: &ParserState) -> &Self::Output { + &self.entities + } +} + +#[test] +fn test_reparse_game_state() { + test_reparse_with_analyser::(|original_state, cut_state| { + assert_eq!(original_state.world, cut_state.world); + assert_eq!(original_state.players, cut_state.players); + assert_eq!(original_state.buildings, cut_state.buildings); + }) +} + +// #[test] +// fn test_reparse_entities() { +// test_reparse_with_analyser::(|original_state, cut_state| { +// assert_eq!(original_state.len(), cut_state.len()); +// panic!(); +// }) +// }