mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added worldgen npcs
This commit is contained in:
parent
595f2bf1f1
commit
b5d10bfb3e
@ -34,7 +34,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use uvth::{ThreadPool, ThreadPoolBuilder};
|
use uvth::{ThreadPool, ThreadPoolBuilder};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
use world::World;
|
use world::{ChunkSupplement, World};
|
||||||
|
|
||||||
const CLIENT_TIMEOUT: f64 = 20.0; // Seconds
|
const CLIENT_TIMEOUT: f64 = 20.0; // Seconds
|
||||||
|
|
||||||
@ -62,8 +62,8 @@ pub struct Server {
|
|||||||
clients: Clients,
|
clients: Clients,
|
||||||
|
|
||||||
thread_pool: ThreadPool,
|
thread_pool: ThreadPool,
|
||||||
chunk_tx: mpsc::Sender<(Vec2<i32>, TerrainChunk)>,
|
chunk_tx: mpsc::Sender<(Vec2<i32>, (TerrainChunk, ChunkSupplement))>,
|
||||||
chunk_rx: mpsc::Receiver<(Vec2<i32>, TerrainChunk)>,
|
chunk_rx: mpsc::Receiver<(Vec2<i32>, (TerrainChunk, ChunkSupplement))>,
|
||||||
pending_chunks: HashSet<Vec2<i32>>,
|
pending_chunks: HashSet<Vec2<i32>>,
|
||||||
|
|
||||||
server_settings: ServerSettings,
|
server_settings: ServerSettings,
|
||||||
@ -237,7 +237,7 @@ impl Server {
|
|||||||
|
|
||||||
// 5) Fetch any generated `TerrainChunk`s and insert them into the terrain.
|
// 5) Fetch any generated `TerrainChunk`s and insert them into the terrain.
|
||||||
// Also, send the chunk data to anybody that is close by.
|
// Also, send the chunk data to anybody that is close by.
|
||||||
if let Ok((key, chunk)) = self.chunk_rx.try_recv() {
|
if let Ok((key, (chunk, supplement))) = self.chunk_rx.try_recv() {
|
||||||
// Send the chunk to all nearby players.
|
// Send the chunk to all nearby players.
|
||||||
for (entity, view_distance, pos) in (
|
for (entity, view_distance, pos) in (
|
||||||
&self.state.ecs().entities(),
|
&self.state.ecs().entities(),
|
||||||
@ -267,6 +267,23 @@ impl Server {
|
|||||||
|
|
||||||
self.state.insert_chunk(key, chunk);
|
self.state.insert_chunk(key, chunk);
|
||||||
self.pending_chunks.remove(&key);
|
self.pending_chunks.remove(&key);
|
||||||
|
|
||||||
|
// Handle chunk supplement
|
||||||
|
for npc in supplement.npcs {
|
||||||
|
self.state
|
||||||
|
.ecs_mut()
|
||||||
|
.create_entity_synced()
|
||||||
|
.with(comp::Pos(npc.pos))
|
||||||
|
.with(comp::Vel(Vec3::zero()))
|
||||||
|
.with(comp::Ori(Vec3::unit_y()))
|
||||||
|
.with(comp::Controller::default())
|
||||||
|
.with(comp::Body::Humanoid(comp::humanoid::Body::random()))
|
||||||
|
.with(comp::Stats::new("Test".to_string()))
|
||||||
|
.with(comp::ActionState::default())
|
||||||
|
.with(comp::Agent::Enemy { target: None })
|
||||||
|
.with(comp::ForceUpdate)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chunk_in_vd(
|
fn chunk_in_vd(
|
||||||
|
@ -17,8 +17,9 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize},
|
terrain::{Block, TerrainChunk, TerrainChunkMeta, TerrainChunkSize},
|
||||||
vol::{VolSize, Vox, WriteVol},
|
vol::{ReadVol, VolSize, Vox, WriteVol},
|
||||||
};
|
};
|
||||||
|
use rand::Rng;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ impl World {
|
|||||||
BlockGen::new(self, ColumnGen::new(self))
|
BlockGen::new(self, ColumnGen::new(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_chunk(&self, chunk_pos: Vec2<i32>) -> TerrainChunk {
|
pub fn generate_chunk(&self, chunk_pos: Vec2<i32>) -> (TerrainChunk, ChunkSupplement) {
|
||||||
let air = Block::empty();
|
let air = Block::empty();
|
||||||
let stone = Block::new(2, Rgb::new(200, 220, 255));
|
let stone = Block::new(2, Rgb::new(200, 220, 255));
|
||||||
let water = Block::new(5, Rgb::new(100, 150, 255));
|
let water = Block::new(5, Rgb::new(100, 150, 255));
|
||||||
@ -72,21 +73,24 @@ impl World {
|
|||||||
{
|
{
|
||||||
Some((base_z, sim_chunk)) => (base_z as i32, sim_chunk),
|
Some((base_z, sim_chunk)) => (base_z as i32, sim_chunk),
|
||||||
None => {
|
None => {
|
||||||
return TerrainChunk::new(
|
return (
|
||||||
|
TerrainChunk::new(
|
||||||
CONFIG.sea_level as i32,
|
CONFIG.sea_level as i32,
|
||||||
water,
|
water,
|
||||||
air,
|
air,
|
||||||
TerrainChunkMeta::void(),
|
TerrainChunkMeta::void(),
|
||||||
|
),
|
||||||
|
ChunkSupplement::default(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let meta = TerrainChunkMeta::new(sim_chunk.get_name(&self.sim), sim_chunk.get_biome());
|
let meta = TerrainChunkMeta::new(sim_chunk.get_name(&self.sim), sim_chunk.get_biome());
|
||||||
|
|
||||||
let mut chunk = TerrainChunk::new(base_z, stone, air, meta);
|
|
||||||
|
|
||||||
let mut sampler = self.sample_blocks();
|
let mut sampler = self.sample_blocks();
|
||||||
|
|
||||||
|
let chunk_block_pos = Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
||||||
|
|
||||||
|
let mut chunk = TerrainChunk::new(base_z, stone, air, meta);
|
||||||
for x in 0..TerrainChunkSize::SIZE.x as i32 {
|
for x in 0..TerrainChunkSize::SIZE.x as i32 {
|
||||||
for y in 0..TerrainChunkSize::SIZE.y as i32 {
|
for y in 0..TerrainChunkSize::SIZE.y as i32 {
|
||||||
let wpos2d = Vec2::new(x, y)
|
let wpos2d = Vec2::new(x, y)
|
||||||
@ -105,8 +109,7 @@ impl World {
|
|||||||
|
|
||||||
for z in min_z as i32..max_z as i32 {
|
for z in min_z as i32..max_z as i32 {
|
||||||
let lpos = Vec3::new(x, y, z);
|
let lpos = Vec3::new(x, y, z);
|
||||||
let wpos =
|
let wpos = chunk_block_pos + lpos;
|
||||||
lpos + Vec3::from(chunk_pos) * TerrainChunkSize::SIZE.map(|e| e as i32);
|
|
||||||
|
|
||||||
if let Some(block) = sampler.get_with_z_cache(wpos, Some(&z_cache)) {
|
if let Some(block) = sampler.get_with_z_cache(wpos, Some(&z_cache)) {
|
||||||
let _ = chunk.set(lpos, block);
|
let _ = chunk.set(lpos, block);
|
||||||
@ -115,6 +118,43 @@ impl World {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk
|
let gen_entity_pos = || {
|
||||||
|
let lpos2d = Vec2::from(TerrainChunkSize::SIZE)
|
||||||
|
.map(|sz| rand::thread_rng().gen::<u32>().rem_euclid(sz));
|
||||||
|
let mut lpos = Vec3::new(lpos2d.x as i32, lpos2d.y as i32, 0);
|
||||||
|
|
||||||
|
while chunk.get(lpos).map(|vox| !vox.is_empty()).unwrap_or(false) {
|
||||||
|
lpos.z += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(chunk_block_pos + lpos).map(|e| e as f32) + 0.5
|
||||||
|
};
|
||||||
|
|
||||||
|
const SPAWN_RATE: f32 = 0.1;
|
||||||
|
let supplement = ChunkSupplement {
|
||||||
|
npcs: if rand::thread_rng().gen::<f32>() < SPAWN_RATE {
|
||||||
|
vec![NpcInfo {
|
||||||
|
pos: gen_entity_pos(),
|
||||||
|
}]
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
(chunk, supplement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NpcInfo {
|
||||||
|
pub pos: Vec3<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ChunkSupplement {
|
||||||
|
pub npcs: Vec<NpcInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ChunkSupplement {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { npcs: Vec::new() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user