Skip to content

Commit

Permalink
Added logic to generate chunks if they can't be read from the world f…
Browse files Browse the repository at this point in the history
…ile.

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.
  • Loading branch information
DaniD3v committed Aug 28, 2024
1 parent 909eb38 commit 2176120
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 22 deletions.
78 changes: 57 additions & 21 deletions pumpkin-world/src/level.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{
fs::OpenOptions,
io::{Read, Seek},
path::{Path, PathBuf},
path::PathBuf,
};

use flate2::{bufread::ZlibDecoder, read::GzDecoder};
Expand All @@ -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,
}
Expand Down Expand Up @@ -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,
}
}
}

Expand Down Expand Up @@ -121,27 +145,39 @@ 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<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,
);

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)
Expand Down
1 change: 0 additions & 1 deletion pumpkin/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down

0 comments on commit 2176120

Please sign in to comment.