1use crate::{
2 Colors, Features,
3 layer::wildlife::{self, DensityFn, SpawnEntry},
4 site::{Site, economy::TradeInformation},
5};
6use common::{
7 assets::{AssetExt, AssetHandle, ReloadWatcher, Ron},
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<Ron<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 colors_reload_watcher: ReloadWatcher,
39 features_reload_watcher: ReloadWatcher,
40 index: Arc<Index>,
41}
42
43impl Deref for IndexOwned {
44 type Target = Index;
45
46 fn deref(&self) -> &Self::Target { &self.index }
47}
48
49#[derive(Clone, Copy)]
53pub struct IndexRef<'a> {
54 pub colors: &'a Colors,
55 pub features: &'a Features,
56 pub index: &'a Index,
57}
58
59impl Deref for IndexRef<'_> {
60 type Target = Index;
61
62 fn deref(&self) -> &Self::Target { self.index }
63}
64
65impl Index {
66 pub fn new(seed: u32) -> Self {
68 let colors = Arc::<Colors>::load_expect(WORLD_COLORS_MANIFEST);
69 let features = Arc::<Features>::load_expect(WORLD_FEATURES_MANIFEST);
70 let wildlife_spawns = wildlife::spawn_manifest()
71 .into_iter()
72 .map(|(e, f)| (Ron::<SpawnEntry>::load_expect(e), f))
73 .collect();
74
75 Self {
76 seed,
77 time: 0.0,
78 noise: Noise::new(seed),
79 sites: Store::default(),
80 trade: Default::default(),
81 wildlife_spawns,
82 colors,
83 features,
84 }
85 }
86
87 pub fn colors(&self) -> impl Deref<Target = Arc<Colors>> + '_ { self.colors.read() }
88
89 pub fn features(&self) -> impl Deref<Target = Arc<Features>> + '_ { self.features.read() }
90
91 pub fn get_site_prices(&self, site_id: SiteId) -> Option<SitePrices> {
92 self.sites
93 .recreate_id(site_id)
94 .map(|i| self.sites.get(i))
95 .and_then(|s| s.economy.as_ref())
96 .map(|econ| econ.get_site_prices())
97 }
98}
99
100impl IndexOwned {
101 pub fn new(index: Index) -> Self {
102 let colors = index.colors.cloned();
103 let features = index.features.cloned();
104 let colors_reload_watcher = index.colors.reload_watcher();
105 let features_reload_watcher = index.features.reload_watcher();
106
107 Self {
108 index: Arc::new(index),
109 colors,
110 features,
111 colors_reload_watcher,
112 features_reload_watcher,
113 }
114 }
115
116 pub fn reload_if_changed<R>(&mut self, reload: impl FnOnce(&mut Self) -> R) -> Option<R> {
124 let colors_reloaded = self.colors_reload_watcher.reloaded();
125 let features_reloaded = self.features_reload_watcher.reloaded();
126 let reloaded = colors_reloaded || features_reloaded;
127 reloaded.then(move || {
128 self.colors = self.index.colors.cloned();
130 self.features = self.index.features.cloned();
131 reload(self)
133 })
134 }
135
136 pub fn as_index_ref(&self) -> IndexRef<'_> {
137 IndexRef {
138 colors: &self.colors,
139 features: &self.features,
140 index: &self.index,
141 }
142 }
143}
144
145pub struct Noise {
146 pub cave_nz: SuperSimplex,
147 pub scatter_nz: SuperSimplex,
148 pub cave_fbm_nz: Fbm<Perlin>,
149}
150
151impl Noise {
152 fn new(seed: u32) -> Self {
153 Self {
154 cave_nz: SuperSimplex::new(seed + 0),
155 scatter_nz: SuperSimplex::new(seed + 1),
156 cave_fbm_nz: Fbm::new(seed + 2).set_octaves(5),
157 }
158 }
159}