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

Commit

Permalink
Add a lot of light tests but it's not enought
Browse files Browse the repository at this point in the history
  • Loading branch information
DimitriTimoz committed Dec 25, 2023
1 parent c78b761 commit 120efd5
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 17 deletions.
177 changes: 162 additions & 15 deletions minecraft-server/src/world/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl SectionLightData {
pub fn set_with(&mut self, level: u8) {
let level = level << 4 | level;
self.0.iter_mut().for_each(|v| *v = level);

}


Expand Down Expand Up @@ -120,6 +121,30 @@ impl LightSystem {
(light_mask, empty_light_mask)
}

/// Set the section mask.
pub fn set_mask(&mut self, section: usize, has_light: bool) {
let mask = 1 << section;
if has_light {
self.light_mask |= mask;
self.empty_light_mask &= !mask;
} else {
self.light_mask &= !mask;
self.empty_light_mask |= mask;
}
}

/// Update the light mask and the empty light mask.
pub fn update_masks(&mut self, section: usize) {
let mask = 1 << section;
if self.light_arrays[section].0.iter().any(|v| *v != 0) {
self.light_mask |= mask;
self.empty_light_mask &= !mask;
} else {
self.light_mask &= !mask;
self.empty_light_mask |= mask;
}
}

/// Get the light data and the light mask and the empty light mask as bitsets.
/// return (light_data, light_mask, empty_light_mask)
pub fn get_packet_data<'a>(&self) -> (Array<'a, Array<'a, u8, VarInt>, VarInt>, BitSet<'a>, BitSet<'a>) {
Expand All @@ -146,24 +171,18 @@ impl LightSystem {
if section != first_section && section != last_section {
// Set the whole section
self.light_arrays[section].set_with(level);
self.set_mask(section, level > 0);
} else {
// Set the part of the section
let first_offset = if section == first_section { first_secion_offset } else { 0 };
let last_offset = if section == last_section { last_section_offset } else { MAX_LIGHT_LEVEL as usize };
for y in first_offset..=last_offset {
self.light_arrays[section].set_layer(y as u8, level)?;
}
}

// Update the mask
let mask = 1 << section;
if self.level > 0 {
self.empty_light_mask &= !mask;
self.light_mask |= mask;
} else {
self.empty_light_mask |= mask;
self.light_mask &= !mask;
}
// Update the mask
self.update_masks(section);
}
}

Ok(())
Expand All @@ -187,6 +206,7 @@ impl LightSystem {
self.light_mask &= !mask;
}
self.light_arrays[section.max(0)].set(position.in_chunk(), level)?;
self.update_masks(section);
Ok(())
}
}
Expand All @@ -202,8 +222,8 @@ impl Light {
sky_light: LightSystem {
level: MAX_LIGHT_LEVEL,
light_arrays: vec![SectionLightData::new(); 24+2],
light_mask: 0,
empty_light_mask: !0,
light_mask: !0,
empty_light_mask: 0,
},
}
}
Expand Down Expand Up @@ -270,11 +290,11 @@ impl LightManager {
unimplemented!();
}

