diff --git a/Cargo.toml b/Cargo.toml index ce66a71..d6483f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "democutter" version = "0.1.0" authors = ["Robin Appelman "] -edition = "2018" +edition = "2021" [lib] crate-type = ["cdylib", "rlib"] @@ -16,7 +16,7 @@ default = ["console_error_panic_hook"] [dependencies] bitbuffer = "0.10" -tf-demo-parser = { version = "0.3", path = "../tf-demo-parser" } +tf-demo-parser = { version = "0.4", path = "../tf-demo-parser" } wasm-bindgen = "0.2.63" web-sys = { version = "0.3", features = ["console"] } @@ -38,5 +38,5 @@ wasm-bindgen-test = "0.3.13" [profile.release] -[profile.dev.overrides."*"] +[profile.dev.package."*"] opt-level = 3 \ No newline at end of file diff --git a/src/entity.rs b/src/entity.rs index 6010b0a..5024a18 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::iter::once; use std::mem::replace; use tf_demo_parser::demo::message::packetentities::{ EntityId, PacketEntitiesMessage, PacketEntity, PVS, @@ -7,6 +8,7 @@ use tf_demo_parser::ParserState; #[derive(Default)] pub struct ActiveEntities { + baselines: [HashMap; 2], entities: HashMap, } @@ -22,49 +24,73 @@ impl ActiveEntities { for deleted in msg.removed_entities.iter() { self.entities.remove(deleted); } + if msg.updated_base_line { + let old_index = msg.base_line as usize; + let new_index = 1 - old_index; + self.baselines.swap(0, 1); + + for entity in &msg.entities { + if entity.pvs == PVS::Enter { + self.baselines[new_index].insert(entity.entity_index, entity.clone()); + } + } + } } fn handle_entity(&mut self, entity: &PacketEntity, state: &ParserState) { - if entity.pvs == PVS::Enter { - self.entities.insert(entity.entity_index, entity.clone()); - } else { - self.entities - .entry(entity.entity_index) - .and_modify(|existing| update_entity(existing, entity, state)) - .or_insert_with(|| entity.clone()); - } + self.entities + .entry(entity.entity_index) + .and_modify(|existing| update_entity(existing, entity, state)) + .or_insert_with(|| entity.clone()); } - pub fn encode(self) -> PacketEntitiesMessage { - let max_entries = self.entities.len() as u16; + pub fn encode(self) -> impl IntoIterator { + let mut baselines = [ + encode_entities(self.baselines[0].clone().into_values().collect::>()), + encode_entities(self.baselines[1].clone().into_values().collect::>()), + ]; + let entities = encode_entities(self.entities.into_values().collect::>()); - let mut entities = self - .entities - .into_iter() - .map(|(_k, v)| v) - .collect::>(); - entities.sort_by(|a, b| a.entity_index.cmp(&b.entity_index)); + baselines[0].updated_base_line = true; + baselines[0].base_line = 1; //the baseline that is updated is the other one - PacketEntitiesMessage { - entities, - removed_entities: vec![], - max_entries, - delta: None, - base_line: 0, - updated_base_line: false, - } + baselines[1].updated_base_line = true; + + baselines.into_iter().chain(once(entities)) + } +} + +fn encode_entities(mut entities: Vec) -> PacketEntitiesMessage { + entities.sort_by(|a, b| a.entity_index.cmp(&b.entity_index)); + let max_entries = entities.len() as u16; + PacketEntitiesMessage { + entities, + removed_entities: vec![], + max_entries, + delta: None, + base_line: 0, + updated_base_line: false, } } fn update_entity(old: &mut PacketEntity, new: &PacketEntity, _state: &ParserState) { - for prop in &new.props { - match old - .props - .iter_mut() - .find(|existing| existing.index == prop.index) - { - Some(existing) => existing.value = prop.value.clone(), - None => old.props.push(prop.clone()), + if old.serial_number != new.serial_number { + *old = new.clone(); + old.pvs = PVS::Enter; + } else { + assert_eq!( + _state.server_classes[usize::from(old.server_class)], + _state.server_classes[usize::from(new.server_class)] + ); + for prop in &new.props { + match old + .props + .iter_mut() + .find(|existing| existing.index == prop.index) + { + Some(existing) => existing.value = prop.value.clone(), + None => old.props.push(prop.clone()), + } } } } diff --git a/src/lib.rs b/src/lib.rs index dd54678..786bf02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ use web_sys::console; static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; const PRESERVE_PACKETS: &[PacketType] = &[ - PacketType::Sigon, + PacketType::Signon, PacketType::DataTables, PacketType::StringTables, PacketType::SyncTick, @@ -82,17 +82,16 @@ pub fn cut(input: &[u8], start_tick: u32, end_tick: u32) -> Vec { panic!("first packet is not a MessagePacket") } - let msg = entities.encode(); + let msgs = entities.encode().into_iter().map(Message::PacketEntities); let packet = Packet::Message(MessagePacket { tick: 0, - messages: vec![ - Message::NetTick(NetTickMessage { - tick: delta_tick, - frame_time: 1881, - std_dev: 263, - }), - Message::PacketEntities(msg), - ], + messages: once(Message::NetTick(NetTickMessage { + tick: delta_tick, + frame_time: 1881, + std_dev: 263, + })) + .chain(msgs) + .collect(), meta: MessagePacketMeta { flags: 0, view_angles: Default::default(),