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.
This commit is contained in:
DaniD3v 2024-08-28 11:39:07 +02:00
parent 43c724dec7
commit 112a899559
2 changed files with 57 additions and 22 deletions

View File

@ -1,7 +1,7 @@
use std::{ use std::{
fs::OpenOptions, fs::OpenOptions,
io::{Read, Seek}, io::{Read, Seek},
path::{Path, PathBuf}, path::PathBuf,
}; };
use flate2::{bufread::ZlibDecoder, read::GzDecoder}; use flate2::{bufread::ZlibDecoder, read::GzDecoder};
@ -10,11 +10,20 @@ use rayon::prelude::*;
use thiserror::Error; use thiserror::Error;
use tokio::sync::mpsc; 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 single Dimension.
/// The Level represents a
pub struct Level { pub struct Level {
save_file: Option<SaveFile>,
world_gen: Box<dyn WorldGenerator>,
}
struct SaveFile {
#[allow(dead_code)]
root_folder: PathBuf, root_folder: PathBuf,
region_folder: PathBuf, region_folder: PathBuf,
} }
@ -84,16 +93,31 @@ impl Compression {
impl Level { impl Level {
pub fn from_root_folder(root_folder: PathBuf) -> Self { pub fn from_root_folder(root_folder: PathBuf) -> Self {
assert!(root_folder.exists(), "World root folder does not exist!"); let world_gen = get_world_gen(Seed(0)); // TODO Read Seed from config.
let region_folder = root_folder.join("region");
assert!(
region_folder.exists(),
"World region folder does not exist!"
);
Level { if root_folder.exists() {
root_folder, let region_folder = root_folder.join("region");
region_folder, assert!(
region_folder.exists(),
"World region folder does not exist, despite there being a root 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(); let channel = channel.clone();
channel channel
.blocking_send(match Self::read_chunk(&self.region_folder, at) { .blocking_send(match &self.save_file {
Err(WorldError::ChunkNotGenerated(_)) => { Some(save_file) => {
// This chunk was not generated yet. match Self::read_chunk(save_file, at) {
todo!("generate chunk here") 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."); .expect("Failed sending ChunkData.");
}) })
} }
fn read_chunk(region_folder: &Path, at: ChunkCoordinates) -> Result<ChunkData, WorldError> { fn read_chunk(save_file: &SaveFile, at: ChunkCoordinates) -> Result<ChunkData, WorldError> {
let region = ( let region = (
((at.x as f32) / 32.0).floor() as i32, ((at.x as f32) / 32.0).floor() as i32,
((at.z 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() let mut region_file = OpenOptions::new()
.read(true) .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() { .map_err(|err| match err.kind() {
std::io::ErrorKind::NotFound => { std::io::ErrorKind::NotFound => {
WorldError::ChunkNotGenerated(ChunkNotGeneratedError::RegionFileMissing) WorldError::ChunkNotGenerated(ChunkNotGeneratedError::RegionFileMissing)

View File

@ -102,7 +102,6 @@ impl Server {
log::info!("Loading Plugins"); log::info!("Loading Plugins");
let plugin_loader = PluginLoader::load(); 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( let world = World::load(Dimension::OverWorld.into_level(
// TODO: load form config // TODO: load form config
"./world".parse().unwrap(), "./world".parse().unwrap(),