Beatsaber Rust Utilities: A Beatsaber V3 parsing library.
beatsaber
beatmap
1//! Defines the structure of a map's `Info.dat` file.
2
3pub mod color_scheme;
4
5#[doc(hidden)]
6pub use color_scheme::*;
7use loose_enum::loose_enum;
8
9use serde::{Deserialize, Serialize};
10
11/// A map's `Info.dat` file.
12#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
13#[cfg_attr(
14 feature = "bevy_reflect",
15 derive(bevy_reflect::Reflect),
16 reflect(Debug, Clone, PartialEq)
17)]
18pub struct Beatmap {
19 /// The info file version, in the form of `2.1.0`.
20 #[serde(rename = "_version")]
21 pub version: String,
22 #[serde(rename = "_songName")]
23 pub name: String,
24 #[serde(rename = "_songSubName")]
25 pub sub_name: String,
26 #[serde(rename = "_songAuthorName")]
27 pub artist: String,
28 #[serde(rename = "_levelAuthorName")]
29 pub mapper: String,
30 #[serde(rename = "_beatsPerMinute")]
31 pub bpm: f32,
32 #[serde(rename = "_songTimeOffset")]
33 pub time_offset: f32,
34 #[serde(rename = "_shuffle")]
35 pub shuffle: f32,
36 #[serde(rename = "_shufflePeriod")]
37 pub shuffle_period: f32,
38 #[serde(rename = "_previewStartTime")]
39 pub preview_start_time: f32,
40 #[serde(rename = "_previewDuration")]
41 pub preview_duration: f32,
42 /// The path to the audio file, relative to the map's folder.
43 #[serde(rename = "_songFilename")]
44 pub audio_file: String,
45 /// The path to the cover image file, relative to the map's folder.
46 #[serde(rename = "_coverImageFilename")]
47 pub cover_image_file: String,
48 /// The environment that will be used for 90 and 360 degree difficulties.
49 ///
50 /// Starting in info file V2.1, individual difficulties can override this using [environment_index](DifficultyInfo::environment_index).
51 #[serde(rename = "_environmentName")]
52 pub environment: Environment,
53 /// The environment that will be used for 90 and 360 degree difficulties.
54 #[serde(rename = "_allDirectionsEnvironmentName")]
55 pub all_directions_environment: AllDirectionEnvironment,
56 /// > Only present in info file V2.1 or higher.
57 #[serde(rename = "_environmentNames")]
58 pub environments: Option<Vec<Environment>>,
59 /// > Only present in info file V2.1 or higher.
60 #[serde(rename = "_colorSchemes")]
61 pub color_schemes: Option<Vec<ColorSchemeOverride>>,
62 #[serde(rename = "_difficultyBeatmapSets")]
63 pub difficulty_sets: Vec<DifficultySet>,
64}
65
66loose_enum! {
67 /// The world that surrounds the player and defines which lights are available.
68 ///
69 /// For 90/360 degree mode, see [`AllDirectionEnvironment`].
70 #[derive(Default, Debug, Clone, Eq, PartialEq, Hash)]
71 #[cfg_attr(
72 feature = "bevy_reflect",
73 derive(bevy_reflect::Reflect),
74 reflect(Debug, Clone, PartialEq)
75 )]
76 pub enum Environment: String {
77 #[default]
78 #[doc(alias = "Default")]
79 TheFirst = "DefaultEnvironment",
80
81 Triangle = "TriangleEnvironment",
82 Nice = "NiceEnvironment",
83 BigMirror = "BigMirrorEnvironment",
84 KDA = "KDAEnvironment",
85 Monstercat = "MonstercatEnvironment",
86 CrabRave = "CrabRaveEnvironment",
87 ImagineDragons = "DragonsEnvironment",
88 Origins = "OriginsEnvironment",
89 PanicAtTheDisco = "PanicEnvironment",
90 RocketLeague = "RocketEnvironment",
91 GreenDay = "GreenDayEnvironment",
92 GreenDayGrenade = "GreenDayGrenadeEnvironment",
93 Timbaland = "TimbalandEnvironment",
94 FitBeat = "FitBeatEnvironment",
95 LinkinPark = "LinkinParkEnvironment",
96 BTS = "BTSEnvironment",
97 Kaleidoscope = "KaleidoscopeEnvironment",
98 Interscope = "InterscopeEnvironment",
99 Skrillex = "SkrillexEnvironment",
100 BillieEilish = "BillieEnvironment",
101 #[doc(alias = "Halloween")]
102 Spooky = "HalloweenEnvironment",
103 LadyGaga = "GagaEnvironment",
104 // V3:
105 Weave = "WeaveEnvironment",
106 #[doc(alias = "Pyro")]
107 FallOutBoy = "PyroEnvironment",
108 EDM = "EDMEnvironment",
109 TheSecond = "TheSecondEnvironment",
110 Lizzo = "LizzoEnvironment",
111 TheWeeknd = "TheWeekndEnvironment",
112 RockMixtape = "RockMixtapeEnvironment",
113 Dragons2 = "Dragons2Environment",
114 PanicAtTheDisco2 = "Panic2Environment",
115 Queen = "QueenEnvironment",
116 LinkinPark2 = "LinkinPark2Environment",
117 TheRollingStones = "TheRollingStonesEnvironment",
118 Lattice = "LatticeEnvironment",
119 DaftPunk = "DaftPunkEnvironment",
120 HipHop = "HipHopEnvironment",
121 Collider = "ColliderEnvironment",
122 BritneySpears = "BritneyEnvironment",
123 Monstercat2 = "Monstercat2Environment",
124 Metallica = "MetallicaEnvironment",
125 }
126}
127
128loose_enum! {
129 /// The world that surrounds the player while playing 90/360 degree mode.
130 ///
131 /// For standard mode, see [`Environment`].
132 #[derive(Default, Debug, Clone, Eq, PartialEq, Hash)]
133 #[cfg_attr(
134 feature = "bevy_reflect",
135 derive(bevy_reflect::Reflect),
136 reflect(Debug, Clone, PartialEq)
137 )]
138 pub enum AllDirectionEnvironment: String {
139 #[default]
140 GlassDesert = "GlassDesertEnvironment",
141 }
142}
143
144/// Describes a group of difficulties, all with the same [characteristic/mode](Characteristic).
145#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
146#[cfg_attr(
147 feature = "bevy_reflect",
148 derive(bevy_reflect::Reflect),
149 reflect(Debug, Clone, PartialEq)
150)]
151pub struct DifficultySet {
152 #[serde(rename = "_beatmapCharacteristicName")]
153 pub characteristic: Characteristic,
154 #[serde(rename = "_difficultyBeatmaps")]
155 pub difficulties: Vec<DifficultyInfo>,
156}
157
158loose_enum! {
159 /// Describes the type/game mode of a difficulty.
160 ///
161 /// Note that [`Lawless`](Self::Lawless) and [`Lightshow`](Self::Lightshow) are modded characteristics,
162 /// and may cause problems in un-modded versions of the game.
163 #[derive(Default, Debug, Clone, Eq, PartialEq, Hash)]
164 #[cfg_attr(
165 feature = "bevy_reflect",
166 derive(bevy_reflect::Reflect),
167 reflect(Debug, Clone, PartialEq)
168 )]
169 pub enum Characteristic: String {
170 #[default]
171 Standard = "Standard",
172 NoArrows = "NoArrows",
173 OneSaber = "OneSaber",
174 Rotate360 = "360Degree",
175 Rotate90 = "90Degree",
176 Legacy = "Legacy",
177 /// > Modded characteristic. May cause problems in un-modded versions of the game.
178 Lawless = "Lawless",
179 /// > Modded characteristic. May cause problems in un-modded versions of the game.
180 Lightshow = "Lightshow",
181 }
182}
183
184/// Describes the settings for a difficulty.
185///
186/// Note that a difficulties [characteristic](Characteristic) is defined by its [`DifficultySet`].
187#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
188#[cfg_attr(
189 feature = "bevy_reflect",
190 derive(bevy_reflect::Reflect),
191 reflect(Debug, Clone, PartialEq)
192)]
193pub struct DifficultyInfo {
194 #[serde(rename = "_difficulty")]
195 pub name: String,
196 #[serde(rename = "_difficultyRank")]
197 pub rank: DifficultyRank,
198 /// The path to the difficulty file, relative to the map's folder.
199 #[serde(rename = "_beatmapFilename")]
200 pub file: String,
201 #[doc(alias = "node_jump_speed")]
202 #[serde(rename = "_noteJumpMovementSpeed")]
203 pub njs: f32,
204 #[doc(alias = "node_jump_distance")]
205 #[serde(rename = "_noteJumpStartBeatOffset")]
206 pub njd: f32,
207 /// > Only present in info file V2.1 or higher.
208 ///
209 /// The ID of environment to use from the map's [environment list](Beatmap::environments).
210 #[serde(rename = "_environmentNameIdx")]
211 pub environment_index: Option<i32>,
212 /// > Only present in info file V2.1 or higher.
213 ///
214 /// The ID of color scheme to use from the map's [color schemes list](Beatmap::color_schemes).
215 #[serde(rename = "_beatmapColorSchemeIdx")]
216 pub color_scheme_index: Option<i32>,
217}
218
219loose_enum! {
220 #[derive(Default, Debug, Clone, Copy, Eq, PartialEq, Hash)]
221 #[cfg_attr(
222 feature = "bevy_reflect",
223 derive(bevy_reflect::Reflect),
224 reflect(Debug, Clone, PartialEq)
225 )]
226 pub enum DifficultyRank: i32 {
227 Easy = 1,
228 Normal = 3,
229 Hard = 5,
230 #[default]
231 Expert = 7,
232 ExpertPlus = 9,
233 }
234}