53 个版本
0.9.14 | 2024 年 7 月 12 日 |
---|---|
0.9.12 | 2024 年 4 月 22 日 |
0.9.11 | 2023 年 11 月 4 日 |
0.9.10 | 2023 年 6 月 16 日 |
0.2.2 | 2018 年 3 月 18 日 |
#157 in 解析器实现
114 每月下载量
在 subtr-actor 中使用
215KB
4.5K SLoC
Boxcars
Boxcars 是一个用 Rust 编写的 Rocket League 回放解析器库。
功能
- ✔ 安全:稳定的 Rust,无 unsafe 代码
- ✔ 快速:每个 CPU 核心每秒解析超过一百个回放
- ✔ 模糊测试:广泛模糊测试,以防止潜在恶意输入
- ✔ 人体工程学:通过 serde 提供序列化支持
查看 Boxcars 的使用情况
- 在 rrrocket CLI 应用程序 中将 Rocket League 回放转换为 JSON
- 编译为 WebAssembly 并嵌入网页
- 支撑着流行的 calculated.gg 网站 的 Python 分析器
快速开始
以下是一个示例,用于将回放结构输出到 JSON
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(())
}
上述示例将解析回放文件的标题和网络数据,如果标题或网络数据有问题,则返回错误。由于网络数据会随着每个 Rocket League 补丁而经常变化,因此默认行为是忽略网络数据的任何错误,同时仍然能够返回标题信息。
变化
如果您只对标题(其中存储像进球和得分这样的 tidbits)感兴趣,则可以通过让 boxcars 仅解析标题来实现 1000 倍的速度提升。
- 通过跳过网络数据,可以在不到一秒的时间内解析和汇总数千个回放,为用户提供即时响应。然后,在有时间的情况下,完整解析回放数据可以提供额外的见解。
- 通过忽略网络数据错误,boxcars 仍然可以根据标题提供有关新补丁回放的详细信息。
Boxcars 还会在出现错误时检查回放损坏,但这可以配置为始终检查损坏或从不检查。
基准测试
运行boxcar基准测试
cargo bench
# Or if you want to see if compiling for the
# given cpu eeks out tangible improvements:
# RUSTFLAGS="-C target-cpu=native" cargo bench
由于Boxcars允许您选择要解析的内容,以下是一个表格,列出了以下选项和估计的耗时。
标题 | 损坏检查 | 正文 | 输出JSON | 耗时 | 吞吐量 |
---|---|---|---|---|---|
✔ | 68.0 µs | ||||
✔ | ✔ | ✔ | 6.6 ms | 223 MiB/s | |
✔ | ✔ | 6.3 ms | 232 MiB/s | ||
✔ | ✔ | ✔ | ✔ | 35 ms | 531 MiB/s ^1 |
^1:JSON序列化吞吐量包括生成的JSON量
特别感谢
特别感谢所有在Rocket League社区中找出回放格式及其所有复杂性的成员。如果没有他们,Boxcars将不会存在。我严重依赖于在rattletrap、RocketLeagueReplayParser和Bakkes的回放解析器中的实现。其中任何一个都应该是您首选的Rocket League回放工具,除非您需要速度,因为那些实现比boxcars更成熟。
rattletrap和boxcars的区别
- Rattletrap是一个二进制文件,它处理Rocket League回放并输出JSON,而boxcars是一个更底层的解析库。Boxcars是Rrrocket的底层,它是一个cli二进制文件,输出的JSON类似于Rattletrap。
- Rattletrap可以往返回放(将它们转换为JSON然后无损地写回回放)。Boxcars专注于解析回放。
- 部分原因是允许往返解析,rattletrap的JSON输出比boxcars(rrrocket)大2倍,即使考虑到输出最小化。
以下是一些模型中的不同点
rattletrap
"properties": {
"value": {
"BuildID": {
"kind": "IntProperty",
"size": "4",
"value": {
"int": 1401925076
}
},
}
}
boxcars
"properties": {
"BuildID": 1401925076
}
rattletrap
"actor_id": {
"limit": 2047,
"value": 1
},
boxcars
"actor_id": 1
rattletrap
"value": {
"spawned": {
"class_name": "TAGame.GameEvent_Soccar_TA",
"flag": true,
"initialization": {
"location": {
"bias": 2,
"size": {
"limit": 21,
"value": 0
},
"x": 0,
"y": 0,
"z": 0
}
},
"name": "GRI_TA_1",
"name_index": 0,
"object_id": 85,
"object_name": "Archetypes.GameEvent.GameEvent_Soccar"
}
}
boxcars
"actor_id": 1,
"name_id": 1,
"object_id": 85,
"initial_trajectory": {
"location": {
"x": 0,
"y": 0,
"z": 0
},
"rotation": null
}
虽然rattletrap提供了便利的转换,但boxcars为了更原始的回放视图而省略了它们
- 推导
object_name
:replay.objects[x.object_id]
- 推导
name
:replay.names[x.name_id]
属性更新
rattletrap
{
"actor_id": {
"limit": 2047,
"value": 7
},
"value": {
"updated": [
{
"id": {
"limit": 98,
"value": 34
},
"name": "Engine.PlayerReplicationInfo:PlayerName",
"value": {
"string": "Nadir"
}
}
]
}
}
boxcars
{
"actor_id": 7,
"stream_id": 34,
"object_id": 161,
"attribute": {
"String": "Nadir"
}
}
要推导rattletrap的name
属性,使用replay.objects[attribute.object_id]
模糊测试
Boxcars包含一个模糊测试套件。如果您想运行它,请首先安装cargo-fuzz
cargo install cargo-fuzz
有几个模糊测试场景(cargo fuzz list
),最好运行的是no-crc-body
,因为回放的所有方面都进行了模糊测试,没有crc检查。
cargo +nightly fuzz run no-crc-body
依赖关系
~4.5MB
~149K SLoC