From 21761202e7fb35fae34cd35747eb3ab721232401 Mon Sep 17 00:00:00 2001 From: DaniD3v Date: Wed, 28 Aug 2024 11:39:07 +0200 Subject: [PATCH] Added logic to generate chunks if they can't be read from the world file. Moved warning about ./world folder to only appear when necessary + Updated warning contents to reflect changes Made the save_file in the `Level` struct optional in case someone wants an entirely generated World. Removed now redundant asserts. --- pumpkin-world/src/level.rs | 78 ++++++++++++++++++++++++++++---------- pumpkin/src/server.rs | 1 - 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/pumpkin-world/src/level.rs b/pumpkin-world/src/level.rs index c95eec84..e066c464 100644 --- a/pumpkin-world/src/level.rs +++ b/pumpkin-world/src/level.rs @@ -1,7 +1,7 @@ use std::{ fs::OpenOptions, io::{Read, Seek}, - path::{Path, PathBuf}, + path::PathBuf, }; use flate2::{bufread::ZlibDecoder, read::GzDecoder}; @@ -10,11 +10,20 @@ use rayon::prelude::*; use thiserror::Error; use tokio::sync::mpsc; -use crate::{chunk::ChunkData, coordinates::ChunkCoordinates}; +use crate::{ + chunk::ChunkData, + coordinates::ChunkCoordinates, + world_gen::{get_world_gen, Seed, WorldGenerator}, +}; -#[allow(dead_code)] -/// The Level represents a +/// The Level represents a single Dimension. pub struct Level { + save_file: Option, + world_gen: Box, +} + +struct SaveFile { + #[allow(dead_code)] root_folder: PathBuf, region_folder: PathBuf, } @@ -84,16 +93,31 @@ impl Compression { impl Level { pub fn from_root_folder(root_folder: PathBuf) -> Self { - assert!(root_folder.exists(), "World root folder does not exist!"); - let region_folder = root_folder.join("region"); - assert!( - region_folder.exists(), - "World region folder does not exist!" - ); + let world_gen = get_world_gen(Seed(0)); // TODO Read Seed from config. + + if root_folder.exists() { + let region_folder = root_folder.join("region"); + assert!( + region_folder.exists(), + "World region folder does not exist, despite there being a root folder." + ); - Level { - root_folder, - region_folder, + Self { + world_gen, + save_file: Some(SaveFile { + root_folder, + region_folder, + }), + } + } else { + log::warn!( + "Pumpkin currently only supports Superflat World generation. Use a vanilla ./world folder to play in a normal world." + ); + + Self { + world_gen, + save_file: None, + } } } @@ -121,19 +145,27 @@ impl Level { let channel = channel.clone(); channel - .blocking_send(match Self::read_chunk(&self.region_folder, at) { - Err(WorldError::ChunkNotGenerated(_)) => { - // This chunk was not generated yet. - todo!("generate chunk here") + .blocking_send(match &self.save_file { + Some(save_file) => { + match Self::read_chunk(save_file, at) { + Err(WorldError::ChunkNotGenerated(_)) => { + // This chunk was not generated yet. + Ok(self.world_gen.generate_chunk(at)) + } + // TODO this doesn't warn the user about the error. fix. + result => result, + } + } + None => { + // There is no savefile yet -> generate the chunks + Ok(self.world_gen.generate_chunk(at)) } - // TODO this doesn't warn the user about the error. fix. - result => result, }) .expect("Failed sending ChunkData."); }) } - fn read_chunk(region_folder: &Path, at: ChunkCoordinates) -> Result { + fn read_chunk(save_file: &SaveFile, at: ChunkCoordinates) -> Result { let region = ( ((at.x as f32) / 32.0).floor() as i32, ((at.z as f32) / 32.0).floor() as i32, @@ -141,7 +173,11 @@ impl Level { let mut region_file = OpenOptions::new() .read(true) - .open(region_folder.join(format!("r.{}.{}.mca", region.0, region.1))) + .open( + save_file + .region_folder + .join(format!("r.{}.{}.mca", region.0, region.1)), + ) .map_err(|err| match err.kind() { std::io::ErrorKind::NotFound => { WorldError::ChunkNotGenerated(ChunkNotGeneratedError::RegionFileMissing) diff --git a/pumpkin/src/server.rs b/pumpkin/src/server.rs index 4ed5a94b..f8e329bb 100644 --- a/pumpkin/src/server.rs +++ b/pumpkin/src/server.rs @@ -102,7 +102,6 @@ impl Server { log::info!("Loading Plugins"); let plugin_loader = PluginLoader::load(); - log::warn!("Pumpkin does currently not have World or Chunk generation, Using ../world folder with vanilla pregenerated chunks"); let world = World::load(Dimension::OverWorld.into_level( // TODO: load form config "./world".parse().unwrap(),