- Rust 99.8%
- Nix 0.2%
DemoHandler::default() starts out at protocol 24 and relies on handle_header to replace that with whatever the demo actually is. Parsing through DemoParser does this for you, but reencode drives the handler itself and never did, so every demo got read as protocol 24. Older protocols put a few fields at different widths, so the message stream desyncs partway in. RawPacketStream reports that as a truncated demo rather than an error, which is why nothing complains about it: reencode_demo on test_data/protocol23.dem writes 1076 bytes, prints a truncation warning and still exits 0. The reencode test missed this because protocol23.dem was never in its list, and because nothing checked the demo had been read to the end. Add a test for that and the same assert to the existing round trip. Output for protocol 24 demos is unchanged, byte for byte. |
||
|---|---|---|
| .forgejo/workflows | ||
| benches | ||
| examples | ||
| fuzz | ||
| nix | ||
| smoker | ||
| src | ||
| test_data | ||
| tests | ||
| .envrc | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| flake.lock | ||
| flake.nix | ||
| pgo_build.sh | ||
| README.md | ||
| rustig.toml | ||
| schema.json | ||
TF Demo Parser
Parsing of tf2 demo files
Building
This project is build using rust and requires cargo and friends, see
the rust website for how to get started.
Once rust is setup building is as simple as
cargo build --release
which will place the binary at target/release/parse_demo
Usage
Basic usage is as simple as parse_demo demofile.dem which will output a
"summary" of the demo file in JSON format.
Passing the detailed_summary argument to the end of parse_demo will output a
table with scoreboard information for all players who were ever on the server
while the demo was being recorded. The player who created the demo will be
highlighted in the output.
Advanced usage
Loop through every packet
use bitbuffer::BitRead;
use main_error::MainError;
use std::fs;
use tf_demo_parser::demo::header::Header;
use tf_demo_parser::demo::parser::{DemoHandler, RawPacketStream};
use tf_demo_parser::Demo;
fn main() -> Result<(), MainError> {
let file = fs::read("demofile.dem")?;
let demo = Demo::new(&file);
let mut handler = DemoHandler::default();
let mut stream = demo.get_stream();
let header = Header::read(&mut stream)?;
handler.handle_header(&header);
let mut packets = RawPacketStream::new(stream);
while let Some(packet) = packets.next(&handler.state_handler)? {
handler.handle_packet(packet).unwrap();
}
assert_eq!(false, packets.incomplete);
Ok(())
}
Handle demo data with a custom analyser
Sometimes it's easier to create a custom Analyser to handle the demo data as
it comes along.
See src/demo/parser/analyser.rs for an example.
Once you have a custom analyser you can use it with:
DemoParser::new_all_with_analyser(demo.get_stream(), CustomAnalyser::new());
let (header, state) = parser.parse()?;