mirror of
https://codeberg.org/demostf/tf-demos-viewer.git
synced 2026-06-03 18:14:11 +02:00
projectiles
This commit is contained in:
parent
c94606b569
commit
0dd6692af7
4 changed files with 226 additions and 105 deletions
161
Cargo.lock
generated
161
Cargo.lock
generated
|
|
@ -19,27 +19,28 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitbuffer"
|
name = "bitbuffer"
|
||||||
version = "0.10.9"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "525586993a118417512a49bada2d143319310891f48b0b116c8f64fbb6486c87"
|
checksum = "367fd16a8072d50e8e205d88e684a7eec9ddfb756165a076ebe9ecc41fd82192"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitbuffer_derive",
|
"bitbuffer_derive",
|
||||||
"err-derive",
|
|
||||||
"memchr",
|
"memchr",
|
||||||
"num-traits 0.2.19",
|
"num-traits 0.2.19",
|
||||||
"serde",
|
"serde",
|
||||||
|
"thiserror 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitbuffer_derive"
|
name = "bitbuffer_derive"
|
||||||
version = "0.10.1"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "052a5a614540ae9bb7de25c2c86a94b6de7374cb7e3230f3128955bdaea62c3f"
|
checksum = "6616c9bbc0c159b0d2473c3c5b40ce36c83fd9e2ece2c96129cd135355c6cccb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"merge",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"structmeta",
|
||||||
"syn_util",
|
"syn 2.0.90",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -102,20 +103,6 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "err-derive"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c34a887c8df3ed90498c1c437ce21f211c8e27672921a8ffa293cb8d6d4caa9e"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro-error",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rustversion",
|
|
||||||
"syn 1.0.109",
|
|
||||||
"synstructure",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
|
@ -140,9 +127,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.10.5"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
@ -198,6 +185,28 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
|
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "merge"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9"
|
||||||
|
dependencies = [
|
||||||
|
"merge_derive",
|
||||||
|
"num-traits 0.2.19",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "merge_derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num"
|
name = "num"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
|
@ -284,23 +293,23 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum"
|
name = "num_enum"
|
||||||
version = "0.5.11"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9"
|
checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num_enum_derive",
|
"num_enum_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum_derive"
|
name = "num_enum_derive"
|
||||||
version = "0.5.11"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799"
|
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 2.0.90",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -311,26 +320,25 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parse-display"
|
name = "parse-display"
|
||||||
version = "0.8.2"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c6509d08722b53e8dafe97f2027b22ccbe3a5db83cb352931e9716b0aa44bc5c"
|
checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
|
||||||
"parse-display-derive",
|
"parse-display-derive",
|
||||||
"regex",
|
"regex",
|
||||||
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parse-display-derive"
|
name = "parse-display-derive"
|
||||||
version = "0.8.2"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68517892c8daf78da08c0db777fcc17e07f2f63ef70041718f8a7630ad84f341"
|
checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"regex",
|
"regex",
|
||||||
"regex-syntax 0.7.5",
|
"regex-syntax",
|
||||||
"structmeta",
|
"structmeta",
|
||||||
"syn 2.0.90",
|
"syn 2.0.90",
|
||||||
]
|
]
|
||||||
|
|
@ -396,7 +404,7 @@ dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata",
|
"regex-automata",
|
||||||
"regex-syntax 0.8.5",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -407,27 +415,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-syntax 0.8.5",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-syntax"
|
|
||||||
version = "0.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustversion"
|
|
||||||
version = "1.0.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
|
|
@ -495,14 +491,14 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"thiserror",
|
"thiserror 1.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structmeta"
|
name = "structmeta"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ad9e09554f0456d67a69c1584c9798ba733a5b50349a6c0d0948710523922d"
|
checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -512,9 +508,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structmeta-derive"
|
name = "structmeta-derive"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00"
|
checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -543,38 +539,12 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn_util"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6754c4559b79657554e9d8a0d56e65e490c76d382b9c23108364ec4125dea23c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "synstructure"
|
|
||||||
version = "0.12.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tf-demo-parser"
|
name = "tf-demo-parser"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c77f64e1dac5137a201d92afaf441fbe4018595bb8ec770fe6e02f6cad4410ef"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitbuffer",
|
"bitbuffer",
|
||||||
"enumflags2",
|
"enumflags2",
|
||||||
"err-derive",
|
|
||||||
"fnv",
|
"fnv",
|
||||||
"itertools",
|
"itertools",
|
||||||
"main_error",
|
"main_error",
|
||||||
|
|
@ -586,11 +556,12 @@ dependencies = [
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"snap",
|
"snap",
|
||||||
"steamid-ng",
|
"steamid-ng",
|
||||||
|
"thiserror 2.0.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tf-demos-viewer"
|
name = "tf-demos-viewer"
|
||||||
version = "0.1.2"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"tf-demo-parser",
|
"tf-demo-parser",
|
||||||
|
|
@ -605,7 +576,16 @@ version = "1.0.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl 1.0.69",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl 2.0.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -619,6 +599,17 @@ dependencies = [
|
||||||
"syn 2.0.90",
|
"syn 2.0.90",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.90",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.8"
|
version = "0.6.8"
|
||||||
|
|
@ -642,12 +633,6 @@ version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "tf-demos-viewer"
|
name = "tf-demos-viewer"
|
||||||
description = "JS bindings for demo parser"
|
description = "JS bindings for demo parser"
|
||||||
version = "0.1.2"
|
version = "0.2.0"
|
||||||
authors = ["Robin Appelman <robin@icewind.nl>"]
|
authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||||
categories = ["wasm"]
|
categories = ["wasm"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
@ -26,5 +26,5 @@ wasm-bindgen = "0.2.96"
|
||||||
wee_alloc = { version = "0.4.2", optional = true }
|
wee_alloc = { version = "0.4.2", optional = true }
|
||||||
web-sys = { version = "0.3.22", features = ["console"] }
|
web-sys = { version = "0.3.22", features = ["console"] }
|
||||||
js-sys = "0.3.22"
|
js-sys = "0.3.22"
|
||||||
tf-demo-parser = "0.5.1"
|
tf-demo-parser = { version = "0.5.1", path = "../tf-demo-parser" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ impl From<World> for WorldBoundaries {
|
||||||
pub struct FlatState {
|
pub struct FlatState {
|
||||||
pub player_count: usize,
|
pub player_count: usize,
|
||||||
pub building_count: usize,
|
pub building_count: usize,
|
||||||
|
pub projectile_count: usize,
|
||||||
pub boundaries: WorldBoundaries,
|
pub boundaries: WorldBoundaries,
|
||||||
pub interval_per_tick: f32,
|
pub interval_per_tick: f32,
|
||||||
pub tick_count: u32,
|
pub tick_count: u32,
|
||||||
|
|
@ -63,23 +64,28 @@ impl FlatState {
|
||||||
players,
|
players,
|
||||||
header,
|
header,
|
||||||
buildings,
|
buildings,
|
||||||
|
projectiles,
|
||||||
max_building_count,
|
max_building_count,
|
||||||
|
max_projectile_count,
|
||||||
tick,
|
tick,
|
||||||
..
|
..
|
||||||
} = parsed;
|
} = parsed;
|
||||||
|
|
||||||
let player_count = players.len();
|
let player_count = players.len();
|
||||||
let building_count = max_building_count;
|
let building_count = max_building_count;
|
||||||
|
let projectile_count = max_projectile_count;
|
||||||
|
|
||||||
let flat: Vec<_> = players
|
let flat: Vec<_> = players
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(buildings)
|
.chain(buildings)
|
||||||
|
.chain(projectiles)
|
||||||
.flat_map(Vec::into_iter)
|
.flat_map(Vec::into_iter)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
FlatState {
|
FlatState {
|
||||||
player_count,
|
player_count,
|
||||||
building_count,
|
building_count,
|
||||||
|
projectile_count,
|
||||||
tick_count: tick as u32,
|
tick_count: tick as u32,
|
||||||
boundaries: world.into(),
|
boundaries: world.into(),
|
||||||
interval_per_tick: header.duration / (header.ticks as f32),
|
interval_per_tick: header.duration / (header.ticks as f32),
|
||||||
|
|
|
||||||
160
src/state.rs
160
src/state.rs
|
|
@ -1,3 +1,4 @@
|
||||||
|
use tf_demo_parser::demo::data::game_state::{Projectile, ProjectileType};
|
||||||
use tf_demo_parser::demo::data::DemoTick;
|
use tf_demo_parser::demo::data::DemoTick;
|
||||||
use tf_demo_parser::demo::header::Header;
|
use tf_demo_parser::demo::header::Header;
|
||||||
use tf_demo_parser::demo::parser::analyser::UserInfo;
|
use tf_demo_parser::demo::parser::analyser::UserInfo;
|
||||||
|
|
@ -30,10 +31,12 @@ pub struct ParsedDemo {
|
||||||
pub tick: usize,
|
pub tick: usize,
|
||||||
pub players: Vec<Vec<u8>>,
|
pub players: Vec<Vec<u8>>,
|
||||||
pub buildings: Vec<Vec<u8>>,
|
pub buildings: Vec<Vec<u8>>,
|
||||||
|
pub projectiles: Vec<Vec<u8>>,
|
||||||
pub kills: Vec<Kill>,
|
pub kills: Vec<Kill>,
|
||||||
pub header: Header,
|
pub header: Header,
|
||||||
pub player_info: Vec<UserInfo>,
|
pub player_info: Vec<UserInfo>,
|
||||||
pub max_building_count: usize,
|
pub max_building_count: usize,
|
||||||
|
pub max_projectile_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParsedDemo {
|
impl ParsedDemo {
|
||||||
|
|
@ -43,9 +46,11 @@ impl ParsedDemo {
|
||||||
tick: 0,
|
tick: 0,
|
||||||
players: Vec::new(),
|
players: Vec::new(),
|
||||||
buildings: Vec::new(),
|
buildings: Vec::new(),
|
||||||
|
projectiles: Vec::new(),
|
||||||
kills: Vec::new(),
|
kills: Vec::new(),
|
||||||
player_info: Vec::new(),
|
player_info: Vec::new(),
|
||||||
max_building_count: 0,
|
max_building_count: 0,
|
||||||
|
max_projectile_count: 0,
|
||||||
header,
|
header,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -101,6 +106,24 @@ impl ParsedDemo {
|
||||||
|
|
||||||
parsed_building.extend_from_slice(&state.pack(world));
|
parsed_building.extend_from_slice(&state.pack(world));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.max_projectile_count =
|
||||||
|
self.max_projectile_count.max(game_state.projectiles.len());
|
||||||
|
for (index, projectile) in game_state.projectiles.values().enumerate() {
|
||||||
|
let state = ProjectileState::new(projectile);
|
||||||
|
|
||||||
|
if self.projectiles.get(index).is_none() {
|
||||||
|
let new_projectile = Vec::with_capacity(
|
||||||
|
self.header.ticks as usize * ProjectileState::PACKET_SIZE,
|
||||||
|
);
|
||||||
|
self.projectiles.push(new_projectile);
|
||||||
|
};
|
||||||
|
|
||||||
|
let parsed_projectiles = &mut self.projectiles[index];
|
||||||
|
parsed_projectiles.resize(self.tick * ProjectileState::PACKET_SIZE, 0);
|
||||||
|
|
||||||
|
parsed_projectiles.extend_from_slice(&state.pack(world));
|
||||||
|
}
|
||||||
self.tick += 1;
|
self.tick += 1;
|
||||||
}
|
}
|
||||||
self.last_tick = game_state.tick;
|
self.last_tick = game_state.tick;
|
||||||
|
|
@ -111,6 +134,9 @@ impl ParsedDemo {
|
||||||
for parsed_building in self.buildings.iter_mut() {
|
for parsed_building in self.buildings.iter_mut() {
|
||||||
parsed_building.resize(self.tick * BuildingState::PACKET_SIZE, 0);
|
parsed_building.resize(self.tick * BuildingState::PACKET_SIZE, 0);
|
||||||
}
|
}
|
||||||
|
for parsed_projectiles in self.projectiles.iter_mut() {
|
||||||
|
parsed_projectiles.resize(self.tick * ProjectileState::PACKET_SIZE, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
|
|
@ -308,6 +334,18 @@ pub struct BuildingState {
|
||||||
level: u8,
|
level: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for the purpose of viewing the demo in the browser we dont really need high accuracy for
|
||||||
|
// position or angle, so we save a bunch of space by truncating those down to half the number
|
||||||
|
// of bits
|
||||||
|
fn pack_f32(val: f32, min: f32, max: f32) -> u16 {
|
||||||
|
let ratio = (val - min) / (max - min);
|
||||||
|
(ratio * u16::MAX as f32) as u16
|
||||||
|
}
|
||||||
|
fn unpack_f32(val: u16, min: f32, max: f32) -> f32 {
|
||||||
|
let ratio = val as f32 / (u16::MAX as f32);
|
||||||
|
ratio * (max - min) + min
|
||||||
|
}
|
||||||
|
|
||||||
impl BuildingState {
|
impl BuildingState {
|
||||||
const PACKET_SIZE: usize = 7;
|
const PACKET_SIZE: usize = 7;
|
||||||
|
|
||||||
|
|
@ -326,15 +364,7 @@ impl BuildingState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pack(&self, world: &World) -> [u8; 7] {
|
pub fn pack(&self, world: &World) -> [u8; Self::PACKET_SIZE] {
|
||||||
// for the purpose of viewing the demo in the browser we dont really need high accuracy for
|
|
||||||
// position or angle, so we save a bunch of space by truncating those down to half the number
|
|
||||||
// of bits
|
|
||||||
fn pack_f32(val: f32, min: f32, max: f32) -> u16 {
|
|
||||||
let ratio = (val - min) / (max - min);
|
|
||||||
(ratio * u16::MAX as f32) as u16
|
|
||||||
}
|
|
||||||
|
|
||||||
let x = pack_f32(self.position.x, world.boundary_min.x, world.boundary_max.x).to_le_bytes();
|
let x = pack_f32(self.position.x, world.boundary_min.x, world.boundary_max.x).to_le_bytes();
|
||||||
let y = pack_f32(self.position.y, world.boundary_min.y, world.boundary_max.y).to_le_bytes();
|
let y = pack_f32(self.position.y, world.boundary_min.y, world.boundary_max.y).to_le_bytes();
|
||||||
// 2 bits level
|
// 2 bits level
|
||||||
|
|
@ -360,12 +390,7 @@ impl BuildingState {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn unpack(bytes: [u8; 7], world: &World) -> Self {
|
pub fn unpack(bytes: [u8; Self::PACKET_SIZE], world: &World) -> Self {
|
||||||
fn unpack_f32(val: u16, min: f32, max: f32) -> f32 {
|
|
||||||
let ratio = val as f32 / (u16::MAX as f32);
|
|
||||||
ratio * (max - min) + min
|
|
||||||
}
|
|
||||||
|
|
||||||
let x = unpack_f32(
|
let x = unpack_f32(
|
||||||
u16::from_le_bytes([bytes[0], bytes[1]]),
|
u16::from_le_bytes([bytes[0], bytes[1]]),
|
||||||
world.boundary_min.x,
|
world.boundary_min.x,
|
||||||
|
|
@ -440,3 +465,108 @@ fn test_building_packing() {
|
||||||
assert!(f32::abs(input.position.x - unpacked.position.x) < 0.5);
|
assert!(f32::abs(input.position.x - unpacked.position.x) < 0.5);
|
||||||
assert!(f32::abs(input.position.y - unpacked.position.y) < 0.5);
|
assert!(f32::abs(input.position.y - unpacked.position.y) < 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
|
pub struct ProjectileState {
|
||||||
|
position: VectorXY,
|
||||||
|
team: Team,
|
||||||
|
ty: ProjectileType,
|
||||||
|
angle: Angle,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProjectileState {
|
||||||
|
const PACKET_SIZE: usize = 6;
|
||||||
|
|
||||||
|
pub fn new(projectile: &Projectile) -> Self {
|
||||||
|
let position = projectile.position;
|
||||||
|
ProjectileState {
|
||||||
|
position: VectorXY {
|
||||||
|
x: position.x,
|
||||||
|
y: position.y,
|
||||||
|
},
|
||||||
|
angle: Angle::from(projectile.rotation.y),
|
||||||
|
team: projectile.team,
|
||||||
|
ty: projectile.ty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pack(&self, world: &World) -> [u8; Self::PACKET_SIZE] {
|
||||||
|
let x = pack_f32(self.position.x, world.boundary_min.x, world.boundary_max.x).to_le_bytes();
|
||||||
|
let y = pack_f32(self.position.y, world.boundary_min.y, world.boundary_max.y).to_le_bytes();
|
||||||
|
// 1 bit team
|
||||||
|
// 3 bits for type
|
||||||
|
// 4 bits for angle, 16 angles should be enough for projectiles
|
||||||
|
let team = if self.team == Team::Blue { 0 } else { 1 };
|
||||||
|
let team_type = ((self.ty as u8) << 5) + ((team as u8) << 4);
|
||||||
|
|
||||||
|
[x[0], x[1], y[0], y[1], team_type, self.angle.0]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn unpack(bytes: [u8; Self::PACKET_SIZE], world: &World) -> Self {
|
||||||
|
let x = unpack_f32(
|
||||||
|
u16::from_le_bytes([bytes[0], bytes[1]]),
|
||||||
|
world.boundary_min.x,
|
||||||
|
world.boundary_max.x,
|
||||||
|
);
|
||||||
|
let y = unpack_f32(
|
||||||
|
u16::from_le_bytes([bytes[2], bytes[3]]),
|
||||||
|
world.boundary_min.y,
|
||||||
|
world.boundary_max.y,
|
||||||
|
);
|
||||||
|
let team_type = bytes[4];
|
||||||
|
let packed_team = (team_type >> 4) & 1;
|
||||||
|
let team = if packed_team == 0 {
|
||||||
|
Team::Blue
|
||||||
|
} else {
|
||||||
|
Team::Red
|
||||||
|
};
|
||||||
|
let ty = ProjectileType::from((team_type >> 5) & 7);
|
||||||
|
let angle = Angle(bytes[5]);
|
||||||
|
|
||||||
|
ProjectileState {
|
||||||
|
position: VectorXY { x, y },
|
||||||
|
angle,
|
||||||
|
team,
|
||||||
|
ty,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_projectile_packing() {
|
||||||
|
use tf_demo_parser::demo::vector::Vector;
|
||||||
|
|
||||||
|
let world = World {
|
||||||
|
boundary_max: Vector {
|
||||||
|
x: 10000.0,
|
||||||
|
y: 10000.0,
|
||||||
|
z: 100.0,
|
||||||
|
},
|
||||||
|
boundary_min: Vector {
|
||||||
|
x: -10000.0,
|
||||||
|
y: -10000.0,
|
||||||
|
z: -100.0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let input = ProjectileState {
|
||||||
|
position: VectorXY {
|
||||||
|
x: 100.0,
|
||||||
|
y: -5000.0,
|
||||||
|
},
|
||||||
|
angle: Angle::from(123.0),
|
||||||
|
team: Team::Blue,
|
||||||
|
ty: ProjectileType::Flare,
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes = input.pack(&world);
|
||||||
|
|
||||||
|
let unpacked = ProjectileState::unpack(bytes, &world);
|
||||||
|
assert_eq!(input.ty, unpacked.ty);
|
||||||
|
assert_eq!(input.team, unpacked.team);
|
||||||
|
assert_eq!(input.angle, unpacked.angle);
|
||||||
|
|
||||||
|
assert!(f32::abs(input.position.x - unpacked.position.x) < 0.5);
|
||||||
|
assert!(f32::abs(input.position.y - unpacked.position.y) < 0.5);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue