Fix a crash on game startup, and fix world gen compat with TFC (TerraFirmaCraft)

This commit is contained in:
TomTheFurry
2023-07-02 18:32:15 +08:00
parent cd95405c6a
commit 6fca33e496
8 changed files with 113 additions and 36 deletions
@@ -20,6 +20,8 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
import com.google.common.collect.ImmutableMap;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.*;
@@ -191,7 +193,21 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
public static ThreadLocal<Boolean> isDistantGeneratorThread = new ThreadLocal<>();
public static ThreadLocal<Object> onDistantGenerationMixinData = new ThreadLocal<>();
public static boolean isCurrentThreadDistantGeneratorThread() { return (isDistantGeneratorThread.get() != null); }
public static void putDistantGenerationMixinData(Object data) {
LodUtil.assertTrue(isCurrentThreadDistantGeneratorThread());
onDistantGenerationMixinData.set(data);
}
public static Object getDistantGenerationMixinData() {
LodUtil.assertTrue(isCurrentThreadDistantGeneratorThread());
return onDistantGenerationMixinData.get();
}
public static void clearDistantGenerationMixinData() {
LodUtil.assertTrue(isCurrentThreadDistantGeneratorThread());
onDistantGenerationMixinData.remove();
}
public static final DhThreadFactory threadFactory = new DhThreadFactory("DH-Gen-Worker-Thread", Thread.MIN_PRIORITY);
@@ -200,10 +216,35 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
//==============//
// constructors //
//==============//
public static ImmutableMap<EDhApiWorldGenerationStep, Integer> BorderNeeded;
public static int MaxBorderNeeded;
static
{
DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
boolean isTerraFirmaCraft = false;
try {
Class.forName("net.dries007.tfc.world.TFCChunkGenerator");
isTerraFirmaCraft = true;
} catch (ClassNotFoundException e) {
//Ignore
}
EVENT_LOGGER.info("DH TerraFirmaCraft detection: " + isTerraFirmaCraft);
ImmutableMap.Builder<EDhApiWorldGenerationStep, Integer> builder = ImmutableMap.builder();
builder.put(EDhApiWorldGenerationStep.EMPTY, 1);
builder.put(EDhApiWorldGenerationStep.STRUCTURE_START, 0);
builder.put(EDhApiWorldGenerationStep.STRUCTURE_REFERENCE, 0);
builder.put(EDhApiWorldGenerationStep.BIOMES, isTerraFirmaCraft ? 1 : 0);
builder.put(EDhApiWorldGenerationStep.NOISE, isTerraFirmaCraft ? 1 : 0);
builder.put(EDhApiWorldGenerationStep.SURFACE, 0);
builder.put(EDhApiWorldGenerationStep.CARVERS, 0);
builder.put(EDhApiWorldGenerationStep.LIQUID_CARVERS, 0);
builder.put(EDhApiWorldGenerationStep.FEATURES, 0);
builder.put(EDhApiWorldGenerationStep.LIGHT, 0);
BorderNeeded = builder.build();
MaxBorderNeeded = BorderNeeded.values().stream().mapToInt(Integer::intValue).max().getAsInt();
}
public BatchGenerationEnvironment(IDhServerLevel serverlevel)
@@ -219,12 +260,17 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
if (generator.getClass().toString().equals("class com.terraforged.mod.chunk.TFChunkGenerator"))
{
EVENT_LOGGER.info("TerraForge Chunk Generator detected: ["+generator.getClass()+"], Distant Generation will try its best to support it.");
EVENT_LOGGER.info("If it does crash, turn Distant Generation off or set it to to ["+EDhApiWorldGenerationStep.EMPTY+"].");
EVENT_LOGGER.info("If it does crash, turn Distant Generation off or set it to to ["+EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY+"].");
}
else if (generator.getClass().toString().equals("class net.dries007.tfc.world.TFCChunkGenerator"))
{
EVENT_LOGGER.info("TerraFirmaCraft Chunk Generator detected: ["+generator.getClass()+"], Distant Generation will try its best to support it.");
EVENT_LOGGER.info("If it does crash, turn Distant Generation off or set it to to ["+ EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY +"].");
}
else
{
EVENT_LOGGER.warn("Unknown Chunk Generator detected: ["+generator.getClass()+"], Distant Generation May Fail!");
EVENT_LOGGER.warn("If it does crash, disable Distant Generation or set the Generation Mode to ["+EDhApiWorldGenerationStep.EMPTY+"].");
EVENT_LOGGER.warn("If it does crash, disable Distant Generation or set the Generation Mode to ["+EDhApiDistantGeneratorMode.PRE_EXISTING_ONLY+"].");
}
}
@@ -357,20 +403,29 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
}
}
private static ArrayGridList<ChunkAccess> GetCutoutFrom(ArrayGridList<ChunkAccess> total, int border) {
return new ArrayGridList<>(total, border, total.gridSize - border);
}
private static ArrayGridList<ChunkAccess> GetCutoutFrom(ArrayGridList<ChunkAccess> total, EDhApiWorldGenerationStep step) {
return GetCutoutFrom(total, MaxBorderNeeded - BorderNeeded.get(step));
}
public void generateLodFromList(GenerationEvent genEvent) throws InterruptedException
{
EVENT_LOGGER.debug("Lod Generate Event: "+genEvent.minPos);
ArrayGridList<ChunkAccess> referencedChunks;
ArrayGridList<ChunkAccess> genChunks;
ArrayGridList<ChunkAccess> totalChunks;
ArrayGridList<ChunkAccess> finalGenChunks;
LightedWorldGenRegion region;
WorldGenLevelLightEngine lightEngine;
LightGetterAdaptor adaptor;
int refSize = genEvent.size+2; // +2 for the border referenced chunks
int refPosX = genEvent.minPos.x - 1; // -1 for the border referenced chunks
int refPosZ = genEvent.minPos.z - 1; // -1 for the border referenced chunks
int borderSize = MaxBorderNeeded;
int refSize = genEvent.size + borderSize * 2;
int refPosX = genEvent.minPos.x - borderSize;
int refPosZ = genEvent.minPos.z - borderSize;
try
{
@@ -399,17 +454,15 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
return target;
};
referencedChunks = new ArrayGridList<>(refSize, (x,z) -> generator.generate(x + refPosX,z + refPosZ));
totalChunks = new ArrayGridList<>(refSize, (x,z) -> generator.generate(x + refPosX,z + refPosZ));
genEvent.refreshTimeout();
region = new LightedWorldGenRegion(params.level, lightEngine, referencedChunks,
region = new LightedWorldGenRegion(params.level, lightEngine, totalChunks,
ChunkStatus.STRUCTURE_STARTS, refSize/2, generator);
adaptor.setRegion(region);
genEvent.threadedParam.makeStructFeat(region, params);
genChunks = new ArrayGridList<>(referencedChunks, RANGE_TO_RANGE_EMPTY_EXTENSION,
referencedChunks.gridSize - RANGE_TO_RANGE_EMPTY_EXTENSION);
this.generateDirect(genEvent, genChunks, genEvent.targetGenerationStep, region);
this.generateDirect(genEvent, totalChunks, borderSize, genEvent.targetGenerationStep, region);
genEvent.timer.nextEvent("cleanup");
}
catch (StepStructureStart.StructStartCorruptedException f)
@@ -417,12 +470,13 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
genEvent.threadedParam.markAsInvalid();
throw (RuntimeException)f.getCause();
}
for (int offsetY = 0; offsetY < genChunks.gridSize; offsetY++)
finalGenChunks = GetCutoutFrom(totalChunks, borderSize);
for (int offsetY = 0; offsetY < finalGenChunks.gridSize; offsetY++)
{
for (int offsetX = 0; offsetX < genChunks.gridSize; offsetX++)
for (int offsetX = 0; offsetX < finalGenChunks.gridSize; offsetX++)
{
ChunkAccess target = genChunks.get(offsetX, offsetY);
ChunkAccess target = finalGenChunks.get(offsetX, offsetY);
ChunkWrapper wrappedChunk = new ChunkWrapper(target, region, null);
if (target instanceof LevelChunk) {
((LevelChunk) target).loaded = true;
@@ -472,7 +526,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
}
}
public void generateDirect(GenerationEvent genEvent, ArrayGridList<ChunkAccess> chunksToGenerate,
public void generateDirect(GenerationEvent genEvent, ArrayGridList<ChunkAccess> chunksToGenerate, int border,
EDhApiWorldGenerationStep step, LightedWorldGenRegion region) throws InterruptedException
{
if (Thread.interrupted())
@@ -500,7 +554,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
genEvent.timer.nextEvent("structStart");
throwIfThreadInterrupted();
stepStructureStart.generateGroup(genEvent.threadedParam, region, chunksToGenerate);
stepStructureStart.generateGroup(genEvent.threadedParam, region, GetCutoutFrom(chunksToGenerate, EDhApiWorldGenerationStep.STRUCTURE_START));
genEvent.refreshTimeout();
if (step == EDhApiWorldGenerationStep.STRUCTURE_START)
{
@@ -509,7 +563,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
genEvent.timer.nextEvent("structRef");
throwIfThreadInterrupted();
stepStructureReference.generateGroup(genEvent.threadedParam, region, chunksToGenerate);
stepStructureReference.generateGroup(genEvent.threadedParam, region, GetCutoutFrom(chunksToGenerate, EDhApiWorldGenerationStep.STRUCTURE_REFERENCE));
genEvent.refreshTimeout();
if (step == EDhApiWorldGenerationStep.STRUCTURE_REFERENCE)
{
@@ -518,7 +572,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
genEvent.timer.nextEvent("biome");
throwIfThreadInterrupted();
stepBiomes.generateGroup(genEvent.threadedParam, region, chunksToGenerate);
stepBiomes.generateGroup(genEvent.threadedParam, region, GetCutoutFrom(chunksToGenerate, EDhApiWorldGenerationStep.BIOMES));
genEvent.refreshTimeout();
if (step == EDhApiWorldGenerationStep.BIOMES)
{
@@ -527,7 +581,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
genEvent.timer.nextEvent("noise");
throwIfThreadInterrupted();
stepNoise.generateGroup(genEvent.threadedParam, region, chunksToGenerate);
stepNoise.generateGroup(genEvent.threadedParam, region, GetCutoutFrom(chunksToGenerate, EDhApiWorldGenerationStep.NOISE));
genEvent.refreshTimeout();
if (step == EDhApiWorldGenerationStep.NOISE)
{
@@ -536,7 +590,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
genEvent.timer.nextEvent("surface");
throwIfThreadInterrupted();
stepSurface.generateGroup(genEvent.threadedParam, region, chunksToGenerate);
stepSurface.generateGroup(genEvent.threadedParam, region, GetCutoutFrom(chunksToGenerate, EDhApiWorldGenerationStep.SURFACE));
genEvent.refreshTimeout();
if (step == EDhApiWorldGenerationStep.SURFACE)
{
@@ -552,7 +606,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
genEvent.timer.nextEvent("feature");
throwIfThreadInterrupted();
stepFeatures.generateGroup(genEvent.threadedParam, region, chunksToGenerate);
stepFeatures.generateGroup(genEvent.threadedParam, region, GetCutoutFrom(chunksToGenerate, EDhApiWorldGenerationStep.FEATURES));
genEvent.refreshTimeout();
}
finally
@@ -566,7 +620,7 @@ public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnv
if (!Thread.interrupted())
{
this.stepLight.generateGroup(region.getLightEngine(), chunksToGenerate);
this.stepLight.generateGroup(region.getLightEngine(), GetCutoutFrom(chunksToGenerate, EDhApiWorldGenerationStep.LIGHT));
}
}
else
@@ -208,7 +208,7 @@ public class LightedWorldGenRegion extends WorldGenRegion
}
// Use this instead of super.hasChunk() to bypass C2ME concurrency checks
private boolean superHasChunk(int x, int z) {
public boolean superHasChunk(int x, int z) {
int k = x - firstPos.x;
int l = z - firstPos.z;
return l >= 0 && l < size && k >= 0 && k < size;
@@ -66,10 +66,12 @@ public final class StepFeatures {
worldGenRegion.setOverrideCenter(chunk.getPos());
environment.params.generator.applyBiomeDecoration(worldGenRegion, tParams.structFeat);
Heightmap.primeHeightmaps(chunk, STATUS.heightmapsAfter());
BatchGenerationEnvironment.clearDistantGenerationMixinData();
#else
environment.params.generator.applyBiomeDecoration(worldGenRegion, chunk,
tParams.structFeat.forWorldGenRegion(worldGenRegion));
Heightmap.primeHeightmaps(chunk, STATUS.heightmapsAfter());
BatchGenerationEnvironment.clearDistantGenerationMixinData();
#endif
} catch (ReportedException e) {
e.printStackTrace();
@@ -1,5 +1,6 @@
package com.seibel.distanthorizons.fabric.mixins.client;
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import net.minecraft.client.renderer.GameRenderer;
import org.apache.logging.log4j.LogManager;
@@ -18,14 +19,22 @@ public class MixinGameRenderer
#if POST_MC_1_17_1
@Inject(method = "shutdownShaders", at = @At("HEAD"))
public void onShutdownShaders(CallbackInfo ci) {
LOGGER.info("Shutting down renderer");
LOGGER.info("Shutting down renderer (fabric)");
if (!DependencySetupDoneCheck.isDone) {
LOGGER.warn("Dependency setup is not done yet, skipping renderer this shutdown event!");
return;
}
ClientApi.INSTANCE.rendererShutdownEvent();
}
// FIXME: This I think will dup multiple renderStartupEvent calls...
@Inject(method = {"reloadShaders", "preloadUiShader", "preloadShader"}, at = @At("TAIL"))
@Inject(method = {"reloadShaders", "preloadUiShader"}, at = @At("TAIL"))
public void onStartupShaders(CallbackInfo ci) {
LOGGER.info("Starting up renderer");
LOGGER.info("Starting up renderer (fabric)");
if (!DependencySetupDoneCheck.isDone) {
LOGGER.warn("Dependency setup is not done yet, skipping renderer this startup event!");
return;
}
ClientApi.INSTANCE.rendererStartupEvent();
}
#else
+2
View File
@@ -85,6 +85,8 @@ dependencies {
addMod("curse.maven:TerraForged-363820:${rootProject.terraforged_version}", rootProject.enable_terraforged)
addMod("curse.maven:TerraFirmaCraft-302973:4616004", rootProject.enable_terrafirmacraft)
// if (System.getProperty("idea.sync.active") != "true") {
// annotationProcessor "org.spongepowered:mixin:0.8.4:processor"
// }
@@ -1,5 +1,6 @@
package com.seibel.distanthorizons.forge.mixins.client;
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import net.minecraft.client.renderer.GameRenderer;
import org.apache.logging.log4j.LogManager;
@@ -18,14 +19,22 @@ public class MixinGameRenderer
#if POST_MC_1_17_1
@Inject(method = "shutdownShaders", at = @At("HEAD"))
public void onShutdownShaders(CallbackInfo ci) {
LOGGER.info("Shutting down renderer");
LOGGER.info("Shutting down renderer (forge)");
if (!DependencySetupDoneCheck.isDone) {
LOGGER.warn("Dependency setup is not done yet, skipping renderer this shutdown event!");
return;
}
ClientApi.INSTANCE.rendererShutdownEvent();
}
// FIXME: This I think will dup multiple renderStartupEvent calls...
@Inject(method = {"reloadShaders", "preloadUiShader", "preloadShader"}, at = @At("TAIL"))
@Inject(method = {"reloadShaders", "preloadUiShader"}, at = @At("TAIL"))
public void onStartupShaders(CallbackInfo ci) {
LOGGER.info("Starting up renderer");
LOGGER.info("Starting up renderer (forge)");
if (!DependencySetupDoneCheck.isDone) {
LOGGER.warn("Dependency setup is not done yet, skipping renderer this startup event!");
return;
}
ClientApi.INSTANCE.rendererStartupEvent();
}
#else
+1
View File
@@ -54,3 +54,4 @@ forge_version=40.2.9
# 2 = Can be referenced in code and runs in client
enable_starlight_forge=0
enable_terraforged=0
enable_terrafirmacraft=0