Skip to content

Commit

Permalink
doc(world): add doc to world::*
Browse files Browse the repository at this point in the history
  • Loading branch information
Liyze09 committed Oct 6, 2024
1 parent b949525 commit d1ab792
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 54 deletions.
2 changes: 2 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 38 additions & 19 deletions crates/kernel/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,60 @@ use sha2::{Digest, Sha256};
use std::sync::LazyLock;
use toml::{toml, Value};

static DEFAULT: LazyLock<Value> = LazyLock::new(|| {
Value::from(toml! {
max-players = 20
view-distance = 12
simulation-distance = 16
seed = 0
port = 25565
worldgen-implementation = "super_flat"
})
});
static TOML: LazyLock<Value> = LazyLock::new(|| {
if let Ok(file) = std::fs::read_to_string("./config.toml") {
toml::from_str(&file).unwrap()
} else {
let toml = Value::from(toml! {
max-players = 20
view-distance = 12
simulation-distance = 16
seed = 0
port = 25565
worldgen-implementation = "super_flat"
});
std::fs::write("./config.toml", toml::to_string_pretty(&toml).unwrap()).unwrap();
toml
std::fs::write("./config.toml", toml::to_string_pretty(&*DEFAULT).unwrap()).unwrap();
DEFAULT.clone()
}
});
pub static WORLDGEN_IMPLEMENTATION: LazyLock<&str> = LazyLock::new(|| {
TOML.get("worldgen-implementation")
.unwrap()
.unwrap_or_else(|| DEFAULT.get("worldgen-implementation").unwrap())
.as_str()
.unwrap()
});
pub static PORT: LazyLock<i32> =
LazyLock::new(|| TOML.get("port").unwrap().as_integer().unwrap() as i32);
pub static MAX_PLAYERS: LazyLock<i32> =
LazyLock::new(|| TOML.get("max-players").unwrap().as_integer().unwrap() as i32);
pub static VIEW_DISTANCE: LazyLock<i32> =
LazyLock::new(|| TOML.get("view-distance").unwrap().as_integer().unwrap() as i32);
pub static PORT: LazyLock<i32> = LazyLock::new(|| {
TOML.get("port")
.unwrap_or_else(|| DEFAULT.get("port").unwrap())
.as_integer()
.unwrap() as i32
});
pub static MAX_PLAYERS: LazyLock<i32> = LazyLock::new(|| {
TOML.get("max-players")
.unwrap_or_else(|| DEFAULT.get("max-players").unwrap())
.as_integer()
.unwrap() as i32
});
pub static VIEW_DISTANCE: LazyLock<i32> = LazyLock::new(|| {
TOML.get("view-distance")
.unwrap_or_else(|| DEFAULT.get("view-distance").unwrap())
.as_integer()
.unwrap() as i32
});
pub static SIMULATION_DISTANCE: LazyLock<i32> = LazyLock::new(|| {
TOML.get("simulation-distance")
.unwrap()
.unwrap_or_else(|| DEFAULT.get("simulation-distance").unwrap())
.as_integer()
.unwrap() as i32
});
pub static SEED: LazyLock<i64> = LazyLock::new(|| TOML.get("seed").unwrap().as_integer().unwrap());
pub static SEED: LazyLock<i64> = LazyLock::new(|| {
TOML.get("seed")
.unwrap_or_else(|| DEFAULT.get("seed").unwrap())
.as_integer()
.unwrap()
});
pub static HASHED_SEED: LazyLock<i64> = LazyLock::new(|| {
let mut sha = Sha256::new();
sha.update(SEED.to_be_bytes());
Expand Down
2 changes: 1 addition & 1 deletion crates/kernel/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod api;
pub mod api;
pub mod block;
pub mod config;
pub mod entity;
Expand Down
54 changes: 26 additions & 28 deletions crates/kernel/src/test/world_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,34 @@ mod chunk {
mod gen {
#[test]
fn worldgen() {
#[test]
fn chunk() {
use crate::block::BLOCKS_BY_NAME;
use crate::world::chunk::Chunk;
use crate::world::dimension::Dimension;
use crate::world::gen::impls::SuperFlatWorldgen;
use crate::world::gen::Worldgen;
use crate::block::BLOCKS_BY_NAME;
use crate::registry::registries::register_vanilla;
use crate::world::chunk::Chunk;
use crate::world::dimension::Dimension;
use crate::world::gen::impls::SuperFlatWorldgen;
use crate::world::gen::Worldgen;

let bedrock = *BLOCKS_BY_NAME.get("minecraft:bedrock").unwrap().value();
let dirt = *BLOCKS_BY_NAME.get("minecraft:dirt").unwrap().value();
let grass_block = *BLOCKS_BY_NAME.get("minecraft:grass_block").unwrap().value();
register_vanilla();
let bedrock = *BLOCKS_BY_NAME.get("minecraft:bedrock").unwrap().value();
let dirt = *BLOCKS_BY_NAME.get("minecraft:dirt").unwrap().value();
let grass_block = *BLOCKS_BY_NAME.get("minecraft:grass_block").unwrap().value();

let chunk =
SuperFlatWorldgen::new(0, vec![bedrock, dirt, grass_block]).gen(Chunk::new(
&Dimension::new(
crate::registry::dimension_type::DIMENSION_TYPES
.get("minecraft:overworld")
.unwrap()
.clone(),
"overworld".to_string(),
0,
),
0,
));
assert_eq!(chunk.get_block(0, 0, 0), Some(bedrock));
assert_eq!(chunk.get_block(0, 1, 0), Some(dirt));
assert_eq!(chunk.get_block(0, 2, 0), Some(grass_block));
assert_eq!(chunk.get_block(0, 3, 0), Some(0));
assert_eq!(chunk.get_block(15, 0, 15), Some(bedrock));
}
let chunk = SuperFlatWorldgen::new(0, vec![bedrock, dirt, grass_block]).gen(Chunk::new(
&Dimension::new(
crate::registry::dimension_type::DIMENSION_TYPES
.get("minecraft:overworld")
.unwrap()
.clone(),
"overworld".to_string(),
0,
),
0,
));
assert_eq!(chunk.get_block(0, 0, 0), Some(bedrock));
assert_eq!(chunk.get_block(0, 1, 0), Some(dirt));
assert_eq!(chunk.get_block(0, 2, 0), Some(grass_block));
assert_eq!(chunk.get_block(0, 3, 0), Some(0));
assert_eq!(chunk.get_block(15, 0, 15), Some(bedrock));
}
}
mod dimension {
Expand Down
17 changes: 16 additions & 1 deletion crates/kernel/src/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct World {
use_2: bool,
}
impl World {
pub fn new() -> World {
pub(crate) fn new() -> World {
let mut dimensions = Vec::with_capacity(DIMENSION_TYPES_INDEX.len());
let mut idx = 0;
while idx < DIMENSION_TYPES_INDEX.len() {
Expand Down Expand Up @@ -68,9 +68,14 @@ impl World {
fn swap_queues(&mut self) {
self.use_2 = !self.use_2;
}
/// Adds a new block update to the block update queue.
///
/// ## Parameters
/// - `update`: The block update information, of type `BlockUpdate`.
pub fn add_block_update(&mut self, update: BlockUpdate) {
self.get_queue().push(update);
}
/// Executes a single tick operation to process all block update events before executing.
pub fn tick(&mut self) {
self.swap_queues();
let queue = self.get_internal_queue();
Expand Down Expand Up @@ -187,6 +192,16 @@ impl World {
self.swap_queues();
}

/// Find a dimension by name
///
/// # Parameters
/// - `name`: &str, the name of the dimension
///
/// # Returns
/// - `Option<Arc<Dimension>>`: Returns `Some(Arc<Dimension>)` if found, otherwise returns `None`
///
/// # Description
/// This method iterates through the internal dimensions collection, finds the first dimension that matches the given name, and returns its clone. If no matching dimension is found, it returns `None`.
pub fn find_dimension(&self, name: &str) -> Option<Arc<Dimension>> {
Some(
self.dimensions
Expand Down
113 changes: 108 additions & 5 deletions crates/kernel/src/world/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ pub struct Chunk {
}

impl Chunk {
/// Creates a new Chunk instance.
///
/// # Parameters
/// - `dimension`:
/// A reference to dimension information
/// used to fetch dimension-specific data such as height.
/// - `Pos`:
/// The position of the Chunk, represented as an unsigned 64-bit integer.
/// The First 32 bits represent the X coordinate, the next 32 bits represent the Z coordinate.
///
/// # Returns
/// Returns a Chunk instance with initialized data and properties.
pub fn new(dimension: &Dimension, pos: u64) -> Chunk {
let height = dimension.dimension_type.height;
let size = (height / 16) as usize;
Expand All @@ -24,13 +36,41 @@ impl Chunk {
pos,
}
}
/// Get the block information at the specified coordinates (x, y, z).
///
/// This function queries the spatial data structure
/// represented by the current object based on the given 3D coordinates.
/// If the coordinate position is valid and the block information exists,
/// it returns the block ID wrapped in Some;
/// otherwise, it returns None.
///
/// # Arguments
/// - `x` - The x-coordinate of the block.
/// - `y` - The y-coordinate of the block.
/// - `z` - The z-coordinate of the block.
///
/// # Returns
/// - `Option<u32>` - The block ID if found, otherwise None.
pub fn get_block(&self, x: i32, y: i32, z: i32) -> Option<u32> {
let idx = check_pos(x, y, z, self.height)?;
let section = self.data.get(idx)?;
let sy = ((y as usize) - (16 * idx)) as u32;
Some(unsafe { section.get_state_unchecked(x as u32, sy, z as u32) })
}

/// Sets a block type at a specific 3D coordinate position.
///
/// # Parameters
/// - `x`: The X coordinate of the block.
/// - `y`: The Y coordinate of the block.
/// - `z`: The Z coordinate of the block.
/// - `block`: The type of block to set.
///
/// This function first validates if the given coordinates are within the valid range
/// (based on the height).
/// If the position is invalid, it returns immediately.
/// If the position is valid, it retrieves the corresponding section (`section`) for that position.
/// If the section does not exist, it returns immediately.
/// Finally, it sets the specified block type within the determined section.
pub fn set_block(&self, x: i32, y: i32, z: i32, block: u32) {
let idx = match check_pos(x, y, z, self.height) {
Some(s) => s,
Expand All @@ -43,11 +83,23 @@ impl Chunk {
let sy = ((y as usize) - (16 * idx)) as u32;
section.set_state(x as u32, sy, z as u32, block)
}

/// Get the section data at the specified index
///
/// # Parameters
/// - `y`: The index of the section, represented as an usize
///
/// # Returns
/// - `Option<SectionDataGuard>`:
/// Returns a Some wrapping a SectionDataGuard object
/// if the section data is successfully retrieved,
/// otherwise returns None
///
/// # Notes
/// This method retrieves the section data based on the provided section
pub fn get_section(&self, y: usize) -> Option<SectionDataGuard> {
Some(self.data.get(y / 16)?.get_data_guard())
}

/// Get a guard object that provides pre-locked access to the chunk data.
pub fn get_guard(&self) -> ChunkGuard<'_> {
let sections = self.data.len();
let mut data = Vec::with_capacity(sections);
Expand Down Expand Up @@ -79,13 +131,41 @@ pub struct ChunkGuard<'a> {
}

impl ChunkGuard<'_> {
/// Retrieves the block information at the specified coordinates (x, y, z).
///
/// This function queries the spatial data structure represented by the current object and returns
/// the identifier of the block at the given position.
/// If the coordinate position is valid and the
/// block information exists, it returns Some wrapping the block identifier;
/// otherwise, it returns None.
///
/// # Parameters
/// - `x`: The x-coordinate, representing the horizontal position.
/// - `Y`: The y-coordinate, representing the vertical position.
/// - `Z`: The z-coordinate, representing the depth position.
///
/// # Returns
/// - `Option<u32>`:
/// Some wrapping the block identifier
/// if the query is successful or the coordinate is invalid.
pub fn get_block(&self, x: i32, y: i32, z: i32) -> Option<u32> {
let idx = check_pos(x, y, z, self.height)?;
let section = self.data.get(idx)?;
let sy = ((y as usize) - (16 * idx)) as u32;
Some(unsafe { section.get_state_unchecked(x as u32, sy, z as u32) })
}

/// Sets the block type at a specified position.
///
/// # Parameters
/// - `x`: The X coordinate of the block.
/// - `y`: The Y coordinate of the block.
/// - `z`: The Z coordinate of the block.
/// - `block`: The block type to set.
///
/// # Description
/// This function sets the block type at the given coordinates in the world.
/// It first validates the coordinates and then finds the corresponding chunk.
/// If the coordinates are out of bounds or the chunk is not accessible, the operation is ignored.
pub fn set_block(&mut self, x: i32, y: i32, z: i32, block: u32) {
let idx = match check_pos(x, y, z, self.height) {
Some(s) => s,
Expand Down Expand Up @@ -175,6 +255,19 @@ pub struct SectionDataGuard<'a> {
}

impl SectionDataGuard<'_> {
/// Retrieves the state value at the specified coordinates
///
/// # Arguments
/// - `x`: The x-coordinate
/// - `y`: The y-coordinate
/// - `z`: The z-coordinate
///
/// # Returns
/// The state value at the given coordinates
///
/// # Description
/// This function computes the index based on x, y,
/// and z coordinates and retrieves the state value from the internal data structure.
pub fn get_state(&self, x: u32, y: u32, z: u32) -> u32 {
let index = (x + 16 * (y + 16 * z)) as usize;
self.data[index]
Expand All @@ -198,7 +291,17 @@ impl SectionDataGuard<'_> {
let index = (x + 16 * (y + 16 * z)) as usize;
*self.data.get_unchecked(index)
}

/// Sets the state at the given coordinates.
///
/// # Parameters
/// - `x`: The x-coordinate, representing the horizontal position in 3D space.
/// - `Y`: The y-coordinate, representing the vertical position in 3D space.
/// - `Z`: The z-coordinate, representing the depth position in 3D space.
/// - `State`: The new state value to set at the given position.
///
/// # Description
/// This function calculates the index based on the 3D coordinates
/// and sets the state of that index in the data array.
pub fn set_state(&mut self, x: u32, y: u32, z: u32, state: u32) {
let index = (x + 16 * (y + 16 * z)) as usize;
self.data[index] = state;
Expand Down
Loading

0 comments on commit d1ab792

Please sign in to comment.