#osu #beatmap #decode #parse #parser

rosu-map

用于解密和编码 .osu 文件的库

3 个版本

新增 0.1.2 2024 年 8 月 17 日
0.1.1 2024 年 3 月 11 日
0.1.0 2024 年 2 月 27 日

393解析器实现

Download history 175/week @ 2024-04-29 4/week @ 2024-05-13 21/week @ 2024-05-20 61/week @ 2024-05-27 22/week @ 2024-06-03 20/week @ 2024-06-10 31/week @ 2024-06-17 167/week @ 2024-06-24 46/week @ 2024-07-01 182/week @ 2024-07-08 46/week @ 2024-07-15 103/week @ 2024-07-22 54/week @ 2024-07-29 67/week @ 2024-08-05 193/week @ 2024-08-12

425 每月下载次数
用于 2 crates

MIT 许可证

240KB
5.5K SLoC

crates.io docs

rosu-map

osu! 解密和编码 .osu 文件的库

是什么

在核心上,rosu-map 提供了 DecodeBeatmap 特性。该特性负责解码文件本身、错误处理和部分解析。实现者需要做的只是保持解析数据的当前状态,并根据部分和文本行修改该状态。

rosu-map 还提供了多个已实现此特性的类型,即每个部分的一个(见 EditorTimingPoints、...),以及一个用于(几乎)全部内容的,Beatmap

为什么

通过特性公开功能,可以在决定解析哪些内容时提供灵活性,从而在不需要所有数据时提高效率。

如果只需要难度属性,通过 Difficulty 结构进行解析将丢弃 [Difficulty] 部分之外的所有内容。同样,如果只对艺术家、标题和版本感兴趣,可以使用 Metadata 结构。

此外,值得注意的是,Beatmap 解析(几乎)一切,这可能对许多用例来说过于冗余。解决方案是定义一个新的自定义类型,复制粘贴 BeatmapDecodeBeatmap 实现并将其不需要的部分删除。

如何

使用类型的 DecodeBeatmap 实现的最简单方法是通过使用 rosu-map 的函数 from_bytesfrom_pathfrom_str

use rosu_map::section::difficulty::Difficulty;

let content = "[Difficulty]
ApproachRate: 9.2
SliderMultiplier: 1.9

[Metadata]
Creator: peppy";

let difficulty = rosu_map::from_str::<Difficulty>(content).unwrap();
assert_eq!(difficulty.approach_rate, 9.2);

let path = "./resources/Soleily - Renatus (Gamu) [Insane].osu";
let map = rosu_map::from_path::<Beatmap>(path).unwrap();
assert_eq!(map.audio_file, "03. Renatus - Soleily 192kbps.mp3");

有关在新的类型上实现 DecodeBeatmap 特性的信息,请查看特性的文档。例如,查看 GeneralHitObjects 如何实现该特性。

编码

Beatmap 结构体通过其 encode* 方法提供了一种将自身转换为 .osu 文件内容的方法。

let path = "./resources/Within Temptation - The Unforgiving (Armin) [Marathon].osu";
let mut map: Beatmap = rosu_map::from_path(path).unwrap();

map.approach_rate = 10.0;

map.encode_to_path("./new_file.osu").unwrap();

let metadata = rosu_map::section::metadata::Metadata {
    title: "song title".to_string(),
    artist: "artist name".to_string(),
    ..Default::default()
};

let content = Beatmap::from(metadata).encode_to_string().unwrap();
assert!(content.contains("Title: song title"));

特性

标志 描述 依赖
默认 无特性
跟踪 在解码过程中遇到的任何错误将通过 tracing::error 记录。如果此特性未启用,则错误将被忽略。 跟踪

其他

内部实现

rosu-map 的一部分是 osu!lazer 的 beatmap {de/en}coding 的移植。它的功能不仅反映了 osu!,而且还翻译了许多测试用例,即使在边缘情况下也提供了可靠的正确性。

异步

经过一些测试和基准测试,结果表明异步 IO 并没有在并发环境中提供任何改进或性能提升。事实上,常规顺序 IO 持续优于其异步对应物。因此,rosu-map 不提供异步接口。

故事板

rosu-map 不提供解析故事板的类型,但 crate rosu-storyboard 提供。

依赖