fix null pointer on dedicated server shutdown

This commit is contained in:
James Seibel
2026-04-27 07:48:06 -05:00
parent 7b252b173b
commit 4d0ed2a6dc
@@ -10,6 +10,7 @@ import com.seibel.distanthorizons.core.util.TimerUtil;
import com.seibel.distanthorizons.core.util.objects.RollingAverage;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo;
import org.jetbrains.annotations.Nullable;
@@ -49,6 +50,7 @@ public class RenderThreadTaskHandler
private long nanoSinceTasksRun = System.nanoTime();
private final boolean running;
@@ -57,7 +59,22 @@ public class RenderThreadTaskHandler
//=============//
//region
private RenderThreadTaskHandler() { TIMER.scheduleAtFixedRate(TimerUtil.createTimerTask(this::manualCleanupTick), MS_BETWEEN_CLEANUP_TICKS, MS_BETWEEN_CLEANUP_TICKS); }
private RenderThreadTaskHandler()
{
// we only want to run this when the client is available
IMinecraftSharedWrapper mcShared = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class);
if (!mcShared.isDedicatedServer())
{
LOGGER.debug("Starting ["+RenderThreadTaskHandler.class.getSimpleName()+"]...");
this.running = true;
TIMER.scheduleAtFixedRate(TimerUtil.createTimerTask(this::manualCleanupTick), MS_BETWEEN_CLEANUP_TICKS, MS_BETWEEN_CLEANUP_TICKS);
}
else
{
this.running = false;
LOGGER.debug("Skipping ["+RenderThreadTaskHandler.class.getSimpleName()+"] startup due to running on a dedicated server.");
}
}
//endregion
@@ -70,6 +87,13 @@ public class RenderThreadTaskHandler
public void queueRunningOnRenderThread(String name, Runnable renderCall)
{
// don't queuing tasks if they'll never be run
if (!this.running)
{
return;
}
// don't get the stacktrace on release to reduce GC pressure
StackTraceElement[] stackTrace = null;
if (ModInfo.IS_DEV_BUILD)
@@ -179,8 +203,19 @@ public class RenderThreadTaskHandler
// this means we could have GL jobs building up.
// Run the queued tasks on MC's executor (hopefully this should always run,
// even if DH's render code isn't being hit).
IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
MC.executeOnRenderThread(() -> this.runRenderThreadTasks(500 * 1_000_000L));
IMinecraftClientWrapper mcClient = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
if (mcClient != null)
{
mcClient.executeOnRenderThread(() -> this.runRenderThreadTasks(500 * 1_000_000L));
}
else
{
// shouldn't happen, but just in case
// somehow the timer started when there wasn't a client wrapper
// this probably means the timer was started on a dedicated server
RATE_LIMITED_LOGGER.warn("["+RenderThreadTaskHandler.class.getSimpleName()+"] timer started when ["+IMinecraftClientWrapper.class.getSimpleName()+"] is null. This shouldn't happen but can likely be ignored.");
}
}
//endregion
@@ -190,7 +225,7 @@ public class RenderThreadTaskHandler
//===========//
// debugging //
//===========//
///region
//region
/**
* if tasks are currently queued the debug
@@ -246,7 +281,7 @@ public class RenderThreadTaskHandler
});
}
///endregion
//endregion