185 lines
7.3 KiB
Java
185 lines
7.3 KiB
Java
|
package net.minecraft.world.level.lighting;
|
||
|
|
||
|
import net.minecraft.core.BlockPos;
|
||
|
import net.minecraft.core.Direction;
|
||
|
import net.minecraft.core.SectionPos;
|
||
|
import net.minecraft.util.BitStorage;
|
||
|
import net.minecraft.util.Mth;
|
||
|
import net.minecraft.util.SimpleBitStorage;
|
||
|
import net.minecraft.world.level.BlockGetter;
|
||
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||
|
import net.minecraft.world.level.block.Blocks;
|
||
|
import net.minecraft.world.level.block.state.BlockState;
|
||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||
|
import net.minecraft.world.phys.shapes.Shapes;
|
||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||
|
|
||
|
public class ChunkSkyLightSources {
|
||
|
private static final int SIZE = 16;
|
||
|
public static final int NEGATIVE_INFINITY = Integer.MIN_VALUE;
|
||
|
private final int minY;
|
||
|
private final BitStorage heightmap;
|
||
|
private final BlockPos.MutableBlockPos mutablePos1 = new BlockPos.MutableBlockPos();
|
||
|
private final BlockPos.MutableBlockPos mutablePos2 = new BlockPos.MutableBlockPos();
|
||
|
|
||
|
public ChunkSkyLightSources(LevelHeightAccessor p_285502_) {
|
||
|
this.minY = p_285502_.getMinY() - 1;
|
||
|
int i = p_285502_.getMaxY() + 1;
|
||
|
int j = Mth.ceillog2(i - this.minY + 1);
|
||
|
this.heightmap = new SimpleBitStorage(j, 256);
|
||
|
}
|
||
|
|
||
|
public void fillFrom(ChunkAccess p_285152_) {
|
||
|
int i = p_285152_.getHighestFilledSectionIndex();
|
||
|
if (i == -1) {
|
||
|
this.fill(this.minY);
|
||
|
} else {
|
||
|
for (int j = 0; j < 16; j++) {
|
||
|
for (int k = 0; k < 16; k++) {
|
||
|
int l = Math.max(this.findLowestSourceY(p_285152_, i, k, j), this.minY);
|
||
|
this.set(index(k, j), l);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private int findLowestSourceY(ChunkAccess p_285214_, int p_285171_, int p_285021_, int p_285226_) {
|
||
|
int i = SectionPos.sectionToBlockCoord(p_285214_.getSectionYFromSectionIndex(p_285171_) + 1);
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = this.mutablePos1.set(p_285021_, i, p_285226_);
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos1 = this.mutablePos2.setWithOffset(blockpos$mutableblockpos, Direction.DOWN);
|
||
|
BlockState blockstate = Blocks.AIR.defaultBlockState();
|
||
|
|
||
|
for (int j = p_285171_; j >= 0; j--) {
|
||
|
LevelChunkSection levelchunksection = p_285214_.getSection(j);
|
||
|
if (levelchunksection.hasOnlyAir()) {
|
||
|
blockstate = Blocks.AIR.defaultBlockState();
|
||
|
int l = p_285214_.getSectionYFromSectionIndex(j);
|
||
|
blockpos$mutableblockpos.setY(SectionPos.sectionToBlockCoord(l));
|
||
|
blockpos$mutableblockpos1.setY(blockpos$mutableblockpos.getY() - 1);
|
||
|
} else {
|
||
|
for (int k = 15; k >= 0; k--) {
|
||
|
BlockState blockstate1 = levelchunksection.getBlockState(p_285021_, k, p_285226_);
|
||
|
if (isEdgeOccluded(blockstate, blockstate1)) {
|
||
|
return blockpos$mutableblockpos.getY();
|
||
|
}
|
||
|
|
||
|
blockstate = blockstate1;
|
||
|
blockpos$mutableblockpos.set(blockpos$mutableblockpos1);
|
||
|
blockpos$mutableblockpos1.move(Direction.DOWN);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return this.minY;
|
||
|
}
|
||
|
|
||
|
public boolean update(BlockGetter p_285514_, int p_284999_, int p_285358_, int p_284944_) {
|
||
|
int i = p_285358_ + 1;
|
||
|
int j = index(p_284999_, p_284944_);
|
||
|
int k = this.get(j);
|
||
|
if (i < k) {
|
||
|
return false;
|
||
|
} else {
|
||
|
BlockPos blockpos = this.mutablePos1.set(p_284999_, p_285358_ + 1, p_284944_);
|
||
|
BlockState blockstate = p_285514_.getBlockState(blockpos);
|
||
|
BlockPos blockpos1 = this.mutablePos2.set(p_284999_, p_285358_, p_284944_);
|
||
|
BlockState blockstate1 = p_285514_.getBlockState(blockpos1);
|
||
|
if (this.updateEdge(p_285514_, j, k, blockpos, blockstate, blockpos1, blockstate1)) {
|
||
|
return true;
|
||
|
} else {
|
||
|
BlockPos blockpos2 = this.mutablePos1.set(p_284999_, p_285358_ - 1, p_284944_);
|
||
|
BlockState blockstate2 = p_285514_.getBlockState(blockpos2);
|
||
|
return this.updateEdge(p_285514_, j, k, blockpos1, blockstate1, blockpos2, blockstate2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private boolean updateEdge(
|
||
|
BlockGetter p_285066_, int p_285184_, int p_285101_, BlockPos p_285446_, BlockState p_285185_, BlockPos p_285103_, BlockState p_285009_
|
||
|
) {
|
||
|
int i = p_285446_.getY();
|
||
|
if (isEdgeOccluded(p_285185_, p_285009_)) {
|
||
|
if (i > p_285101_) {
|
||
|
this.set(p_285184_, i);
|
||
|
return true;
|
||
|
}
|
||
|
} else if (i == p_285101_) {
|
||
|
this.set(p_285184_, this.findLowestSourceBelow(p_285066_, p_285103_, p_285009_));
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private int findLowestSourceBelow(BlockGetter p_285279_, BlockPos p_285119_, BlockState p_285096_) {
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = this.mutablePos1.set(p_285119_);
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos1 = this.mutablePos2.setWithOffset(p_285119_, Direction.DOWN);
|
||
|
BlockState blockstate = p_285096_;
|
||
|
|
||
|
while (blockpos$mutableblockpos1.getY() >= this.minY) {
|
||
|
BlockState blockstate1 = p_285279_.getBlockState(blockpos$mutableblockpos1);
|
||
|
if (isEdgeOccluded(blockstate, blockstate1)) {
|
||
|
return blockpos$mutableblockpos.getY();
|
||
|
}
|
||
|
|
||
|
blockstate = blockstate1;
|
||
|
blockpos$mutableblockpos.set(blockpos$mutableblockpos1);
|
||
|
blockpos$mutableblockpos1.move(Direction.DOWN);
|
||
|
}
|
||
|
|
||
|
return this.minY;
|
||
|
}
|
||
|
|
||
|
private static boolean isEdgeOccluded(BlockState p_285219_, BlockState p_285512_) {
|
||
|
if (p_285512_.getLightBlock() != 0) {
|
||
|
return true;
|
||
|
} else {
|
||
|
VoxelShape voxelshape = LightEngine.getOcclusionShape(p_285219_, Direction.DOWN);
|
||
|
VoxelShape voxelshape1 = LightEngine.getOcclusionShape(p_285512_, Direction.UP);
|
||
|
return Shapes.faceShapeOccludes(voxelshape, voxelshape1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int getLowestSourceY(int p_285247_, int p_285082_) {
|
||
|
int i = this.get(index(p_285247_, p_285082_));
|
||
|
return this.extendSourcesBelowWorld(i);
|
||
|
}
|
||
|
|
||
|
public int getHighestLowestSourceY() {
|
||
|
int i = Integer.MIN_VALUE;
|
||
|
|
||
|
for (int j = 0; j < this.heightmap.getSize(); j++) {
|
||
|
int k = this.heightmap.get(j);
|
||
|
if (k > i) {
|
||
|
i = k;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return this.extendSourcesBelowWorld(i + this.minY);
|
||
|
}
|
||
|
|
||
|
private void fill(int p_285311_) {
|
||
|
int i = p_285311_ - this.minY;
|
||
|
|
||
|
for (int j = 0; j < this.heightmap.getSize(); j++) {
|
||
|
this.heightmap.set(j, i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void set(int p_285323_, int p_285220_) {
|
||
|
this.heightmap.set(p_285323_, p_285220_ - this.minY);
|
||
|
}
|
||
|
|
||
|
private int get(int p_284951_) {
|
||
|
return this.heightmap.get(p_284951_) + this.minY;
|
||
|
}
|
||
|
|
||
|
private int extendSourcesBelowWorld(int p_284953_) {
|
||
|
return p_284953_ == this.minY ? Integer.MIN_VALUE : p_284953_;
|
||
|
}
|
||
|
|
||
|
private static int index(int p_284980_, int p_285277_) {
|
||
|
return p_284980_ + p_285277_ * 16;
|
||
|
}
|
||
|
}
|