Skip to content

Commit

Permalink
change: Reorder lightmap handling, fixes MC-169913 (#17)
Browse files Browse the repository at this point in the history
* Reorder lightmap removal
* Add lightmap handling to ProtoChunk
  • Loading branch information
PhiProven committed Aug 30, 2020
1 parent 6c5b89d commit 3d74a16
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package me.jellysquid.mods.phosphor.mixin.chunk;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.chunk.ProtoChunk;
import net.minecraft.world.chunk.light.LightingProvider;

@Mixin(ProtoChunk.class)
public abstract class MixinProtoChunk {
@Shadow
public abstract LightingProvider getLightingProvider();

@Shadow
public abstract ChunkStatus getStatus();

@Unique
private static final ChunkStatus PRE_LIGHT = ChunkStatus.LIGHT.getPrevious();

@Inject(
method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)Lnet/minecraft/block/BlockState;",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/chunk/ChunkSection;setBlockState(IIILnet/minecraft/block/BlockState;)Lnet/minecraft/block/BlockState;"
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void addLightmap(final BlockPos pos, final BlockState state, final boolean moved, final CallbackInfoReturnable<BlockState> ci, final int x, final int y, final int z, final ChunkSection section) {
if (this.getStatus().isAtLeast(PRE_LIGHT) && ChunkSection.isEmpty(section)) {
this.getLightingProvider().updateSectionStatus(pos, false);
}
}

@Inject(
method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)Lnet/minecraft/block/BlockState;",
slice = @Slice(
from = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/chunk/ChunkSection;setBlockState(IIILnet/minecraft/block/BlockState;)Lnet/minecraft/block/BlockState;"
)
),
at = @At(
value = "RETURN",
ordinal = 0
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void removeLightmap(final BlockPos pos, final BlockState state, final boolean moved, final CallbackInfoReturnable<BlockState> ci, final int x, final int y, final int z, final ChunkSection section) {
if (this.getStatus().isAtLeast(PRE_LIGHT) && ChunkSection.isEmpty(section)) {
this.getLightingProvider().updateSectionStatus(pos, true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.WorldChunk;
import net.minecraft.world.chunk.light.LightingProvider;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -67,4 +70,14 @@ public Stream<BlockPos> getLightSourcesStream() {

return list.stream();
}

@Redirect(
method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)Lnet/minecraft/block/BlockState;",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/chunk/light/LightingProvider;updateSectionStatus(Lnet/minecraft/util/math/BlockPos;Z)V"
)
)
private void disablelLightmapHandling(final LightingProvider lightingProvider, final BlockPos pos, final boolean status) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package me.jellysquid.mods.phosphor.mixin.chunk.light;

import java.util.function.IntSupplier;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;

import net.minecraft.server.world.ServerLightingProvider;
import net.minecraft.util.Util;
import net.minecraft.util.math.ChunkSectionPos;
import net.minecraft.world.chunk.ChunkProvider;
import net.minecraft.world.chunk.light.LightingProvider;

@Mixin(ServerLightingProvider.class)
public abstract class MixinServerLightingProvider extends LightingProvider
{
private MixinServerLightingProvider(final ChunkProvider chunkProvider, final boolean hasBlockLight, final boolean hasSkyLight) {
super(chunkProvider, hasBlockLight, hasSkyLight);
}

@Shadow
protected abstract void enqueue(int x, int z, IntSupplier completedLevelSupplier, ServerLightingProvider.Stage stage, Runnable task);

@Shadow
protected abstract void enqueue(int x, int z, ServerLightingProvider.Stage stage, Runnable task);

/**
* @author PhiPro
* @reason Re-implement
*/
@Overwrite
public void updateSectionStatus(final ChunkSectionPos pos, final boolean empty)
{
if (empty) {
// Schedule after light updates have been carried out
this.enqueue(pos.getSectionX(), pos.getSectionZ(), ServerLightingProvider.Stage.POST_UPDATE, Util.debugRunnable(() -> {
super.updateSectionStatus(pos, true);
},
() -> "updateSectionStatus " + pos + " " + true
));
} else {
// Schedule before light updates are carried out
this.enqueue(pos.getSectionX(), pos.getSectionZ(), () -> 0, ServerLightingProvider.Stage.PRE_UPDATE, Util.debugRunnable(() -> {
super.updateSectionStatus(pos, false);
},
() -> "updateSectionStatus " + pos + " " + false
));

// Schedule another version in POST_UPDATE to achieve reliable final state
this.enqueue(pos.getSectionX(), pos.getSectionZ(), ServerLightingProvider.Stage.POST_UPDATE, Util.debugRunnable(() -> {
super.updateSectionStatus(pos, false);
},
() -> "updateSectionStatus " + pos + " " + false
));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package me.jellysquid.mods.phosphor.mixin.world;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.WorldChunk;

@Mixin(World.class)
public abstract class MixinWorld implements WorldAccess {
@Inject(
method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;II)Z",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/chunk/WorldChunk;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)Lnet/minecraft/block/BlockState;"
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void addLightmap(final BlockPos pos, final BlockState state, final int flags, final int maxUpdateDepth, final CallbackInfoReturnable<Boolean> ci, final WorldChunk chunk) {
if (ChunkSection.isEmpty(chunk.getSectionArray()[pos.getY() >> 4])) {
this.getChunkManager().getLightingProvider().updateSectionStatus(pos, false);
}
}

@Inject(
method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;II)Z",
slice = @Slice(
from = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/chunk/WorldChunk;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Z)Lnet/minecraft/block/BlockState;"
)
),
at = @At("RETURN"),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void removeLightmap(final BlockPos pos, final BlockState state, final int flags, final int maxUpdateDepth, final CallbackInfoReturnable<Boolean> ci, final WorldChunk chunk) {
if (ChunkSection.isEmpty(chunk.getSectionArray()[pos.getY() >> 4])) {
this.getChunkManager().getLightingProvider().updateSectionStatus(pos, true);
}
}
}
2 changes: 2 additions & 0 deletions src/main/resources/phosphor.accesswidener
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ accessWidener v1 named

accessible class net/minecraft/block/AbstractBlock$AbstractBlockState$ShapeCache

accessible class net/minecraft/server/world/ServerLightingProvider$Stage

accessible method net/minecraft/world/chunk/light/LightStorage hasLight (J)Z
accessible method net/minecraft/world/chunk/light/SkyLightStorage method_15565 (J)Z
accessible method net/minecraft/world/chunk/light/SkyLightStorage isAboveMinHeight (I)Z
5 changes: 4 additions & 1 deletion src/main/resources/phosphor.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
"chunk.light.MixinLevelPropagator",
"chunk.light.MixinLightStorage",
"chunk.light.MixinSkyLightStorage",
"chunk.light.MixinSkyLightStorageData"
"chunk.light.MixinSkyLightStorageData",
"chunk.light.MixinServerLightingProvider",
"world.MixinWorld",
"chunk.MixinProtoChunk"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit 3d74a16

Please sign in to comment.