Skip to main content

veloren_world/
index.rs

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/// An owned reference to indexed data.
30///
31/// The data are split out so that we can replace the colors without disturbing
32/// the rest of the index, while also keeping all the data within a single
33/// indirection.
34#[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/// A shared reference to indexed data.
50///
51/// This is copyable and can be used from either style of index.
52#[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    /// NOTE: Panics if the color manifest cannot be loaded.
67    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    /// NOTE: Callback is called only when colors actually have to be reloaded.
117    /// The server is responsible for making sure that all affected chunks are
118    /// reloaded; a naive approach will just regenerate every chunk on the
119    /// server, but it is possible that eventually we can find a better
120    /// solution.
121    ///
122    /// Ideally, this should be called about once per tick.
123    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            // Reload the fields from the asset handle, which is updated automatically
129            self.colors = self.index.colors.cloned();
130            self.features = self.index.features.cloned();
131            // Update wildlife spawns which is based on base_density in features
132            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}