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::{
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<SaveFile>,
world_gen: Box<dyn WorldGenerator>,
}
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 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!"
"World region folder does not exist, despite there being a root folder."
);
Level {
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) {
.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.
todo!("generate chunk here")
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))
}
})
.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 = (
((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)

View File

@ -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(),