π Getting StartedΒΆ
RequirementsΒΆ
Python 3.11+
Rust toolchain (for building from source)
InstallationΒΆ
We recommend using uv:
uv add boon-deadlock
If you donβt use uv, pip works too:
pip install boon-deadlock
Boon is a Rust library with Python bindings built using PyO3 and maturin.
Quick StartΒΆ
The Demo class is the entrypoint for all parsing. Pass it a path to a .dem file, then access the datasets you need as properties. Each property is parsed on first access, so you only pay for what you use. If you need several datasets at once, load() parses them in a single pass. Call Demo.available_datasets() to see all dataset names.
Most properties return Polars DataFrames, so you get the full Polars API for filtering, grouping, and analysis out of the box.
from boon import Demo
demo = Demo("match.dem")
# Metadata properties (not DataFrames)
print(demo.map_name) # "dl_midtown"
print(demo.total_ticks) # 54000
print(demo.total_clock_time) # "30:00"
print(demo.match_id) # 28309863
# Dataset properties return Polars DataFrames
players = demo.players
print(players)
# shape: (12, 5)
# βββββββββββββββ¬ββββββββββββββββ¬ββββββββββ¬βββββββββββ¬βββββββββββββ
# β player_name β steam_id β hero_id β team_num β start_lane β
# β --- β --- β --- β --- β --- β
# β str β u64 β i64 β i64 β i64 β
# βββββββββββββββͺββββββββββββββββͺββββββββββͺβββββββββββͺβββββββββββββ‘
# β Player1 β 7656119... β 13 β 2 β 1 β
# β ... β ... β ... β ... β ... β
# βββββββββββββββ΄ββββββββββββββββ΄ββββββββββ΄βββββββββββ΄βββββββββββββ
# Batch-load multiple datasets in a single parse pass
demo.load("kills", "damage", "item_purchases", "ability_upgrades")
# Cached β no additional parsing needed
print(f"Kills: {len(demo.kills)}")
print(f"Damage events: {len(demo.damage)}")
Working with Tick DataΒΆ
# World state per tick
world = demo.world_ticks
print(world.columns) # ['tick', 'is_paused', 'next_midboss']
# Player state per tick (one row per player per tick)
player_ticks = demo.player_ticks
print(player_ticks.shape) # (648000, 50) β 12 players Γ 54000 ticks
print(player_ticks.columns) # ['tick', 'hero_id', 'x', 'y', 'z', ...]
Events and EconomyΒΆ
# Kill events
kills = demo.kills
# Damage events
damage = demo.damage
# Item shop transactions
item_purchases = demo.item_purchases
# Ability point spending
ability_upgrades = demo.ability_upgrades
# Chat messages
chat = demo.chat
Objectives and Map StateΒΆ
# Objective health state changes (walkers, barracks, shrines, patron, mid boss)
objectives = demo.objectives
# Mid boss lifecycle (spawn, kill, rejuv buffs)
mid_boss = demo.mid_boss
# Lane troopers and guardians (opt-in, large dataset)
troopers = demo.troopers
# trooper_type is "trooper" (lane creeps) or "trooper_boss" (lane guardian)
Filtering with PolarsΒΆ
Boon returns Polars DataFrames, so you can use the full Polars API for filtering, grouping, and analysis:
import polars as pl
# Get a single player's data
haze = player_ticks.filter(pl.col("hero_id") == 13)
# Health over time
haze.select("tick", "health", "max_health")
# Net worth at end of game
final_tick = player_ticks.filter(pl.col("tick") == player_ticks["tick"].max())
final_tick.select("hero_id", "gold_net_worth", "ap_net_worth", "kills", "deaths", "assists")
Error HandlingΒΆ
Boon raises its own exceptions for invalid or malformed demo files. See the Exceptions section of the API reference for the full list.