mirror of
https://github.com/griffi-gh/kubi.git
synced 2024-12-25 13:18:21 -06:00
Placement queue, binary transparency, WIP trees
This commit is contained in:
parent
916f9058be
commit
58344cf838
|
@ -32,6 +32,9 @@ pub enum Block {
|
|||
Cobblestone,
|
||||
TallGrass,
|
||||
Planks,
|
||||
Torch,
|
||||
Wood,
|
||||
Leaf,
|
||||
}
|
||||
|
||||
impl Block {
|
||||
|
@ -90,6 +93,24 @@ impl Block {
|
|||
collision: CollisionType::Solid,
|
||||
raycast_collision: true,
|
||||
},
|
||||
Self::Torch => BlockDescriptor {
|
||||
name: "torch",
|
||||
render: RenderType::CrossShape(CrossTexture::all(BlockTexture::Torch)),
|
||||
collision: CollisionType::None,
|
||||
raycast_collision: true,
|
||||
},
|
||||
Self::Wood => BlockDescriptor {
|
||||
name: "leaf",
|
||||
render: RenderType::SolidBlock(CubeTexture::horizontal_vertical(BlockTexture::Wood, BlockTexture::WoodTop)),
|
||||
collision: CollisionType::Solid,
|
||||
raycast_collision: true,
|
||||
},
|
||||
Self::Leaf => BlockDescriptor {
|
||||
name: "leaf",
|
||||
render: RenderType::BinaryTransparency(CubeTexture::all(BlockTexture::Leaf)),
|
||||
collision: CollisionType::Solid,
|
||||
raycast_collision: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,5 +191,6 @@ pub enum CollisionType {
|
|||
pub enum RenderType {
|
||||
None,
|
||||
SolidBlock(CubeTexture),
|
||||
BinaryTransparency(CubeTexture),
|
||||
CrossShape(CrossTexture),
|
||||
}
|
||||
|
|
|
@ -29,10 +29,27 @@ fn local_y_position(height: i32, chunk_position: IVec3) -> Option<usize> {
|
|||
(0..CHUNK_SIZE as i32).contains(&position).then_some(position as usize)
|
||||
}
|
||||
|
||||
pub fn generate_world(chunk_position: IVec3, seed: u64) -> BlockData {
|
||||
pub struct QueuedBlock {
|
||||
pub position: IVec3,
|
||||
pub block_type: Block,
|
||||
}
|
||||
|
||||
pub fn generate_world(chunk_position: IVec3, seed: u64) -> (BlockData, Vec<QueuedBlock>) {
|
||||
let offset = chunk_position * CHUNK_SIZE as i32;
|
||||
let mut blocks = Box::new([[[Block::Air; CHUNK_SIZE]; CHUNK_SIZE]; CHUNK_SIZE]);
|
||||
|
||||
let mut queue = Vec::with_capacity(0);
|
||||
|
||||
let mut smart_place = |blocks: &mut BlockData, position: IVec3, block: Block| {
|
||||
if position.to_array().iter().any(|&x| !(0..CHUNK_SIZE).contains(&(x as usize))) {
|
||||
queue.push(QueuedBlock {
|
||||
position: offset + position,
|
||||
block_type: block
|
||||
});
|
||||
} else {
|
||||
blocks[position.x as usize][position.y as usize][position.z as usize] = block;
|
||||
}
|
||||
};
|
||||
|
||||
let mut height_noise = FastNoise::seeded(seed);
|
||||
height_noise.set_fractal_type(FractalType::FBM);
|
||||
height_noise.set_fractal_octaves(4);
|
||||
|
@ -46,10 +63,10 @@ pub fn generate_world(chunk_position: IVec3, seed: u64) -> BlockData {
|
|||
let mut rng = Xoshiro256StarStar::seed_from_u64(
|
||||
seed
|
||||
^ ((chunk_position.x as u32 as u64) << 0)
|
||||
^ ((chunk_position.y as u32 as u64) << 16)
|
||||
^ ((chunk_position.z as u32 as u64) << 32)
|
||||
);
|
||||
let tall_grass_map: [[u8; CHUNK_SIZE]; CHUNK_SIZE] = rng.gen();
|
||||
let rng_map_a: [[f32; CHUNK_SIZE]; CHUNK_SIZE] = rng.gen();
|
||||
let rng_map_b: [[f32; CHUNK_SIZE]; CHUNK_SIZE] = rng.gen();
|
||||
|
||||
// let mut cave_noise = FastNoise::seeded(seed.rotate_left(1));
|
||||
// cave_noise.set_fractal_type(FractalType::FBM);
|
||||
|
@ -86,11 +103,22 @@ pub fn generate_world(chunk_position: IVec3, seed: u64) -> BlockData {
|
|||
blocks[x][y][z] = Block::Grass;
|
||||
}
|
||||
//place tall grass
|
||||
if tall_grass_map[x][z] < 10 {
|
||||
if rng_map_a[x][z] < 0.03 {
|
||||
if let Some(y) = local_y_position(height + 1, chunk_position) {
|
||||
blocks[x][y][z] = Block::TallGrass;
|
||||
}
|
||||
}
|
||||
//place trees!
|
||||
if rng_map_a[x][z] < 0.001 {
|
||||
if let Some(y) = local_y_position(height + 1, chunk_position) {
|
||||
let tree_pos = ivec3(x as i32, y as i32, z as i32);
|
||||
let tree_height = 6 + (rng_map_b[x][z] * 6.).round() as i32;
|
||||
for tree_y in 0..tree_height {
|
||||
smart_place(&mut blocks, tree_pos + IVec3::Y * tree_y, Block::Wood);
|
||||
}
|
||||
smart_place(&mut blocks, tree_pos + IVec3::Y * tree_height, Block::Leaf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,8 +139,8 @@ pub fn generate_world(chunk_position: IVec3, seed: u64) -> BlockData {
|
|||
// }
|
||||
}
|
||||
|
||||
blocks
|
||||
|
||||
(blocks, queue)
|
||||
|
||||
// let mut cave_noise = FastNoise::seeded(seed);
|
||||
// cave_noise.set_fractal_type(FractalType::FBM);
|
||||
// cave_noise.set_frequency(0.1);
|
||||
|
|
|
@ -23,6 +23,7 @@ const BLOCK_KEY_MAP: &[(VirtualKeyCode, Block)] = &[
|
|||
(VirtualKeyCode::Key4, Block::Grass),
|
||||
(VirtualKeyCode::Key5, Block::Sand),
|
||||
(VirtualKeyCode::Key6, Block::Stone),
|
||||
(VirtualKeyCode::Key7, Block::Torch),
|
||||
];
|
||||
|
||||
fn pick_block_with_number_keys(
|
||||
|
|
|
@ -11,7 +11,8 @@ use crate::{
|
|||
use super::{
|
||||
ChunkStorage, ChunkMeshStorage,
|
||||
chunk::{Chunk, DesiredChunkState, CHUNK_SIZE, ChunkMesh, CurrentChunkState, ChunkData},
|
||||
tasks::{ChunkTaskManager, ChunkTaskResponse, ChunkTask},
|
||||
tasks::{ChunkTaskManager, ChunkTaskResponse, ChunkTask},
|
||||
queue::{BlockUpdateQueue, BlockUpdateEvent},
|
||||
};
|
||||
|
||||
const MAX_CHUNK_OPS_INGAME: usize = 6;
|
||||
|
@ -170,12 +171,13 @@ fn process_completed_tasks(
|
|||
mut world: UniqueViewMut<ChunkStorage>,
|
||||
mut meshes: NonSendSync<UniqueViewMut<ChunkMeshStorage>>,
|
||||
renderer: NonSendSync<UniqueView<Renderer>>,
|
||||
state: UniqueView<GameState>
|
||||
state: UniqueView<GameState>,
|
||||
mut queue: UniqueViewMut<BlockUpdateQueue>,
|
||||
) {
|
||||
let mut ops: usize = 0;
|
||||
while let Some(res) = task_manager.receive() {
|
||||
match res {
|
||||
ChunkTaskResponse::LoadedChunk { position, chunk_data } => {
|
||||
ChunkTaskResponse::LoadedChunk { position, chunk_data, queued } => {
|
||||
//check if chunk exists
|
||||
let Some(chunk) = world.chunks.get_mut(&position) else {
|
||||
log::warn!("blocks data discarded: chunk doesn't exist");
|
||||
|
@ -196,6 +198,14 @@ fn process_completed_tasks(
|
|||
//update chunk state
|
||||
chunk.current_state = CurrentChunkState::Loaded;
|
||||
|
||||
//push queued blocks
|
||||
for event in queued {
|
||||
queue.push(BlockUpdateEvent {
|
||||
position: event.position,
|
||||
value: event.block_type,
|
||||
});
|
||||
}
|
||||
|
||||
//increase ops counter
|
||||
ops += 1;
|
||||
},
|
||||
|
|
|
@ -39,12 +39,16 @@ pub fn generate_mesh(data: MeshGenData) -> (Vec<ChunkVertex>, Vec<u32>) {
|
|||
let descriptor = block.descriptor();
|
||||
match descriptor.render {
|
||||
RenderType::None => continue,
|
||||
RenderType::SolidBlock(textures) => {
|
||||
RenderType::SolidBlock(textures) | RenderType::BinaryTransparency(textures) => {
|
||||
for face in CubeFace::iter() {
|
||||
let facing_direction = face.normal();
|
||||
let facing_coord = coord + facing_direction;
|
||||
let facing_descriptor = get_block(facing_coord).descriptor();
|
||||
let face_obstructed = matches!(facing_descriptor.render, RenderType::SolidBlock(_));
|
||||
let face_obstructed = match descriptor.render {
|
||||
RenderType::SolidBlock(_) => matches!(facing_descriptor.render, RenderType::SolidBlock(_)),
|
||||
RenderType::BinaryTransparency(_) => matches!(facing_descriptor.render, RenderType::SolidBlock(_) | RenderType::BinaryTransparency(_)),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
if !face_obstructed {
|
||||
let face_texture = match face {
|
||||
CubeFace::Top => textures.top,
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use flume::{Sender, Receiver};
|
||||
use glam::IVec3;
|
||||
use kubi_shared::networking::messages::{ClientToServerMessage, ServerToClientMessage};
|
||||
use kubi_shared::{
|
||||
networking::messages::{ClientToServerMessage, ServerToClientMessage},
|
||||
worldgen::QueuedBlock
|
||||
};
|
||||
use shipyard::{Unique, UniqueView, View, IntoIter};
|
||||
use rayon::{ThreadPool, ThreadPoolBuilder};
|
||||
use super::{
|
||||
|
@ -8,7 +11,10 @@ use super::{
|
|||
mesh::{generate_mesh, data::MeshGenData},
|
||||
worldgen::generate_world,
|
||||
};
|
||||
use crate::{rendering::world::ChunkVertex, networking::{UdpClient, NetworkEvent}};
|
||||
use crate::{
|
||||
rendering::world::ChunkVertex,
|
||||
networking::{UdpClient, NetworkEvent}
|
||||
};
|
||||
use kubi_udp::client::ClientEvent;
|
||||
|
||||
pub enum ChunkTask {
|
||||
|
@ -25,6 +31,7 @@ pub enum ChunkTaskResponse {
|
|||
LoadedChunk {
|
||||
position: IVec3,
|
||||
chunk_data: BlockData,
|
||||
queued: Vec<QueuedBlock>
|
||||
},
|
||||
GeneratedMesh {
|
||||
position: IVec3,
|
||||
|
@ -59,8 +66,8 @@ impl ChunkTaskManager {
|
|||
ChunkTaskResponse::GeneratedMesh { position, vertices, indexes }
|
||||
},
|
||||
ChunkTask::LoadChunk { position, seed } => {
|
||||
let chunk_data = generate_world(position, seed);
|
||||
ChunkTaskResponse::LoadedChunk { position, chunk_data }
|
||||
let (chunk_data, queued) = generate_world(position, seed);
|
||||
ChunkTaskResponse::LoadedChunk { position, chunk_data, queued }
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -97,7 +104,9 @@ pub fn inject_network_responses_into_manager_queue(
|
|||
if let ClientEvent::MessageReceived(ServerToClientMessage::ChunkResponse { chunk, data }) = &event.0 {
|
||||
let position = IVec3::from_array(*chunk);
|
||||
manager.add_sussy_response(ChunkTaskResponse::LoadedChunk {
|
||||
position, chunk_data: data.clone()
|
||||
position,
|
||||
chunk_data: data.clone(),
|
||||
queued: Vec::with_capacity(0)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue