mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Optimised sub-terrain chonk storage, fixed hash chunk bug, altered terrain base
This commit is contained in:
parent
910eccee82
commit
92f2d36b0c
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2569,6 +2569,7 @@ dependencies = [
|
||||
name = "veloren-client"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"specs 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vek 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -7,6 +7,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
common = { package = "veloren-common", path = "../common" }
|
||||
|
||||
log = "0.4"
|
||||
specs = "0.14"
|
||||
vek = "0.9"
|
||||
threadpool = "1.7"
|
||||
|
@ -12,18 +12,21 @@ use common::{
|
||||
msg::{ClientMsg, ClientState, ServerInfo, ServerMsg},
|
||||
net::PostBox,
|
||||
state::State,
|
||||
terrain::chonk::ChonkMetrics,
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
net::SocketAddr,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use threadpool::ThreadPool;
|
||||
use log::info;
|
||||
use vek::*;
|
||||
|
||||
const SERVER_TIMEOUT: Duration = Duration::from_secs(20);
|
||||
|
||||
const DEBUG_METRICS: bool = true;
|
||||
|
||||
pub enum Event {
|
||||
Chat(String),
|
||||
Disconnect,
|
||||
@ -308,6 +311,15 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
// Output debug metrics
|
||||
if DEBUG_METRICS && self.tick % 600 == 0 {
|
||||
let metrics = self.state
|
||||
.terrain()
|
||||
.iter()
|
||||
.fold(ChonkMetrics::default(), |a, (_, c)| a + c.get_metrics());
|
||||
info!("{:?}", metrics);
|
||||
}
|
||||
|
||||
// 7) Finish the tick, pass control back to the frontend.
|
||||
|
||||
self.tick += 1;
|
||||
|
@ -4,7 +4,10 @@ use crate::{
|
||||
volumes::chunk::{Chunk, ChunkErr},
|
||||
};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::{
|
||||
ops::Add,
|
||||
collections::HashMap,
|
||||
};
|
||||
use vek::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -43,6 +46,24 @@ impl Chonk {
|
||||
self.z_offset + (self.sub_chunks.len() as u32 * SUB_CHUNK_HEIGHT) as i32
|
||||
}
|
||||
|
||||
pub fn get_metrics(&self) -> ChonkMetrics {
|
||||
ChonkMetrics {
|
||||
chonks: 1,
|
||||
homogeneous: self.sub_chunks
|
||||
.iter()
|
||||
.filter(|s| match s { SubChunk::Homogeneous(_) => true, _ => false })
|
||||
.count(),
|
||||
hash: self.sub_chunks
|
||||
.iter()
|
||||
.filter(|s| match s { SubChunk::Hash(_, _) => true, _ => false })
|
||||
.count(),
|
||||
heterogeneous: self.sub_chunks
|
||||
.iter()
|
||||
.filter(|s| match s { SubChunk::Heterogeneous(_) => true, _ => false })
|
||||
.count(),
|
||||
}
|
||||
}
|
||||
|
||||
fn sub_chunk_idx(&self, z: i32) -> usize {
|
||||
((z - self.z_offset) as u32 / SUB_CHUNK_HEIGHT as u32) as usize
|
||||
}
|
||||
@ -75,7 +96,7 @@ impl ReadVol for Chonk {
|
||||
- Vec3::unit_z()
|
||||
* (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32);
|
||||
|
||||
Ok(map.get(&rpos).unwrap_or(cblock))
|
||||
Ok(map.get(&rpos.map(|e| e as u8)).unwrap_or(cblock))
|
||||
}
|
||||
SubChunk::Heterogeneous(chunk) => {
|
||||
let rpos = pos
|
||||
@ -92,59 +113,61 @@ impl ReadVol for Chonk {
|
||||
impl WriteVol for Chonk {
|
||||
#[inline(always)]
|
||||
fn set(&mut self, pos: Vec3<i32>, block: Block) -> Result<(), ChonkError> {
|
||||
if pos.z < self.z_offset {
|
||||
Err(ChonkError::OutOfBounds)
|
||||
} else {
|
||||
let sub_chunk_idx = self.sub_chunk_idx(pos.z);
|
||||
while pos.z < self.z_offset {
|
||||
self.sub_chunks.insert(0, SubChunk::Homogeneous(self.below));
|
||||
self.z_offset -= SUB_CHUNK_HEIGHT as i32;
|
||||
}
|
||||
|
||||
while self.sub_chunks.get(sub_chunk_idx).is_none() {
|
||||
self.sub_chunks.push(SubChunk::Homogeneous(self.above));
|
||||
}
|
||||
|
||||
let rpos = pos
|
||||
- Vec3::unit_z() * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32);
|
||||
|
||||
match &mut self.sub_chunks[sub_chunk_idx] {
|
||||
// Can't fail
|
||||
SubChunk::Homogeneous(cblock) if *cblock == block => Ok(()),
|
||||
SubChunk::Homogeneous(cblock) => {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(rpos, block);
|
||||
|
||||
self.sub_chunks[sub_chunk_idx] = SubChunk::Hash(*cblock, map);
|
||||
Ok(())
|
||||
}
|
||||
SubChunk::Hash(cblock, map) if map.len() < 1024 => {
|
||||
map.insert(rpos, block);
|
||||
Ok(())
|
||||
}
|
||||
SubChunk::Hash(cblock, map) => {
|
||||
let mut new_chunk = Chunk::filled(*cblock, ());
|
||||
new_chunk.set(rpos, block).unwrap(); // Can't fail (I hope)
|
||||
|
||||
for (map_pos, map_block) in map {
|
||||
new_chunk.set(*map_pos, *map_block).unwrap(); // Can't fail (I hope!)
|
||||
}
|
||||
|
||||
self.sub_chunks[sub_chunk_idx] = SubChunk::Heterogeneous(new_chunk);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/*
|
||||
SubChunk::Homogeneous(cblock) => {
|
||||
let mut new_chunk = Chunk::filled(*cblock, ());
|
||||
|
||||
new_chunk.set(rpos, block).unwrap(); // Can't fail (I hope!)
|
||||
|
||||
self.sub_chunks[sub_chunk_idx] = SubChunk::Heterogeneous(new_chunk);
|
||||
Ok(())
|
||||
}
|
||||
*/
|
||||
SubChunk::Heterogeneous(chunk) => chunk
|
||||
.set(rpos, block)
|
||||
.map_err(|err| ChonkError::ChunkError(err)),
|
||||
//_ => unimplemented!(),
|
||||
let sub_chunk_idx = self.sub_chunk_idx(pos.z);
|
||||
|
||||
while self.sub_chunks.get(sub_chunk_idx).is_none() {
|
||||
self.sub_chunks.push(SubChunk::Homogeneous(self.above));
|
||||
}
|
||||
|
||||
let rpos = pos
|
||||
- Vec3::unit_z() * (self.z_offset + sub_chunk_idx as i32 * SUB_CHUNK_HEIGHT as i32);
|
||||
|
||||
match &mut self.sub_chunks[sub_chunk_idx] {
|
||||
// Can't fail
|
||||
SubChunk::Homogeneous(cblock) if block == *cblock => Ok(()),
|
||||
SubChunk::Homogeneous(cblock) => {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(rpos.map(|e| e as u8), block);
|
||||
|
||||
self.sub_chunks[sub_chunk_idx] = SubChunk::Hash(*cblock, map);
|
||||
Ok(())
|
||||
},
|
||||
SubChunk::Hash(cblock, map) if block == *cblock => Ok(()),
|
||||
SubChunk::Hash(cblock, map) if map.len() < 4096 => {
|
||||
map.insert(rpos.map(|e| e as u8), block);
|
||||
Ok(())
|
||||
},
|
||||
SubChunk::Hash(cblock, map) => {
|
||||
let mut new_chunk = Chunk::filled(*cblock, ());
|
||||
new_chunk.set(rpos, block).unwrap(); // Can't fail (I hope)
|
||||
|
||||
for (map_pos, map_block) in map {
|
||||
new_chunk.set(map_pos.map(|e| e as i32), *map_block).unwrap(); // Can't fail (I hope!)
|
||||
}
|
||||
|
||||
self.sub_chunks[sub_chunk_idx] = SubChunk::Heterogeneous(new_chunk);
|
||||
Ok(())
|
||||
},
|
||||
|
||||
/*
|
||||
SubChunk::Homogeneous(cblock) => {
|
||||
let mut new_chunk = Chunk::filled(*cblock, ());
|
||||
|
||||
new_chunk.set(rpos, block).unwrap(); // Can't fail (I hope!)
|
||||
|
||||
self.sub_chunks[sub_chunk_idx] = SubChunk::Heterogeneous(new_chunk);
|
||||
Ok(())
|
||||
}
|
||||
*/
|
||||
SubChunk::Heterogeneous(chunk) => chunk
|
||||
.set(rpos, block)
|
||||
.map_err(|err| ChonkError::ChunkError(err)),
|
||||
//_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,7 +175,7 @@ impl WriteVol for Chonk {
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum SubChunk {
|
||||
Homogeneous(Block),
|
||||
Hash(Block, HashMap<Vec3<i32>, Block>),
|
||||
Hash(Block, HashMap<Vec3<u8>, Block>),
|
||||
Heterogeneous(Chunk<Block, TerrainChunkSize, ()>),
|
||||
}
|
||||
|
||||
@ -161,3 +184,35 @@ impl SubChunk {
|
||||
SubChunk::Homogeneous(block)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ChonkMetrics {
|
||||
chonks: usize,
|
||||
homogeneous: usize,
|
||||
hash: usize,
|
||||
heterogeneous: usize,
|
||||
}
|
||||
|
||||
impl Default for ChonkMetrics {
|
||||
fn default() -> Self {
|
||||
ChonkMetrics {
|
||||
chonks: 0,
|
||||
homogeneous: 0,
|
||||
hash: 0,
|
||||
heterogeneous: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for ChonkMetrics {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self::Output) -> Self {
|
||||
Self::Output {
|
||||
chonks: self.chonks + other.chonks,
|
||||
homogeneous: self.homogeneous + other.homogeneous,
|
||||
hash: self.hash + other.hash,
|
||||
heterogeneous: self.heterogeneous + other.heterogeneous,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,8 +151,8 @@ impl Terrain {
|
||||
.fold(i32::MIN, |max, (_, chunk)| chunk.get_z_max().max(max));
|
||||
|
||||
let aabb = Aabb {
|
||||
min: Vec3::from(aabr.min) + Vec3::unit_z() * z_min,
|
||||
max: Vec3::from(aabr.max) + Vec3::unit_z() * z_max,
|
||||
min: Vec3::from(aabr.min) + Vec3::unit_z() * (z_min - 1),
|
||||
max: Vec3::from(aabr.max) + Vec3::unit_z() * (z_max + 1),
|
||||
};
|
||||
|
||||
// Clone various things so that they can be moved into the thread.
|
||||
|
@ -49,7 +49,10 @@ impl World {
|
||||
|
||||
let warp_nz = BasicMulti::new().set_octaves(3).set_seed(self.sim.seed + 0);
|
||||
|
||||
let base_z = match self.sim.get_base_z(chunk_pos.map(|e| e as u32)) {
|
||||
let base_z = match self.sim
|
||||
.get(chunk_pos.map(|e| e as u32))
|
||||
.map(|chunk| chunk.get_base_z())
|
||||
{
|
||||
Some(base_z) => base_z as i32,
|
||||
None => return TerrainChunk::new(0, water, air, TerrainChunkMeta::void()),
|
||||
};
|
||||
@ -64,12 +67,17 @@ impl World {
|
||||
+ Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
||||
let wposf2d = wpos2d.map(|e| e as f64);
|
||||
|
||||
let min_z = self
|
||||
.sim
|
||||
.get_interpolated(wpos2d, |chunk| chunk.get_min_z())
|
||||
.unwrap_or(0.0) as i32;
|
||||
|
||||
let max_z = self
|
||||
.sim
|
||||
.get_interpolated(wpos2d, |chunk| chunk.get_max_z())
|
||||
.unwrap_or(0.0) as i32;
|
||||
|
||||
for z in base_z..max_z.max(sim::SEA_LEVEL as i32) {
|
||||
for z in min_z..max_z {
|
||||
let lpos = Vec3::new(x, y, z);
|
||||
let wpos =
|
||||
lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
||||
|
@ -746,10 +746,14 @@ impl SimChunk {
|
||||
}
|
||||
|
||||
pub fn get_base_z(&self) -> f32 {
|
||||
self.alt - 8.0
|
||||
}
|
||||
|
||||
pub fn get_min_z(&self) -> f32 {
|
||||
self.alt - Z_TOLERANCE.0 * (self.chaos + 0.3)
|
||||
}
|
||||
|
||||
pub fn get_max_z(&self) -> f32 {
|
||||
self.alt + Z_TOLERANCE.1
|
||||
(self.alt + Z_TOLERANCE.1).max(SEA_LEVEL)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user