rosu_mods/lib.rs
1//! A library to provide types for all [osu!] gamemods as defined in the official [mods.json] file.
2//!
3//! Individual gamemod types are generated automatically through the [`generate-mods`] binary.
4//!
5//! ## Types
6//!
7//! In total there are three different collections for mods.
8//!
9//! ### `GameModsLegacy`
10//!
11//! [`GameModsLegacy`] is a lightweight type that is essentially just bitflags for the [legacy mods].
12//!
13//! ```
14//! use rosu_mods::GameModsLegacy;
15//!
16//! let hdnc = GameModsLegacy::Nightcore | GameModsLegacy::Hidden;
17//! assert_eq!(hdnc.to_string(), "HDNC");
18//! assert!(hdnc.contains(GameModsLegacy::DoubleTime));
19//! ```
20//!
21//! ### `GameMods`
22//!
23//! [`GameMods`] is a collection of the [`GameMod`] enum. [`GameMod`] distinguishes between each
24//! mode so if a mod is valid for multiple modes, each of those modes will have a variant for that
25//! mod.
26//!
27//! ```
28//! use rosu_mods::{GameMod, GameMods, generated_mods::AccuracyChallengeMania};
29//!
30//! # let mut mods = GameMods::new();
31//! # mods.insert(GameMod::HardRockTaiko(Default::default()));
32//! # mods.insert(GameMod::AccuracyChallengeTaiko(Default::default()));
33//! # /*
34//! // The `mods!` macro is only available if the `macros` feature is enabled
35//! let mut mods: GameMods = rosu_mods::mods!(Taiko: AC HR);
36//! # */
37#![cfg_attr(
38 feature = "macros",
39 doc = "# assert_eq!(mods, rosu_mods::mods!(Taiko: AC HR));"
40)]
41//!
42//! // In addition to the two taiko mods, let's add a mania mod too
43//! mods.insert(GameMod::AccuracyChallengeMania(AccuracyChallengeMania {
44//! restart: Some(true),
45//! ..Default::default()
46//! }));
47//!
48//! assert_eq!(mods.to_string(), "ACHRAC");
49//!
50//! let mut iter = mods.into_iter();
51//! assert_eq!(iter.next(), Some(GameMod::AccuracyChallengeTaiko(Default::default())));
52//! assert_eq!(iter.next(), Some(GameMod::HardRockTaiko(Default::default())));
53//! assert_eq!(iter.next(), Some(GameMod::AccuracyChallengeMania(AccuracyChallengeMania {
54//! restart: Some(true),
55//! minimum_accuracy: None,
56//! accuracy_judge_mode: None,
57//! })));
58//! assert_eq!(iter.next(), None);
59//! ```
60//!
61//! ### `GameModsIntermode`
62//!
63//! [`GameModsIntermode`] is a collection of the [`GameModIntermode`] enum. Unlike [`GameMod`],
64//! this enum does not distinguish between modes. As such, variants do not carry further data
65//! because a mod may have different settings depending on the mode.
66//!
67//! Since [`GameModsIntermode`] does not carry additional data and also consists of fewer variants,
68//! it is generally easier to deal with than [`GameMods`].
69//!
70//! ```
71//! use rosu_mods::{GameModIntermode, GameModsIntermode};
72//!
73//! # let mut mods = GameModsIntermode::new();
74//! # mods.insert(GameModIntermode::Wiggle);
75//! # mods.insert(GameModIntermode::FadeIn);
76//! # /*
77//! // The `mods!` macro is only available if the `macros` feature is enabled
78//! let mut mods: GameModsIntermode = rosu_mods::mods!(WG FI);
79//! # */
80#![cfg_attr(
81 feature = "macros",
82 doc = "# assert_eq!(mods, rosu_mods::mods!(WG FI));"
83)]
84//!
85//! // Let's add some more mods
86//! mods.extend([GameModIntermode::Easy, GameModIntermode::HardRock]);
87//!
88//! assert_eq!(mods.to_string(), "EZFIHRWG");
89//!
90//! let mut iter = mods.into_iter();
91//! assert_eq!(iter.next(), Some(GameModIntermode::Easy));
92//! assert_eq!(iter.next(), Some(GameModIntermode::FadeIn));
93//! assert_eq!(iter.next(), Some(GameModIntermode::HardRock));
94//! assert_eq!(iter.next(), Some(GameModIntermode::Wiggle));
95//! assert_eq!(iter.next(), None);
96//! ```
97//!
98//! ## Features
99//!
100//! | Flag | Description | Dependencies
101//! | --------- | ------------------------------------------------------------------------------------------------ | ------------
102//! | `default` | No features enabled |
103//! | `macros` | Enables the `mods!` macro | [`paste`]
104//! | `serde` | Implements `serde::{Deserialize, Serialize}` for all types and enables the `serde` module | [`serde`]
105//! | `rkyv` | Implements `rkyv::{Archive, Serialize, Deserialize}` for all types and enables the `rkyv` module | [`rkyv`]
106//!
107//! [osu!]: https://osu.ppy.sh/home
108//! [mods.json]: https://github.com/ppy/osu-web/blob/master/database/mods.json
109//! [`generate-mods`]: https://github.com/MaxOhn/rosu-mods/tree/main/generate-mods
110//! [legacy mods]: https://github.com/ppy/osu-api/wiki#reference
111//! [`paste`]: https://docs.rs/paste
112//! [`serde`]: https://docs.rs/serde
113//! [`rkyv`]: https://docs.rs/rkyv
114//! [`GameModsLegacy`]: crate::legacy::GameModsLegacy
115//! [`GameMods`]: crate::mods::GameMods
116//! [`GameMod`]: crate::generated_mods::gamemod::GameMod
117//! [`GameModsIntermode`]: crate::intermode::GameModsIntermode
118//! [`GameModIntermode`]: crate::generated_mods::intermode::GameModIntermode
119
120#![cfg_attr(all(docsrs, not(doctest)), feature(doc_cfg))]
121#![deny(rustdoc::broken_intra_doc_links, rustdoc::missing_crate_level_docs)]
122#![warn(clippy::missing_const_for_fn, clippy::pedantic)]
123#![allow(
124 clippy::missing_errors_doc,
125 clippy::module_name_repetitions,
126 clippy::must_use_candidate,
127 clippy::struct_excessive_bools,
128 clippy::match_same_arms,
129 clippy::cast_possible_truncation,
130 clippy::cast_precision_loss,
131 clippy::cast_sign_loss,
132 clippy::explicit_iter_loop,
133 clippy::similar_names,
134 clippy::cast_possible_wrap,
135 clippy::default_trait_access
136)]
137
138#[cfg(feature = "macros")]
139extern crate paste;
140
141#[macro_use]
142#[doc(hidden)]
143pub mod macros;
144
145mod acronym;
146mod intermode;
147mod kind;
148mod legacy;
149mod mod_manual;
150mod mode;
151mod mods;
152mod order;
153mod util;
154
155/// Error types
156pub mod error;
157
158pub mod generated_mods;
159
160/// Types to calculate intersecting mods.
161pub mod intersection;
162
163/// Iterator types for mods.
164pub mod iter;
165
166#[cfg(feature = "rkyv")]
167#[doc(inline)]
168pub use generated_mods::rkyv;
169
170/// Types for (de)serialization through `serde`.
171#[cfg_attr(all(docsrs, not(doctest)), doc(cfg(feature = "serde")))]
172pub mod serde;
173
174pub use self::{mode::GameMode, mods::GameMods};
175
176#[doc(inline)]
177pub use self::{
178 acronym::Acronym,
179 generated_mods::{GameMod, GameModIntermode},
180 intermode::GameModsIntermode,
181 kind::GameModKind,
182 legacy::GameModsLegacy,
183};