pub async fn set_block(&mut self, block_position: BlockPosition, block: BlockWithState) {
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() {
/*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()));
Expand All @@ -288,7 +308,7 @@ impl LightManager {
to_explore.extend(postion.clone().get_neighbors(24));
}
}
}
}*/

// Clear locked chunks

Expand Down Expand Up @@ -395,4 +415,131 @@ mod tests {
assert_eq!(sky_light.light_arrays[4].get(BlockPositionInChunk { bx: 9, by: 0, bz: 10 }).unwrap(), 0);
}

#[test]
fn test_init_independant_light() {
let chunk_column = ChunkColumn::flat();

for x in 0..16 {
for z in 0..16 {
for y in 0..(chunk_column.get_highest_block() as u16) {
assert_eq!(chunk_column.light.sky_light.get_level(LightPositionInChunkColumn { bx: x, y: y as usize, bz: z }).unwrap(), 0);
}
for y in (chunk_column.get_highest_block() as u16 + 1)..255 {
assert_eq!(chunk_column.light.sky_light.get_level(LightPositionInChunkColumn { bx: x, y: y as usize, bz: z }).unwrap(), MAX_LIGHT_LEVEL);
}
}
}
}

#[test]
fn test_get_light_level() {
let mut light_system = LightSystem {
level: 15,
light_arrays: vec![SectionLightData([0; 2048].to_vec()); 16],
light_mask: 0,
empty_light_mask: u64::MAX,
};

// Set light level at position (1, 2, 3) to 10
let position = LightPositionInChunkColumn { bx: 1, y: 2, bz: 3 };
light_system.set_level(position.clone(), 10).unwrap();

// Get light level at position (1, 2, 3)
let level = light_system.get_level(position).unwrap();
assert_eq!(level, 10);
}

#[test]
fn test_set_mask() {
let mut light_system = LightSystem {
level: 15,
light_arrays: vec![SectionLightData([0; 2048].to_vec()); 16],
light_mask: 0,
empty_light_mask: u64::MAX,
};

// Set mask for section 2 to true
light_system.set_mask(2, true);

// Check if mask is set correctly
assert_eq!(light_system.light_mask, 4);
assert_eq!(light_system.empty_light_mask, u64::MAX - 4);

// Set mask for section 2 to false
light_system.set_mask(2, false);

// Check if mask is set correctly
assert_eq!(light_system.light_mask, 0);
assert_eq!(light_system.empty_light_mask, u64::MAX);
}

#[test]
fn test_update_masks() {
let mut light_system = LightSystem {
level: 15,
light_arrays: vec![SectionLightData([0; 2048].to_vec()); 16],
light_mask: 0,
empty_light_mask: u64::MAX,
};

// Set light level at position (1, 2, 3) to 10
let position = LightPositionInChunkColumn { bx: 1, y: 33, bz: 3 };
light_system.set_level(position.clone(), 10).unwrap();

// Update masks for section 2
light_system.update_masks(2);

// Check if masks are updated correctly
assert_eq!(light_system.light_mask, 4);
assert_eq!(light_system.empty_light_mask, u64::MAX - 4);

// Set light level at position (1, 2, 3) to 0
light_system.set_level(position, 0).unwrap();

// Update masks for section 2
light_system.update_masks(2);

// Check if masks are updated correctly
assert_eq!(light_system.light_mask, 0);
assert_eq!(light_system.empty_light_mask, u64::MAX);
}

#[test]
fn test_to_array() {
let light_system = LightSystem {
level: MAX_LIGHT_LEVEL,
light_arrays: vec![SectionLightData::new(); 24+2],
light_mask: !0,
empty_light_mask: 0,
};

// Convert light data to array
let light_array = light_system.to_array();

// Check if array is created correctly
assert_eq!(light_array.items.len(), 24+2);
assert_eq!(light_array.items[0].items.len(), 2048);
assert_eq!(light_array.items[1].items.len(), 2048);
assert_eq!(light_array.items[24].items[0], 0);
}

#[test]
fn test_masks_to_bitset() {
let light_system = LightSystem {
level: 15,
light_arrays: vec![SectionLightData([0; 2048].to_vec()); 16],
light_mask: 5,
empty_light_mask: u64::MAX - 5,
};

// Convert masks to bitsets
let (light_mask, empty_light_mask) = light_system.masks_to_bitset();

// Check if bitsets are created correctly
assert_eq!(light_mask.items.len(), 1);
assert!(light_mask.items.contains(&5));
assert_eq!(empty_light_mask.items.len(), 1);
assert!(empty_light_mask.items.contains(&((u64::MAX - 5) as i64)));
}

}
3 changes: 1 addition & 2 deletions minecraft-server/src/world/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ impl WorldMap {
sky_light,
block_light: Array::default(),
}};

let serialized = chunk_data.serialize_minecraft_packet().ok()?;
Some(serialized)
}
Expand Down Expand Up @@ -652,7 +652,6 @@ mod tests {
let high_block = flat_column.get_block(BlockPositionInChunkColumn { bx: 0, y: 120, bz: 0 });
assert_eq!(high_block.block_state_id().unwrap(), BlockWithState::Air.block_state_id().unwrap());
}

#[tokio::test]
async fn test_world_map() {
let world = Box::leak(Box::new(World::new(broadcast_channel(100).1)));
Expand Down

0 comments on commit 120efd5

Please sign in to comment.