Skip to content
This repository has been archived by the owner on Jul 1, 2024. It is now read-only.

Commit

Permalink
Basic implementation of LightManager
Browse files Browse the repository at this point in the history
  • Loading branch information
DimitriTimoz committed Dec 25, 2023
1 parent 600395b commit bfd88f7
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 17 deletions.
92 changes: 92 additions & 0 deletions minecraft-server/src/world/light.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
use std::collections::BinaryHeap;

use minecraft_protocol::ids::blocks::Block;
use tokio::sync::OwnedRwLockWriteGuard;

use crate::prelude::*;
use super::*;

Expand Down Expand Up @@ -211,3 +216,90 @@ impl Light {
self.sky_light.get_level(position).unwrap_or_default()
}
}

pub struct LightManager {
world_map: &'static WorldMap,
current_shard_id: Option<usize>,
current_shard: Option<OwnedRwLockWriteGuard<HashMap<ChunkColumnPosition, ChunkColumn>>>,
}

impl LightManager {
fn new(world_map: &'static WorldMap) -> Self {
Self {
world_map,
current_shard: None,
current_shard_id: None,
}
}

pub async fn update_light(world_map: &'static WorldMap, block_position: BlockPosition, block: BlockWithState) {
let mut light_manager = Self::new(world_map);

light_manager.set_block(block_position, block).await;
}

async fn ensure_shard(&mut self, shard_id: usize) {
if let Some(current_shard_id) = self.current_shard_id {
if current_shard_id == shard_id {
return;
}
}
self.current_shard = Some(self.world_map.write_shard(shard_id).await);
self.current_shard_id = Some(shard_id);
}

async fn get_chunk_column(&mut self, chunk_column_position: ChunkColumnPosition) -> Option<&mut ChunkColumn> {
let shard_id = chunk_column_position.shard(self.world_map.get_shard_count());

self.ensure_shard(shard_id).await;

if let Some(shard) = &mut self.current_shard {
// Here, we use a reference to `shard` instead of trying to move it
shard.get_mut(&chunk_column_position)
} else {
unreachable!("ensure shard always sets to current_shard the requested shard")
}
}



async fn set_light_level(&mut self, position: LightPosition, level: u8) {
unimplemented!();
}

async fn get_light_level(&mut self, position: LightPosition) -> u8 {
unimplemented!();
}

pub async fn set_block(&mut self, block_position: BlockPosition, block: BlockWithState) {
let mut to_explore = BinaryHeap::new();
let position = LightPosition::from(block_position.clone());
to_explore.extend(position.get_neighbors(24));
while let Some(postion) = to_explore.pop() {

if let Some(column) = self.get_chunk_column(position.clone().into()).await {
let block = Block::from(column.get_block(position.clone().into()));

if block.is_transparent() {
let highest_block = column.get_highest_block_at(&block_position.in_chunk_column());
let is_inside = highest_block > postion.clone().y as u16 + 1;
let new_level = if is_inside { postion.clone().y as u8 - block.light_absorption() - 1 } else { MAX_LIGHT_LEVEL };
let new_position = LightPositionInChunkColumn::from(postion.clone());

to_explore.extend(postion.clone().get_neighbors(24));
}
}
}

// Clear locked chunks

}


pub async fn init_chunk_column_light(world_map: &'static WorldMap, chunk_column_position: ChunkColumnPosition) {

// Clear locked chubks
}
}


26 changes: 13 additions & 13 deletions minecraft-server/src/world/map.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{collections::HashMap, cmp::Ordering};
use minecraft_protocol::{components::chunk::PalettedData, ids::blocks::Block};
use tokio::sync::RwLock;
use tokio::sync::{RwLock, OwnedRwLockWriteGuard};
use crate::prelude::*;

pub struct WorldMap {
Expand Down Expand Up @@ -432,7 +432,10 @@ impl WorldMap {
for _ in 0..shard_count {
shards.push(Arc::new(RwLock::new(HashMap::new())));
}
WorldMap { shard_count, shards }
WorldMap {
shard_count,
shards
}
}

pub async fn get_block(&self, position: BlockPosition) -> BlockWithState {
Expand All @@ -449,17 +452,6 @@ impl WorldMap {
inner_get_block(self, position).await.unwrap_or(BlockWithState::Air)
}

pub async fn get_network_chunk(&self, position: ChunkPosition) -> Option<NetworkChunk> {
let chunk_column_position = position.chunk_column();
let shard = chunk_column_position.shard(self.shard_count);
let cy_in_vec: usize = position.cy.saturating_add(4).try_into().ok()?;

let shard = self.shards[shard].read().await;
let chunk_column = shard.get(&chunk_column_position)?;
let chunk = chunk_column.chunks.get(cy_in_vec)?;

Some(chunk.as_network_chunk().clone())
}

pub async fn set_block(&self, position: BlockPosition, block: BlockWithState) {
async fn inner_get_block(s: &WorldMap, position: BlockPosition, block: BlockWithState) -> Option<()> {
Expand Down Expand Up @@ -494,6 +486,14 @@ impl WorldMap {
movement.clone() // Would be more logic if it returned validated, but this way we avoid precision errors
}

pub fn get_shard_count(&self) -> usize {
self.shard_count
}

pub(super) async fn write_shard(&self, shard: usize) -> OwnedRwLockWriteGuard<HashMap<ChunkColumnPosition, ChunkColumn>> {
self.shards[shard].clone().write_owned().await
}

#[cfg_attr(feature = "trace", instrument(skip(self)))]
pub async fn load(&self, position: ChunkColumnPosition) {
let chunk = ChunkColumn::flat(); // TODO: load from disk
Expand Down
4 changes: 0 additions & 4 deletions minecraft-server/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ impl World {
Some(self.map.get_block(position).await)
}

pub async fn get_network_chunk(&self, position: ChunkPosition) -> Option<NetworkChunk> {
self.map.get_network_chunk(position).await
}

pub async fn set_block(&self, position: BlockPosition, block: BlockWithState) {
self.map.set_block(position.clone(), block.clone()).await;
self.notify(&position.chunk_column(), WorldChange::Block(position, block)).await;
Expand Down

0 comments on commit bfd88f7

Please sign in to comment.