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(IVersionConstants.class, VersionConstants.INSTANCE);
SingletonInjector.INSTANCE.bind(IWrapperFactory.class, WrapperFactory.INSTANCE); SingletonInjector.INSTANCE.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
SingletonInjector.INSTANCE.bind(IKeyedClientLevelManager.class, KeyedClientLevelManager.INSTANCE); SingletonInjector.INSTANCE.bind(IKeyedClientLevelManager.class, KeyedClientLevelManager.INSTANCE);
WorldGenThreadCheck.isSetup = true;
} }
public static void createServerBindings() 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.NotNull;
import org.jetbrains.annotations.Nullable; 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.StepBiomes;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepFeatures; import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepFeatures;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.step.StepNoise; 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; public static final int MAX_WORLD_GEN_CHUNK_BORDER_NEEDED;
private final IDhServerLevel serverLevel; 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 LinkedBlockingQueue<GenerationEvent> generationEventList = new LinkedBlockingQueue<>();
public final GlobalWorldGenParams params; public final GlobalWorldGenParams params;
public final StepStructureStart stepStructureStart = new StepStructureStart(this); public final StepStructureStart stepStructureStart = new StepStructureStart(this);
public final StepStructureReference stepStructureReference = new StepStructureReference(this); public final StepStructureReference stepStructureReference = new StepStructureReference(this);
public final StepBiomes stepBiomes = new StepBiomes(this); public final StepBiomes stepBiomes = new StepBiomes(this);
public final StepNoise stepNoise = new StepNoise(this); public final StepNoise stepNoise = new StepNoise(this);
public final StepSurface stepSurface = new StepSurface(this); public final StepSurface stepSurface = new StepSurface(this);
public final StepFeatures stepFeatures = new StepFeatures(this); public final StepFeatures stepFeatures = new StepFeatures(this);
public boolean unsafeThreadingRecorded = false; public boolean unsafeThreadingRecorded = false;
public static final long EXCEPTION_TIMER_RESET_TIME = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS); 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 EXCEPTION_COUNTER_TRIGGER = 20;
public static final int RANGE_TO_RANGE_EMPTY_EXTENSION = 1;
public int unknownExceptionCount = 0; public int unknownExceptionCount = 0;
public long lastExceptionTriggerTime = 0; public long lastExceptionTriggerTime = 0;
@@ -170,7 +169,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
} }
public static ThreadLocal<Boolean> isDhWorldGenThreadRef = new ThreadLocal<>(); 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 static
{ {
// TODO can this be handled directly?
WorldGenThreadCheck.isCurrentThreadDhWorldGenThread = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
boolean isTerraFirmaCraftPresent = false; boolean isTerraFirmaCraftPresent = false;
try try
{ {
@@ -218,7 +214,7 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
{ {
this.serverLevel = serverLevel; this.serverLevel = serverLevel;
LOGGER.info("================WORLD_GEN_STEP_INITING============="); LOGGER.info("Creating Batch Generator");
serverLevel.getServerLevelWrapper().getDimensionType(); serverLevel.getServerLevelWrapper().getDimensionType();
@@ -345,8 +341,6 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
/** @throws RejectedExecutionException if the given {@link Executor} is cancelled. */ /** @throws RejectedExecutionException if the given {@link Executor} is cancelled. */
public CompletableFuture<Void> generateLodFromListAsync(GenerationEvent genEvent, Executor executor) throws RejectedExecutionException, InterruptedException 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), // Minecraft's generation events expect odd chunk width areas (3x3, 7x7, or 11x11),
// but DH submits square generation events (4x4). // but DH submits square generation events (4x4).
// We handle this later, although that handling would need to change if the gen size ever changes. // 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. * otherwise this will return an empty chunk.
*/ */
private CompletableFuture<ChunkAccess> createEmptyOrPreExistingChunkAsync( private CompletableFuture<ChunkAccess> createEmptyOrPreExistingChunkAsync(
int x, int z, int chunkX, int chunkZ,
Map<DhChunkPos, ChunkLightStorage> chunkSkyLightingByDhPos, Map<DhChunkPos, ChunkLightStorage> chunkSkyLightingByDhPos,
Map<DhChunkPos, ChunkLightStorage> chunkBlockLightingByDhPos, Map<DhChunkPos, ChunkLightStorage> chunkBlockLightingByDhPos,
Map<DhChunkPos, ChunkAccess> generatedChunkByDhPos) Map<DhChunkPos, ChunkAccess> generatedChunkByDhPos)
{ {
ChunkPos chunkPos = new ChunkPos(x, z); ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
DhChunkPos dhChunkPos = new DhChunkPos(x, z); DhChunkPos dhChunkPos = new DhChunkPos(chunkX, chunkZ);
if (generatedChunkByDhPos.containsKey(dhChunkPos)) 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, 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, 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 @Override
public void close() public void close()
{ {
@@ -1145,20 +1159,6 @@ public final class BatchGenerationEnvironment implements IBatchGeneratorEnvironm
LOGGER.info(BatchGenerationEnvironment.class.getSimpleName() + " shutdown complete."); 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()) 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(() -> worldGeneratorThreadPool.execute(() ->
{ {
// TODO why not just always set this each time? // TODO why not just always set this each time?
boolean alreadyMarked = BatchGenerationEnvironment.isCurrentThreadDistantGeneratorThread(); boolean alreadyMarked = BatchGenerationEnvironment.isThisDhWorldGenThread();
if (!alreadyMarked) if (!alreadyMarked)
{ {
BatchGenerationEnvironment.isDhWorldGenThreadRef.set(true); BatchGenerationEnvironment.isDhWorldGenThreadRef.set(true);
@@ -36,15 +36,29 @@ import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
#if MC_VER < MC_1_19_2 #if MC_VER < MC_1_19_2
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
#else #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 #endif
import net.minecraft.world.level.storage.WorldData; 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 class GlobalWorldGenParams
{ {
public final ChunkGenerator generator; public final ChunkGenerator generator;
@@ -87,7 +101,7 @@ public final class GlobalWorldGenParams
MinecraftServer server = this.level.getServer(); MinecraftServer server = this.level.getServer();
WorldData worldData = server.getWorldData(); WorldData worldData = server.getWorldData();
this.registry = server.registryAccess(); this.registry = server.registryAccess();
#if MC_VER < MC_1_19_4 #if MC_VER < MC_1_19_4
this.worldGenSettings = worldData.worldGenSettings(); this.worldGenSettings = worldData.worldGenSettings();
this.biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY); this.biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
@@ -116,4 +130,6 @@ public final class GlobalWorldGenParams
#endif #endif
} }
} }
@@ -31,17 +31,20 @@ import net.minecraft.world.level.levelgen.structure.StructureCheck;
public final class ThreadWorldGenParams 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; final ServerLevel level;
public WorldGenStructFeatManager structFeat = null; public WorldGenStructFeatManager structFeat = null;
#if MC_VER >= MC_1_18_2 #if MC_VER >= MC_1_18_2
public StructureCheck structCheck; public StructureCheck structCheck;
#endif #endif
boolean isValid = true; boolean isValid = true;
public final PerfCalculator perf = new PerfCalculator(); public final PerfCalculator perf = new PerfCalculator();
// used for some older MC versions
private static GlobalWorldGenParams previousGlobalWorldGenParams = null; private static GlobalWorldGenParams previousGlobalWorldGenParams = null;
@@ -52,7 +55,7 @@ public final class ThreadWorldGenParams
public static ThreadWorldGenParams getOrMake(GlobalWorldGenParams globalParams) public static ThreadWorldGenParams getOrMake(GlobalWorldGenParams globalParams)
{ {
ThreadWorldGenParams threadParam = LOCAL_PARAM.get(); ThreadWorldGenParams threadParam = LOCAL_PARAM_REF.get();
if (threadParam != null if (threadParam != null
&& threadParam.isValid && threadParam.isValid
&& threadParam.level == globalParams.level) && threadParam.level == globalParams.level)
@@ -61,7 +64,7 @@ public final class ThreadWorldGenParams
} }
threadParam = new ThreadWorldGenParams(globalParams); threadParam = new ThreadWorldGenParams(globalParams);
LOCAL_PARAM.set(threadParam); LOCAL_PARAM_REF.set(threadParam);
return threadParam; return threadParam;
} }
@@ -70,45 +73,54 @@ public final class ThreadWorldGenParams
previousGlobalWorldGenParams = param; previousGlobalWorldGenParams = param;
this.level = param.level; this.level = param.level;
#if MC_VER < MC_1_18_2 #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 #elif MC_VER < MC_1_19_2
this.structCheck = this.createStructureCheck(param); this.structCheck = this.createStructureCheck(param);
#else #else
this.structCheck = new StructureCheck(param.chunkScanner, param.registry, param.structures, 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); param.dataFixer);
#endif #endif
} }
//==========//
// builders //
//==========//
public void makeStructFeat(WorldGenLevel genLevel, GlobalWorldGenParams param) public void makeStructFeat(WorldGenLevel genLevel, GlobalWorldGenParams param)
{ {
#if MC_VER < MC_1_19_4 #if MC_VER < MC_1_18_2
this.structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel #if MC_VER >= MC_1_18_2 , this.structCheck #endif ); this.structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel);
#elif MC_VER < MC_1_19_4
this.structFeat = new WorldGenStructFeatManager(param.worldGenSettings, genLevel, this.structCheck);
#else #else
this.structFeat = new WorldGenStructFeatManager(param.worldOptions, genLevel, this.structCheck); this.structFeat = new WorldGenStructFeatManager(param.worldOptions, genLevel, this.structCheck);
#endif #endif
} }
#if MC_VER < MC_1_18_2
#if MC_VER >= MC_1_18_2 && MC_VER < MC_1_19_2 #elif MC_VER < MC_1_19_2
public void recreateStructureCheck() 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, return new StructureCheck(param.chunkScanner, param.registry, param.structures,
param.level.dimension(), param.generator, this.level, param.generator.getBiomeSource(), param.worldSeed, param.level.dimension(), param.generator, this.level, param.generator.getBiomeSource(), param.worldSeed,
param.fixerUpper); param.dataFixer);
} }
#else #else
public void recreateStructureCheck() { /* do nothing */ } public void recreateStructureCheck() { /* do nothing */ }
#endif #endif
} }
@@ -13,8 +13,7 @@ public class MixinLevelTicks<T>
#else #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.LevelTicks;
import net.minecraft.world.ticks.ScheduledTick; 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+ @Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
public class MixinLevelTicks<T> 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) @Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci) 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 // 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). // this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
if (isWorldGenThread()) if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{ {
ci.cancel(); ci.cancel();
} }
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.fabric.mixins.server; package com.seibel.distanthorizons.fabric.mixins.server;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
#if MC_VER < MC_1_21_3 #if MC_VER < MC_1_21_3
@@ -35,7 +36,6 @@ public class MixinTracingExecutor
} }
#else #else
import com.seibel.distanthorizons.common.wrappers.WorldGenThreadCheck;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService; import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import net.minecraft.TracingExecutor; import net.minecraft.TracingExecutor;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -54,16 +54,11 @@ import java.util.concurrent.Executor;
@Mixin(TracingExecutor.class) @Mixin(TracingExecutor.class)
public class MixinTracingExecutor 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+ // replaced with TracingExecutor in MC 1.21.3+
@Inject(method = "forName(Ljava/lang/String;)Ljava/util/concurrent/Executor;", at = @At("HEAD"), cancellable = true) @Inject(method = "forName(Ljava/lang/String;)Ljava/util/concurrent/Executor;", at = @At("HEAD"), cancellable = true)
private void forName(String executorName, CallbackInfoReturnable<Executor> ci) 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 // run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService()); ci.setReturnValue(new RunOnThisThreadExecutorService());
@@ -19,14 +19,19 @@
package com.seibel.distanthorizons.fabric.mixins.server; 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 com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.Util; 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 #if MC_VER < MC_1_16_5
#elif MC_VER < MC_1_21_3 #elif MC_VER < MC_1_21_3
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier; import java.util.function.Supplier;
#else #else
#endif #endif
@@ -41,15 +46,11 @@ import java.util.function.Supplier;
@Mixin(Util.class) @Mixin(Util.class)
public class MixinUtilBackgroundThread public class MixinUtilBackgroundThread
{ {
private static boolean isWorldGenThread()
{ return WorldGenThreadCheck.isSetup && WorldGenThreadCheck.isCurrentThreadDhWorldGenThread.get(); }
#if MC_VER < MC_1_21_3 #if MC_VER < MC_1_21_3
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true) @Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci) 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 // run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService()); ci.setReturnValue(new RunOnThisThreadExecutorService());
@@ -65,7 +66,7 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true) at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci) private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
{ {
if (isWorldGenThread()) if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{ {
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered"); //ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
ci.setReturnValue(r); ci.setReturnValue(r);
@@ -81,7 +82,7 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true) at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci) private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
{ {
if (isWorldGenThread()) if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{ {
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered"); //ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
ci.setReturnValue(r); ci.setReturnValue(r);
@@ -22,12 +22,15 @@ package com.seibel.distanthorizons.forge.mixins.server;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.function.Supplier; 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.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService; import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import net.minecraft.Util; import net.minecraft.Util;
@@ -35,17 +38,17 @@ import net.minecraft.Util;
@Mixin(Util.class) @Mixin(Util.class)
public class MixinUtilBackgroundThread public class MixinUtilBackgroundThread
{ {
private static boolean shouldApplyOverride() @Unique
{ private static final DhLogger LOGGER = new DhLoggerBuilder().name("MixinUtilBackgroundThread").build();
return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get();
}
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true) @Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci) 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()); ci.setReturnValue(new RunOnThisThreadExecutorService());
} }
} }
@@ -55,21 +58,22 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true) at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci) 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); ci.setReturnValue(r);
} }
} }
#endif #endif
#if MC_VER >= MC_1_18_2 #if MC_VER >= MC_1_18_2
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;", @Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;",
at = @At("HEAD"), cancellable = true) at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci) 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); ci.setReturnValue(r);
} }
} }
@@ -30,8 +30,7 @@ import java.util.function.Supplier;
#if MC_VER < MC_1_20_6 #if MC_VER < MC_1_20_6
import net.neoforged.neoforge.event.TickEvent; import net.neoforged.neoforge.event.TickEvent;
#else #else
import net.neoforged.neoforge.event.tick.ServerTickEvent;
#endif #endif
@@ -52,7 +51,7 @@ public class NeoforgeServerProxy implements AbstractModInitializer.IEventProxy
public NeoforgeServerProxy(boolean isDedicated) public NeoforgeServerProxy(boolean isDedicated)
{ {
this.isDedicated = isDedicated; this.isDedicated = isDedicated;
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread; isGenerationThreadChecker = BatchGenerationEnvironment::isThisDhWorldGenThread;
} }
@Override @Override
@@ -13,7 +13,7 @@ public class MixinLevelTicks<T>
#else #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.LevelTicks;
import net.minecraft.world.ticks.ScheduledTick; import net.minecraft.world.ticks.ScheduledTick;
import org.spongepowered.asm.mixin.Mixin; 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+ @Mixin(LevelTicks.class) // available in 1.18.2+, but only needed in 1.21.4+
public class MixinLevelTicks<T> 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) @Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
private void onChunkSave(ScheduledTick<T> tick, CallbackInfo ci) 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 // 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). // this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
if (isWorldGenThread()) if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{ {
ci.cancel(); ci.cancel();
} }
@@ -35,7 +35,7 @@ public class MixinTracingExecutor
} }
#else #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 com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import net.minecraft.TracingExecutor; import net.minecraft.TracingExecutor;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@@ -55,11 +55,6 @@ import java.util.concurrent.Executor;
@Mixin(TracingExecutor.class) @Mixin(TracingExecutor.class)
public class MixinTracingExecutor public class MixinTracingExecutor
{ {
// TODO put in a common location
private static boolean isWorldGenThread()
{ return WorldGenThreadCheck.isSetup && WorldGenThreadCheck.isCurrentThreadDhWorldGenThread.get(); }
// Util.backgroundExecutor().forName("init_biomes") // Util.backgroundExecutor().forName("init_biomes")
// needed for world gen // 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) @Inject(method = "forName(Ljava/lang/String;)Ljava/util/concurrent/Executor;", at = @At("HEAD"), cancellable = true)
private void forName(String executorName, CallbackInfoReturnable<Executor> ci) 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 // run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService()); ci.setReturnValue(new RunOnThisThreadExecutorService());
@@ -19,11 +19,10 @@
package com.seibel.distanthorizons.neoforge.mixins.server; package com.seibel.distanthorizons.neoforge.mixins.server;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService; import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import com.seibel.distanthorizons.common.wrappers.WorldGenThreadCheck;
import net.minecraft.Util; import net.minecraft.Util;
/** /**
@@ -36,16 +35,13 @@ import net.minecraft.Util;
@Mixin(Util.class) @Mixin(Util.class)
public class MixinUtilBackgroundThread public class MixinUtilBackgroundThread
{ {
private static boolean isWorldGenThread()
{ return WorldGenThreadCheck.isSetup && WorldGenThreadCheck.isCurrentThreadDhWorldGenThread.get(); }
#if MC_VER < MC_1_21_3 #if MC_VER < MC_1_21_3
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true) @Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci) 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 // run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService()); ci.setReturnValue(new RunOnThisThreadExecutorService());
@@ -61,7 +57,7 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true) at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci) private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
{ {
if (isWorldGenThread()) if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{ {
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered"); //ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
ci.setReturnValue(r); ci.setReturnValue(r);
@@ -77,7 +73,7 @@ public class MixinUtilBackgroundThread
at = @At("HEAD"), cancellable = true) at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci) private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
{ {
if (isWorldGenThread()) if (BatchGenerationEnvironment.isThisDhWorldGenThread())
{ {
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered"); //ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
ci.setReturnValue(r); ci.setReturnValue(r);