mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Began work integrating new sites into the world
This commit is contained in:
parent
6af0e77efd
commit
c7e82aea26
@ -8,6 +8,7 @@ use crate::{
|
|||||||
sim::WorldSim,
|
sim::WorldSim,
|
||||||
site::{namegen::NameGen, Castle, Dungeon, Settlement, Site as WorldSite},
|
site::{namegen::NameGen, Castle, Dungeon, Settlement, Site as WorldSite},
|
||||||
util::{attempt, seed_expan, MapVec, CARDINALS, NEIGHBORS},
|
util::{attempt, seed_expan, MapVec, CARDINALS, NEIGHBORS},
|
||||||
|
site2,
|
||||||
Index,
|
Index,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
@ -107,6 +108,7 @@ impl Civs {
|
|||||||
attempt(5, || {
|
attempt(5, || {
|
||||||
let (kind, size) = match ctx.rng.gen_range(0..8) {
|
let (kind, size) = match ctx.rng.gen_range(0..8) {
|
||||||
0 => (SiteKind::Castle, 3),
|
0 => (SiteKind::Castle, 3),
|
||||||
|
1 => (SiteKind::Refactor, 5),
|
||||||
_ => (SiteKind::Dungeon, 0),
|
_ => (SiteKind::Dungeon, 0),
|
||||||
};
|
};
|
||||||
let loc = find_site_loc(&mut ctx, None, size)?;
|
let loc = find_site_loc(&mut ctx, None, size)?;
|
||||||
@ -142,14 +144,13 @@ impl Civs {
|
|||||||
|
|
||||||
// Flatten ground around sites
|
// Flatten ground around sites
|
||||||
for site in this.sites.values() {
|
for site in this.sites.values() {
|
||||||
let radius = 48i32;
|
|
||||||
|
|
||||||
let wpos = site.center * TerrainChunkSize::RECT_SIZE.map(|e: u32| e as i32);
|
let wpos = site.center * TerrainChunkSize::RECT_SIZE.map(|e: u32| e as i32);
|
||||||
|
|
||||||
let flatten_radius = match &site.kind {
|
let (radius, flatten_radius) = match &site.kind {
|
||||||
SiteKind::Settlement => 10.0,
|
SiteKind::Settlement => (32i32, 10.0),
|
||||||
SiteKind::Dungeon => 2.0,
|
SiteKind::Dungeon => (8i32, 2.0),
|
||||||
SiteKind::Castle => 5.0,
|
SiteKind::Castle => (16i32, 5.0),
|
||||||
|
SiteKind::Refactor => (0i32, 0.0),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (raise, raise_dist): (f32, i32) = match &site.kind {
|
let (raise, raise_dist): (f32, i32) = match &site.kind {
|
||||||
@ -215,6 +216,13 @@ impl Civs {
|
|||||||
SiteKind::Castle => {
|
SiteKind::Castle => {
|
||||||
WorldSite::castle(Castle::generate(wpos, Some(ctx.sim), &mut rng))
|
WorldSite::castle(Castle::generate(wpos, Some(ctx.sim), &mut rng))
|
||||||
},
|
},
|
||||||
|
SiteKind::Refactor => {
|
||||||
|
WorldSite::refactor({
|
||||||
|
let mut site = site2::Site::generate(&mut rng);
|
||||||
|
site.origin = wpos;
|
||||||
|
site
|
||||||
|
})
|
||||||
|
},
|
||||||
});
|
});
|
||||||
sim_site.site_tmp = Some(site);
|
sim_site.site_tmp = Some(site);
|
||||||
let site_ref = &index.sites[site];
|
let site_ref = &index.sites[site];
|
||||||
@ -893,6 +901,7 @@ pub enum SiteKind {
|
|||||||
Settlement,
|
Settlement,
|
||||||
Dungeon,
|
Dungeon,
|
||||||
Castle,
|
Castle,
|
||||||
|
Refactor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Site {
|
impl Site {
|
||||||
|
@ -185,7 +185,7 @@ pub fn apply_trees_to(canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
|
|||||||
TreeModel::Procedural(t, leaf_block) => Some(
|
TreeModel::Procedural(t, leaf_block) => Some(
|
||||||
match t.is_branch_or_leaves_at(model_pos.map(|e| e as f32 + 0.5)) {
|
match t.is_branch_or_leaves_at(model_pos.map(|e| e as f32 + 0.5)) {
|
||||||
(_, _, true, _) => StructureBlock::Block(BlockKind::Wood, Rgb::new(110, 68, 22)),
|
(_, _, true, _) => StructureBlock::Block(BlockKind::Wood, Rgb::new(110, 68, 22)),
|
||||||
(_, _, _, true) => StructureBlock::Hollow,
|
(_, _, _, true) => StructureBlock::None,
|
||||||
(true, _, _, _) => StructureBlock::Log,
|
(true, _, _, _) => StructureBlock::Log,
|
||||||
(_, true, _, _) => *leaf_block,
|
(_, true, _, _) => *leaf_block,
|
||||||
_ => StructureBlock::None,
|
_ => StructureBlock::None,
|
||||||
@ -299,17 +299,17 @@ impl TreeConfig {
|
|||||||
let log_scale = 1.0 + scale.log2().max(0.0);
|
let log_scale = 1.0 + scale.log2().max(0.0);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
trunk_len: 32.0 * scale,
|
trunk_len: 24.0 * scale,
|
||||||
trunk_radius: 1.25 * scale,
|
trunk_radius: 1.25 * scale,
|
||||||
branch_child_len: 0.3 / scale,
|
branch_child_len: 0.4 / scale,
|
||||||
branch_child_radius: 0.0,
|
branch_child_radius: 0.0,
|
||||||
leaf_radius: 1.5 * log_scale..2.0 * log_scale,
|
leaf_radius: 1.5 * log_scale..2.0 * log_scale,
|
||||||
straightness: 0.0,
|
straightness: 0.0,
|
||||||
max_depth: 1,
|
max_depth: 1,
|
||||||
splits: 50.0..70.0,
|
splits: 50.0..70.0,
|
||||||
split_range: 0.1..1.2,
|
split_range: 0.15..1.2,
|
||||||
branch_len_bias: 0.75,
|
branch_len_bias: 0.75,
|
||||||
leaf_vertical_scale: 0.3,
|
leaf_vertical_scale: 0.5,
|
||||||
proportionality: 1.0,
|
proportionality: 1.0,
|
||||||
inhabited: false,
|
inhabited: false,
|
||||||
}
|
}
|
||||||
@ -362,6 +362,7 @@ impl ProceduralTree {
|
|||||||
0,
|
0,
|
||||||
None,
|
None,
|
||||||
rng,
|
rng,
|
||||||
|
true,
|
||||||
);
|
);
|
||||||
this.trunk_idx = trunk_idx;
|
this.trunk_idx = trunk_idx;
|
||||||
|
|
||||||
@ -382,6 +383,7 @@ impl ProceduralTree {
|
|||||||
depth: usize,
|
depth: usize,
|
||||||
sibling_idx: Option<usize>,
|
sibling_idx: Option<usize>,
|
||||||
rng: &mut impl Rng,
|
rng: &mut impl Rng,
|
||||||
|
has_stairs: bool,
|
||||||
) -> (usize, Aabb<f32>) {
|
) -> (usize, Aabb<f32>) {
|
||||||
let end = start + dir * branch_len;
|
let end = start + dir * branch_len;
|
||||||
let line = LineSegment3 { start, end };
|
let line = LineSegment3 { start, end };
|
||||||
@ -392,7 +394,7 @@ impl ProceduralTree {
|
|||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
|
|
||||||
let has_stairs = config.inhabited && depth < config.max_depth && branch_radius > 6.5 && start.xy().distance(end.xy()) < (start.z - end.z).abs() * 1.5;
|
let has_stairs = /*has_stairs &&*/ config.inhabited && depth < config.max_depth && branch_radius > 6.5 && start.xy().distance(end.xy()) < (start.z - end.z).abs() * 1.5;
|
||||||
let bark_radius = if has_stairs { 5.0 } else { 0.0 } + wood_radius * 0.25;
|
let bark_radius = if has_stairs { 5.0 } else { 0.0 } + wood_radius * 0.25;
|
||||||
|
|
||||||
// The AABB that covers this branch, along with wood and leaves that eminate
|
// The AABB that covers this branch, along with wood and leaves that eminate
|
||||||
@ -458,6 +460,7 @@ impl ProceduralTree {
|
|||||||
depth + 1,
|
depth + 1,
|
||||||
child_idx,
|
child_idx,
|
||||||
rng,
|
rng,
|
||||||
|
has_stairs,
|
||||||
);
|
);
|
||||||
child_idx = Some(branch_idx);
|
child_idx = Some(branch_idx);
|
||||||
// Parent branches AABBs include the AABBs of child branches to allow for
|
// Parent branches AABBs include the AABBs of child branches to allow for
|
||||||
@ -485,30 +488,30 @@ impl ProceduralTree {
|
|||||||
pub fn get_bounds(&self) -> Aabb<f32> { self.branches[self.trunk_idx].aabb }
|
pub fn get_bounds(&self) -> Aabb<f32> { self.branches[self.trunk_idx].aabb }
|
||||||
|
|
||||||
// Recursively search for branches or leaves by walking the tree's branch graph.
|
// Recursively search for branches or leaves by walking the tree's branch graph.
|
||||||
fn is_branch_or_leaves_at_inner(&self, pos: Vec3<f32>, parent_d2: f32, branch_idx: usize) -> (bool, bool, bool, bool) {
|
fn is_branch_or_leaves_at_inner(&self, pos: Vec3<f32>, parent: &Branch, branch_idx: usize) -> (bool, bool, bool, bool) {
|
||||||
let branch = &self.branches[branch_idx];
|
let branch = &self.branches[branch_idx];
|
||||||
// Always probe the sibling branch, since our AABB doesn't include its bounds
|
// Always probe the sibling branch, since our AABB doesn't include its bounds
|
||||||
// (it's not one of our children)
|
// (it's not one of our children)
|
||||||
let branch_or_leaves = branch
|
let branch_or_leaves = branch
|
||||||
.sibling_idx
|
.sibling_idx
|
||||||
.map(|idx| Vec4::<bool>::from(self.is_branch_or_leaves_at_inner(pos, parent_d2, idx)))
|
.map(|idx| Vec4::<bool>::from(self.is_branch_or_leaves_at_inner(pos, parent, idx)))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
// Only continue probing this sub-graph of the tree if the sample position falls
|
// Only continue probing this sub-graph of the tree if the sample position falls
|
||||||
// within its AABB
|
// within its AABB
|
||||||
if branch.aabb.contains_point(pos) {
|
if branch.aabb.contains_point(pos) {
|
||||||
// Probe this branch
|
// Probe this branch
|
||||||
let (this, d2) = branch.is_branch_or_leaves_at(pos, parent_d2);
|
let (this, d2) = branch.is_branch_or_leaves_at(pos, parent);
|
||||||
|
|
||||||
let siblings = branch_or_leaves | Vec4::from(this);
|
let siblings = branch_or_leaves | Vec4::from(this);
|
||||||
|
|
||||||
// Probe the children of this branch
|
// Probe the children of this branch
|
||||||
let children = branch.child_idx
|
let children = branch.child_idx
|
||||||
.map(|idx| Vec4::from(self.is_branch_or_leaves_at_inner(pos, d2, idx)))
|
.map(|idx| Vec4::<bool>::from(self.is_branch_or_leaves_at_inner(pos, branch, idx)))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
// Only allow empties for children if there is no solid at the current depth
|
// Only allow empties for children if there is no solid at the current depth
|
||||||
(siblings | (children & Vec4::new(true, true, true, !(siblings.x | siblings.y)))).into_tuple()
|
(siblings | children).into_tuple()
|
||||||
} else {
|
} else {
|
||||||
branch_or_leaves.into_tuple()
|
branch_or_leaves.into_tuple()
|
||||||
}
|
}
|
||||||
@ -518,7 +521,8 @@ impl ProceduralTree {
|
|||||||
/// position in the tree.
|
/// position in the tree.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_branch_or_leaves_at(&self, pos: Vec3<f32>) -> (bool, bool, bool, bool) {
|
pub fn is_branch_or_leaves_at(&self, pos: Vec3<f32>) -> (bool, bool, bool, bool) {
|
||||||
self.is_branch_or_leaves_at_inner(pos, 10000.0, self.trunk_idx)
|
let (log, leaf, platform, air) = self.is_branch_or_leaves_at_inner(pos, &self.branches[self.trunk_idx], self.trunk_idx);
|
||||||
|
(log /*& !air*/, leaf & !air, platform & !air, air)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,26 +547,36 @@ struct Branch {
|
|||||||
impl Branch {
|
impl Branch {
|
||||||
/// Determine whether there are either branches or leaves at the given
|
/// Determine whether there are either branches or leaves at the given
|
||||||
/// position in the branch.
|
/// position in the branch.
|
||||||
pub fn is_branch_or_leaves_at(&self, pos: Vec3<f32>, parent_d2: f32) -> ((bool, bool, bool, bool), f32) {
|
pub fn is_branch_or_leaves_at(&self, pos: Vec3<f32>, parent: &Branch) -> ((bool, bool, bool, bool), f32) {
|
||||||
// fn finvsqrt(x: f32) -> f32 {
|
// fn finvsqrt(x: f32) -> f32 {
|
||||||
// let y = f32::from_bits(0x5f375a86 - (x.to_bits() >> 1));
|
// let y = f32::from_bits(0x5f375a86 - (x.to_bits() >> 1));
|
||||||
// y * (1.5 - ( x * 0.5 * y * y ))
|
// y * (1.5 - ( x * 0.5 * y * y ))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn smooth(a: f32, b: f32, k: f32) -> f32 {
|
fn length_factor(line: LineSegment3<f32>, p: Vec3<f32>) -> f32 {
|
||||||
// let h = (0.5 + 0.5 * (b - a) / k).clamped(0.0, 1.0);
|
let len_sq = line.start.distance_squared(line.end);
|
||||||
// Lerp::lerp(b, a, h) - k * h * (1.0 - h)
|
if len_sq < 0.001 {
|
||||||
|
0.0
|
||||||
let h = (k-(a-b).abs()).max(0.0);
|
} else {
|
||||||
a.min(b) - h * h * 0.25 / k
|
(p - line.start).dot(line.end - line.start) / len_sq
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn smooth(a: f32, b: f32, k: f32) -> f32 {
|
||||||
|
// // let h = (0.5 + 0.5 * (b - a) / k).clamped(0.0, 1.0);
|
||||||
|
// // Lerp::lerp(b, a, h) - k * h * (1.0 - h)
|
||||||
|
|
||||||
|
// let h = (k-(a-b).abs()).max(0.0);
|
||||||
|
// a.min(b) - h * h * 0.25 / k
|
||||||
|
// }
|
||||||
|
|
||||||
let p = self.line.projected_point(pos);
|
let p = self.line.projected_point(pos);
|
||||||
let d2 = p.distance_squared(pos);
|
let d2 = p.distance_squared(pos);
|
||||||
|
|
||||||
let d2_smooth = d2;//smooth(d2.sqrt(), parent_d2.sqrt(), 30.0).powi(2);
|
let length_factor = length_factor(self.line, pos);
|
||||||
|
let wood_radius = Lerp::lerp(parent.wood_radius, self.wood_radius, length_factor);
|
||||||
|
|
||||||
let mask = if d2_smooth < self.wood_radius.powi(2) {
|
let mask = if d2 < wood_radius.powi(2) {
|
||||||
(true, false, false, false) // Wood
|
(true, false, false, false) // Wood
|
||||||
} else if {
|
} else if {
|
||||||
let diff = (p - pos) / Vec3::new(1.0, 1.0, self.leaf_vertical_scale);
|
let diff = (p - pos) / Vec3::new(1.0, 1.0, self.leaf_vertical_scale);
|
||||||
@ -571,13 +585,25 @@ impl Branch {
|
|||||||
(false, true, false, false) // Leaves
|
(false, true, false, false) // Leaves
|
||||||
} else {
|
} else {
|
||||||
let stair_width = 5.0;
|
let stair_width = 5.0;
|
||||||
let stair_thickness = 1.5;
|
let stair_thickness = 2.0;
|
||||||
let stair_space = 6.0;
|
let stair_space = 5.0;
|
||||||
if self.has_stairs && d2_smooth < (self.wood_radius + stair_width).powi(2) {
|
if self.has_stairs {
|
||||||
let rpos = pos.xy() - p.xy();
|
let (platform, air) = if pos.z >= self.line.start.z.min(self.line.end.z) - 1.0 && pos.z <= self.line.start.z.max(self.line.end.z) + stair_thickness + stair_space && d2 < (wood_radius + stair_width).powi(2) {
|
||||||
let stretch = 32.0;
|
let rpos = pos.xy() - p;
|
||||||
let stair_section = ((rpos.x as f32).atan2(rpos.y as f32) / (f32::consts::PI * 2.0) * stretch + pos.z).rem_euclid(stretch);
|
let stretch = 32.0;
|
||||||
(false, false, stair_section < stair_thickness, stair_section >= stair_thickness && stair_section < stair_thickness + stair_space) // Stairs
|
let stair_section = ((rpos.x as f32).atan2(rpos.y as f32) / (f32::consts::PI * 2.0) * stretch + pos.z).rem_euclid(stretch);
|
||||||
|
(stair_section < stair_thickness, stair_section >= stair_thickness && stair_section < stair_thickness + stair_space) // Stairs
|
||||||
|
} else {
|
||||||
|
(false, false)
|
||||||
|
};
|
||||||
|
|
||||||
|
let platform = platform || (self.has_stairs
|
||||||
|
&& self.wood_radius > 4.0
|
||||||
|
&& !air
|
||||||
|
&& d2 < (wood_radius + 10.0).powi(2)
|
||||||
|
&& pos.z % 48.0 < stair_thickness);
|
||||||
|
|
||||||
|
(false, false, platform, air)
|
||||||
} else {
|
} else {
|
||||||
(false, false, false, false)
|
(false, false, false, false)
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,7 @@ impl World {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
civ::SiteKind::Castle => world_msg::SiteKind::Castle,
|
civ::SiteKind::Castle => world_msg::SiteKind::Castle,
|
||||||
|
civ::SiteKind::Refactor => world_msg::SiteKind::Town,
|
||||||
},
|
},
|
||||||
wpos: site.center * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
|
wpos: site.center * TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
|
||||||
}
|
}
|
||||||
@ -294,7 +295,7 @@ impl World {
|
|||||||
|
|
||||||
// Apply site generation
|
// Apply site generation
|
||||||
sim_chunk.sites.iter().for_each(|site| {
|
sim_chunk.sites.iter().for_each(|site| {
|
||||||
index.sites[*site].apply_to(index, chunk_wpos2d, sample_get, &mut chunk)
|
index.sites[*site].apply_to(&mut canvas, &mut dynamic_rng)
|
||||||
});
|
});
|
||||||
|
|
||||||
let gen_entity_pos = |dynamic_rng: &mut rand::rngs::ThreadRng| {
|
let gen_entity_pos = |dynamic_rng: &mut rand::rngs::ThreadRng| {
|
||||||
|
@ -11,7 +11,12 @@ pub use self::{
|
|||||||
settlement::Settlement,
|
settlement::Settlement,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{column::ColumnSample, IndexRef};
|
use crate::{
|
||||||
|
column::ColumnSample,
|
||||||
|
IndexRef,
|
||||||
|
site2,
|
||||||
|
Canvas,
|
||||||
|
};
|
||||||
use common::{
|
use common::{
|
||||||
generation::ChunkSupplement,
|
generation::ChunkSupplement,
|
||||||
terrain::Block,
|
terrain::Block,
|
||||||
@ -45,6 +50,7 @@ pub enum SiteKind {
|
|||||||
Settlement(Settlement),
|
Settlement(Settlement),
|
||||||
Dungeon(Dungeon),
|
Dungeon(Dungeon),
|
||||||
Castle(Castle),
|
Castle(Castle),
|
||||||
|
Refactor(site2::Site),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Site {
|
impl Site {
|
||||||
@ -69,11 +75,19 @@ impl Site {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn refactor(s: site2::Site) -> Self {
|
||||||
|
Self {
|
||||||
|
kind: SiteKind::Refactor(s),
|
||||||
|
economy: Economy::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn radius(&self) -> f32 {
|
pub fn radius(&self) -> f32 {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
SiteKind::Settlement(s) => s.radius(),
|
SiteKind::Settlement(s) => s.radius(),
|
||||||
SiteKind::Dungeon(d) => d.radius(),
|
SiteKind::Dungeon(d) => d.radius(),
|
||||||
SiteKind::Castle(c) => c.radius(),
|
SiteKind::Castle(c) => c.radius(),
|
||||||
|
SiteKind::Refactor(s) => s.radius(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +96,7 @@ impl Site {
|
|||||||
SiteKind::Settlement(s) => s.get_origin(),
|
SiteKind::Settlement(s) => s.get_origin(),
|
||||||
SiteKind::Dungeon(d) => d.get_origin(),
|
SiteKind::Dungeon(d) => d.get_origin(),
|
||||||
SiteKind::Castle(c) => c.get_origin(),
|
SiteKind::Castle(c) => c.get_origin(),
|
||||||
|
SiteKind::Refactor(s) => s.origin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +105,7 @@ impl Site {
|
|||||||
SiteKind::Settlement(s) => s.spawn_rules(wpos),
|
SiteKind::Settlement(s) => s.spawn_rules(wpos),
|
||||||
SiteKind::Dungeon(d) => d.spawn_rules(wpos),
|
SiteKind::Dungeon(d) => d.spawn_rules(wpos),
|
||||||
SiteKind::Castle(c) => c.spawn_rules(wpos),
|
SiteKind::Castle(c) => c.spawn_rules(wpos),
|
||||||
|
SiteKind::Refactor(s) => s.spawn_rules(wpos),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,20 +114,24 @@ impl Site {
|
|||||||
SiteKind::Settlement(s) => s.name(),
|
SiteKind::Settlement(s) => s.name(),
|
||||||
SiteKind::Dungeon(d) => d.name(),
|
SiteKind::Dungeon(d) => d.name(),
|
||||||
SiteKind::Castle(c) => c.name(),
|
SiteKind::Castle(c) => c.name(),
|
||||||
|
SiteKind::Refactor(s) => "Experimental",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_to<'a>(
|
pub fn apply_to<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
index: IndexRef,
|
canvas: &mut Canvas,
|
||||||
wpos2d: Vec2<i32>,
|
dynamic_rng: &mut impl Rng,
|
||||||
get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
|
||||||
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
|
|
||||||
) {
|
) {
|
||||||
|
let info = canvas.info();
|
||||||
|
let get_col = |wpos| info.col(wpos + info.wpos);
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
SiteKind::Settlement(s) => s.apply_to(index, wpos2d, get_column, vol),
|
SiteKind::Settlement(s) => s.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
|
||||||
SiteKind::Dungeon(d) => d.apply_to(index, wpos2d, get_column, vol),
|
SiteKind::Dungeon(d) => d.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
|
||||||
SiteKind::Castle(c) => c.apply_to(index, wpos2d, get_column, vol),
|
SiteKind::Castle(c) => c.apply_to(canvas.index, canvas.wpos, get_col, canvas.chunk),
|
||||||
|
SiteKind::Refactor(s) => {
|
||||||
|
s.render(canvas, dynamic_rng);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,6 +149,7 @@ impl Site {
|
|||||||
},
|
},
|
||||||
SiteKind::Dungeon(d) => d.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
SiteKind::Dungeon(d) => d.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
||||||
SiteKind::Castle(c) => c.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
SiteKind::Castle(c) => c.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
||||||
|
SiteKind::Refactor(_) => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,18 +5,38 @@ use self::{
|
|||||||
plot::{Plot, PlotKind},
|
plot::{Plot, PlotKind},
|
||||||
tile::TileGrid,
|
tile::TileGrid,
|
||||||
};
|
};
|
||||||
use crate::util::Grid;
|
use crate::{
|
||||||
|
site::SpawnRules,
|
||||||
|
util::Grid,
|
||||||
|
Canvas,
|
||||||
|
};
|
||||||
use common::store::{Id, Store};
|
use common::store::{Id, Store};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Site {
|
pub struct Site {
|
||||||
|
pub(crate) origin: Vec2<i32>,
|
||||||
tiles: TileGrid,
|
tiles: TileGrid,
|
||||||
plots: Store<Plot>,
|
plots: Store<Plot>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Site {
|
impl Site {
|
||||||
|
pub fn radius(&self) -> f32 {
|
||||||
|
(tile::MAX_BLOCK_RADIUS.pow(2) as f32 * 2.0).sqrt()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_rules(&self, wpos: Vec2<i32>) -> SpawnRules {
|
||||||
|
if wpos.distance_squared(self.origin) < 100i32.pow(2) {
|
||||||
|
SpawnRules {
|
||||||
|
trees: false,
|
||||||
|
..SpawnRules::default()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SpawnRules::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bounds(&self) -> Aabr<i32> {
|
pub fn bounds(&self) -> Aabr<i32> {
|
||||||
let radius = tile::MAX_BLOCK_RADIUS;
|
let radius = tile::MAX_BLOCK_RADIUS;
|
||||||
Aabr {
|
Aabr {
|
||||||
@ -47,6 +67,10 @@ impl Site {
|
|||||||
|
|
||||||
site
|
site
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render(&self, canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn test_site() -> Site { Site::generate(&mut thread_rng()) }
|
pub fn test_site() -> Site { Site::generate(&mut thread_rng()) }
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
use common::spiral::Spiral2d;
|
||||||
|
|
||||||
pub const TILE_SIZE: u32 = 7;
|
pub const TILE_SIZE: u32 = 7;
|
||||||
pub const ZONE_SIZE: u32 = 16;
|
pub const ZONE_SIZE: u32 = 16;
|
||||||
@ -19,7 +20,9 @@ impl Default for TileGrid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TileGrid {
|
impl TileGrid {
|
||||||
pub fn get(&self, tpos: Vec2<i32>) -> Option<&Tile> {
|
pub fn get(&self, tpos: Vec2<i32>) -> &Tile {
|
||||||
|
static EMPTY: Tile = Tile::empty();
|
||||||
|
|
||||||
let tpos = tpos + TILE_RADIUS as i32;
|
let tpos = tpos + TILE_RADIUS as i32;
|
||||||
self.zones
|
self.zones
|
||||||
.get(tpos)
|
.get(tpos)
|
||||||
@ -28,6 +31,7 @@ impl TileGrid {
|
|||||||
.get(tpos.map(|e| e.rem_euclid(ZONE_SIZE as i32)))
|
.get(tpos.map(|e| e.rem_euclid(ZONE_SIZE as i32)))
|
||||||
})
|
})
|
||||||
.and_then(|tile| tile.as_ref())
|
.and_then(|tile| tile.as_ref())
|
||||||
|
.unwrap_or(&EMPTY)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mut(&mut self, tpos: Vec2<i32>) -> Option<&mut Tile> {
|
pub fn get_mut(&mut self, tpos: Vec2<i32>) -> Option<&mut Tile> {
|
||||||
@ -41,8 +45,14 @@ impl TileGrid {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, tpos: Vec2<i32>, tile: Tile) -> Option<Tile> {
|
||||||
|
self.get_mut(tpos).map(|t| std::mem::replace(t, tile))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn find_near(&self, tpos: Vec2<i32>, f: impl Fn(&Tile) -> bool) -> Option<Vec2<i32>> {
|
pub fn find_near(&self, tpos: Vec2<i32>, f: impl Fn(&Tile) -> bool) -> Option<Vec2<i32>> {
|
||||||
None
|
const MAX_SEARCH_RADIUS_BLOCKS: u32 = 256;
|
||||||
|
const MAX_SEARCH_CELLS: u32 = ((MAX_SEARCH_RADIUS_BLOCKS / TILE_SIZE) * 2).pow(2);
|
||||||
|
Spiral2d::new().take(MAX_SEARCH_CELLS as usize).map(|r| tpos + r).find(|tpos| (&f)(self.get(*tpos)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +69,7 @@ pub struct Tile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Tile {
|
impl Tile {
|
||||||
pub fn empty() -> Self {
|
pub const fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
kind: TileKind::Empty,
|
kind: TileKind::Empty,
|
||||||
plot: None,
|
plot: None,
|
||||||
|
Loading…
Reference in New Issue
Block a user