Boxcars
repository·master·Indexed 40 days ago
https://github.com/nickbabcock/boxcarsA high-performance, safe, and ergonomic Rust library for parsing Rocket League replay files. It serves as a low-level parsing engine suitable for CLI tools, backend analyzers, or web applications via WebAssembly. Boxcars allows for optimized parsing by skipping network data to extract header metadata (such as goals and scores) up to 1000x faster. Version 0.11.5.
What's inside Boxcars
- Boxcars can check for replay corruption during the parsing process. This behavior can be configured to always check for corruption, never check, or use the default behavior.
Understand the Boxcars data model vs rattletrap
masterBoxcars provides a lower-level, more raw view of replay data compared to
rattletrap. Whilerattletrapperforms convenience conversions and produces larger JSON output, Boxcars omits these to remain lightweight and focused on parsing.To derive information that
rattletrapprovides automatically, you can use the following patterns in Boxcars:- To derive
object_name: Accessreplay.objects[x.object_id] - To derive
name: Accessreplay.names[x.name_id] - To derive attribute
name: Accessreplay.objects[attribute.object_id]
- To derive
Optimize parsing by skipping network data
masterIf you only need metadata like goals or scores, you can achieve a significant speedup (up to 1000x) by directing Boxcars to only parse the replay header and skipping the network data (the body). This is useful for aggregating thousands of replays quickly to provide immediate responses, followed by a full parse later for deeper insights.Run the Boxcars fuzzing suite
masterBoxcars is extensively fuzzed against malicious input. To run the fuzzing suite, you must first install
cargo-fuzz. The recommended scenario to run isno-crc-body, which fuzzed all aspects of the replay without a CRC check.# Install cargo-fuzz cargo install cargo-fuzz # Run the recommended fuzzing scenario cargo +nightly fuzz run no-crc-bodyRun Boxcars benchmarks
masterYou can run the built-in benchmarks using
cargo bench. To see if compiling for your specific CPU architecture provides performance improvements, use thetarget-cpu=nativeflag.cargo bench # For CPU-specific optimizations: RUSTFLAGS="-C target-cpu=native" cargo benchQuick Start: Parse a Rocket League replay to JSON
masterTo parse a Rocket League replay file and output its structure as JSON, use the
ParserBuilderto configure the parsing requirements. By default, Boxcars ignores errors in the network data (the body) to ensure you can still access header information even after a game patch. To require both header and network data to be valid, use the.must_parse_network_data()method.use boxcars::{ParseError, Replay}; use std::error; use std::fs; use std::io::{self, Read}; fn parse_rl(data: &[u8]) -> Result<Replay, ParseError> { boxcars::ParserBuilder::new(data) .must_parse_network_data() .parse() } fn run(filename: &str) -> Result<(), Box<dyn error::Error>> { let filename = "assets/replays/good/rumble.replay"; let buffer = fs::read(filename)?; let replay = parse_rl(&buffer)?; serde_json::to_writer(&mut io::stdout(), &replay)?; Ok(()) }Identify TickMarks in replays
masterA
TickMarkrepresents a significant game event (like a goal) that is placed in the replay slightly before the event actually occurs to allow for ramp-up time.Example: A tickmark at frame 396 might represent a goal occurring at frame 441.
pub struct TickMark { pub description: String, pub frame: i32, }Identify Actors, Objects, and Streams
masterThe network data uses several distinct ID types to track entities:
ActorId: Identifies a specific entity (e.g., a car or ball). Note that IDs can be reused if an actor is destroyed and a new one spawns.ObjectId: A unique identifier for an object in the replay hierarchy.StreamId: A compressed version of anObjectIdused within the attribute stream to save space.
Understand the Frame data structure
masterA
Framerepresents a single point in time in the replay. It contains:time: The timestamp in seconds.delta: The time elapsed since the previous frame.new_actors: A list ofNewActorobjects that appeared this frame.deleted_actors: A list ofActorIds that were destroyed.updated_actors: A list ofUpdatedAttributeobjects representing property changes (like position or rotation) for existing actors.
Configure corruption checking in ParserBuilder
masterBoxcars can be configured to handle replay corruption checks differently. By default, it checks for corruption when an error occurs, but you can configure the parser to either always check for corruption or never check for it.Understand the Replay data model
masterA Rocket League replay is decoded into a
Replaystruct. This struct contains the header information, network frames, keyframes, and various metadata like tick marks and debug info.Note on Serialization: The
Replaymodel is designed for JSON serialization. However, deserialization from JSON is not implemented because the JSON output is lossy (e.g., distinguishing betweenNameandStrtypes or different numeric types). For lossless persistence of already-decoded network data, use the types incrate::networkinstead.// The core structure representing a decoded replay pub struct Replay { pub header_size: i32, pub header_crc: u32, pub major_version: i32, pub minor_version: i32, pub net_version: Option<i32>, pub game_type: String, pub properties: Vec<(String, HeaderProp)>, pub content_size: i32, pub content_crc: u32, pub network_frames: Option<NetworkFrames>, pub levels: Vec<String>, pub keyframes: Vec<KeyFrame>, pub debug_info: Vec<DebugInfo>, pub tick_marks: Vec<TickMark>, pub packages: Vec<String>, pub objects: Vec<String>, pub names: Vec<String>, pub class_indices: Vec<ClassIndex>, pub net_cache: Vec<ClassNetCache>, }Optimize parsing speed by skipping network data
masterIf you only need metadata stored in the replay header (such as goals or scores), you can achieve up to a 1000x speedup by skipping the network data parsing. This is ideal for high-performance aggregation tasks where you need to process thousands of replays per second to provide immediate responses.