diff --git a/src/level.rs b/src/level.rs index ec353da..e07d5ba 100644 --- a/src/level.rs +++ b/src/level.rs @@ -1,3 +1,5 @@ +pub mod generation; + /// a classic level #[derive(Debug, Clone)] pub struct Level { diff --git a/src/level/generation.rs b/src/level/generation.rs new file mode 100644 index 0000000..6865d37 --- /dev/null +++ b/src/level/generation.rs @@ -0,0 +1,93 @@ +use rand::Rng; +use serde::{Deserialize, Serialize}; + +use super::Level; + +/// enum for different kinds of level generation +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum LevelGeneration { + /// an empty level + Empty, + /// a level where every block up to the given height is randomized + FullRandom { height: usize }, + /// a flat level with the given preset + Flat(FlatPreset), +} + +/// enum for level presents +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "flat_type")] +pub enum FlatPreset { + /// the level is mostly stone, then dirt, then a layer of grass on the top + StoneAndGrass, + /// the level layers are custom as defined in server config + Custom { layers: Vec }, +} + +/// description of a flat world's layer +#[derive(Debug, Serialize, Deserialize)] +pub struct FlatLayer { + /// the block for the layer + pub block: u8, + /// the depth of the layer + pub depth: usize, +} + +impl LevelGeneration { + /// generates the level + pub fn generate(&self, level: &mut Level, rng: &mut R) + where + R: Rng, + { + match self { + Self::Empty => {} + Self::FullRandom { height } => { + let height = *height.min(&level.y_size); + for x in 0..level.x_size { + for y in 0..height { + for z in 0..level.z_size { + level.set_block(x, y, z, rng.gen_range(0..49)); + } + } + } + } + Self::Flat(preset) => { + let custom_layers; + let layers_ref; + + match preset { + FlatPreset::StoneAndGrass => { + custom_layers = vec![ + FlatLayer { + block: 1, + depth: level.y_size / 2 - 4, + }, + FlatLayer { block: 3, depth: 3 }, + FlatLayer { block: 2, depth: 1 }, + ]; + layers_ref = &custom_layers; + } + FlatPreset::Custom { layers } => { + layers_ref = layers; + } + } + + let mut y = 0; + for layer in layers_ref { + for _ in 0..layer.depth { + for x in 0..level.x_size { + for z in 0..level.z_size { + level.set_block(x, y, z, layer.block); + } + } + y += 1; + if y >= level.y_size { + return; + } + } + } + } + } + } +} diff --git a/src/server.rs b/src/server.rs index 9afafcb..312f966 100644 --- a/src/server.rs +++ b/src/server.rs @@ -3,8 +3,6 @@ mod network; use std::sync::Arc; -// use parking_lot::RwLock; -use rand::Rng; use tokio::{net::TcpListener, sync::RwLock}; use crate::{level::Level, player::Player}; @@ -50,13 +48,7 @@ impl Server { ) }; let mut level = Level::new(level_x, level_y, level_z); - for x in 0..level.x_size { - for y in 0..(level.y_size / 2) { - for z in 0..level.z_size { - level.set_block(x, y, z, rng.gen_range(0..50)); - } - } - } + config.generation.generate(&mut level, &mut rng); println!("done!"); Self::new_with_level(config, level).await diff --git a/src/server/config.rs b/src/server/config.rs index 15acc11..9c43c3f 100644 --- a/src/server/config.rs +++ b/src/server/config.rs @@ -1,5 +1,7 @@ use serde::{Deserialize, Serialize}; +use crate::level::generation::LevelGeneration; + /// configuration for the server #[derive(Debug, Serialize, Deserialize)] pub struct ServerConfig { @@ -13,6 +15,8 @@ pub struct ServerConfig { pub level_size: Option, /// the level's spawn point pub spawn: Option, + /// the method to generate the server's level with + pub generation: LevelGeneration, } impl Default for ServerConfig { @@ -23,6 +27,7 @@ impl Default for ServerConfig { password: None, level_size: None, spawn: None, + generation: LevelGeneration::Empty, } } }