diff --git a/Cargo.lock b/Cargo.lock index 01b46a6d3..c7ce270de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1980,11 +1980,13 @@ dependencies = [ "futures", "itertools 0.13.0", "lazy_static", + "log", "num-derive", "num-traits", "rayon", "serde", "serde_json", + "static_assertions", "thiserror", "tokio", ] @@ -2565,6 +2567,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "subtle" version = "2.6.1" diff --git a/pumpkin-world/Cargo.toml b/pumpkin-world/Cargo.toml index c158369b1..516711d8d 100644 --- a/pumpkin-world/Cargo.toml +++ b/pumpkin-world/Cargo.toml @@ -16,6 +16,8 @@ flate2 = "1.0.33" serde = { version = "1.0", features = ["derive"] } lazy_static = "1.5.0" serde_json = "1.0" +static_assertions = "1.1.0" +log.workspace = true num-traits = "0.2" num-derive = "0.4" diff --git a/pumpkin-world/src/world_gen/generator.rs b/pumpkin-world/src/world_gen/generator.rs new file mode 100644 index 000000000..c5a10480c --- /dev/null +++ b/pumpkin-world/src/world_gen/generator.rs @@ -0,0 +1,25 @@ +use static_assertions::assert_obj_safe; + +use crate::biome::Biome; +use crate::block::BlockId; +use crate::chunk::ChunkData; +use crate::coordinates::{BlockCoordinates, ChunkCoordinates, XZBlockCoordinates}; +use crate::world_gen::Seed; + +pub trait GeneratorInit { + fn new(seed: Seed) -> Self; +} + +pub trait WorldGenerator: Sync + Send { + #[allow(dead_code)] + fn generate_chunk(&self, at: ChunkCoordinates) -> ChunkData; +} +assert_obj_safe! {WorldGenerator} + +pub(crate) trait BiomeGenerator: Sync + Send { + fn generate_biome(&self, at: XZBlockCoordinates) -> Biome; +} + +pub(crate) trait TerrainGenerator: Sync + Send { + fn generate_block(&self, at: BlockCoordinates, biome: Biome) -> BlockId; +} diff --git a/pumpkin-world/src/world_gen/generic_generator.rs b/pumpkin-world/src/world_gen/generic_generator.rs new file mode 100644 index 000000000..d6a60ea5c --- /dev/null +++ b/pumpkin-world/src/world_gen/generic_generator.rs @@ -0,0 +1,66 @@ +use crate::{ + chunk::{ChunkBlocks, ChunkData}, + coordinates::{ + ChunkCoordinates, ChunkRelativeBlockCoordinates, ChunkRelativeXZBlockCoordinates, + }, + WORLD_LOWEST_Y, WORLD_MAX_Y, +}; + +use super::{ + generator::{BiomeGenerator, GeneratorInit, TerrainGenerator, WorldGenerator}, + Seed, +}; + +pub struct GenericGenerator { + biome_generator: B, + terrain_generator: T, +} + +impl GeneratorInit + for GenericGenerator +{ + fn new(seed: Seed) -> Self { + Self { + biome_generator: B::new(seed), + terrain_generator: T::new(seed), + } + } +} + +impl WorldGenerator for GenericGenerator { + fn generate_chunk(&self, at: ChunkCoordinates) -> ChunkData { + let mut blocks = ChunkBlocks::default(); + + for x in 0..16u8 { + for z in 0..16u8 { + let biome = self.biome_generator.generate_biome( + ChunkRelativeXZBlockCoordinates { + x: x.into(), + z: z.into(), + } + .with_chunk_coordinates(at), + ); + + // Iterate from the highest block to the lowest, in order to minimize the heightmap updates + for y in (WORLD_LOWEST_Y..WORLD_MAX_Y).rev() { + let coordinates = ChunkRelativeBlockCoordinates { + x: x.into(), + y: y.into(), + z: z.into(), + }; + + blocks.set_block( + coordinates, + self.terrain_generator + .generate_block(coordinates.with_chunk_coordinates(at), biome), + ); + } + } + } + + ChunkData { + blocks, + position: at, + } + } +} diff --git a/pumpkin-world/src/world_gen/mod.rs b/pumpkin-world/src/world_gen/mod.rs index 1db8d3c21..43a5ca1a6 100644 --- a/pumpkin-world/src/world_gen/mod.rs +++ b/pumpkin-world/src/world_gen/mod.rs @@ -1 +1,11 @@ +mod generator; +mod generic_generator; mod seed; + +pub use generator::WorldGenerator; +pub use seed::Seed; + +#[allow(dead_code)] +pub fn get_world_gen(_: Seed) -> Box { + todo!() +}