Address maintainer feedback: single level loading system, TimerUtil cleanup, consistent formatting

This commit is contained in:
Michael Harvey
2026-01-05 18:31:56 +01:00
committed by Acuadragon100
parent 6316587ebe
commit 3080102f06
2 changed files with 68 additions and 26 deletions
@@ -99,34 +99,24 @@ public abstract class MixinMinecraft
}
#endif
@Inject(at = @At("HEAD"), method = "updateLevelInEngines")
public void updateLevelInEngines(ClientLevel level, CallbackInfo ci)
{
// Skip normal level events when Immersive Portals is active
// IP suppresses these events and we use render-driven loading instead
if (!com.seibel.distanthorizons.common.ImmersivePortalsCompat.isImmersivePortalsActive())
{
if (this.lastLevel != null && level != this.lastLevel)
{
ClientApi.INSTANCE.clientLevelUnloadEvent(ClientLevelWrapper.getWrapper(this.lastLevel));
}
if (level != null)
{
ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(level, true));
}
}
this.lastLevel = level;
}
// Level load/unload is handled via renderer-driven loading for Immersive Portals
// and via render hooks in MixinLevelRenderer. Avoid duplicating level
// load/unload logic here to keep a single, consistent system.
@Inject(at = @At("HEAD"), method = "close()V")
public void close(CallbackInfo ci) { SelfUpdater.onClose(); }
@Inject(at = @At("HEAD"), method = "tick")
private void onTick(CallbackInfo ci)
// Use a dedicated timer for cleanup instead of MC tick events
@Unique
private static final java.util.Timer CLIENT_CLEANUP_TIMER = com.seibel.distanthorizons.core.util.TimerUtil.CreateTimer("ClientLevelTickCleanup");
@Unique
private static final java.util.TimerTask CLIENT_CLEANUP_TASK = com.seibel.distanthorizons.core.util.TimerUtil.createTimerTask(() -> com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper.tickCleanup());
static
{
ClientLevelWrapper.tickCleanup();
// 20 ticks per second (50ms interval)
CLIENT_CLEANUP_TIMER.scheduleAtFixedRate(CLIENT_CLEANUP_TASK, 0, 1000 / 20);
}
}
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.neoforge;
import com.seibel.distanthorizons.common.AbstractModInitializer;
import com.seibel.distanthorizons.common.ImmersivePortalsCompat;
import com.seibel.distanthorizons.common.util.ProxyUtil;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
@@ -51,6 +52,7 @@ import net.minecraft.client.Minecraft;
import net.neoforged.neoforge.client.event.InputEvent;
import net.neoforged.bus.api.SubscribeEvent;
import org.lwjgl.opengl.GL32;
import com.seibel.distanthorizons.common.ImmersivePortalsCompat;
#if MC_VER < MC_1_20_6
import net.neoforged.neoforge.event.TickEvent;
@@ -162,12 +164,18 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
{
//LOGGER.trace("break or block attack at blockPos: " + event.getPos());
LevelAccessor level = event.getLevel();
ChunkAccess chunk = level.getChunk(event.getPos());
SharedApi.INSTANCE.applyChunkUpdate(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
this.onBlockChangeEvent(level, chunk);
});
}
}
}
private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk)
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level);
SharedApi.INSTANCE.chunkBlockChangedEvent(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
}
@@ -234,6 +242,21 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
// handled via the same mixin as fabric for consistency
#endif
if (ClientApi.RENDER_STATE.clientLevelWrapper instanceof ClientLevelWrapper)
{
ClientLevelWrapper wrapper = (ClientLevelWrapper) ClientApi.RENDER_STATE.clientLevelWrapper;
if (ImmersivePortalsCompat.isImmersivePortalsActive())
{
if (!wrapper.isDhLevelLoaded())
{
LOGGER.debug("IP detected - On-demand loading level " + wrapper.getDhIdentifier() + " during rendering");
ClientApi.INSTANCE.clientLevelLoadEvent(wrapper);
}
}
wrapper.markRendered();
}
ClientApi.INSTANCE.renderFadeOpaque();
}
@@ -248,6 +271,21 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
#else
// handled via the same mixin as fabric for consistency
#endif
if (ClientApi.RENDER_STATE.clientLevelWrapper instanceof ClientLevelWrapper)
{
ClientLevelWrapper wrapper = (ClientLevelWrapper) ClientApi.RENDER_STATE.clientLevelWrapper;
if (ImmersivePortalsCompat.isImmersivePortalsActive())
{
if (!wrapper.isDhLevelLoaded())
{
LOGGER.debug("IP detected - On-demand loading level " + wrapper.getDhIdentifier() + " during rendering");
ClientApi.INSTANCE.clientLevelLoadEvent(wrapper);
}
}
wrapper.markRendered();
}
}
@SubscribeEvent
@@ -260,8 +298,22 @@ public class NeoforgeClientProxy implements AbstractModInitializer.IEventProxy
#else
// handled via the same mixin as fabric for consistency
#endif
if (ClientApi.RENDER_STATE.clientLevelWrapper instanceof ClientLevelWrapper)
{
ClientLevelWrapper wrapper = (ClientLevelWrapper) ClientApi.RENDER_STATE.clientLevelWrapper;
if (ImmersivePortalsCompat.isImmersivePortalsActive())
{
if (!wrapper.isDhLevelLoaded())
{
LOGGER.debug("IP detected - On-demand loading level " + wrapper.getDhIdentifier() + " during rendering");
ClientApi.INSTANCE.clientLevelLoadEvent(wrapper);
}
}
wrapper.markRendered();
}
try
{
// should generally only need to be set once per game session