filter out deletes that are already processed

This commit is contained in:
Robin Appelman 2022-04-19 23:42:33 +02:00
commit 18049bfc96
3 changed files with 63 additions and 18 deletions

3
.gitignore vendored
View file

@ -4,4 +4,5 @@ Cargo.lock
bin/ bin/
pkg/ pkg/
wasm-pack.log wasm-pack.log
out.dem out.dem
test_data/*

View file

@ -1,4 +1,4 @@
use std::collections::HashMap; use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::iter::once; use std::iter::once;
use std::mem::replace; use std::mem::replace;
use tf_demo_parser::demo::message::packetentities::{ use tf_demo_parser::demo::message::packetentities::{
@ -9,7 +9,7 @@ use tf_demo_parser::ParserState;
#[derive(Default)] #[derive(Default)]
pub struct ActiveEntities { pub struct ActiveEntities {
entities: HashMap<EntityId, PacketEntity>, entities: BTreeMap<EntityId, PacketEntity>,
max_entities: u16, max_entities: u16,
} }
@ -57,6 +57,10 @@ impl ActiveEntities {
.or_insert_with(|| entity.clone()); .or_insert_with(|| entity.clone());
} }
pub fn entity_ids(&self) -> BTreeSet<EntityId> {
self.entities.keys().copied().collect()
}
pub fn encode( pub fn encode(
mut self, mut self,
state: &ParserState, state: &ParserState,

View file

@ -9,10 +9,11 @@ use crate::string_tables::StringTablesUpdates;
use crate::utils::set_panic_hook; use crate::utils::set_panic_hook;
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian}; use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
use std::cmp::{max, min}; use std::cmp::{max, min};
use std::collections::BTreeSet;
use std::convert::TryInto; use std::convert::TryInto;
use std::iter::once; use std::iter::once;
use tf_demo_parser::demo::header::Header; use tf_demo_parser::demo::header::Header;
use tf_demo_parser::demo::message::packetentities::PacketEntitiesMessage; use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntitiesMessage, UpdateType};
use tf_demo_parser::demo::message::{Message, NetTickMessage}; use tf_demo_parser::demo::message::{Message, NetTickMessage};
use tf_demo_parser::demo::packet::message::{MessagePacket, MessagePacketMeta}; use tf_demo_parser::demo::packet::message::{MessagePacket, MessagePacketMeta};
use tf_demo_parser::demo::packet::stop::StopPacket; use tf_demo_parser::demo::packet::stop::StopPacket;
@ -72,12 +73,19 @@ pub fn cut(input: &[u8], start_tick: u32, end_tick: u32) -> Vec<u8> {
let mut next = packets.next(&start_handler.state_handler).unwrap().unwrap(); let mut next = packets.next(&start_handler.state_handler).unwrap().unwrap();
let mut delta_tick = 0; let mut delta_tick = 0;
let mut max = 0;
let mut baseline = 0;
if let Packet::Message(MessagePacket { messages, .. }) = &next { if let Packet::Message(MessagePacket { messages, .. }) = &next {
for msg in messages { for msg in messages {
if let Message::PacketEntities(PacketEntitiesMessage { if let Message::PacketEntities(PacketEntitiesMessage {
delta: Some(delta), .. delta: Some(delta),
max_entries,
base_line,
..
}) = msg }) = msg
{ {
max = *max_entries;
baseline = *base_line;
delta_tick = delta.get(); delta_tick = delta.get();
} }
} }
@ -85,6 +93,8 @@ pub fn cut(input: &[u8], start_tick: u32, end_tick: u32) -> Vec<u8> {
panic!("first packet is not a MessagePacket, pick a different start tick") panic!("first packet is not a MessagePacket, pick a different start tick")
} }
let start_entities = entities.entity_ids();
let string_table_updates = string_tables let string_table_updates = string_tables
.encode() .encode()
.into_iter() .into_iter()
@ -98,7 +108,7 @@ pub fn cut(input: &[u8], start_tick: u32, end_tick: u32) -> Vec<u8> {
tick: 0, tick: 0,
messages: vec![ messages: vec![
Message::NetTick(NetTickMessage { Message::NetTick(NetTickMessage {
tick: delta_tick, tick: delta_tick - 1,
frame_time: 1881, frame_time: 1881,
std_dev: 263, std_dev: 263,
}), }),
@ -120,15 +130,13 @@ pub fn cut(input: &[u8], start_tick: u32, end_tick: u32) -> Vec<u8> {
} }
// create the net ticks needed for later deltas // create the net ticks needed for later deltas
let fill_ticks = ((delta_tick + 1)..=last_server_tick) let fill_ticks = (delta_tick..=last_server_tick).into_iter().map(|tick| {
.into_iter() Message::NetTick(NetTickMessage {
.map(|tick| { tick,
Message::NetTick(NetTickMessage { frame_time: 1881,
tick, std_dev: 263,
frame_time: 1881, })
std_dev: 263, });
})
});
let fill_packets = fill_ticks.map(|msg| { let fill_packets = fill_ticks.map(|msg| {
Packet::Message(MessagePacket { Packet::Message(MessagePacket {
tick: 0, tick: 0,
@ -137,9 +145,9 @@ pub fn cut(input: &[u8], start_tick: u32, end_tick: u32) -> Vec<u8> {
Message::PacketEntities(PacketEntitiesMessage { Message::PacketEntities(PacketEntitiesMessage {
entities: vec![], entities: vec![],
removed_entities: vec![], removed_entities: vec![],
max_entries: 0, max_entries: max,
delta: Some(delta_tick.try_into().unwrap()), delta: Some((delta_tick - 1).try_into().unwrap()),
base_line: 0, base_line: baseline,
updated_base_line: false, updated_base_line: false,
}), }),
], ],
@ -157,6 +165,7 @@ pub fn cut(input: &[u8], start_tick: u32, end_tick: u32) -> Vec<u8> {
.unwrap(); .unwrap();
} }
remove_already_deletes(&mut next, &start_entities, last_server_tick);
next.set_tick(next.tick() - start_tick); next.set_tick(next.tick() - start_tick);
next.encode(&mut out_stream, &handler.state_handler) next.encode(&mut out_stream, &handler.state_handler)
.unwrap(); .unwrap();
@ -166,6 +175,9 @@ pub fn cut(input: &[u8], start_tick: u32, end_tick: u32) -> Vec<u8> {
let ty = packet.packet_type(); let ty = packet.packet_type();
let original_tick = packet.tick(); let original_tick = packet.tick();
packet.set_tick(original_tick - start_tick); packet.set_tick(original_tick - start_tick);
remove_already_deletes(&mut packet, &start_entities, last_server_tick);
if ty != PacketType::ConsoleCmd { if ty != PacketType::ConsoleCmd {
packet packet
.encode(&mut out_stream, &handler.state_handler) .encode(&mut out_stream, &handler.state_handler)
@ -227,3 +239,31 @@ fn skip_start<'a>(
(entities, string_tables, start_packets, server_tick) (entities, string_tables, start_packets, server_tick)
} }
// filter out any ongoing deletes of entities that don't exist
fn remove_already_deletes(
packet: &mut Packet,
current_entities: &BTreeSet<EntityId>,
till_delta: u32,
) {
if let Packet::Message(msg_packet) = packet {
for msg in &mut msg_packet.messages {
if let Message::PacketEntities(msg) = msg {
if let Some(delta) = msg.delta {
if delta.get() < till_delta {
let packet_entities = std::mem::take(&mut msg.entities);
msg.entities = packet_entities
.into_iter()
.filter(|ent| match ent.update_type {
UpdateType::Delete | UpdateType::Leave => {
current_entities.contains(&ent.entity_index)
}
_ => true,
})
.collect();
}
}
}
}
}
}