mirror of
https://codeberg.org/demostf/edit.git
synced 2026-06-03 20:04:06 +02:00
fmt + CL_PreserveExistingEntity wip fix
This commit is contained in:
parent
4a970e81a2
commit
e95a9e4a2c
11 changed files with 139 additions and 49 deletions
|
|
@ -1,6 +1,7 @@
|
|||
use tf_demo_parser::demo::message::Message;
|
||||
use tf_demo_parser::demo::message::usermessage::UserMessageType;
|
||||
use crate::missing_preserve::RemoveInvalidPreserveEntity;
|
||||
use crate::mutate::MutatorList;
|
||||
use tf_demo_parser::demo::message::usermessage::UserMessageType;
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
|
||||
/// General cleanup we always want to do
|
||||
pub fn clean_demo(mutators: &mut MutatorList) {
|
||||
|
|
@ -11,4 +12,5 @@ pub fn clean_demo(mutators: &mut MutatorList) {
|
|||
true
|
||||
}
|
||||
});
|
||||
mutators.push_message_mutator(RemoveInvalidPreserveEntity::new());
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
use tf_demo_parser::demo::message::Message;
|
||||
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntity};
|
||||
use tf_demo_parser::demo::sendprop::{SendPropIdentifier, SendPropValue};
|
||||
use tf_demo_parser::ParserState;
|
||||
use crate::mutate::MessageMutator;
|
||||
use crate::MutatorList;
|
||||
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntity};
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
use tf_demo_parser::demo::sendprop::{SendPropIdentifier, SendPropValue};
|
||||
use tf_demo_parser::ParserState;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
|
||||
|
||||
use tf_demo_parser::demo::data::{DemoTick, ServerTick};
|
||||
use tf_demo_parser::demo::message::packetentities::{
|
||||
EntityId, PacketEntitiesMessage, PacketEntity, UpdateType,
|
||||
};
|
||||
use tf_demo_parser::demo::packet::datatable::ClassId;
|
||||
use tf_demo_parser::demo::sendprop::{SendPropIdentifier};
|
||||
use tf_demo_parser::demo::sendprop::SendPropIdentifier;
|
||||
use tf_demo_parser::ParserState;
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -20,7 +18,12 @@ pub struct ActiveEntities {
|
|||
}
|
||||
|
||||
impl ActiveEntities {
|
||||
pub fn handle_message(&mut self, msg: &PacketEntitiesMessage, state: &ParserState, tick: DemoTick) {
|
||||
pub fn handle_message(
|
||||
&mut self,
|
||||
msg: &PacketEntitiesMessage,
|
||||
state: &ParserState,
|
||||
tick: DemoTick,
|
||||
) {
|
||||
self.max_entities = self.max_entities.max(msg.max_entries);
|
||||
for entity in &msg.entities {
|
||||
self.removed_entities.remove(&entity.entity_index);
|
||||
|
|
@ -160,7 +163,7 @@ impl ActiveEntities {
|
|||
},
|
||||
serial_number: 0,
|
||||
delay: None,
|
||||
delta: None
|
||||
delta: None,
|
||||
}))
|
||||
.collect::<Vec<_>>(),
|
||||
self.max_entities,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ mod entity;
|
|||
mod string_tables;
|
||||
|
||||
use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
|
||||
use std::cmp::{min};
|
||||
use std::cmp::min;
|
||||
use std::collections::BTreeSet;
|
||||
use std::convert::TryInto;
|
||||
use std::iter::once;
|
||||
|
|
@ -10,19 +10,18 @@ use std::mem::take;
|
|||
use tf_demo_parser::demo::header::Header;
|
||||
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntitiesMessage, UpdateType};
|
||||
|
||||
use tf_demo_parser::demo::data::{DemoTick, ServerTick};
|
||||
use tf_demo_parser::demo::message::{Message, NetTickMessage};
|
||||
use tf_demo_parser::demo::packet::message::{MessagePacket};
|
||||
use tf_demo_parser::demo::packet::message::MessagePacket;
|
||||
use tf_demo_parser::demo::packet::stop::StopPacket;
|
||||
use tf_demo_parser::demo::packet::{Packet, PacketType};
|
||||
use tf_demo_parser::demo::parser::{DemoHandler, Encode, NullHandler, RawPacketStream};
|
||||
use tf_demo_parser::{Demo, ParserState};
|
||||
use tf_demo_parser::demo::data::{DemoTick, ServerTick};
|
||||
|
||||
|
||||
use crate::cut::entity::ActiveEntities;
|
||||
use crate::cut::string_tables::StringTablesUpdates;
|
||||
use crate::mutate::MessageMutator;
|
||||
use crate::{EditOptions, find_stv, PacketMutator};
|
||||
use crate::{find_stv, EditOptions, PacketMutator};
|
||||
|
||||
const PRESERVE_PACKETS: &[PacketType] = &[
|
||||
PacketType::Signon,
|
||||
|
|
@ -78,10 +77,12 @@ pub fn cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
|||
.encode()
|
||||
.into_iter()
|
||||
.map(|msg| Message::UpdateStringTable(msg));
|
||||
let (baseline_updates, entity_update, removed_update) =
|
||||
start_state
|
||||
.entities
|
||||
.encode(&start_handler.state_handler, delta_tick - 2, start_tick, &start_handler.state_handler);
|
||||
let (baseline_updates, entity_update, removed_update) = start_state.entities.encode(
|
||||
&start_handler.state_handler,
|
||||
delta_tick - 2,
|
||||
start_tick,
|
||||
&start_handler.state_handler,
|
||||
);
|
||||
let baseline_updates = baseline_updates.into_iter().map(Message::PacketEntities);
|
||||
let start_packets = string_table_updates
|
||||
.chain(baseline_updates)
|
||||
|
|
@ -105,7 +106,8 @@ pub fn cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
|||
}
|
||||
|
||||
// create the net ticks needed for later deltas
|
||||
let fill_ticks = (delta_tick + 1).range_inclusive(start_state.server_tick)
|
||||
let fill_ticks = (delta_tick + 1)
|
||||
.range_inclusive(start_state.server_tick)
|
||||
.into_iter()
|
||||
.map(|tick| net_tick(tick));
|
||||
let fill_packets = fill_ticks.map(|msg| {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use std::collections::BTreeMap;
|
||||
use tf_demo_parser::demo::message::stringtable::{UpdateStringTableMessage};
|
||||
use tf_demo_parser::demo::message::stringtable::UpdateStringTableMessage;
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
use tf_demo_parser::demo::packet::stringtable::StringTableEntry;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@ impl Args {
|
|||
EditOptions {
|
||||
unlock_pov: self.unlock_pov,
|
||||
cut: if let (Some(from), Some(to)) = (self.from, self.to) {
|
||||
Some(TickRange { from: from.into(), to: to.into() })
|
||||
Some(TickRange {
|
||||
from: from.into(),
|
||||
to: to.into(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
|
|
@ -30,6 +33,7 @@ impl Args {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
let args: Args = Args::parse();
|
||||
let options = args.get_options();
|
||||
let file = fs::read(&args.path).unwrap();
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
mod mutate;
|
||||
mod pov;
|
||||
mod clean;
|
||||
mod cond;
|
||||
mod cut;
|
||||
pub mod missing_preserve;
|
||||
mod mutate;
|
||||
mod options;
|
||||
mod pov;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
use tf_demo_parser::{Demo, DemoParser};
|
||||
use tf_demo_parser::demo::header::Header;
|
||||
use tf_demo_parser::demo::parser::{RawPacketStream, DemoHandler, Encode};
|
||||
use tf_demo_parser::demo::packet::PacketType;
|
||||
use bitbuffer::{BitRead, BitWriteStream, LittleEndian};
|
||||
use tf_demo_parser::demo::header::Header;
|
||||
use tf_demo_parser::demo::message::packetentities::EntityId;
|
||||
use tf_demo_parser::demo::packet::PacketType;
|
||||
use tf_demo_parser::demo::parser::{DemoHandler, Encode, RawPacketStream};
|
||||
use tf_demo_parser::{Demo, DemoParser};
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use bitbuffer::BitWrite;
|
||||
use tf_demo_parser::demo::data::DemoTick;
|
||||
|
|
@ -20,7 +21,7 @@ use crate::clean::clean_demo;
|
|||
use crate::cond::strip_cond;
|
||||
use crate::cut::cut;
|
||||
use crate::mutate::{MutatorList, PacketMutator};
|
||||
pub use crate::options::{EditOptions, TickRange, CondOptions};
|
||||
pub use crate::options::{CondOptions, EditOptions, TickRange};
|
||||
use crate::pov::unlock_pov;
|
||||
|
||||
extern crate web_sys;
|
||||
|
|
@ -92,7 +93,9 @@ fn no_cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
|||
while let Some(mut packet) = packets.next(&handler.state_handler).unwrap() {
|
||||
mutators.mutate_packet(&mut packet, &handler.state_handler);
|
||||
|
||||
if packet.packet_type() != PacketType::ConsoleCmd && packet.packet_type() != PacketType::UserCmd {
|
||||
if packet.packet_type() != PacketType::ConsoleCmd
|
||||
&& packet.packet_type() != PacketType::UserCmd
|
||||
{
|
||||
packet
|
||||
.encode(&mut out_stream, &handler.state_handler)
|
||||
.unwrap();
|
||||
|
|
@ -106,6 +109,8 @@ fn no_cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
|||
fn find_stv(demo: &Demo) -> Option<EntityId> {
|
||||
let parser = DemoParser::new(demo.get_stream());
|
||||
let (_, data) = parser.parse().expect("failed to parse demo");
|
||||
data.users.values().find(|user| user.steam_id == "BOT")
|
||||
data.users
|
||||
.values()
|
||||
.find(|user| user.steam_id == "BOT")
|
||||
.map(|user| user.entity_id)
|
||||
}
|
||||
71
wasm/src/missing_preserve.rs
Normal file
71
wasm/src/missing_preserve.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
use crate::mutate::MessageMutator;
|
||||
use log::{info, warn};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntity, UpdateType};
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
use tf_demo_parser::demo::packet::datatable::{ClassId, ServerClass};
|
||||
use tf_demo_parser::ParserState;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RemoveInvalidPreserveEntity {
|
||||
known_entities: RefCell<BTreeSet<EntityId>>,
|
||||
deferred_delete: RefCell<Vec<EntityId>>,
|
||||
}
|
||||
|
||||
impl RemoveInvalidPreserveEntity {
|
||||
pub fn new() -> RemoveInvalidPreserveEntity {
|
||||
RemoveInvalidPreserveEntity::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl MessageMutator for RemoveInvalidPreserveEntity {
|
||||
fn mutate_message(&self, message: &mut Message, _state: &ParserState) {
|
||||
if let Message::PacketEntities(ent_message) = message {
|
||||
let deferred_deletes = self.deferred_delete.take();
|
||||
for entity in ent_message.entities.iter() {
|
||||
match entity.update_type {
|
||||
UpdateType::Enter => {
|
||||
self.known_entities.borrow_mut().insert(entity.entity_index);
|
||||
}
|
||||
UpdateType::Preserve => {
|
||||
if !self.known_entities.borrow().contains(&entity.entity_index) {
|
||||
warn!("preserving missing entity {}", entity.entity_index);
|
||||
}
|
||||
}
|
||||
UpdateType::Delete => {
|
||||
self.known_entities.borrow_mut().remove(&entity.entity_index);
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
ent_message.removed_entities.retain(|id| {
|
||||
if self.known_entities.borrow().contains(&id) {
|
||||
// just not deleting makes the demo play, but with some ERROR entities
|
||||
// having a Delete or Leave makes it crash further in the demo
|
||||
|
||||
// warn!("inserting delete for {}", id);
|
||||
// only entity_index and update_type is used
|
||||
// ent_message.entities.push(PacketEntity {
|
||||
// entity_index: *id,
|
||||
// server_class: 0.into(),
|
||||
// props: vec![],
|
||||
// in_pvs: false,
|
||||
// update_type: UpdateType::Leave,
|
||||
// serial_number: 0,
|
||||
// delay: None,
|
||||
// delta: None,
|
||||
// baseline_index: 0,
|
||||
// });
|
||||
// self.deferred_delete.borrow_mut().push(*id);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
ent_message.entities.sort_by(|a, b| a.entity_index.cmp(&b.entity_index));
|
||||
ent_message.removed_entities.extend(deferred_deletes);
|
||||
ent_message.removed_entities.sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ impl<T: MessageMutator> PacketMutator for PacketMessageMutator<T> {
|
|||
.messages
|
||||
.iter_mut()
|
||||
.for_each(|msg| self.mutator.mutate_message(msg, state));
|
||||
},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -114,4 +114,3 @@ impl PacketMutator for MutatorList {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{clean_demo, strip_cond, unlock_pov, MutatorList};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tf_demo_parser::demo::data::DemoTick;
|
||||
use tf_demo_parser::demo::message::packetentities::EntityId;
|
||||
use crate::{clean_demo, MutatorList, strip_cond, unlock_pov};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
use crate::mutate::{MessageMutator, MutatorList};
|
||||
use std::cell::Cell;
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
use tf_demo_parser::demo::message::packetentities::{EntityId, PacketEntity, UpdateType};
|
||||
use tf_demo_parser::demo::message::usermessage::{UserMessage};
|
||||
use tf_demo_parser::demo::message::usermessage::UserMessage;
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
use tf_demo_parser::demo::packet::Packet;
|
||||
use tf_demo_parser::ParserState;
|
||||
use crate::mutate::{MessageMutator, MutatorList};
|
||||
|
||||
struct AddStvEntity {
|
||||
added: Cell<bool>,
|
||||
|
|
@ -25,7 +25,11 @@ impl MessageMutator for AddStvEntity {
|
|||
if !self.added.get() {
|
||||
if let Message::PacketEntities(ent_message) = message {
|
||||
if ent_message.base_line == 0 {
|
||||
let player_entity = ent_message.entities.iter().find(|ent| ent.entity_index >= 1 && ent.entity_index < 255).expect("Failed to find a player entity");
|
||||
let player_entity = ent_message
|
||||
.entities
|
||||
.iter()
|
||||
.find(|ent| ent.entity_index >= 1 && ent.entity_index < 255)
|
||||
.expect("Failed to find a player entity");
|
||||
if player_entity.entity_index == self.entity_index {
|
||||
// already stv?
|
||||
self.added.set(true);
|
||||
|
|
@ -42,9 +46,11 @@ impl MessageMutator for AddStvEntity {
|
|||
serial_number: 1234567,
|
||||
delay: None,
|
||||
delta: None,
|
||||
baseline_index: 0
|
||||
baseline_index: 0,
|
||||
});
|
||||
ent_message.entities.sort_by(|a, b| a.entity_index.cmp(&b.entity_index));
|
||||
ent_message
|
||||
.entities
|
||||
.sort_by(|a, b| a.entity_index.cmp(&b.entity_index));
|
||||
self.added.set(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -58,9 +64,7 @@ pub fn unlock_pov(mutators: &mut MutatorList, spectator_id: EntityId) {
|
|||
info.player_slot = u32::from(spectator_id) as u8 - 1;
|
||||
}
|
||||
});
|
||||
mutators.push_message_filter(|message: &Message| {
|
||||
!matches!(message, Message::SetView(_))
|
||||
});
|
||||
mutators.push_message_filter(|message: &Message| !matches!(message, Message::SetView(_)));
|
||||
mutators.push_message_filter(|message: &Message| {
|
||||
!matches!(message, Message::UserMessage(UserMessage::VGuiMenu(_)))
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue