mirror of
https://codeberg.org/demostf/edit.git
synced 2026-10-01 07:34:05 +02:00
rewrite instance baselines after the array size fixup
This commit is contained in:
parent
04790ad6f4
commit
46e955b411
6 changed files with 302 additions and 187 deletions
157
wasm/Cargo.lock
generated
157
wasm/Cargo.lock
generated
|
|
@ -89,7 +89,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"structmeta 0.3.0",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -151,7 +151,7 @@ dependencies = [
|
|||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -227,7 +227,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -301,9 +301,9 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
|||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||
checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
|
@ -335,7 +335,7 @@ checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -356,9 +356,9 @@ checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
|
||||
|
||||
[[package]]
|
||||
name = "main_error"
|
||||
|
|
@ -397,7 +397,7 @@ dependencies = [
|
|||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -430,11 +430,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num_enum"
|
||||
version = "0.7.4"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a"
|
||||
checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26"
|
||||
dependencies = [
|
||||
"num_enum_derive 0.7.4",
|
||||
"num_enum_derive 0.7.6",
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
|
|
@ -452,14 +452,14 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num_enum_derive"
|
||||
version = "0.7.4"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d"
|
||||
checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8"
|
||||
dependencies = [
|
||||
"proc-macro-crate 3.4.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -487,13 +487,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "parse-display"
|
||||
version = "0.9.1"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a"
|
||||
checksum = "e78deb158fb1d73b29efb4b7e9b9860b78059c670de06bd28df8d0b458ded0eb"
|
||||
dependencies = [
|
||||
"parse-display-derive 0.9.1",
|
||||
"parse-display-derive 0.11.0",
|
||||
"regex",
|
||||
"regex-syntax 0.8.6",
|
||||
"regex-syntax 0.8.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -513,16 +513,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "parse-display-derive"
|
||||
version = "0.9.1"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281"
|
||||
checksum = "8e95a50d1084dab562913062c4c34bb204b68fc6ec38a1395909ff5aaaf4f10a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"regex-syntax 0.8.6",
|
||||
"regex-syntax 0.8.11",
|
||||
"structmeta 0.3.0",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -578,48 +578,48 @@ dependencies = [
|
|||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.41"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
|
||||
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.3"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c"
|
||||
checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax 0.8.6",
|
||||
"regex-syntax 0.8.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.11"
|
||||
version = "0.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad"
|
||||
checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.8.6",
|
||||
"regex-syntax 0.8.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -630,9 +630,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.6"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
|
||||
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
|
|
@ -640,12 +640,6 @@ version = "1.0.22"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
|
|
@ -657,9 +651,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
|
|
@ -678,46 +672,46 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
version = "1.0.229"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 3.0.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.145"
|
||||
version = "1.0.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
||||
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.20"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
|
||||
checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 3.0.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -728,9 +722,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|||
|
||||
[[package]]
|
||||
name = "snap"
|
||||
version = "1.1.1"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b"
|
||||
checksum = "199905e6153d6405f9728fe44daace35f8f837bbf830bb6e85fbd5828709a886"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
|
|
@ -759,7 +753,7 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"structmeta-derive 0.3.0",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -781,7 +775,7 @@ checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -797,9 +791,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.106"
|
||||
version = "2.0.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -808,7 +813,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tf-demo-parser"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
dependencies = [
|
||||
"bitbuffer",
|
||||
"const-fnv1a-hash",
|
||||
|
|
@ -818,8 +823,8 @@ dependencies = [
|
|||
"log",
|
||||
"main_error",
|
||||
"num-traits",
|
||||
"num_enum 0.7.4",
|
||||
"parse-display 0.9.1",
|
||||
"num_enum 0.7.6",
|
||||
"parse-display 0.11.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
|
|
@ -829,22 +834,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.17"
|
||||
version = "2.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
|
||||
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.17"
|
||||
version = "2.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
||||
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 3.0.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -911,7 +916,7 @@ checksum = "1ecb9ecf7799210407c14a8cfdfe0173365780968dc57973ed082211958e0b18"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -959,7 +964,7 @@ dependencies = [
|
|||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
|
@ -994,7 +999,7 @@ checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
|
@ -1029,7 +1034,7 @@ checksum = "b673bca3298fe582aeef8352330ecbad91849f85090805582400850f8270a2e8"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1191,3 +1196,9 @@ checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
|
|||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||
|
|
|
|||
|
|
@ -39,7 +39,9 @@ pub fn cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
|||
let mut stream = demo.get_stream();
|
||||
let mut header = Header::read(&mut stream).unwrap();
|
||||
|
||||
let mut mutators = options.as_mutator(spectator_id);
|
||||
let mut mutators = options
|
||||
.as_mutator(spectator_id, &header, &stream)
|
||||
.expect("invalid demo");
|
||||
let start_tick = options.cut.unwrap().from;
|
||||
let end_tick = options.cut.unwrap().to;
|
||||
|
||||
|
|
@ -105,9 +107,9 @@ 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)
|
||||
.map(net_tick);
|
||||
let next_tick = delta_tick + 1;
|
||||
let tick_range = next_tick.range_inclusive(start_state.server_tick);
|
||||
let fill_ticks = tick_range.map(net_tick);
|
||||
let fill_packets = fill_ticks.map(|msg| {
|
||||
Packet::Message(MessagePacket {
|
||||
messages: vec![
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ mod cut;
|
|||
pub mod missing_preserve;
|
||||
mod mutate;
|
||||
mod options;
|
||||
mod pov;
|
||||
mod player_count;
|
||||
mod pov;
|
||||
|
||||
use bitbuffer::{BitRead, BitWriteStream, LittleEndian};
|
||||
use tf_demo_parser::demo::header::Header;
|
||||
|
|
@ -92,12 +92,15 @@ fn no_cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
|||
let mut output_handler = DemoHandler::default();
|
||||
output_handler.handle_header(&header);
|
||||
|
||||
let mutators = options.as_mutator(spectator_id);
|
||||
let mut mutators = options
|
||||
.as_mutator(spectator_id, &header, &stream)
|
||||
.expect("invalid demo");
|
||||
|
||||
while let Some(mut packet) = packets.next(&handler.state_handler).unwrap() {
|
||||
handler.handle_packet(packet.clone()).expect("failed to handle source packet");
|
||||
handler
|
||||
.handle_packet(packet.clone())
|
||||
.expect("failed to handle source packet");
|
||||
mutators.mutate_packet(&mut packet, &handler.state_handler);
|
||||
output_handler.handle_packet(packet.clone()).expect("failed to handle mutated packet");
|
||||
|
||||
if packet.packet_type() != PacketType::ConsoleCmd
|
||||
&& packet.packet_type() != PacketType::UserCmd
|
||||
|
|
@ -106,6 +109,10 @@ fn no_cut(input: &[u8], options: EditOptions) -> Vec<u8> {
|
|||
.encode(&mut out_stream, &output_handler.state_handler)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
output_handler
|
||||
.handle_packet(packet)
|
||||
.expect("failed to handle mutated packet");
|
||||
}
|
||||
}
|
||||
out_buffer
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use tf_demo_parser::demo::packet::Packet;
|
|||
use tf_demo_parser::ParserState;
|
||||
|
||||
pub trait PacketMutator {
|
||||
fn mutate_packet(&self, packet: &mut Packet, state: &ParserState);
|
||||
fn mutate_packet(&mut self, packet: &mut Packet, state: &ParserState);
|
||||
}
|
||||
|
||||
pub trait MessageMutator {
|
||||
|
|
@ -20,7 +20,7 @@ pub struct PacketMessageMutator<T: MessageMutator> {
|
|||
}
|
||||
|
||||
impl<T: MessageMutator> PacketMutator for PacketMessageMutator<T> {
|
||||
fn mutate_packet(&self, packet: &mut Packet, state: &ParserState) {
|
||||
fn mutate_packet(&mut self, packet: &mut Packet, state: &ParserState) {
|
||||
match packet {
|
||||
Packet::Message(msg_packet) | Packet::Signon(msg_packet) => {
|
||||
msg_packet
|
||||
|
|
@ -34,7 +34,7 @@ impl<T: MessageMutator> PacketMutator for PacketMessageMutator<T> {
|
|||
}
|
||||
|
||||
impl<F: Fn(&mut Packet)> PacketMutator for F {
|
||||
fn mutate_packet(&self, packet: &mut Packet, _state: &ParserState) {
|
||||
fn mutate_packet(&mut self, packet: &mut Packet, _state: &ParserState) {
|
||||
self(packet)
|
||||
}
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ pub struct PacketMessageFilter<T: MessageFilter> {
|
|||
}
|
||||
|
||||
impl<T: MessageFilter> PacketMutator for PacketMessageFilter<T> {
|
||||
fn mutate_packet(&self, packet: &mut Packet, _state: &ParserState) {
|
||||
fn mutate_packet(&mut self, packet: &mut Packet, _state: &ParserState) {
|
||||
match packet {
|
||||
Packet::Message(msg_packet) | Packet::Signon(msg_packet) => {
|
||||
let messages = take(&mut msg_packet.messages);
|
||||
|
|
@ -108,8 +108,8 @@ impl MutatorList {
|
|||
}
|
||||
|
||||
impl PacketMutator for MutatorList {
|
||||
fn mutate_packet(&self, packet: &mut Packet, state: &ParserState) {
|
||||
for mutator in self.mutators.iter() {
|
||||
fn mutate_packet(&mut self, packet: &mut Packet, state: &ParserState) {
|
||||
for mutator in self.mutators.iter_mut() {
|
||||
mutator.mutate_packet(packet, state);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
use crate::missing_preserve::removed_invalid_deletes;
|
||||
use crate::player_count::fix_player_count;
|
||||
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::header::Header;
|
||||
use tf_demo_parser::demo::message::packetentities::EntityId;
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
use crate::player_count::fix_player_count;
|
||||
use tf_demo_parser::{ParseError, Stream};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
#[non_exhaustive]
|
||||
|
|
@ -27,7 +29,12 @@ pub struct EditOptions {
|
|||
}
|
||||
|
||||
impl EditOptions {
|
||||
pub fn as_mutator(&self, spectator_id: EntityId) -> MutatorList {
|
||||
pub fn as_mutator(
|
||||
&self,
|
||||
spectator_id: EntityId,
|
||||
header: &Header,
|
||||
stream: &Stream,
|
||||
) -> Result<MutatorList, ParseError> {
|
||||
let mut mutators = MutatorList::new();
|
||||
|
||||
mutators.push_message_mutator(|message: &mut Message| {
|
||||
|
|
@ -56,10 +63,10 @@ impl EditOptions {
|
|||
}
|
||||
|
||||
if self.fix_player_count {
|
||||
fix_player_count(&mut mutators);
|
||||
fix_player_count(&mut mutators, header, stream)?;
|
||||
}
|
||||
|
||||
mutators
|
||||
Ok(mutators)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,57 +1,43 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use crate::mutate::{MutatorList, PacketMutator};
|
||||
use tf_demo_parser::demo::header::Header;
|
||||
use tf_demo_parser::demo::message::Message;
|
||||
use tf_demo_parser::demo::packet::datatable::{DataTablePacket, SendTable};
|
||||
use tf_demo_parser::demo::packet::stringtable::{ExtraData, StringTable, StringTableEntry};
|
||||
use tf_demo_parser::demo::packet::Packet;
|
||||
use tf_demo_parser::ParserState;
|
||||
use tf_demo_parser::demo::parser::state::StaticBaseline;
|
||||
use tf_demo_parser::demo::parser::{DemoHandler, RawPacketStream};
|
||||
use tf_demo_parser::{ParseError, ParserState, Stream};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PlayerCount {}
|
||||
pub struct PlayerCount {
|
||||
baselines: Option<Baselines>,
|
||||
string_table_names: Vec<String>,
|
||||
}
|
||||
|
||||
/// property arrays that got renamed and new items
|
||||
const PLAYER_ARRAY_PROPS_RENAMED: &[(&str, u16, u16)] = &[
|
||||
("m_aBonusPlayerRoll_33", 33, 101),
|
||||
("m_ConditionData_128", 128, 131),
|
||||
];
|
||||
fn find_data_tables(header: &Header, stream: Stream) -> Result<DataTablePacket, ParseError> {
|
||||
let mut packets = RawPacketStream::new(stream);
|
||||
let mut handler = DemoHandler::default();
|
||||
handler.handle_header(header);
|
||||
while let Some(packet) = packets.next(&handler.state_handler)? {
|
||||
if let Packet::DataTables(tables) = &packet {
|
||||
return Ok(tables.clone());
|
||||
}
|
||||
handler.handle_packet(packet)?;
|
||||
}
|
||||
Err(ParseError::InvalidDemo("missing data tables"))
|
||||
}
|
||||
|
||||
/// property arrays that just got new items
|
||||
const PLAYER_ARRAY_PROPS: &[(&str, u16)] = &[
|
||||
("m_iPing", 101),
|
||||
("m_iScore", 101),
|
||||
("m_iDeaths", 101),
|
||||
("m_bConnected", 101),
|
||||
("m_iTeam", 101),
|
||||
("m_bAlive", 101),
|
||||
("m_iHealth", 101),
|
||||
("m_iAccountID", 101),
|
||||
("m_bValid", 101),
|
||||
("m_iUserID", 101),
|
||||
("m_bPlayerReady", 101),
|
||||
("m_ePlayerWantsRematch", 101),
|
||||
("m_bPlayerIsPackMember", 101),
|
||||
("m_bPlayerDominated", 101),
|
||||
("m_bPlayerDominatingMe", 101),
|
||||
("m_iTotalScore", 101),
|
||||
("m_iMaxHealth", 101),
|
||||
("m_iMaxBuffedHealth", 101),
|
||||
("m_iPlayerClass", 101),
|
||||
("m_bArenaSpectator", 101),
|
||||
("m_iActiveDominations", 101),
|
||||
("m_flNextRespawnTime", 101),
|
||||
("m_iChargeLevel", 101),
|
||||
("m_iDamage", 101),
|
||||
("m_iDamageAssist", 101),
|
||||
("m_iDamageBoss", 101),
|
||||
("m_iHealing", 101),
|
||||
("m_iHealingAssist", 101),
|
||||
("m_iDamageBlocked", 101),
|
||||
("m_iCurrencyCollected", 101),
|
||||
("m_iBonusPoints", 101),
|
||||
("m_iPlayerLevel", 101),
|
||||
("m_iUpgradeRefundCredits", 101),
|
||||
("m_iBuybackCredits", 101),
|
||||
("m_iPlayerClassWhenKilled", 101),
|
||||
("m_iConnectionState", 101),
|
||||
("m_flConnectTime", 101),
|
||||
("m_iStreaks", 407),
|
||||
];
|
||||
impl PlayerCount {
|
||||
pub fn new(header: &Header, stream: Stream) -> Result<PlayerCount, ParseError> {
|
||||
let data_tables = find_data_tables(header, stream)?;
|
||||
let baselines = Baselines::new(&header, &data_tables)?;
|
||||
Ok(PlayerCount {
|
||||
baselines,
|
||||
string_table_names: Vec::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// property values that got changed
|
||||
const PLAYER_PROPS_VALUES: &[(&str, &str, u16, u16)] = &[
|
||||
|
|
@ -60,61 +46,163 @@ const PLAYER_PROPS_VALUES: &[(&str, &str, u16, u16)] = &[
|
|||
("DT_TFTeam", r#""team_object_array""#, 198, 606),
|
||||
];
|
||||
|
||||
fn new_prop_size(table: &str, prop: &str) -> Option<u16> {
|
||||
for (changed_table, changed_prop, _, new_size) in PLAYER_PROPS_VALUES.iter().copied() {
|
||||
if changed_table == table && changed_prop == prop {
|
||||
return Some(new_size);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
impl PacketMutator for PlayerCount {
|
||||
fn mutate_packet(&self, packet: &mut Packet, _state: &ParserState) {
|
||||
if let Packet::DataTables(data_tables) = packet {
|
||||
for table in &mut data_tables.tables {
|
||||
let table_name = table.name.as_str();
|
||||
if let Some(new_length) = PLAYER_ARRAY_PROPS.iter().copied().find_map(|(name, new_length)| (name == table_name).then_some(new_length)) {
|
||||
let base = table.props.last().unwrap().clone();
|
||||
let old_length = table.props.len() as u16;
|
||||
for i in old_length ..= new_length {
|
||||
let mut prop = base.clone();
|
||||
prop.name = format!("{i:03}").into();
|
||||
table.props.push(prop);
|
||||
fn mutate_packet(&mut self, packet: &mut Packet, _state: &ParserState) {
|
||||
match packet {
|
||||
Packet::DataTables(data_tables) => {
|
||||
fixup_tables(data_tables);
|
||||
}
|
||||
} else if let Some((old_length, new_length)) = PLAYER_ARRAY_PROPS_RENAMED.iter().copied().find_map(|(name, old_length, new_length)| table_name.ends_with(name).then_some((old_length, new_length))) {
|
||||
if table_name.starts_with("_ST_") {
|
||||
let base = table.props.last().unwrap().clone();
|
||||
for i in old_length.. new_length { // non-inclusive range, because for some reasons these arrays are one short
|
||||
let mut prop = base.clone();
|
||||
prop.name = format!("{i:03}").into();
|
||||
table.props.push(prop);
|
||||
}
|
||||
} else if table_name.starts_with("_LPT_") {
|
||||
table.props[0].name = format!("lengthprop{new_length}").into();
|
||||
}
|
||||
let name_prefix = table_name.rsplit_once('_').unwrap().0;
|
||||
table.name = format!("{name_prefix}_{}", new_length).into();
|
||||
} else if let Some((prop_name, _, new_length)) = PLAYER_PROPS_VALUES.iter().copied().find_map(|(name, prop_name, old_length, new_length)| table_name.eq(name).then_some((prop_name, old_length, new_length))) {
|
||||
for prop in &mut table.props {
|
||||
if prop.name == prop_name {
|
||||
prop.element_count = new_length.into();
|
||||
Packet::StringTables(tables_packet) => {
|
||||
if let Some(baselines) = self.baselines.as_mut() {
|
||||
for table in tables_packet.tables.iter_mut() {
|
||||
self.string_table_names.push(table.name.as_ref().into());
|
||||
baselines.rewrite_table(table);
|
||||
}
|
||||
}
|
||||
}
|
||||
for prop in &mut table.props {
|
||||
if let Some(target_name) = &mut prop.table_name {
|
||||
if let Some((_, new_length)) = PLAYER_ARRAY_PROPS_RENAMED.iter().copied().find_map(|(name, old_length, new_length)| target_name.ends_with(name).then_some((old_length, new_length))) {
|
||||
let name_prefix = target_name.rsplit_once('_').unwrap().0;
|
||||
*target_name = format!("{name_prefix}_{}", new_length).into();
|
||||
Packet::Signon(message_packet) | Packet::Message(message_packet) => {
|
||||
for msg in message_packet.messages.iter_mut() {
|
||||
if let Some(baselines) = self.baselines.as_mut() {
|
||||
baselines.rewrite_message(msg, &self.string_table_names);
|
||||
}
|
||||
}
|
||||
}
|
||||
// let table_name = table.name.as_str();
|
||||
// for prop in &mut table.props {
|
||||
// println!(
|
||||
// "{}.{}: {}",
|
||||
// table_name,
|
||||
// prop.name,
|
||||
// prop.element_count.unwrap_or_default()
|
||||
// );
|
||||
// }
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fix_player_count(mutators: &mut MutatorList) {
|
||||
mutators.push_packet_mutator(PlayerCount::default())
|
||||
pub fn fix_player_count(
|
||||
mutators: &mut MutatorList,
|
||||
header: &Header,
|
||||
stream: &Stream,
|
||||
) -> Result<(), ParseError> {
|
||||
PlayerCount::new(header, stream.clone())
|
||||
.map(|player_count| mutators.push_packet_mutator(player_count))
|
||||
}
|
||||
|
||||
/// Raise the MAX_PLAYERS arrays from the pre-100-player sizes, which a current
|
||||
/// client rejects with "RecvProp type doesn't match server type".
|
||||
///
|
||||
/// Also changes the encoding: the length field is log2(element_count) + 1 bits.
|
||||
/// See `Baselines`.
|
||||
fn fixup_tables(tables: &mut DataTablePacket) -> bool {
|
||||
let mut changed = false;
|
||||
for table in tables.tables.iter_mut() {
|
||||
for prop in table.props.iter_mut() {
|
||||
if let Some(size) = new_prop_size(table.name.as_str(), prop.name.as_str()) {
|
||||
if prop.element_count != Some(size) {
|
||||
prop.element_count = Some(size);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
changed
|
||||
}
|
||||
|
||||
/// Re-encodes instance baselines to match the tables `fixup_tables` rewrote.
|
||||
///
|
||||
/// Left stale, SourceTV demos decode team data wrongly and POV demos overflow
|
||||
/// the baseline merge buffer.
|
||||
struct Baselines {
|
||||
old: Vec<SendTable>,
|
||||
new: Vec<SendTable>,
|
||||
/// Classes whose props encode differently. The rest are left untouched.
|
||||
affected: HashSet<u32>,
|
||||
}
|
||||
|
||||
impl Baselines {
|
||||
fn new(header: &Header, tables: &DataTablePacket) -> Result<Option<Self>, ParseError> {
|
||||
let mut fixed = tables.clone();
|
||||
if !fixup_tables(&mut fixed) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let mut before = DemoHandler::default();
|
||||
before.handle_header(header);
|
||||
before.handle_packet(Packet::DataTables(tables.clone()))?;
|
||||
|
||||
let mut after = DemoHandler::default();
|
||||
after.handle_header(header);
|
||||
after.handle_packet(Packet::DataTables(fixed))?;
|
||||
|
||||
let old = before.state_handler.send_tables.clone();
|
||||
let new = after.state_handler.send_tables.clone();
|
||||
let affected = old
|
||||
.iter()
|
||||
.zip(new.iter())
|
||||
.enumerate()
|
||||
.filter(|(_, (o, n))| o.flattened_props != n.flattened_props)
|
||||
.map(|(id, _)| id as u32)
|
||||
.collect();
|
||||
|
||||
Ok(Some(Baselines { old, new, affected }))
|
||||
}
|
||||
|
||||
/// `table_names` is the handler's `string_table_names`, which maps the id
|
||||
/// an UpdateStringTable carries back to the table it belongs to.
|
||||
fn rewrite_message(&mut self, message: &mut Message, string_tables: &[String]) {
|
||||
match message {
|
||||
Message::CreateStringTable(create) => self.rewrite_table(&mut create.table),
|
||||
Message::UpdateStringTable(update) => {
|
||||
let name = string_tables
|
||||
.get(update.table_id as usize)
|
||||
.map(String::as_str);
|
||||
if name == Some("instancebaseline") {
|
||||
for (_, entry) in update.entries.iter_mut() {
|
||||
self.rewrite_entry(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn rewrite_table(&mut self, table: &mut StringTable) {
|
||||
if table.name.as_ref() != "instancebaseline" {
|
||||
return;
|
||||
}
|
||||
for (_, entry) in table.entries.iter_mut() {
|
||||
self.rewrite_entry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
fn rewrite_entry(&mut self, entry: &mut StringTableEntry) {
|
||||
let Some(class_id) = entry
|
||||
.text
|
||||
.as_ref()
|
||||
.and_then(|t| t.trim().parse::<u32>().ok())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !self.affected.contains(&class_id) {
|
||||
return;
|
||||
}
|
||||
let (Some(from), Some(to), Some(extra)) = (
|
||||
self.old.get(class_id as usize),
|
||||
self.new.get(class_id as usize),
|
||||
entry.extra_data.as_ref(),
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let baseline = StaticBaseline {
|
||||
class_id: (class_id as u16).into(),
|
||||
raw: extra.data.to_owned(),
|
||||
};
|
||||
// A blob we cannot read is better left alone than half written.
|
||||
if let Ok(raw) = baseline.reencode(from, to) {
|
||||
entry.extra_data = Some(ExtraData::new(raw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue