use crate::{
layer::wildlife::{self, DensityFn, SpawnEntry},
site::{economy::TradeInformation, Site},
Colors, Features,
};
use common::{
assets::{AssetExt, AssetHandle},
store::Store,
trade::{SiteId, SitePrices},
};
use core::ops::Deref;
use noise::{Fbm, MultiFractal, Perlin, SuperSimplex};
use std::sync::Arc;
const WORLD_COLORS_MANIFEST: &str = "world.style.colors";
const WORLD_FEATURES_MANIFEST: &str = "world.features";
pub struct Index {
pub seed: u32,
pub time: f32,
pub noise: Noise,
pub sites: Store<Site>,
pub trade: TradeInformation,
pub wildlife_spawns: Vec<(AssetHandle<SpawnEntry>, DensityFn)>,
colors: AssetHandle<Arc<Colors>>,
features: AssetHandle<Arc<Features>>,
}
#[derive(Clone)]
pub struct IndexOwned {
colors: Arc<Colors>,
features: Arc<Features>,
index: Arc<Index>,
}
impl Deref for IndexOwned {
type Target = Index;
fn deref(&self) -> &Self::Target { &self.index }
}
#[derive(Clone, Copy)]
pub struct IndexRef<'a> {
pub colors: &'a Colors,
pub features: &'a Features,
pub index: &'a Index,
}
impl<'a> Deref for IndexRef<'a> {
type Target = Index;
fn deref(&self) -> &Self::Target { self.index }
}
impl Index {
pub fn new(seed: u32) -> Self {
let colors = Arc::<Colors>::load_expect(WORLD_COLORS_MANIFEST);
let features = Arc::<Features>::load_expect(WORLD_FEATURES_MANIFEST);
let wildlife_spawns = wildlife::spawn_manifest()
.into_iter()
.map(|(e, f)| (SpawnEntry::load_expect(e), f))
.collect();
Self {
seed,
time: 0.0,
noise: Noise::new(seed),
sites: Store::default(),
trade: Default::default(),
wildlife_spawns,
colors,
features,
}
}
pub fn colors(&self) -> impl Deref<Target = Arc<Colors>> + '_ { self.colors.read() }
pub fn features(&self) -> impl Deref<Target = Arc<Features>> + '_ { self.features.read() }
pub fn get_site_prices(&self, site_id: SiteId) -> Option<SitePrices> {
self.sites
.recreate_id(site_id)
.map(|i| self.sites.get(i))
.map(|s| s.economy.get_site_prices())
}
}
impl IndexOwned {
pub fn new(index: Index) -> Self {
let colors = index.colors.cloned();
let features = index.features.cloned();
Self {
index: Arc::new(index),
colors,
features,
}
}
pub fn reload_if_changed<R>(&mut self, reload: impl FnOnce(&mut Self) -> R) -> Option<R> {
let reloaded = self.index.colors.reloaded_global() || self.index.features.reloaded_global();
reloaded.then(move || {
self.colors = self.index.colors.cloned();
self.features = self.index.features.cloned();
reload(self)
})
}
pub fn as_index_ref(&self) -> IndexRef {
IndexRef {
colors: &self.colors,
features: &self.features,
index: &self.index,
}
}
}
pub struct Noise {
pub cave_nz: SuperSimplex,
pub scatter_nz: SuperSimplex,
pub cave_fbm_nz: Fbm<Perlin>,
}
impl Noise {
fn new(seed: u32) -> Self {
Self {
cave_nz: SuperSimplex::new(seed + 0),
scatter_nz: SuperSimplex::new(seed + 1),
cave_fbm_nz: Fbm::new(seed + 2).set_octaves(5),
}
}
}