boon-deadlock
A fast Deadlock demo file (.dem) parser for Rust.
Part of the Boon project.
Features
- Memory-mapped, zero-copy parsing for maximum throughput
- Match metadata (map, players, duration, build number)
- Full entity state at any tick via snapshot seeking
- Game event extraction with protobuf decoding
- Filtered tick streaming for efficient per-entity-class analysis
- Ability and modifier name lookups
Installation
Add to your Cargo.toml:
[]
= "0.1"
Requires Rust 1.88+ (edition 2024).
Quick Start
use Path;
use Parser;
let parser = from_file.unwrap;
parser.verify.unwrap;
// File header
let header = parser.file_header.unwrap;
println!;
println!;
// File info (playback time, players)
let info = parser.file_info.unwrap;
println!;
API Overview
Parser
The main entry point. Owns the demo file data (memory-mapped or in-memory).
| Method | Description |
|---|---|
Parser::from_file(path) |
Open and memory-map a .dem file |
Parser::from_bytes(bytes) |
Parse from an in-memory buffer |
verify() |
Check magic bytes |
file_header() |
Decode CDemoFileHeader (map, server, build) |
file_info() |
Decode CDemoFileInfo (duration, players) |
messages() |
List all command headers in the file |
events(max_tick) |
Extract game events (legacy + Citadel user messages) |
parse_to_tick(tick) |
Parse to a specific tick, returning full entity state |
run_to_end(callback) |
Stream every tick with a callback |
run_to_end_filtered(filter, callback) |
Stream with an entity class filter (much faster) |
Context
Returned by parse_init, parse_to_tick, and passed to tick callbacks. Contains:
entities— all active entities (EntityContainer)serializers— field definitions per classclass_info— class ID to name mappingsstring_tables— key-value tables (models, baselines, etc.)tick— current ticktick_interval— seconds per tick
Entity
A single networked entity with class name and decoded field values.
// Look up fields by dotted path
let health = entity.get_by_name;
let x = entity.get_by_name;
Helper Functions
ability_name(id)— resolve an ability hash to its namemodifier_name(id)— resolve a modifier hash to its namedecode_event_payload(msg_type, data)— decode a game event's protobuf payload
Examples
Runnable examples are in examples/. Each accepts a demo file path as a CLI argument.
# Match metadata
# Game events (optionally filtered by name)
# Entity snapshot at a specific tick
# Stream all ticks with a class filter
| Example | What it shows |
|---|---|
info |
file_header(), file_info(), match metadata and player list |
events |
events(), event filtering, decode_event_payload() |
entities |
parse_to_tick(), entity iteration, get_by_name(), ability_name() |
player_ticks |
run_to_end_filtered(), resolve_field_key(), per-tick streaming |
Performance
For best throughput when you only need specific entity types, use run_to_end_filtered with a class filter. This skips field decoding for entities outside the filter set.
use HashSet;
let filter: = .into_iter.collect;
parser.run_to_end_filtered.unwrap;
License
MIT — see LICENSE for details.