122 lines
3.8 KiB
Rust
122 lines
3.8 KiB
Rust
use noise::{NoiseFn, Perlin};
|
|
use pumpkin_core::math::vector2::Vector2;
|
|
|
|
use crate::{
|
|
chunk::{ChunkBlocks, ChunkData},
|
|
coordinates::{ChunkRelativeBlockCoordinates, ChunkRelativeXZBlockCoordinates},
|
|
WORLD_LOWEST_Y,
|
|
};
|
|
|
|
use super::{
|
|
generator::{BiomeGenerator, GeneratorInit, PerlinTerrainGenerator, WorldGenerator},
|
|
Seed,
|
|
};
|
|
|
|
pub struct GenericGenerator<B: BiomeGenerator, T: PerlinTerrainGenerator> {
|
|
biome_generator: B,
|
|
terrain_generator: T,
|
|
// TODO: May make this optional?. But would be pain to use in most biomes then. Maybe make a new trait like
|
|
// PerlinTerrainGenerator
|
|
perlin: Perlin,
|
|
}
|
|
|
|
impl<B: BiomeGenerator + GeneratorInit, T: PerlinTerrainGenerator + GeneratorInit> GeneratorInit
|
|
for GenericGenerator<B, T>
|
|
{
|
|
fn new(seed: Seed) -> Self {
|
|
Self {
|
|
biome_generator: B::new(seed),
|
|
terrain_generator: T::new(seed),
|
|
perlin: Perlin::new(seed.0 as u32),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<B: BiomeGenerator, T: PerlinTerrainGenerator> WorldGenerator for GenericGenerator<B, T> {
|
|
fn generate_chunk(&self, at: Vector2<i32>) -> ChunkData {
|
|
let mut blocks = ChunkBlocks::default();
|
|
self.terrain_generator.prepare_chunk(&at, &self.perlin);
|
|
let noise_value = self.perlin.get([at.x as f64 / 16.0, at.z as f64 / 16.0]);
|
|
|
|
let base_height = 64.0;
|
|
let height_variation = 16.0;
|
|
let chunk_height = noise_value.mul_add(height_variation, base_height) as i32;
|
|
|
|
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..chunk_height as i16).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),
|
|
chunk_height as i16,
|
|
biome,
|
|
)
|
|
.into(),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
ChunkData {
|
|
blocks,
|
|
position: at,
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: implement static terrain generator
|
|
/*
|
|
fn generate_chunk(&mut self, at: Vector2<i32>) -> ChunkData {
|
|
let mut blocks = ChunkBlocks::default();
|
|
self.terrain_generator.prepare_chunk(&at, &self.perlin);
|
|
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,
|
|
}
|
|
}
|
|
*/
|