Skip to content

Commit

Permalink
[1.20.4] Improve detection of dynamic block light sources during ligh…
Browse files Browse the repository at this point in the history
…t updates in chunk generation and loading (neoforged#765)
  • Loading branch information
XFactHD authored Apr 10, 2024
1 parent 9f0d3d4 commit 21d61cd
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 18 deletions.
20 changes: 10 additions & 10 deletions patches/net/minecraft/world/level/chunk/ChunkAccess.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,35 @@
public static final int NO_FILLED_SECTION = -1;
private static final Logger LOGGER = LogUtils.getLogger();
private static final LongSet EMPTY_REFERENCE_SET = new LongOpenHashSet();
@@ -308,23 +_,28 @@
@@ -308,10 +_,19 @@

@Override
public final void findBlockLightSources(BiConsumer<BlockPos, BlockState> p_285269_) {
- this.findBlocks(p_284897_ -> p_284897_.getLightEmission() != 0, p_285269_);
+ this.findBlocks((p_284897_, pos) -> p_284897_.getLightEmission(this, pos) != 0, p_285269_);
+ this.findBlocks(p_284897_ -> p_284897_.hasDynamicLightEmission() || p_284897_.getLightEmission(net.minecraft.world.level.EmptyBlockGetter.INSTANCE, BlockPos.ZERO) != 0, (p_284897_, pos) -> p_284897_.getLightEmission(this, pos) != 0, p_285269_);
}

public void findBlocks(Predicate<BlockState> p_285343_, BiConsumer<BlockPos, BlockState> p_285030_) {
+ findBlocks((state, pos) -> p_285343_.test(state), p_285030_);
+ findBlocks(p_285343_, (state, pos) -> p_285343_.test(state), p_285030_);
+ }
+
+ @Deprecated(forRemoval = true)
+ public void findBlocks(java.util.function.BiPredicate<BlockState, BlockPos> p_285343_, BiConsumer<BlockPos, BlockState> p_285030_) {
+ findBlocks(state -> p_285343_.test(state, BlockPos.ZERO), p_285343_, p_285030_);
+ }
+
+ public void findBlocks(Predicate<BlockState> p_285343_, java.util.function.BiPredicate<BlockState, BlockPos> fineFilter, BiConsumer<BlockPos, BlockState> p_285030_) {
BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos();

for(int i = this.getMinSection(); i < this.getMaxSection(); ++i) {
LevelChunkSection levelchunksection = this.getSection(this.getSectionIndexFromSectionY(i));
- if (levelchunksection.maybeHas(p_285343_)) {
+ if (levelchunksection.maybeHas((state) -> p_285343_.test(state, BlockPos.ZERO))) {
BlockPos blockpos = SectionPos.of(this.chunkPos, i).origin();

for(int j = 0; j < 16; ++j) {
@@ -323,8 +_,9 @@
for(int k = 0; k < 16; ++k) {
for(int l = 0; l < 16; ++l) {
BlockState blockstate = levelchunksection.getBlockState(l, j, k);
- if (p_285343_.test(blockstate)) {
- p_285030_.accept(blockpos$mutableblockpos.setWithOffset(blockpos, l, j, k), blockstate);
+ blockpos$mutableblockpos.setWithOffset(blockpos, l, j, k);
+ if (p_285343_.test(blockstate, blockpos$mutableblockpos.immutable())) {
+ if (fineFilter.test(blockstate, blockpos$mutableblockpos)) {
+ p_285030_.accept(blockpos$mutableblockpos, blockstate);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
--- a/net/minecraft/world/level/chunk/ImposterProtoChunk.java
+++ b/net/minecraft/world/level/chunk/ImposterProtoChunk.java
@@ -217,6 +_,10 @@
@@ -217,6 +_,15 @@
}

@Override
+ public void findBlocks(java.util.function.BiPredicate<BlockState, BlockPos> p_285343_, BiConsumer<BlockPos, BlockState> p_285030_) {
+ this.wrapped.findBlocks(p_285343_, p_285030_);
+ public void findBlocks(java.util.function.BiPredicate<BlockState, BlockPos> p_285465_, BiConsumer<BlockPos, BlockState> p_285030_) {
+ this.wrapped.findBlocks(p_285465_, p_285030_);
+ }
+
+ @Override
+ public void findBlocks(Predicate<BlockState> p_285465_, java.util.function.BiPredicate<BlockState, BlockPos> fineFilter, BiConsumer<BlockPos, BlockState> p_285030_) {
+ this.wrapped.findBlocks(p_285465_, fineFilter, p_285030_);
+ }
+
public TickContainerAccess<Block> getBlockTicks() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
Expand Down Expand Up @@ -104,19 +105,32 @@ default float getFriction(BlockState state, LevelReader level, BlockPos pos, @Nu
return self().getFriction();
}

/**
* Whether this block has dynamic light emission which is not solely based on the {@link BlockState} and instead
* uses the {@link BlockPos}, the {@link AuxiliaryLightManager} or another external data source to determine its
* light value in {@link #getLightEmission(BlockState, BlockGetter, BlockPos)}
*
* @param state the block state being checked
* @return true if this block cannot determine its light emission solely based on the block state, false otherwise
*/
default boolean hasDynamicLightEmission(BlockState state) {
return false;
}

/**
* Get a light value for this block, taking into account the given state and coordinates, normal ranges are between 0 and 15
*
* @param state The state of this block
* @param level The level this block is in
* @param pos The position of this block in the level, will be {@link BlockPos#ZERO} when the chunk being loaded or
* generated calls this to check whether it contains any light sources
* @param level The level this block is in, may be {@link EmptyBlockGetter#INSTANCE}, see implementation notes
* @param pos The position of this block in the level, may be {@link BlockPos#ZERO}, see implementation notes
* @return The light value
* @implNote <ul>
* <li>
* If the given state of this block may emit light but requires position context to determine the light
* value, then it must return a non-zero light value if {@code (pos == BlockPos.ZERO)} in order for the
* chunk calling this to be considered as containing light sources.
* value, then it must return {@code true} from {@link #hasDynamicLightEmission(BlockState)}, otherwise
* this method will be called with {@link EmptyBlockGetter#INSTANCE} and {@link BlockPos#ZERO} during
* chunk generation or loading to determine whether a chunk may contain a light-emitting block,
* resulting in erroneous data if it's determined with the given level and/or the given position.
* </li>
* <li>
* The given {@link BlockGetter} may be a chunk. Block, fluid or block entity accesses outside of its bounds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import net.neoforged.neoforge.common.IPlantable;
import net.neoforged.neoforge.common.ToolAction;
import net.neoforged.neoforge.common.ToolActions;
import net.neoforged.neoforge.common.world.AuxiliaryLightManager;
import net.neoforged.neoforge.event.EventHooks;
import org.jetbrains.annotations.Nullable;

Expand All @@ -68,6 +69,17 @@ default float getFriction(LevelReader level, BlockPos pos, @Nullable Entity enti
return self().getBlock().getFriction(self(), level, pos, entity);
}

/**
* Whether this block state has dynamic light emission which is not solely based on its underlying block or its
* state properties and instead uses the {@link BlockPos}, the {@link AuxiliaryLightManager} or another external
* data source to determine its light value in {@link #getLightEmission(BlockGetter, BlockPos)}
*
* @return true if this block state cannot determine its light emission solely based on its properties, false otherwise
*/
default boolean hasDynamicLightEmission() {
return self().getBlock().hasDynamicLightEmission(self());
}

/**
* Get a light value for this block, taking into account the given state and coordinates, normal ranges are between 0 and 15
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player
return InteractionResult.SUCCESS;
}

@Override
public boolean hasDynamicLightEmission(BlockState state) {
return true;
}

@Override
public int getLightEmission(BlockState state, BlockGetter level, BlockPos pos) {
AuxiliaryLightManager lightManager = level.getAuxLightManager(pos);
Expand Down

0 comments on commit 21d61cd

Please sign in to comment.