1use crate::{
2 Colors, Features,
3 layer::wildlife::{self, DensityFn, SpawnEntry},
4 site::{Site, economy::TradeInformation},
5};
6use common::{
7 assets::{AssetExt, AssetHandle},
8 store::Store,
9 trade::{SiteId, SitePrices},
10};
11use core::ops::Deref;
12use noise::{Fbm, MultiFractal, Perlin, SuperSimplex};
13use std::sync::Arc;
14
15const WORLD_COLORS_MANIFEST: &str = "world.style.colors";
16const WORLD_FEATURES_MANIFEST: &str = "world.features";
17
18pub struct Index {
19 pub seed: u32,
20 pub time: f32,
21 pub noise: Noise,
22 pub sites: Store<Site>,
23 pub trade: TradeInformation,
24 pub wildlife_spawns: Vec<(AssetHandle<SpawnEntry>, DensityFn)>,
25 colors: AssetHandle<Arc<Colors>>,
26 features: AssetHandle<Arc<Features>>,
27}
28
29#[derive(Clone)]
35pub struct IndexOwned {
36 colors: Arc<Colors>,
37 features: Arc<Features>,
38 index: Arc<Index>,
39}
40
41impl Deref for IndexOwned {
42 type Target = Index;
43
44 fn deref(&self) -> &Self::Target { &self.index }
45}
46
47#[derive(Clone, Copy)]
51pub struct IndexRef<'a> {
52 pub colors: &'a Colors,
53 pub features: &'a Features,
54 pub index: &'a Index,
55}
56
57impl Deref for IndexRef<'_> {
58 type Target = Index;
59
60 fn deref(&self) -> &Self::Target { self.index }
61}
62
63impl Index {
64 pub fn new(seed: u32) -> Self {
66 let colors = Arc::<Colors>::load_expect(WORLD_COLORS_MANIFEST);
67 let features = Arc::<Features>::load_expect(WORLD_FEATURES_MANIFEST);
68 let wildlife_spawns = wildlife::spawn_manifest()
69 .into_iter()
70 .map(|(e, f)| (SpawnEntry::load_expect(e), f))
71 .collect();
72
73 Self {
74 seed,
75 time: 0.0,
76 noise: Noise::new(seed),
77 sites: Store::default(),
78 trade: Default::default(),
79 wildlife_spawns,
80 colors,
81 features,
82 }
83 }
84
85 pub fn colors(&self) -> impl Deref<Target = Arc<Colors>> + '_ { self.colors.read() }
86
87 pub fn features(&self) -> impl Deref<Target = Arc<Features>> + '_ { self.features.read() }
88
89 pub fn get_site_prices(&self, site_id: SiteId) -> Option<SitePrices> {
90 self.sites
91 .recreate_id(site_id)
92 .map(|i| self.sites.get(i))
93 .and_then(|s| s.economy.as_ref())
94 .map(|econ| econ.get_site_prices())
95 }
96}
97
98impl IndexOwned {
99 pub fn new(index: Index) -> Self {
100 let colors = index.colors.cloned();
101 let features = index.features.cloned();
102
103 Self {
104 index: Arc::new(index),
105 colors,
106 features,
107 }
108 }
109
110 pub fn reload_if_changed<R>(&mut self, reload: impl FnOnce(&mut Self) -> R) -> Option<R> {
118 let reloaded = self.index.colors.reloaded_global() || self.index.features.reloaded_global();
119 reloaded.then(move || {
120 self.colors = self.index.colors.cloned();
122 self.features = self.index.features.cloned();
123 reload(self)
125 })
126 }
127
128 pub fn as_index_ref(&self) -> IndexRef {
129 IndexRef {
130 colors: &self.colors,
131 features: &self.features,
132 index: &self.index,
133 }
134 }
135}
136
137pub struct Noise {
138 pub cave_nz: SuperSimplex,
139 pub scatter_nz: SuperSimplex,
140 pub cave_fbm_nz: Fbm<Perlin>,
141}
142
143impl Noise {
144 fn new(seed: u32) -> Self {
145 Self {
146 cave_nz: SuperSimplex::new(seed + 0),
147 scatter_nz: SuperSimplex::new(seed + 1),
148 cave_fbm_nz: Fbm::new(seed + 2).set_octaves(5),
149 }
150 }
151}