mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added christmas snow
This commit is contained in:
parent
e3203080ed
commit
3ddacb96ab
@ -2713,6 +2713,7 @@ fn handle_debug_column(
|
||||
_action: &ChatCommand,
|
||||
) -> CmdResult<()> {
|
||||
let sim = server.world.sim();
|
||||
let calendar = (*server.state.ecs().read_resource::<Calendar>()).clone();
|
||||
let sampler = server.world.sample_columns();
|
||||
let wpos = if let (Some(x), Some(y)) = parse_args!(args, i32, i32) {
|
||||
Vec2::new(x, y)
|
||||
@ -2721,7 +2722,7 @@ fn handle_debug_column(
|
||||
// FIXME: Deal with overflow, if needed.
|
||||
pos.0.xy().map(|x| x as i32)
|
||||
};
|
||||
let msg_generator = || {
|
||||
let msg_generator = |calendar| {
|
||||
let alt = sim.get_interpolated(wpos, |chunk| chunk.alt)?;
|
||||
let basement = sim.get_interpolated(wpos, |chunk| chunk.basement)?;
|
||||
let water_alt = sim.get_interpolated(wpos, |chunk| chunk.water_alt)?;
|
||||
@ -2733,7 +2734,7 @@ fn handle_debug_column(
|
||||
let spawn_rate = sim.get_interpolated(wpos, |chunk| chunk.spawn_rate)?;
|
||||
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| e / sz as i32);
|
||||
let chunk = sim.get(chunk_pos)?;
|
||||
let col = sampler.get((wpos, server.index.as_index_ref()))?;
|
||||
let col = sampler.get((wpos, server.index.as_index_ref(), Some(calendar)))?;
|
||||
let gradient = sim.get_gradient_approx(chunk_pos)?;
|
||||
let downhill = chunk.downhill;
|
||||
let river = &chunk.river;
|
||||
@ -2772,7 +2773,7 @@ spawn_rate {:?} "#,
|
||||
spawn_rate
|
||||
))
|
||||
};
|
||||
if let Some(s) = msg_generator() {
|
||||
if let Some(s) = msg_generator(&calendar) {
|
||||
server.notify_client(client, ServerGeneral::server_msg(ChatType::CommandInfo, s));
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -361,7 +361,7 @@ impl Server {
|
||||
);
|
||||
|
||||
#[cfg(feature = "worldgen")]
|
||||
let map = world.get_map_data(index.as_index_ref(), state.thread_pool());
|
||||
let map = world.get_map_data(index.as_index_ref(), Some(&settings.calendar_mode.calendar_now()), state.thread_pool());
|
||||
|
||||
#[cfg(not(feature = "worldgen"))]
|
||||
let (world, index) = World::generate(settings.world_seed);
|
||||
@ -597,12 +597,7 @@ impl Server {
|
||||
// Update calendar events as time changes
|
||||
// TODO: If a lot of calendar events get added, this might become expensive.
|
||||
// Maybe don't do this every tick?
|
||||
let new_calendar = match &self.state.ecs().read_resource::<Settings>().calendar_mode {
|
||||
CalendarMode::None => Calendar::default(),
|
||||
CalendarMode::Auto => Calendar::from_tz(None),
|
||||
CalendarMode::Timezone(tz) => Calendar::from_tz(Some(*tz)),
|
||||
CalendarMode::Events(events) => Calendar::from_events(events.clone()),
|
||||
};
|
||||
let new_calendar = self.state.ecs().read_resource::<Settings>().calendar_mode.calendar_now();
|
||||
*self.state.ecs_mut().write_resource::<Calendar>() = new_calendar;
|
||||
|
||||
// This tick function is the centre of the Veloren universe. Most server-side
|
||||
|
@ -14,7 +14,7 @@ pub use server_description::ServerDescription;
|
||||
pub use whitelist::{Whitelist, WhitelistInfo, WhitelistRecord};
|
||||
|
||||
use chrono::Utc;
|
||||
use common::{calendar::CalendarEvent, resources::BattleMode};
|
||||
use common::{calendar::{Calendar, CalendarEvent}, resources::BattleMode};
|
||||
use core::time::Duration;
|
||||
use portpicker::pick_unused_port;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -74,6 +74,17 @@ impl Default for CalendarMode {
|
||||
fn default() -> Self { Self::Auto }
|
||||
}
|
||||
|
||||
impl CalendarMode {
|
||||
pub fn calendar_now(&self) -> Calendar {
|
||||
match self {
|
||||
CalendarMode::None => Calendar::default(),
|
||||
CalendarMode::Auto => Calendar::from_tz(None),
|
||||
CalendarMode::Timezone(tz) => Calendar::from_tz(Some(*tz)),
|
||||
CalendarMode::Events(events) => Calendar::from_events(events.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct Settings {
|
||||
|
@ -3,9 +3,12 @@ use crate::{
|
||||
util::{FastNoise, RandomField, RandomPerm, Sampler, SmallCache},
|
||||
IndexRef,
|
||||
};
|
||||
use common::terrain::{
|
||||
structure::{self, StructureBlock},
|
||||
Block, BlockKind, SpriteKind,
|
||||
use common::{
|
||||
calendar::Calendar,
|
||||
terrain::{
|
||||
structure::{self, StructureBlock},
|
||||
Block, BlockKind, SpriteKind,
|
||||
},
|
||||
};
|
||||
use core::ops::{Div, Mul, Range};
|
||||
use serde::Deserialize;
|
||||
@ -33,17 +36,18 @@ impl<'a> BlockGen<'a> {
|
||||
cache: &'b mut SmallCache<Option<ColumnSample<'a>>>,
|
||||
wpos: Vec2<i32>,
|
||||
index: IndexRef<'a>,
|
||||
calendar: Option<&'a Calendar>,
|
||||
) -> Option<&'b ColumnSample<'a>> {
|
||||
cache
|
||||
.get(wpos, |wpos| column_gen.get((wpos, index)))
|
||||
.get(wpos, |wpos| column_gen.get((wpos, index, calendar)))
|
||||
.as_ref()
|
||||
}
|
||||
|
||||
pub fn get_z_cache(&mut self, wpos: Vec2<i32>, index: IndexRef<'a>) -> Option<ZCache<'a>> {
|
||||
pub fn get_z_cache(&mut self, wpos: Vec2<i32>, index: IndexRef<'a>, calendar: Option<&'a Calendar>) -> Option<ZCache<'a>> {
|
||||
let BlockGen { column_gen } = self;
|
||||
|
||||
// Main sample
|
||||
let sample = column_gen.get((wpos, index))?;
|
||||
let sample = column_gen.get((wpos, index, calendar))?;
|
||||
|
||||
Some(ZCache { sample })
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use crate::{
|
||||
util::{Grid, Sampler},
|
||||
};
|
||||
use common::{
|
||||
calendar::Calendar,
|
||||
generation::EntityInfo,
|
||||
terrain::{Block, BlockKind, Structure, TerrainChunk, TerrainChunkSize},
|
||||
vol::{ReadVol, RectVolSize, WriteVol},
|
||||
@ -24,6 +25,7 @@ pub struct CanvasInfo<'a> {
|
||||
pub(crate) chunks: &'a WorldSim,
|
||||
pub(crate) index: IndexRef<'a>,
|
||||
pub(crate) chunk: &'a SimChunk,
|
||||
pub(crate) calendar: Option<&'a Calendar>,
|
||||
}
|
||||
|
||||
impl<'a> CanvasInfo<'a> {
|
||||
@ -52,7 +54,7 @@ impl<'a> CanvasInfo<'a> {
|
||||
pub fn col_or_gen(&self, wpos: Vec2<i32>) -> Option<Cow<'a, ColumnSample>> {
|
||||
self.col(wpos).map(Cow::Borrowed).or_else(|| {
|
||||
Some(Cow::Owned(
|
||||
ColumnGen::new(self.chunks()).get((wpos, self.index()))?,
|
||||
ColumnGen::new(self.chunks()).get((wpos, self.index(), self.calendar))?,
|
||||
))
|
||||
})
|
||||
}
|
||||
@ -122,6 +124,7 @@ impl<'a> CanvasInfo<'a> {
|
||||
chunks: sim,
|
||||
index,
|
||||
chunk: &sim_chunk,
|
||||
calendar: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ use crate::{
|
||||
IndexRef, CONFIG,
|
||||
};
|
||||
use common::{
|
||||
calendar::{Calendar, CalendarEvent},
|
||||
terrain::{
|
||||
quadratic_nearest_point, river_spline_coeffs, uniform_idx_as_vec2, vec2_as_uniform_idx,
|
||||
TerrainChunkSize,
|
||||
@ -64,10 +65,10 @@ impl<'a> ColumnGen<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
type Index = (Vec2<i32>, IndexRef<'a>);
|
||||
type Index = (Vec2<i32>, IndexRef<'a>, Option<&'a Calendar>);
|
||||
type Sample = Option<ColumnSample<'a>>;
|
||||
|
||||
fn get(&self, (wpos, index): Self::Index) -> Option<ColumnSample<'a>> {
|
||||
fn get(&self, (wpos, index, calendar): Self::Index) -> Option<ColumnSample<'a>> {
|
||||
let wposf = wpos.map(|e| e as f64);
|
||||
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| e / sz as i32);
|
||||
|
||||
@ -1079,8 +1080,13 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
);
|
||||
|
||||
// Snow covering
|
||||
let thematic_snow = calendar.map_or(false, |c| c.is_event(CalendarEvent::Christmas));
|
||||
let snow_cover = temp
|
||||
.sub(CONFIG.snow_temp)
|
||||
.sub(if thematic_snow {
|
||||
CONFIG.tropical_temp
|
||||
} else {
|
||||
CONFIG.snow_temp
|
||||
})
|
||||
.max(-humidity.sub(CONFIG.desert_hum))
|
||||
.mul(4.0)
|
||||
.add(((marble - 0.5) / 0.5) * 0.5)
|
||||
|
@ -7,6 +7,7 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
assets::AssetHandle,
|
||||
calendar::{Calendar, CalendarEvent},
|
||||
terrain::{
|
||||
structure::{Structure, StructureBlock, StructuresGroup},
|
||||
Block, BlockKind, SpriteKind,
|
||||
@ -33,7 +34,7 @@ static MODEL_RAND: RandomPerm = RandomPerm::new(0xDB21C052);
|
||||
static UNIT_CHOOSER: UnitChooser = UnitChooser::new(0x700F4EC7);
|
||||
static QUIRKY_RAND: RandomPerm = RandomPerm::new(0xA634460F);
|
||||
|
||||
pub fn apply_trees_to(canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
|
||||
pub fn apply_trees_to(canvas: &mut Canvas, dynamic_rng: &mut impl Rng, calendar: Option<&Calendar>) {
|
||||
// TODO: Get rid of this
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
enum TreeModel {
|
||||
@ -63,7 +64,7 @@ pub fn apply_trees_to(canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
|
||||
} in trees
|
||||
{
|
||||
let tree = if let Some(tree) = tree_cache.entry(pos).or_insert_with(|| {
|
||||
let col = ColumnGen::new(info.chunks()).get((pos, info.index()))?;
|
||||
let col = ColumnGen::new(info.chunks()).get((pos, info.index(), calendar))?;
|
||||
|
||||
// Ensure that it's valid to place a *thing* here
|
||||
if col.alt < col.water_level
|
||||
@ -135,7 +136,7 @@ pub fn apply_trees_to(canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
|
||||
ForestKind::Pine => {
|
||||
break 'model TreeModel::Procedural(
|
||||
ProceduralTree::generate(
|
||||
TreeConfig::pine(&mut RandomPerm::new(seed), scale),
|
||||
TreeConfig::pine(&mut RandomPerm::new(seed), scale, calendar),
|
||||
&mut RandomPerm::new(seed),
|
||||
),
|
||||
StructureBlock::PineLeaves,
|
||||
@ -547,7 +548,7 @@ impl TreeConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pine(rng: &mut impl Rng, scale: f32) -> Self {
|
||||
pub fn pine(rng: &mut impl Rng, scale: f32, calendar: Option<&Calendar>) -> Self {
|
||||
let scale = scale * (1.0 + rng.gen::<f32>().powi(4) * 0.5);
|
||||
let log_scale = 1.0 + scale.log2().max(0.0);
|
||||
|
||||
@ -567,7 +568,11 @@ impl TreeConfig {
|
||||
leaf_vertical_scale: 0.3,
|
||||
proportionality: 1.0,
|
||||
inhabited: false,
|
||||
hanging_sprites: &[(0.0001, SpriteKind::Beehive)],
|
||||
hanging_sprites: if calendar.map_or(false, |c| c.is_event(CalendarEvent::Christmas)) {
|
||||
&[(0.0001, SpriteKind::Beehive), (0.01, SpriteKind::Orb)]
|
||||
} else {
|
||||
&[(0.0001, SpriteKind::Beehive)]
|
||||
},
|
||||
trunk_block: StructureBlock::Filled(BlockKind::Wood, Rgb::new(90, 35, 15)),
|
||||
}
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
index: IndexRef,
|
||||
chunk: &SimChunk,
|
||||
supplement: &mut ChunkSupplement,
|
||||
time: Option<(TimeOfDay, Calendar)>,
|
||||
time: Option<&(TimeOfDay, Calendar)>,
|
||||
) {
|
||||
let scatter = &index.wildlife_spawns;
|
||||
|
||||
@ -305,7 +305,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
|
||||
};
|
||||
|
||||
let underwater = col_sample.water_level > col_sample.alt;
|
||||
let (current_day_period, calendar) = if let Some((time, calendar)) = &time {
|
||||
let (current_day_period, calendar) = if let Some((time, calendar)) = time {
|
||||
(DayPeriod::from(time.0), Some(calendar))
|
||||
} else {
|
||||
(DayPeriod::Noon, None)
|
||||
|
@ -120,7 +120,7 @@ impl World {
|
||||
// TODO
|
||||
}
|
||||
|
||||
pub fn get_map_data(&self, index: IndexRef, threadpool: &rayon::ThreadPool) -> WorldMapMsg {
|
||||
pub fn get_map_data(&self, index: IndexRef, calendar: Option<&Calendar>, threadpool: &rayon::ThreadPool) -> WorldMapMsg {
|
||||
threadpool.install(|| {
|
||||
// we need these numbers to create unique ids for cave ends
|
||||
let num_sites = self.civs().sites().count() as u64;
|
||||
@ -179,14 +179,14 @@ impl World {
|
||||
}),
|
||||
)
|
||||
.collect(),
|
||||
..self.sim.get_map(index)
|
||||
..self.sim.get_map(index, calendar)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sample_columns(
|
||||
&self,
|
||||
) -> impl Sampler<Index = (Vec2<i32>, IndexRef), Sample = Option<ColumnSample>> + '_ {
|
||||
) -> impl Sampler<Index = (Vec2<i32>, IndexRef, Option<&'_ Calendar>), Sample = Option<ColumnSample>> + '_ {
|
||||
ColumnGen::new(&self.sim)
|
||||
}
|
||||
|
||||
@ -218,6 +218,8 @@ impl World {
|
||||
mut should_continue: impl FnMut() -> bool,
|
||||
time: Option<(TimeOfDay, Calendar)>,
|
||||
) -> Result<(TerrainChunk, ChunkSupplement), ()> {
|
||||
let calendar = time.as_ref().map(|(_, cal)| cal);
|
||||
|
||||
let mut sampler = self.sample_blocks();
|
||||
|
||||
let chunk_wpos2d = chunk_pos * TerrainChunkSize::RECT_SIZE.map(|e| e as i32);
|
||||
@ -225,7 +227,7 @@ impl World {
|
||||
let grid_border = 4;
|
||||
let zcache_grid = Grid::populate_from(
|
||||
TerrainChunkSize::RECT_SIZE.map(|e| e as i32) + grid_border * 2,
|
||||
|offs| sampler.get_z_cache(chunk_wpos2d - grid_border + offs, index),
|
||||
|offs| sampler.get_z_cache(chunk_wpos2d - grid_border + offs, index, calendar),
|
||||
);
|
||||
|
||||
let air = Block::air(SpriteKind::Empty);
|
||||
@ -348,6 +350,7 @@ impl World {
|
||||
chunks: &self.sim,
|
||||
index,
|
||||
chunk: sim_chunk,
|
||||
calendar,
|
||||
},
|
||||
chunk: &mut chunk,
|
||||
entities: Vec::new(),
|
||||
@ -363,7 +366,7 @@ impl World {
|
||||
layer::apply_shrubs_to(&mut canvas, &mut dynamic_rng);
|
||||
}
|
||||
if index.features.trees {
|
||||
layer::apply_trees_to(&mut canvas, &mut dynamic_rng);
|
||||
layer::apply_trees_to(&mut canvas, &mut dynamic_rng, calendar);
|
||||
}
|
||||
if index.features.scatter {
|
||||
layer::apply_scatter_to(&mut canvas, &mut dynamic_rng);
|
||||
@ -425,7 +428,7 @@ impl World {
|
||||
index,
|
||||
sim_chunk,
|
||||
&mut supplement,
|
||||
time,
|
||||
time.as_ref(),
|
||||
);
|
||||
|
||||
// Apply site supplementary information
|
||||
|
@ -39,6 +39,7 @@ use crate::{
|
||||
IndexRef, CONFIG,
|
||||
};
|
||||
use common::{
|
||||
calendar::Calendar,
|
||||
assets::{self, AssetExt},
|
||||
grid::Grid,
|
||||
lottery::Lottery,
|
||||
@ -1460,7 +1461,7 @@ impl WorldSim {
|
||||
|
||||
/// Draw a map of the world based on chunk information. Returns a buffer of
|
||||
/// u32s.
|
||||
pub fn get_map(&self, index: IndexRef) -> WorldMapMsg {
|
||||
pub fn get_map(&self, index: IndexRef, calendar: Option<&Calendar>) -> WorldMapMsg {
|
||||
let mut map_config = MapConfig::orthographic(
|
||||
self.map_size_lg(),
|
||||
core::ops::RangeInclusive::new(CONFIG.sea_level, CONFIG.sea_level + self.max_height),
|
||||
@ -1485,8 +1486,11 @@ impl WorldSim {
|
||||
|| Box::new(BlockGen::new(ColumnGen::new(self))),
|
||||
|_block_gen, posi| {
|
||||
let sample = column_sample.get(
|
||||
(uniform_idx_as_vec2(self.map_size_lg(), posi) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
|
||||
index)
|
||||
(
|
||||
uniform_idx_as_vec2(self.map_size_lg(), posi) * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
|
||||
index,
|
||||
calendar,
|
||||
)
|
||||
)?;
|
||||
// sample.water_level = CONFIG.sea_level.max(sample.water_level);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user