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 解析器实现

Download history 82/week @ 2024-04-26 38/week @ 2024-05-03 143/week @ 2024-05-10 71/week @ 2024-05-17 38/week @ 2024-05-24 39/week @ 2024-05-31 45/week @ 2024-06-07 39/week @ 2024-06-14 37/week @ 2024-06-21 30/week @ 2024-06-28 37/week @ 2024-07-05 134/week @ 2024-07-12 32/week @ 2024-07-19 33/week @ 2024-07-26 28/week @ 2024-08-02 15/week @ 2024-08-09

114 每月下载量
subtr-actor 中使用

MIT 许可证

215KB
4.5K SLoC

Boxcars

ci Version

Boxcars 是一个用 Rust 编写的 Rocket League 回放解析器库。

功能

  • ✔ 安全:稳定的 Rust,无 unsafe 代码
  • ✔ 快速:每个 CPU 核心每秒解析超过一百个回放
  • ✔ 模糊测试:广泛模糊测试,以防止潜在恶意输入
  • ✔ 人体工程学:通过 serde 提供序列化支持

查看 Boxcars 的使用情况

快速开始

以下是一个示例,用于将回放结构输出到 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将不会存在。我严重依赖于在rattletrapRocketLeagueReplayParserBakkes的回放解析器中的实现。其中任何一个都应该是您首选的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_namereplay.objects[x.object_id]
  • 推导namereplay.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