Skip to main content

game_toolkit_platformer/sim/
custom_id.rs

1//! [`CustomId`]: the name of a move or event of your own, for [`Mode::Custom`] and
2//! [`Event::Custom`].
3//!
4//! An id is a hash of a name you choose, worked out at compile time, so two abilities from
5//! different crates never have to agree on numbers: name them after their crate and move
6//! (`"my_crate::lunge"`) and they don't collide. The same name always gives the same id,
7//! in every build and on every machine, so replays and cloned worlds stay deterministic.
8//!
9//! ```
10//! use game_toolkit_platformer::sim::CustomId;
11//!
12//! const LUNGE: CustomId = CustomId::new("my_game::lunge");
13//! const POGO: CustomId = CustomId::new("pogo_crate::pogo");
14//! assert_ne!(LUNGE, POGO);
15//! assert_eq!(LUNGE, CustomId::new("my_game::lunge"));
16//! ```
17//!
18//! [`Mode::Custom`]: super::Mode::Custom
19//! [`Event::Custom`]: super::Event::Custom
20
21/// The id of a move or event of your own: a 64-bit hash of its name (see the module docs).
22/// Usable in patterns: `Mode::Custom { id: LUNGE, .. }`.
23#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
24pub struct CustomId(pub u64);
25
26impl CustomId {
27    /// The id named `name` (FNV-1a over its bytes). Prefix it with your crate's name.
28    pub const fn new(name: &str) -> Self {
29        let bytes = name.as_bytes();
30        let mut hash: u64 = 0xcbf2_9ce4_8422_2325;
31        let mut i = 0;
32        while i < bytes.len() {
33            hash ^= bytes[i] as u64;
34            hash = hash.wrapping_mul(0x0000_0100_0000_01b3);
35            i += 1;
36        }
37        Self(hash)
38    }
39}