Add ChunkEvent.LightingCalculated, fixes #8354 (#10533)

This commit is contained in:
Erizamanu authored and GitHub committed 2025-04-22 21:11:26 +01:00
1 parent 504dcad849
commit eb001a6382
7 files changed
+130 -30

No files matched your search

@@ -0,0 +1,10 @@
--- a/net/minecraft/server/level/ThreadedLevelLightEngine.java
+++ b/net/minecraft/server/level/ThreadedLevelLightEngine.java
@@ -171,6 +_,7 @@
}, () -> "lightChunk " + chunkpos + " " + p_9355_));
return CompletableFuture.supplyAsync(() -> {
p_9354_.setLightCorrect(true);
+ net.minecraftforge.common.ForgeHooks.fireLightingCalculatedEvent(p_9354_);
return p_9354_;
}, p_280982_ -> this.addTask(chunkpos.x, chunkpos.z, ThreadedLevelLightEngine.TaskType.POST_UPDATE, p_280982_));
}
@@ -153,6 +153,7 @@ import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.entity.living.LivingGetProjectileEvent;
import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.event.level.NoteBlockEvent;
import net.minecraftforge.event.level.ChunkEvent;
import net.minecraftforge.event.network.CustomPayloadEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fluids.FluidType;
@@ -188,6 +189,7 @@ import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.chunk.ChunkAccess;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.jetbrains.annotations.ApiStatus;
@@ -204,6 +206,10 @@ public final class ForgeHooks {
private ForgeHooks() {}
public static void fireLightingCalculatedEvent(ChunkAccess chunk) {
MinecraftForge.EVENT_BUS.post(new ChunkEvent.LightingCalculated(chunk));
}
public static boolean canContinueUsing(@NotNull ItemStack from, @NotNull ItemStack to) {
if (!from.isEmpty() && !to.isEmpty()) {
return from.getItem().canContinueUsing(from, to);
@@ -22,24 +22,20 @@ import org.jetbrains.annotations.ApiStatus;
* <br>
* All children of this event are fired on the {@link MinecraftForge#EVENT_BUS}.<br>
**/
public class ChunkEvent extends LevelEvent
{
public class ChunkEvent extends LevelEvent {
private final ChunkAccess chunk;
public ChunkEvent(ChunkAccess chunk)
{
public ChunkEvent(ChunkAccess chunk) {
super(chunk.getWorldForge());
this.chunk = chunk;
}
public ChunkEvent(ChunkAccess chunk, LevelAccessor level)
{
public ChunkEvent(ChunkAccess chunk, LevelAccessor level) {
super(level);
this.chunk = chunk;
}
public ChunkAccess getChunk()
{
public ChunkAccess getChunk() {
return chunk;
}
@@ -56,13 +52,11 @@ public class ChunkEvent extends LevelEvent
* <br>
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.<br>
**/
public static final class Load extends ChunkEvent
{
public static final class Load extends ChunkEvent {
private final boolean newChunk;
@ApiStatus.Internal
public Load(ChunkAccess chunk, boolean newChunk)
{
public Load(ChunkAccess chunk, boolean newChunk) {
super(chunk);
this.newChunk = newChunk;
}
@@ -74,8 +68,7 @@ public class ChunkEvent extends LevelEvent
*
* @return whether the Chunk is newly generated
*/
public boolean isNewChunk()
{
public boolean isNewChunk() {
return newChunk;
}
}
@@ -91,10 +84,27 @@ public class ChunkEvent extends LevelEvent
* <br>
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.<br>
**/
public static final class Unload extends ChunkEvent
{
public Unload(ChunkAccess chunk)
{
public static final class Unload extends ChunkEvent {
public Unload(ChunkAccess chunk) {
super(chunk);
}
}
/**
* ChunkEvent.LightingCalculated is fired when MinecraftForge flags that lighting is correct in a chunk.<br>
* This event is fired during light propagation in ThreadedLevelLightEngine.CompletableFuture(), specifically upon setting
* the ChunkAccess isLightCorrect to true.<br>
* <br>
* The game test for this event is lighting_event_test in net.minecraftforge.debug.chunk<br>
* <br>
* This event is not {@link Cancelable}.<br>
* <br>
* This event does not have a result. {@link HasResult} <br>
* <br>
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.<br>
**/
public static final class LightingCalculated extends ChunkEvent {
public LightingCalculated(ChunkAccess chunk) {
super(chunk);
}
}
+10 -10
View File
@@ -5,13 +5,13 @@ logoFile="forge_logo.png"
license="LGPL v2.1"
[[mods]]
modId="forge"
version="${global.forgeVersion}"
updateJSONURL="https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json"
displayURL="https://minecraftforge.net/"
displayName="Forge"
credits="Anyone who has contributed on Github and supports our development"
authors="LexManos,cpw"
description='''
Forge, a broad compatibility API.
'''
modId="forge"
version="${global.forgeVersion}"
updateJSONURL="https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json"
displayURL="https://minecraftforge.net/"
displayName="Forge"
credits="Anyone who has contributed on Github and supports our development"
authors="LexManos,cpw"
description='''
Forge, a broad compatibility API.
'''
@@ -0,0 +1,7 @@
{
"type": "minecraft:function",
"environment": "minecraft:default",
"function": "forge:lighting_event_test/test_lighting_event_fires",
"max_ticks": 100,
"structure": "forge:empty3x3x3"
}
@@ -0,0 +1,67 @@
package net.minecraftforge.debug.chunk;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.network.chat.Component;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraftforge.event.level.ChunkEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.gametest.GameTest;
import net.minecraftforge.gametest.GameTestNamespace;
import net.minecraftforge.test.BaseTestMod;
/**
* This is a test for the ChunkEvent.LightingCalculated event.
*/
@GameTestNamespace("forge")
@Mod(LightingEventTest.MODID)
public class LightingEventTest extends BaseTestMod {
public static final String MODID = "lighting_event_test";
private static final int MAX_CHUNK_LOCATION_ATTEMPTS = 5;
public LightingEventTest(FMLJavaModLoadingContext context) {
super(context);
}
@GameTest
public static void testLightingEventFires(GameTestHelper helper) {
var eventFired = helper.boolFlag("eventFired");
helper.<ChunkEvent.LightingCalculated>addEventListener(event -> eventFired.set(true));
var random = RandomSource.create();
var level = helper.getLevel();
var chunkSource = level.getChunkSource();
// try to find a far away chunk that is not already ticking
int attempts;
var origin = helper.absolutePos(BlockPos.ZERO);
ChunkAccess chunk = null;
for (attempts = 0; attempts < MAX_CHUNK_LOCATION_ATTEMPTS && chunk == null; attempts++) {
int x = random.nextInt(1, 10) * 10000;
int z = random.nextInt(1, 10) * 10000;
chunk = level.getChunk(origin.offset(x, 0, z));
// If the chunk is already ticking, we can't force it
chunk = chunkSource.isPositionTicking(chunk.getPos().toLong()) ? null : chunk;
}
if (chunk == null) {
helper.fail(Component.literal("Failed to find a far away chunk that is not already ticking after " + MAX_CHUNK_LOCATION_ATTEMPTS + " attempts"));
return;
} else if (attempts > 1) {
helper.say("WARNING: Finding a far away chunk took " + attempts + " attempts.", ChatFormatting.YELLOW);
}
helper.runAfterDelay(20, () -> {
if (!eventFired.getBool()) {
helper.fail("LightingCalculated event was not fired!");
}
helper.succeed();
});
}
}
@@ -22,12 +22,12 @@ import net.minecraftforge.test.BaseTestMod;
public class ForcedChunkLoadingTest extends BaseTestMod {
static final String MOD_ID = "forced_chunk_loading";
private static final int MAX_CHUNK_LOCATION_ATTEMPTS = 5;
public ForcedChunkLoadingTest(FMLJavaModLoadingContext context) {
super(context);
}
private static final int MAX_CHUNK_LOCATION_ATTEMPTS = 5;
@GameTest
public static void force_far_away_chunk(GameTestHelper helper) {
var random = RandomSource.create();