This commit is contained in:
Joshua Barretto 2019-06-23 20:43:02 +01:00
parent 397c909bd4
commit f781aca8e9
6 changed files with 184 additions and 133 deletions

View File

@ -152,27 +152,29 @@ fn handle_kill(server: &mut Server, entity: EcsEntity, _args: String, _action: &
fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) {
let time = scan_fmt!(&args, action.arg_fmt, String);
server
.state
.ecs_mut()
.write_resource::<TimeOfDay>()
.0 = match time.as_ref().map(|s| s.as_str()) {
Some("day") => 12.0 * 3600.0,
Some("night") => 24.0 * 3600.0,
Some("dawn") => 5.0 * 3600.0,
Some("dusk") => 17.0 * 3600.0,
Some(n) => match n.parse() {
Ok(n) => n,
Err(_) => {
server.clients.notify(entity, ServerMsg::Chat(format!("'{}' is not a time!", n)));
return;
},
},
None => {
server.clients.notify(entity, ServerMsg::Chat("You must specify a time!".to_string()));
server.state.ecs_mut().write_resource::<TimeOfDay>().0 = match time.as_ref().map(|s| s.as_str())
{
Some("day") => 12.0 * 3600.0,
Some("night") => 24.0 * 3600.0,
Some("dawn") => 5.0 * 3600.0,
Some("dusk") => 17.0 * 3600.0,
Some(n) => match n.parse() {
Ok(n) => n,
Err(_) => {
server
.clients
.notify(entity, ServerMsg::Chat(format!("'{}' is not a time!", n)));
return;
},
};
}
},
None => {
server.clients.notify(
entity,
ServerMsg::Chat("You must specify a time!".to_string()),
);
return;
}
};
}
fn handle_alias(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) {

View File

@ -141,7 +141,7 @@ widget_ids! {
image_ids! {
struct Imgs {
<VoxelGraphic>
<VoxelGraphic>
button: "voxygen/element/buttons/button.vox",
button_hover: "voxygen/element/buttons/button_hover.vox",
button_press: "voxygen/element/buttons/button_press.vox",
@ -169,7 +169,7 @@ image_ids! {
frame_open_press: "voxygen/element/buttons/frame/open_press.png",
skin_eyes_window: "voxygen/element/frames/skin_eyes.png",
hair_window: "voxygen/element/frames/skin_eyes.png",
accessories_window: "voxygen/element/frames/skin_eyes.png",
accessories_window: "voxygen/element/frames/skin_eyes.png",
slider_range: "voxygen/element/slider/track.png",
slider_indicator: "voxygen/element/slider/indicator.png",
window_frame_2: "voxygen/element/frames/window_2.png",

View File

@ -30,7 +30,8 @@ impl<'a> BlockGen<'a> {
fn sample_column(
column_gen: &ColumnGen<'a>,
cache: &mut HashCache<Vec2<i32>, Option<ColumnSample<'a>>>, wpos: Vec2<i32>,
cache: &mut HashCache<Vec2<i32>, Option<ColumnSample<'a>>>,
wpos: Vec2<i32>,
) -> Option<ColumnSample<'a>> {
cache
.get(Vec2::from(wpos), |wpos| column_gen.get(wpos))
@ -44,25 +45,34 @@ impl<'a> BlockGen<'a> {
close_cliffs: &[(Vec2<i32>, u32); 9],
cliff_hill: f32,
) -> f32 {
close_cliffs
.iter()
.fold(0.0f32, |max_height, (cliff_pos, seed)| {
match Self::sample_column(column_gen, cache, Vec2::from(*cliff_pos)) {
Some(cliff_sample) if cliff_sample.cliffs => {
let cliff_pos3d = Vec3::from(*cliff_pos);
close_cliffs.iter().fold(
0.0f32,
|max_height, (cliff_pos, seed)| match Self::sample_column(
column_gen,
cache,
Vec2::from(*cliff_pos),
) {
Some(cliff_sample) if cliff_sample.cliffs => {
let cliff_pos3d = Vec3::from(*cliff_pos);
let height = RandomField::new(seed + 1).get(cliff_pos3d) % 48;
let radius = RandomField::new(seed + 2).get(cliff_pos3d) % 48 + 8;
let height = RandomField::new(seed + 1).get(cliff_pos3d) % 48;
let radius = RandomField::new(seed + 2).get(cliff_pos3d) % 48 + 8;
max_height.max(if cliff_pos.map(|e| e as f32).distance_squared(wpos) < (radius * radius) as f32 {
cliff_sample.alt + height as f32 * (1.0 - cliff_sample.chaos) + cliff_hill
max_height.max(
if cliff_pos.map(|e| e as f32).distance_squared(wpos)
< (radius * radius) as f32
{
cliff_sample.alt
+ height as f32 * (1.0 - cliff_sample.chaos)
+ cliff_hill
} else {
0.0
})
},
_ => max_height,
},
)
}
})
_ => max_height,
},
)
}
}
@ -99,38 +109,53 @@ impl<'a> SamplerMut for BlockGen<'a> {
let wposf = wpos.map(|e| e as f64);
let (definitely_underground, height, water_height) = if (wposf.z as f32) < alt - 64.0 * chaos {
// Shortcut warping
(true, alt, water_level)
} else {
// Apply warping
let warp = (world
.sim()
.gen_ctx
.warp_nz
.get((wposf.div(Vec3::new(150.0, 150.0, 150.0))).into_array())
as f32)
.mul((chaos - 0.1).max(0.0))
.mul(115.0);
let height = if (wposf.z as f32) < alt + warp - 10.0 {
// Shortcut cliffs
alt + warp
let (definitely_underground, height, water_height) =
if (wposf.z as f32) < alt - 64.0 * chaos {
// Shortcut warping
(true, alt, water_level)
} else {
let turb = Vec2::new(
world.sim().gen_ctx.turb_x_nz.get((wposf.div(48.0)).into_array()) as f32,
world.sim().gen_ctx.turb_y_nz.get((wposf.div(48.0)).into_array()) as f32,
) * 12.0;
// Apply warping
let warp = (world
.sim()
.gen_ctx
.warp_nz
.get((wposf.div(Vec3::new(150.0, 150.0, 150.0))).into_array())
as f32)
.mul((chaos - 0.1).max(0.0))
.mul(115.0);
let wpos_turb = Vec2::from(wpos).map(|e: i32| e as f32) + turb;
let cliff_height = Self::get_cliff_height(column_gen, column_cache, wpos_turb, &close_cliffs, cliff_hill);
let height = if (wposf.z as f32) < alt + warp - 10.0 {
// Shortcut cliffs
alt + warp
} else {
let turb = Vec2::new(
world
.sim()
.gen_ctx
.turb_x_nz
.get((wposf.div(48.0)).into_array()) as f32,
world
.sim()
.gen_ctx
.turb_y_nz
.get((wposf.div(48.0)).into_array()) as f32,
) * 12.0;
(alt + warp).max(cliff_height)
let wpos_turb = Vec2::from(wpos).map(|e: i32| e as f32) + turb;
let cliff_height = Self::get_cliff_height(
column_gen,
column_cache,
wpos_turb,
&close_cliffs,
cliff_hill,
);
(alt + warp).max(cliff_height)
};
(false, height, water_level + warp)
};
(false, height, water_level + warp)
};
// Sample blocks
let stone_col = Rgb::new(200, 220, 255);
@ -162,7 +187,9 @@ impl<'a> SamplerMut for BlockGen<'a> {
let col = Lerp::lerp(
sub_surface_color,
surface_color,
(wposf.z as f32 - (height - grass_depth)).div(grass_depth).powf(0.5),
(wposf.z as f32 - (height - grass_depth))
.div(grass_depth)
.powf(0.5),
);
// Surface
Some(Block::new(1, col.map(|e| (e * 255.0) as u8)))
@ -260,36 +287,49 @@ impl<'a> SamplerMut for BlockGen<'a> {
Some(block) => block,
None => (&close_trees)
.iter()
.fold(air, |block, (tree_pos, tree_seed)| if !block.is_empty() {
block
} else {
match Self::sample_column(column_gen, column_cache, Vec2::from(*tree_pos)) {
Some(tree_sample)
if tree_sample.tree_density
> 0.5 + (*tree_seed as f32 / 1000.0).fract() * 0.2
&& tree_sample.alt > tree_sample.water_level =>
{
let cliff_height = Self::get_cliff_height(column_gen, column_cache, tree_pos.map(|e| e as f32), &tree_sample.close_cliffs, cliff_hill);
let height = tree_sample.alt.max(cliff_height);
let tree_pos3d = Vec3::new(tree_pos.x, tree_pos.y, height as i32);
let rpos = wpos - tree_pos3d;
.fold(air, |block, (tree_pos, tree_seed)| {
if !block.is_empty() {
block
} else {
match Self::sample_column(
column_gen,
column_cache,
Vec2::from(*tree_pos),
) {
Some(tree_sample)
if tree_sample.tree_density
> 0.5 + (*tree_seed as f32 / 1000.0).fract() * 0.2
&& tree_sample.alt > tree_sample.water_level =>
{
let cliff_height = Self::get_cliff_height(
column_gen,
column_cache,
tree_pos.map(|e| e as f32),
&tree_sample.close_cliffs,
cliff_hill,
);
let height = tree_sample.alt.max(cliff_height);
let tree_pos3d =
Vec3::new(tree_pos.x, tree_pos.y, height as i32);
let rpos = wpos - tree_pos3d;
let trees = tree::kinds(tree_sample.forest_kind); // Choose tree kind
let trees = tree::kinds(tree_sample.forest_kind); // Choose tree kind
block.or(trees[*tree_seed as usize % trees.len()]
.get((rpos * 128) / 128) // Scaling
.map(|b| {
block_from_structure(
*b,
rpos,
*tree_pos,
*tree_seed,
&tree_sample,
)
})
.unwrap_or(Block::empty()))
block.or(trees[*tree_seed as usize % trees.len()]
.get((rpos * 128) / 128) // Scaling
.map(|b| {
block_from_structure(
*b,
rpos,
*tree_pos,
*tree_seed,
&tree_sample,
)
})
.unwrap_or(Block::empty()))
}
_ => block,
}
_ => block,
}
}),
}

View File

@ -2,8 +2,7 @@ use crate::{
all::ForestKind,
sim::{Location, LocationInfo},
util::Sampler,
World,
CONFIG,
World, CONFIG,
};
use common::{
terrain::{Block, TerrainChunkSize},
@ -64,8 +63,8 @@ impl<'a> Sampler for ColumnGen<'a> {
.max(0.0)
.mul((1.0 - (chaos - 0.15) * 20.0).max(0.0).min(1.0));
let cliff_hill = (sim.gen_ctx.small_nz.get((wposf.div(128.0)).into_array()) as f32)
.mul(16.0);
let cliff_hill =
(sim.gen_ctx.small_nz.get((wposf.div(128.0)).into_array()) as f32).mul(16.0);
let riverless_alt = sim.get_interpolated(wpos, |chunk| chunk.alt)?
+ (sim.gen_ctx.small_nz.get((wposf.div(256.0)).into_array()) as f32)
@ -100,7 +99,8 @@ impl<'a> Sampler for ColumnGen<'a> {
let marble_small = (sim.gen_ctx.hill_nz.get((wposf3d.div(3.0)).into_array()) as f32)
.add(1.0)
.mul(0.5);
let marble = (sim.gen_ctx.hill_nz.get((wposf3d.div(48.0)).into_array()) as f32).mul(0.75)
let marble = (sim.gen_ctx.hill_nz.get((wposf3d.div(48.0)).into_array()) as f32)
.mul(0.75)
.add(1.0)
.mul(0.5)
.add(marble_small.mul(0.25));
@ -118,11 +118,7 @@ impl<'a> Sampler for ColumnGen<'a> {
let sand = Rgb::lerp(beach_sand, desert_sand, marble);
let cliff = Rgb::lerp(cold_stone, warm_stone, marble);
let dirt = Lerp::lerp(
Rgb::new(0.2, 0.1, 0.05),
Rgb::new(0.4, 0.25, 0.0),
marble,
);
let dirt = Lerp::lerp(Rgb::new(0.2, 0.1, 0.05), Rgb::new(0.4, 0.25, 0.0), marble);
let turf = grass;
@ -139,18 +135,27 @@ impl<'a> Sampler for ColumnGen<'a> {
);
// Work out if we're on a path or near a town
let near_0 = sim_chunk.location.as_ref().map(|l| l.near[0].block_pos).unwrap_or(Vec2::zero()).map(|e| e as f32);
let near_1 = sim_chunk.location.as_ref().map(|l| l.near[1].block_pos).unwrap_or(Vec2::zero()).map(|e| e as f32);
let near_0 = sim_chunk
.location
.as_ref()
.map(|l| l.near[0].block_pos)
.unwrap_or(Vec2::zero())
.map(|e| e as f32);
let near_1 = sim_chunk
.location
.as_ref()
.map(|l| l.near[1].block_pos)
.unwrap_or(Vec2::zero())
.map(|e| e as f32);
let dist_to_path = (0.0
+ (near_1.y - near_0.y) * wposf_turb.x as f32
let dist_to_path = (0.0 + (near_1.y - near_0.y) * wposf_turb.x as f32
- (near_1.x - near_0.x) * wposf_turb.y as f32
+ near_1.x * near_0.y
- near_0.x * near_1.y)
.abs()
.div(near_0.distance(near_1));
.abs()
.div(near_0.distance(near_1));
let on_path = dist_to_path < 5.0;// || near_0.distance(wposf_turb.map(|e| e as f32)) < 150.0;
let on_path = dist_to_path < 5.0; // || near_0.distance(wposf_turb.map(|e| e as f32)) < 150.0;
let (alt, ground) = if on_path {
(alt - 1.0, dirt)

View File

@ -48,12 +48,12 @@ fn generate_name<R: Rng>(rng: &mut R) -> String {
];
let mid = ["ka", "se", "au", "da", "di"];
let tails = [
/*"mill",*/ "ben", "sel", "dori", "theas", "dar", "bur", "to", "vis", "ten", "stone", "tiva",
"id", "and", "or", "el", "ond", "ia", "eld", "ald", "aft", "ift", "ity", "well", "oll",
"ill", "all", "wyn", "light", " Hill", "lin", "mont", "mor", "cliff", "rok", "den", "mi",
"rock", "glenn", "rovi", "lea", "gate", "view", "ley", "wood", "ovia", "cliff", "marsh",
"kor", "ice", /*"river",*/ "acre", "venn", "crest", "field", "vale", "spring", " Vale",
"grasp", "fel", "fall", "grove", "wyn", "edge",
/*"mill",*/ "ben", "sel", "dori", "theas", "dar", "bur", "to", "vis", "ten", "stone",
"tiva", "id", "and", "or", "el", "ond", "ia", "eld", "ald", "aft", "ift", "ity", "well",
"oll", "ill", "all", "wyn", "light", " Hill", "lin", "mont", "mor", "cliff", "rok", "den",
"mi", "rock", "glenn", "rovi", "lea", "gate", "view", "ley", "wood", "ovia", "cliff",
"marsh", "kor", "ice", /*"river",*/ "acre", "venn", "crest", "field", "vale",
"spring", " Vale", "grasp", "fel", "fall", "grove", "wyn", "edge",
];
let mut name = String::new();

View File

@ -5,14 +5,17 @@ pub use self::location::Location;
use crate::{
all::ForestKind,
util::{StructureGen2d, Sampler},
util::{Sampler, StructureGen2d},
CONFIG,
};
use common::{
terrain::{BiomeKind, TerrainChunkSize},
vol::VolSize,
};
use noise::{BasicMulti, HybridMulti, MultiFractal, NoiseFn, RidgedMulti, Seedable, OpenSimplex, SuperSimplex};
use noise::{
BasicMulti, HybridMulti, MultiFractal, NoiseFn, OpenSimplex, RidgedMulti, Seedable,
SuperSimplex,
};
use rand::{prng::XorShiftRng, Rng, SeedableRng};
use std::{
ops::{Add, Div, Mul, Neg, Sub},
@ -132,12 +135,12 @@ impl WorldSim {
self.rng.gen::<usize>() % grid_size.y,
);
let wpos = (cell_pos * cell_size)
.map2(
Vec2::from(TerrainChunkSize::SIZE),
|e, sz: u32| e as i32 * sz as i32,
);
.map2(Vec2::from(TerrainChunkSize::SIZE), |e, sz: u32| {
e as i32 * sz as i32
});
locations[cell_pos.y * grid_size.x + cell_pos.x] = Some(Arc::new(Location::generate(wpos, &mut rng)));
locations[cell_pos.y * grid_size.x + cell_pos.x] =
Some(Arc::new(Location::generate(wpos, &mut rng)));
}
// Simulate invasion!
@ -148,10 +151,8 @@ impl WorldSim {
if locations[j * grid_size.x + i].is_none() {
const R_COORDS: [i32; 5] = [-1, 0, 1, 0, -1];
let idx = self.rng.gen::<usize>() % 4;
let loc = Vec2::new(
i as i32 + R_COORDS[idx],
j as i32 + R_COORDS[idx + 1],
).map(|e| e as usize);
let loc = Vec2::new(i as i32 + R_COORDS[idx], j as i32 + R_COORDS[idx + 1])
.map(|e| e as usize);
locations[j * grid_size.x + i] = locations
.get(loc.y * grid_size.x + loc.x)
@ -175,7 +176,9 @@ impl WorldSim {
.iter()
.map(|(pos, seed)| RegionInfo {
chunk_pos: *pos,
block_pos: pos.map2(Vec2::from(TerrainChunkSize::SIZE), |e, sz: u32| e * sz as i32),
block_pos: pos.map2(Vec2::from(TerrainChunkSize::SIZE), |e, sz: u32| {
e * sz as i32
}),
dist: (pos - chunk_pos).map(|e| e as f32).magnitude(),
seed: *seed,
})
@ -189,10 +192,7 @@ impl WorldSim {
.get(nearest_cell_pos.y * grid_size.x + nearest_cell_pos.x)
.cloned()
.unwrap_or(None)
.map(|loc| LocationInfo {
loc,
near,
});
.map(|loc| LocationInfo { loc, near });
}
}
@ -409,7 +409,10 @@ impl SimChunk {
.sub(0.1)
.mul(1.3)
.max(0.0),
cliffs: cliff > 0.5 && dryness > 0.05 && alt > CONFIG.sea_level + 5.0 && dryness.abs() > 0.075,
cliffs: cliff > 0.5
&& dryness > 0.05
&& alt > CONFIG.sea_level + 5.0
&& dryness.abs() > 0.075,
near_cliffs: cliff > 0.4,
tree_density: (gen_ctx.tree_nz.get((wposf.div(1024.0)).into_array()) as f32)
.add(1.0)
@ -447,7 +450,8 @@ impl SimChunk {
}
pub fn get_max_z(&self) -> f32 {
(self.alt + Z_TOLERANCE.1 * if self.near_cliffs { 1.0 } else { 0.5 }).max(CONFIG.sea_level + 2.0)
(self.alt + Z_TOLERANCE.1 * if self.near_cliffs { 1.0 } else { 0.5 })
.max(CONFIG.sea_level + 2.0)
}
pub fn get_name(&self) -> Option<String> {