Skip to main content

nms_core/
system.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4use crate::address::GalacticAddress;
5use crate::biome::{Biome, BiomeSubType};
6
7/// A star system containing one or more planets.
8///
9/// The galaxy (reality index) is encoded in the `address` field.
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11#[non_exhaustive]
12pub struct System {
13    pub address: GalacticAddress,
14    pub name: Option<String>,
15    pub discoverer: Option<String>,
16    pub timestamp: Option<DateTime<Utc>>,
17    pub planets: Vec<Planet>,
18}
19
20impl System {
21    pub fn new(
22        address: GalacticAddress,
23        name: Option<String>,
24        discoverer: Option<String>,
25        timestamp: Option<DateTime<Utc>>,
26        planets: Vec<Planet>,
27    ) -> Self {
28        Self {
29            address,
30            name,
31            discoverer,
32            timestamp,
33            planets,
34        }
35    }
36
37    /// Galaxy index (convenience accessor for `address.reality_index`).
38    pub fn reality_index(&self) -> u8 {
39        self.address.reality_index
40    }
41}
42
43/// A planet within a star system.
44#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45#[cfg_attr(
46    feature = "archive",
47    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
48)]
49#[non_exhaustive]
50pub struct Planet {
51    /// Planet index within the system (0-15).
52    pub index: u8,
53    pub biome: Option<Biome>,
54    pub biome_subtype: Option<BiomeSubType>,
55    /// Whether the planet has infested (biological horror) variant.
56    pub infested: bool,
57    pub name: Option<String>,
58    /// Procedural generation seed.
59    pub seed_hash: Option<u64>,
60}
61
62impl Planet {
63    pub fn new(
64        index: u8,
65        biome: Option<Biome>,
66        biome_subtype: Option<BiomeSubType>,
67        infested: bool,
68        name: Option<String>,
69        seed_hash: Option<u64>,
70    ) -> Self {
71        Self {
72            index,
73            biome,
74            biome_subtype,
75            infested,
76            name,
77            seed_hash,
78        }
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn system_reality_index_from_address() {
88        let addr = GalacticAddress::new(0, 0, 0, 0x123, 0, 42);
89        let sys = System::new(addr, None, None, None, vec![]);
90        assert_eq!(sys.reality_index(), 42);
91    }
92
93    #[test]
94    fn planet_constructor() {
95        let p = Planet::new(3, Some(Biome::Lush), None, false, Some("Eden".into()), None);
96        assert_eq!(p.index, 3);
97        assert_eq!(p.biome, Some(Biome::Lush));
98        assert!(!p.infested);
99    }
100}