diff --git a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java
index a069e5da3..45eac51f3 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.api;
import com.seibel.distanthorizons.api.interfaces.events.IDhApiEventInjector;
+import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory;
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGeneratorOverrideRegister;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy;
@@ -45,7 +46,7 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverri
* the concrete object we replaced, there would be issues.
*
* @author James Seibel
- * @version 2023-8-26
+ * @version 2023-12-16
* @since API 1.0.0
*/
public class DhApi
@@ -114,6 +115,12 @@ public class DhApi
*/
public static IDhApiRenderProxy renderProxy = null;
+ /**
+ * Used to create wrappers for Minecraft objects needed by other Distant Horizons API methods.
+ * @since API 1.1.0
+ */
+ public static IDhApiWrapperFactory wrapperFactory = null;
+
}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/factories/IDhApiWrapperFactory.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/factories/IDhApiWrapperFactory.java
new file mode 100644
index 000000000..d8dd81ffa
--- /dev/null
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/factories/IDhApiWrapperFactory.java
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the Distant Horizons mod
+ * licensed under the GNU LGPL v3 License.
+ *
+ * Copyright (C) 2020-2023 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 .
+ */
+
+package com.seibel.distanthorizons.api.interfaces.factories;
+
+import com.seibel.distanthorizons.api.interfaces.block.IDhApiBiomeWrapper;
+import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper;
+import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
+import com.seibel.distanthorizons.api.DhApi;
+
+import java.io.IOException;
+
+/**
+ * This handles creating abstract wrapper objects.
+ *
+ * @author James Seibel
+ * @version 2023-12-16
+ * @since API 1.1.0
+ */
+public interface IDhApiWrapperFactory
+{
+ /**
+ * Constructs a {@link IDhApiBiomeWrapper} for use by other DhApi methods.
+ *
+ * @param objectArray Expects the following Minecraft objects (in order) for each MC version:
+ * 1.16 and 1.17
+ * - [net.minecraft.world.level.biome.Biome]
+ * 1.18 and newer
+ * - {@literal [net.minecraft.core.Holder] }
+ *
+ * @param levelWrapper Expects a {@link IDhApiLevelWrapper} returned by one of DH's {@link DhApi.Delayed#worldProxy} methods.
+ * A custom implementation of {@link IDhApiLevelWrapper} will not be accepted.
+ *
+ * @throws ClassCastException if any of the given parameters is of the wrong type.
+ * If thrown the error message will contain the list of expected object types in order.
+ *
+ * @since API 1.1.0
+ */
+ IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) throws ClassCastException;
+
+ /**
+ * Constructs a {@link IDhApiBlockStateWrapper} for use by other DhApi methods.
+ *
+ * @param objectArray Expects the following Minecraft objects (in order) for each MC version:
+ * 1.16 and newer
+ * - [net.minecraft.world.level.block.state.BlockState]
+ *
+ * @param levelWrapper Expects a {@link IDhApiBlockStateWrapper} returned by one of DH's {@link DhApi.Delayed#worldProxy} methods.
+ * A custom implementation of {@link IDhApiBlockStateWrapper} will not be accepted.
+ *
+ * @throws ClassCastException if any of the given parameters is of the wrong type.
+ * If thrown the error message will contain the list of expected object types in order.
+ *
+ * @since API 1.1.0
+ */
+ IDhApiBlockStateWrapper getBlockStateWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) throws ClassCastException;
+
+ /**
+ * Returns the {@link IDhApiBlockStateWrapper} representing air.
+ * @since API 1.1.0
+ */
+ IDhApiBlockStateWrapper getAirBlockStateWrapper();
+
+
+
+ ///**
+ // * Specifically designed to be used with the API.
+ // *
+ // * @throws ClassCastException with instructions on expected objects if the object couldn't be cast
+ // */
+ //IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException;
+
+}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java
index 3070c8511..5ec1293f0 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java
@@ -48,6 +48,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* TODO: System currently only supports 1x1 block per data.
*
* @see EDhApiDetailLevel
+ * @since API 1.0.0
*/
default byte getSmallestDataDetailLevel() { return EDhApiDetailLevel.BLOCK.detailLevel; }
/**
@@ -57,6 +58,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}.
*
* @see EDhApiDetailLevel
+ * @since API 1.0.0
*/
default byte getLargestDataDetailLevel() { return EDhApiDetailLevel.BLOCK.detailLevel; }
@@ -69,6 +71,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}.
*
* @see EDhApiDetailLevel
+ * @since API 1.0.0
*/
default byte getMinGenerationGranularity() { return EDhApiDetailLevel.CHUNK.detailLevel; }
@@ -81,10 +84,14 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}.
*
* @see EDhApiDetailLevel
+ * @since API 1.0.0
*/
default byte getMaxGenerationGranularity() { return (byte) (EDhApiDetailLevel.CHUNK.detailLevel + 2); }
- /** @return true if the generator is unable to accept new generation requests. */
+ /**
+ * @return true if the generator is unable to accept new generation requests.
+ * @since API 1.0.0
+ */
boolean isBusy();
@@ -115,7 +122,10 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* @param generatorMode how far into the world gen pipeline this method run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
* @param worldGeneratorThreadPool the thread pool that should be used when generating the returned {@link CompletableFuture}.
* @param resultConsumer the consumer that should be fired whenever a chunk finishes generating.
+ *
* @return a future that should run on the worldGeneratorThreadPool and complete once the given generation task has completed.
+ *
+ * @since API 1.0.0
*/
CompletableFuture generateChunks(
int chunkPosMinX, int chunkPosMinZ,
@@ -131,6 +141,8 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
/**
* Called before a new generator task is started.
* This can be used to run cleanup on existing tasks before new tasks are started.
+ *
+ * @since API 1.0.0
*/
void preGeneratorTaskStart();
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
index 6aad47dc6..1e174b3d5 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
@@ -19,7 +19,9 @@
package com.seibel.distanthorizons.core;
+import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.file.DataSourceReferenceTracker;
+import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.distanthorizons.coreapi.ModInfo;
import com.seibel.distanthorizons.core.world.DhApiWorldProxy;
import com.seibel.distanthorizons.core.api.external.methods.config.DhApiConfig;
@@ -67,6 +69,11 @@ public class Initializer
DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE;
DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE;
DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE;
+ DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
+ if (DhApi.Delayed.wrapperFactory == null)
+ {
+ LOGGER.error("Programmer Error: No ["+IWrapperFactory.class.getSimpleName()+"] assigned to the DhApi.");
+ }
DataSourceReferenceTracker.startGarbageCollectorBackgroundThread();
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/SingleColumnFullDataAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/SingleColumnFullDataAccessor.java
index c26c4f23e..7fde6050c 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/SingleColumnFullDataAccessor.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/fullData/accessor/SingleColumnFullDataAccessor.java
@@ -43,6 +43,10 @@ public class SingleColumnFullDataAccessor implements IFullDataAccessor
+ //=============//
+ // constructor //
+ //=============//
+
public SingleColumnFullDataAccessor(FullDataPointIdMap mapping, long[][] dataArrays, int dataArrayIndex)
{
this.dataArrays = dataArrays;
@@ -54,6 +58,10 @@ public class SingleColumnFullDataAccessor implements IFullDataAccessor
+ //=========//
+ // methods //
+ //=========//
+
/** @return true if any data exists in this column. */
public boolean doesColumnExist()
{
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java
index ffb0444fa..994f6a567 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java
@@ -277,16 +277,33 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
else if (genTaskResult.success)
{
// generation completed, update the files and listener(s)
- this.flushAndSaveAsync(pos).join();
- // FIXME this is a bad fix to prevent full data sources saving incomplete, causing holes in the world after generation.
- // The problem appears to be that the save may be happening too quickly,
- // potentially happening before the meta file has the newly generated data added to it.
- CHUNK_GEN_FINISHED_TIMER.schedule(new TimerTask()
+ try
{
- @Override
- public void run() { GeneratedFullDataFileHandler.this.flushAndSaveAsync(pos).join(); }
- }, 4000L);
+ // timeout necessary in case the flush gets stuck or there are issues down stream
+ // otherwise the world gen might get stuck and never finish
+ this.flushAndSaveAsync(pos).get(10_000, TimeUnit.MILLISECONDS);
+
+
+ // FIXME this is a bad fix to prevent full data sources saving incompletely, causing holes in the world after generation.
+ // The problem appears to be that the save may be happening too quickly,
+ // potentially happening before the meta file has the newly generated data added to it.
+ CHUNK_GEN_FINISHED_TIMER.schedule(new TimerTask()
+ {
+ @Override
+ public void run() { GeneratedFullDataFileHandler.this.flushAndSaveAsync(pos); }
+ }, 4_000L);
+
+ }
+ catch (InterruptedException | TimeoutException e)
+ {
+ LOGGER.warn("Unable to flush and save after waiting [10] seconds. Error: "+e.getMessage(), e);
+ }
+ catch (ExecutionException e)
+ {
+ LOGGER.error("Unexpected issue saving world gen result. Error: "+e.getMessage(), e);
+ }
+
this.fireOnGenPosSuccessListeners(pos);
return;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java
index 1edae45a5..1d10bbe84 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java
@@ -172,10 +172,7 @@ public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhS
public boolean hasSkyLight() { return this.serverLevelWrapper.hasSkyLight(); }
@Override
- public void saveWrites(ChunkSizedFullDataAccessor data)
- {
- clientside.writeChunkDataToFile(data);
- }
+ public void saveWrites(ChunkSizedFullDataAccessor data) { this.clientside.writeChunkDataToFile(data); }
@Override
public int getMinY() { return getLevelWrapper().getMinHeight(); }
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java
index c77fe15df..38044f584 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java
@@ -38,10 +38,7 @@ public abstract class DhLevel implements IDhLevel
@Override
- public int getMinY()
- {
- return 0;
- }
+ public int getMinY() { return 0; }
@Override
public CompletableFuture updateChunkAsync(IChunkWrapper chunk)
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java
index 5411e8057..d3cbd2097 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java
@@ -19,7 +19,6 @@
package com.seibel.distanthorizons.core.util;
-import com.seibel.distanthorizons.api.enums.config.EOverdrawPrevention;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
@@ -47,6 +46,7 @@ public class RenderUtil
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
+
//=================//
// culling methods //
//=================//
@@ -62,7 +62,7 @@ public class RenderUtil
&& pos.x <= center.x + MC_RENDER.getRenderDistance())
&&
(pos.z >= center.z - MC_RENDER.getRenderDistance()
- && pos.z <= center.z + MC_RENDER.getRenderDistance());
+ && pos.z <= center.z + MC_RENDER.getRenderDistance());
}
/**
@@ -76,7 +76,7 @@ public class RenderUtil
&& x <= centerCoordinate + MC_RENDER.getRenderDistance())
&&
(z >= centerCoordinate - MC_RENDER.getRenderDistance()
- && z <= centerCoordinate + MC_RENDER.getRenderDistance());
+ && z <= centerCoordinate + MC_RENDER.getRenderDistance());
}
/**
@@ -91,7 +91,7 @@ public class RenderUtil
&& i <= lodRadius + halfRadius)
&&
(j >= lodRadius - halfRadius
- && j <= lodRadius + halfRadius);
+ && j <= lodRadius + halfRadius);
}
/**
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java
index 6090d3dc0..651b9a231 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/IWrapperFactory.java
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.core.wrapperInterfaces;
+import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory;
import com.seibel.distanthorizons.core.level.IDhLevel;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
@@ -36,7 +37,7 @@ import java.util.HashSet;
* @author James Seibel
* @version 2022-12-5
*/
-public interface IWrapperFactory extends IBindable
+public interface IWrapperFactory extends IDhApiWrapperFactory, IBindable
{
AbstractBatchGenerationEnvironmentWrapper createBatchGenerator(IDhLevel targetLevel);
IBiomeWrapper deserializeBiomeWrapper(String str, ILevelWrapper levelWrapper) throws IOException;