Pumpkin/crates/pumpkin-util/src/world_seed.rs
2026-08-06 12:56:40 +02:00

50 lines
1.5 KiB
Rust

use crate::{
math::java_string_hash,
random::{RandomImpl, get_seed, legacy_rand::LegacyRand},
};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// Represents a world generation seed.
///
/// The seed is stored as a `u64` but follows Java-style behaviour:
/// - Numeric strings are parsed as `i64` and then cast.
/// - Non-numeric strings are hashed using the Java string hash algorithm.
/// - Empty or whitespace-only input generates a random seed.
///
/// This allows compatibility with typical Minecraft-style seed inputs.
#[derive(Clone, Copy)]
pub struct Seed(pub u64);
impl From<&str> for Seed {
fn from(value: &str) -> Self {
let trimmed = value.trim();
let value = (!trimmed.is_empty()).then(|| {
let i64_value = trimmed
.parse::<i64>()
.unwrap_or_else(|_| i64::from(java_string_hash(trimmed)));
i64_value as u64
});
Self(value.unwrap_or_else(|| LegacyRand::from_seed(get_seed()).next_i64() as u64))
}
}
impl Serialize for Seed {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&(self.0 as i64).to_string())
}
}
impl<'de> Deserialize<'de> for Seed {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let raw = String::deserialize(deserializer)?;
Ok(Self::from(raw.as_str()))
}
}