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::() .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(&self, serializer: S) -> Result where S: Serializer, { serializer.serialize_str(&(self.0 as i64).to_string()) } } impl<'de> Deserialize<'de> for Seed { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let raw = String::deserialize(deserializer)?; Ok(Self::from(raw.as_str())) } }