replace and simplify WorldGenThreadCheck

This commit is contained in:
James Seibel
2025-11-22 09:25:55 -06:00
parent af8dea9d9f
commit 91da0bf252
15 changed files with 118 additions and 153 deletions
@@ -56,7 +56,6 @@ public class DependencySetup
SingletonInjector.INSTANCE.bind(IVersionConstants.class, VersionConstants.INSTANCE);
SingletonInjector.INSTANCE.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
SingletonInjector.INSTANCE.bind(IKeyedClientLevelManager.class, KeyedClientLevelManager.INSTANCE);
WorldGenThreadCheck.isSetup = true;
}
public static void createServerBindings()
@@ -1,39 +0,0 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import java.util.function.Supplier;
public class WorldGenThreadCheck
{
public static boolean isSetup = false;
/**
* This is used so we can override some MC logic when running
* in DH's world generator.
* Specifically so we can redirect threads to run on DH threads instead
* of MC threads.
*/
//public static Supplier<Boolean> isCurrentThreadDhWorldGenThread = (() -> { return false; });
public static Supplier<Boolean> isCurrentThreadDhWorldGenThread = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread; // TODO can we just do this?
}
@@ -58,7 +58,6 @@ import java.util.stream.StreamSupport;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.seibel.distanthorizons.common.wrappers.WorldGenThreadCheck;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepBiomes;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepFeatures;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepNoise;
@@ -126,6 +125,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
public static final int MAX_WORLD_GEN_CHUNK_BORDER_NEEDED;
private final IDhServerLevel serverLevel;
/**
@@ -137,20 +137,19 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
//=================Generation Step===================
public final LinkedBlockingQueue<GenerationEvent> generationEventList = new LinkedBlockingQueue<>();
public final GlobalWorldGenParams params;
public final StepStructureStart stepStructureStart = new StepStructureStart(this);
public final StepStructureReference stepStructureReference = new StepStructureReference(this);
public final StepBiomes stepBiomes = new StepBiomes(this);
public final StepNoise stepNoise = new StepNoise(this);
public final StepSurface stepSurface = new StepSurface(this);
public final StepFeatures stepFeatures = new StepFeatures(this);
public boolean unsafeThreadingRecorded = false;
public static final long EXCEPTION_TIMER_RESET_TIME = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
public static final int EXCEPTION_COUNTER_TRIGGER = 20;
public static final int RANGE_TO_RANGE_EMPTY_EXTENSION = 1;
public int unknownExceptionCount = 0;
public long lastExceptionTriggerTime = 0;
@@ -170,7 +169,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
}
public static ThreadLocal<Boolean> isDhWorldGenThreadRef = new ThreadLocal<>();
public static boolean isCurrentThreadDistantGeneratorThread() { return (isDhWorldGenThreadRef.get() != null); }
public static boolean isThisDhWorldGenThread() { return (isDhWorldGenThreadRef.get() != null); }
@@ -180,9 +179,6 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
static
{
// TODO can this be handled directly?
WorldGenThreadCheck.isCurrentThreadDhWorldGenThread = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
boolean isTerraFirmaCraftPresent = false;
try
{
@@ -218,7 +214,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
{
this.serverLevel = serverLevel;
LOGGER.info("================WORLD_GEN_STEP_INITING=============");
LOGGER.info("Creating Batch Generator");
serverLevel.getServerLevelWrapper().getDimensionType();
@@ -345,8 +341,6 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
/** @throws RejectedExecutionException if the given {@link Executor} is cancelled. */
public CompletableFuture<Void> generateLodFromListAsync(GenerationEvent genEvent, Executor executor) throws RejectedExecutionException, InterruptedException
{
LOGGER.debug("Lod Generate Event: " + genEvent.minPos);
// Minecraft's generation events expect odd chunk width areas (3x3, 7x7, or 11x11),
// but DH submits square generation events (4x4).
// We handle this later, although that handling would need to change if the gen size ever changes.
@@ -561,13 +555,13 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
* otherwise this will return an empty chunk.
*/
private CompletableFuture<ChunkAccess> createEmptyOrPreExistingChunkAsync(
int x, int z,
int chunkX, int chunkZ,
Map<DhChunkPos, ChunkLightStorage> chunkSkyLightingByDhPos,
Map<DhChunkPos, ChunkLightStorage> chunkBlockLightingByDhPos,
Map<DhChunkPos, ChunkAccess> generatedChunkByDhPos)
{
ChunkPos chunkPos = new ChunkPos(x, z);
DhChunkPos dhChunkPos = new DhChunkPos(x, z);
ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
DhChunkPos dhChunkPos = new DhChunkPos(chunkX, chunkZ);
if (generatedChunkByDhPos.containsKey(dhChunkPos))
{
@@ -1110,9 +1104,29 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
}
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, int border) { return new ArrayGridList<>(total, border, total.gridSize - border); }
private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, WORLD_GEN_CHUNK_BORDER_NEEDED_BY_GEN_STEP.get(step)); }
//private static <T> ArrayGridList<T> GetCutoutFrom(ArrayGridList<T> total, EDhApiWorldGenerationStep step) { return GetCutoutFrom(total, 0); }
@Override
public CompletableFuture<Void> generateChunks(
int minX, int minZ, int genSize,
EDhApiDistantGeneratorMode generatorMode, EDhApiWorldGenerationStep targetStep,
ExecutorService worldGeneratorThreadPool, Consumer<IChunkWrapper> resultConsumer)
{
//System.out.println("GenerationEvent: "+genSize+"@"+minX+","+minZ+" "+targetStep);
// TODO: Check event overlap via e.tooClose()
GenerationEvent genEvent = GenerationEvent.startEvent(new DhChunkPos(minX, minZ), genSize, this, generatorMode, targetStep, resultConsumer, worldGeneratorThreadPool);
this.generationEventList.add(genEvent);
return genEvent.future;
}
//================//
// base overrides //
//================//
@Override
public void close()
{
@@ -1145,20 +1159,6 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
LOGGER.info(BatchGenerationEnvironment.class.getSimpleName() + " shutdown complete.");
}
@Override
public CompletableFuture<Void> generateChunks(
int minX, int minZ, int genSize,
EDhApiDistantGeneratorMode generatorMode, EDhApiWorldGenerationStep targetStep,
ExecutorService worldGeneratorThreadPool, Consumer<IChunkWrapper> resultConsumer)
{
//System.out.println("GenerationEvent: "+genSize+"@"+minX+","+minZ+" "+targetStep);
// TODO: Check event overlap via e.tooClose()
GenerationEvent genEvent = GenerationEvent.startEvent(new DhChunkPos(minX, minZ), genSize, this, generatorMode, targetStep, resultConsumer, worldGeneratorThreadPool);
this.generationEventList.add(genEvent);
return genEvent.future;
}
//================//
@@ -1174,7 +1174,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
{
if (Thread.interrupted())
{
throw new InterruptedException(BatchGenerationEnvironment.class.getSimpleName() + " task interrupted.");
throw new InterruptedException("["+BatchGenerationEnvironment.class.getSimpleName()+"] task interrupted.");
}
}
@@ -102,7 +102,7 @@ public final class GenerationEvent
worldGeneratorThreadPool.execute(() ->
{
// TODO why not just always set this each time?
boolean alreadyMarked = BatchGenerationEnvironment.isCurrentThreadDistantGeneratorThread();
boolean alreadyMarked = BatchGenerationEnvironment.isThisDhWorldGenThread();
if (!alreadyMarked)
{
BatchGenerationEnvironment.isDhWorldGenThreadRef.set(true);
@@ -36,15 +36,29 @@ import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
#if MC_VER < MC_1_19_2
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
#else
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.levelgen.RandomState;
#if MC_VER >= MC_1_19_4
import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.core.registries.Registries;
#endif
#endif
import net.minecraft.world.level.storage.WorldData;
#if MC_VER < MC_1_19_4
#elif MC_VER < MC_1_21_3
import net.minecraft.core.registries.Registries;
#else
import net.minecraft.core.registries.Registries;
#endif
#if MC_VER < MC_1_19_4
import net.minecraft.world.level.levelgen.WorldGenSettings;
#else
import net.minecraft.world.level.levelgen.WorldOptions;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
import net.minecraft.world.level.levelgen.RandomState;
#endif
/**
* Handles parameters that are relevant for the entire MC world.
*
* @see ThreadWorldGenParams
*/
public final class GlobalWorldGenParams
{
public final ChunkGenerator generator;
@@ -116,4 +130,6 @@ public final class GlobalWorldGenParams
#endif
}
}
@@ -31,17 +31,20 @@ import net.minecraft.world.level.levelgen.structure.StructureCheck;
public final class ThreadWorldGenParams
{
private static final ThreadLocal<ThreadWorldGenParams> LOCAL_PARAM = new ThreadLocal<>();
private static final ThreadLocal<ThreadWorldGenParams> LOCAL_PARAM_REF = new ThreadLocal<>();
final ServerLevel level;
public WorldGenStructFeatManager structFeat = null;
#if MC_VER >= MC_1_18_2
public StructureCheck structCheck;
#endif
boolean isValid = true;
public final PerfCalculator perf = new PerfCalculator();
// used for some older MC versions
private static GlobalWorldGenParams previousGlobalWorldGenParams = null;
@@ -52,7 +55,7 @@ public final class ThreadWorldGenParams
public static ThreadWorldGenParams getOrMake(GlobalWorldGenParams globalParams)
{
ThreadWorldGenParams threadParam = LOCAL_PARAM.get();
ThreadWorldGenParams threadParam = LOCAL_PARAM_REF.get();
if (threadParam != null
&& threadParam.isValid
&& threadParam.level == globalParams.level)
@@ -61,7 +64,7 @@ public final class ThreadWorldGenParams
}
threadParam = new ThreadWorldGenParams(globalParams);
LOCAL_PARAM.set(threadParam);
LOCAL_PARAM_REF.set(threadParam);
return threadParam;
}
@@ -70,45 +73,54 @@ public final class ThreadWorldGenParams
previousGlobalWorldGenParams = param;
this.level = param.level;
#if MC_VER < MC_1_18_2
this.structFeat = new WorldGenStructFeatManager(param.worldGenSettings, level);
this.structFeat = new WorldGenStructFeatManager(param.worldGenSettings, this.level);
#elif MC_VER < MC_1_19_2
this.structCheck = this.createStructureCheck(param);
#else
this.structCheck = new StructureCheck(param.chunkScanner, param.registry, param.structures,
param.level.dimension(), param.generator, param.randomState, level, param.generator.getBiomeSource(), param.worldSeed,
param.level.dimension(), param.generator, param.randomState, this.level, param.generator.getBiomeSource(), param.worldSeed,
param.dataFixer);
#endif
}
//==========//
// builders //
//==========//
public void makeStructFeat(WorldGenLevel genLevel, GlobalWorldGenParams param)
{
#if MC_VER < MC_1_19_4
this.structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel #if MC_VER >= MC_1_18_2 , this.structCheck #endif );
#if MC_VER < MC_1_18_2
this.structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel);
#elif MC_VER < MC_1_19_4
this.structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel, this.structCheck);
#else
this.structFeat = new WorldGenStructFeatManager(param.worldOptions, genLevel, this.structCheck);
#endif
}
#if MC_VER >= MC_1_18_2 && MC_VER < MC_1_19_2
#if MC_VER < MC_1_18_2
#elif MC_VER < MC_1_19_2
public void recreateStructureCheck()
{
if (previousGlobalParameters != null)
if (previousGlobalWorldGenParams != null)
{
this.structCheck = createStructureCheck(previousGlobalParameters);
this.structCheck = this.createStructureCheck(previousGlobalWorldGenParams);
}
}
private StructureCheck createStructureCheck(GlobalParameters param)
private StructureCheck createStructureCheck(GlobalWorldGenParams param)
{
return new StructureCheck(param.chunkScanner, param.registry, param.structures,
param.level.dimension(), param.generator, this.level, param.generator.getBiomeSource(), param.worldSeed,
param.fixerUpper);
param.dataFixer);
}
#else
public void recreateStructureCheck() { /* do nothing */ }
#endif
}
@@ -13,8 +13,7 @@ public class MixinLevelTicks<T>
#else
import com.seibel.distanthorizons.common.wrappers.WorldGenThreadCheck;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import net.minecraft.world.ticks.LevelTicks;
import net.minecraft.world.ticks.ScheduledTick;
@@ -26,18 +25,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
public class MixinLevelTicks<T>
{
// TODO put in a common location
private static boolean isWorldGenThread()
{ return WorldGenThreadCheck.isSetup && WorldGenThreadCheck.isCurrentThreadDhWorldGenThread.get(); }
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci)
{
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
ci.cancel();
}
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.fabric.mixins.server;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import org.spongepowered.asm.mixin.Mixin;
#if MC_VER < MC_1_21_3
@@ -35,7 +36,6 @@ public class MixinTracingExecutor
}
#else
import com.seibel.distanthorizons.common.wrappers.WorldGenThreadCheck;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import net.minecraft.TracingExecutor;
import org.spongepowered.asm.mixin.injection.At;
@@ -54,16 +54,11 @@ import java.util.concurrent.Executor;
@Mixin(TracingExecutor.class)
public class MixinTracingExecutor
{
// TODO put in a common location
private static boolean isWorldGenThread()
{ return WorldGenThreadCheck.isSetup && WorldGenThreadCheck.isCurrentThreadDhWorldGenThread.get(); }
// replaced with TracingExecutor in MC 1.21.3+
@Inject(method = "forName(Ljava/lang/String;)Ljava/util/concurrent/Executor;", at = @At("HEAD"), cancellable = true)
private void forName(String executorName, CallbackInfoReturnable<Executor> ci)
{
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
// run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService());
@@ -19,14 +19,19 @@
package com.seibel.distanthorizons.fabric.mixins.server;
import com.seibel.distanthorizons.common.wrappers.WorldGenThreadCheck;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.Util;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
#if MC_VER < MC_1_16_5
#elif MC_VER < MC_1_21_3
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
#else
#endif
@@ -41,15 +46,11 @@ import java.util.function.Supplier;
@Mixin(Util.class)
public class MixinUtilBackgroundThread
{
private static boolean isWorldGenThread()
{ return WorldGenThreadCheck.isSetup && WorldGenThreadCheck.isCurrentThreadDhWorldGenThread.get(); }
#if MC_VER < MC_1_21_3
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
{
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
// run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService());
@@ -65,7 +66,7 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
{
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
ci.setReturnValue(r);
@@ -81,7 +82,7 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
{
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
ci.setReturnValue(r);
@@ -22,12 +22,15 @@ package com.seibel.distanthorizons.forge.mixins.server;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.distanthorizons.core.logging.DhLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import org.spongepowered.asm.mixin.Mixin;
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.callback.CallbackInfoReturnable;
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import net.minecraft.Util;
@@ -35,17 +38,17 @@ import net.minecraft.Util;
@Mixin(Util.class)
public class MixinUtilBackgroundThread
{
private static boolean shouldApplyOverride()
{
return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get();
}
@Unique
private static final DhLogger LOGGER = new DhLoggerBuilder().name("MixinUtilBackgroundThread").build();
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
{
if (shouldApplyOverride())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
//ApiShared.LOGGER.info("util backgroundExecutor triggered");
//LOGGER.info("util backgroundExecutor triggered");
ci.setReturnValue(new RunOnThisThreadExecutorService());
}
}
@@ -55,21 +58,22 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
{
if (shouldApplyOverride())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
//LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
ci.setReturnValue(r);
}
}
#endif
#if MC_VER >= MC_1_18_2
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;",
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
{
if (shouldApplyOverride())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
//LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
ci.setReturnValue(r);
}
}
@@ -31,7 +31,6 @@ import java.util.function.Supplier;
#if MC_VER < MC_1_20_6
import net.neoforged.neoforge.event.TickEvent;
#else
import net.neoforged.neoforge.event.tick.ServerTickEvent;
#endif
@@ -52,7 +51,7 @@ public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
public NeoforgeServerProxy(boolean isDedicated)
{
this.isDedicated = isDedicated;
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
isGenerationThreadChecker = BatchGenerationEnvironment::isThisDhWorldGenThread;
}
@Override
@@ -13,7 +13,7 @@ public class MixinLevelTicks<T>
#else
import com.seibel.distanthorizons.common.wrappers.WorldGenThreadCheck;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import net.minecraft.world.ticks.LevelTicks;
import net.minecraft.world.ticks.ScheduledTick;
import org.spongepowered.asm.mixin.Mixin;
@@ -24,18 +24,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
public class MixinLevelTicks<T>
{
// TODO put in a common location
private static boolean isWorldGenThread()
{ return WorldGenThreadCheck.isSetup && WorldGenThreadCheck.isCurrentThreadDhWorldGenThread.get(); }
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci)
{
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
ci.cancel();
}
@@ -35,7 +35,7 @@ public class MixinTracingExecutor
}
#else
import com.seibel.distanthorizons.common.wrappers.WorldGenThreadCheck;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import net.minecraft.TracingExecutor;
import org.spongepowered.asm.mixin.Mixin;
@@ -55,11 +55,6 @@ import java.util.concurrent.Executor;
@Mixin(TracingExecutor.class)
public class MixinTracingExecutor
{
// TODO put in a common location
private static boolean isWorldGenThread()
{ return WorldGenThreadCheck.isSetup && WorldGenThreadCheck.isCurrentThreadDhWorldGenThread.get(); }
// Util.backgroundExecutor().forName("init_biomes")
// needed for world gen
@@ -67,7 +62,7 @@ public class MixinTracingExecutor
@Inject(method = "forName(Ljava/lang/String;)Ljava/util/concurrent/Executor;", at = @At("HEAD"), cancellable = true)
private void forName(String executorName, CallbackInfoReturnable<Executor> ci)
{
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
// run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService());
@@ -19,11 +19,10 @@
package com.seibel.distanthorizons.neoforge.mixins.server;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import org.spongepowered.asm.mixin.Mixin;
import com.seibel.distanthorizons.common.wrappers.WorldGenThreadCheck;
import net.minecraft.Util;
/**
@@ -36,16 +35,13 @@ import net.minecraft.Util;
@Mixin(Util.class)
public class MixinUtilBackgroundThread
{
private static boolean isWorldGenThread()
{ return WorldGenThreadCheck.isSetup && WorldGenThreadCheck.isCurrentThreadDhWorldGenThread.get(); }
#if MC_VER < MC_1_21_3
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
{
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
// run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService());
@@ -61,7 +57,7 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
{
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
ci.setReturnValue(r);
@@ -77,7 +73,7 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
{
if (isWorldGenThread())
if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
ci.setReturnValue(r);