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 a04faaad0..79f67940b 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java
@@ -23,8 +23,9 @@ 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.IDhApiCustomRenderRegister;
+import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy;
+import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
import com.seibel.distanthorizons.api.methods.override.DhApiWorldGeneratorOverrideRegister;
import com.seibel.distanthorizons.coreapi.ModInfo;
@@ -128,11 +129,12 @@ public class DhApi
*/
public static IDhApiWrapperFactory wrapperFactory = null;
- ///**
- // * Used to add custom objects to DH's render pass.
- // * @since API 3.0.0
- // */
- //public static IDhApiCustomRenderRegister renderRegister = null;
+ /**
+ * Used to create custom renderable objects.
+ * These objects can be added to the renderer in {@link IDhApiLevelWrapper}
+ * @since API 3.0.0
+ */
+ public static IDhApiCustomRenderObjectFactory customRenderObjectFactory = null;
}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java
new file mode 100644
index 000000000..7e78e0c60
--- /dev/null
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java
@@ -0,0 +1,26 @@
+package com.seibel.distanthorizons.api.interfaces.render;
+
+import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
+import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
+
+import java.util.List;
+
+/**
+ * Handles creating
+ * {@link IDhApiRenderableBoxGroup} objects,
+ * which can be added via a {@link IDhApiCustomRenderRegister}.
+ *
+ * @see IDhApiCustomRenderRegister
+ * @see IDhApiRenderableBoxGroup
+ *
+ * @author James Seibel
+ * @version 2024-7-3
+ * @since API 3.0.0
+ */
+public interface IDhApiCustomRenderObjectFactory
+{
+ IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox cube);
+ IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List cubeList);
+ IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List cubeList);
+
+}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java
index 6b9b06daf..c156c0c8c 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderRegister.java
@@ -1,18 +1,24 @@
package com.seibel.distanthorizons.api.interfaces.render;
-import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
-import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
-
-import java.util.List;
+import com.seibel.distanthorizons.api.DhApi;
+import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
+import com.seibel.distanthorizons.api.interfaces.world.IDhApiWorldProxy;
/**
- * Handles adding, removing, and creating
+ * Handles adding and removing
* {@link IDhApiRenderableBoxGroup} objects,
- * which can be used to render custom objects into
- * DH's terrain.
+ * from DH's renderer.
+ *
+ * Can be accessed in
+ * {@link DhApi.Delayed#worldProxy} -> {@link IDhApiLevelWrapper}.
+ *
+ * @see IDhApiCustomRenderObjectFactory
+ * @see IDhApiRenderableBoxGroup
+ * @see IDhApiWorldProxy
+ * @see IDhApiLevelWrapper
*
* @author James Seibel
- * @version 2024-6-30
+ * @version 2024-7-3
* @since API 3.0.0
*/
public interface IDhApiCustomRenderRegister
@@ -21,9 +27,4 @@ public interface IDhApiCustomRenderRegister
IDhApiRenderableBoxGroup remove(long id);
-
- IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox cube);
- IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List cubeList);
- IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List cubeList);
-
}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java
index 2583dfb4a..30d9e161c 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/world/IDhApiLevelWrapper.java
@@ -21,6 +21,7 @@ package com.seibel.distanthorizons.api.interfaces.world;
import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
+import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
/**
* Can be either a Server or Client level.
@@ -49,4 +50,10 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper
*/
default int getMinHeight() { return 0; }
+ /**
+ * Will return null if called on the server,
+ * or if called before the renderer has been set up.
+ */
+ IDhApiCustomRenderRegister getRenderRegister();
+
}
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 dbf715181..91a4d88f7 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
@@ -20,7 +20,7 @@
package com.seibel.distanthorizons.core;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
-import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer;
+import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory;
import com.seibel.distanthorizons.core.sql.DatabaseUpdater;
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.distanthorizons.coreapi.ModInfo;
@@ -94,7 +94,7 @@ public class Initializer
DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE;
DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE;
DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE;
- //DhApi.Delayed.renderRegister = GenericObjectRenderer.INSTANCE;
+ DhApi.Delayed.customRenderObjectFactory = GenericRenderObjectFactory.INSTANCE;
DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
if (DhApi.Delayed.wrapperFactory == null)
{
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java
index 56eb78972..5ecc362dc 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java
@@ -31,6 +31,7 @@ import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.render.renderer.GenericObjectRenderer;
+import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO;
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
@@ -207,6 +208,8 @@ public abstract class AbstractDhLevel implements IDhLevel
public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List newBeamList)
{
GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer();
+
+ // should always be non-null, but just in case
if (this.beaconBeamRepo != null
&& genericObjectRenderer != null)
{
@@ -253,7 +256,7 @@ public abstract class AbstractDhLevel implements IDhLevel
// new beam found, add to DB
this.beaconBeamRepo.save(newBeam);
- IDhApiRenderableBoxGroup beaconBox = genericObjectRenderer.createForSingleBox(new DhApiRenderableBox(
+ IDhApiRenderableBoxGroup beaconBox = GenericRenderObjectFactory.INSTANCE.createForSingleBox(new DhApiRenderableBox(
new DhApiVec3f(newBeam.pos.x, newBeam.pos.y+1, newBeam.pos.z),
new DhApiVec3f(newBeam.pos.x+1, 6_000, newBeam.pos.z+1),
newBeam.color
@@ -295,6 +298,8 @@ public abstract class AbstractDhLevel implements IDhLevel
public void loadBeaconBeamsInPos(long pos)
{
GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer();
+
+ // should always be non-null, but just in case
if (this.beaconBeamRepo != null
&& genericObjectRenderer != null)
{
@@ -304,7 +309,7 @@ public abstract class AbstractDhLevel implements IDhLevel
{
BeaconBeamDTO beam = existingBeamList.get(i);
- IDhApiRenderableBoxGroup beaconBox = genericObjectRenderer.createForSingleBox(new DhApiRenderableBox(
+ IDhApiRenderableBoxGroup beaconBox = GenericRenderObjectFactory.INSTANCE.createForSingleBox(new DhApiRenderableBox(
new DhApiVec3f(beam.pos.x, beam.pos.y+1, beam.pos.z),
new DhApiVec3f(beam.pos.x+1, 6_000, beam.pos.z+1),
beam.color
@@ -335,6 +340,8 @@ public abstract class AbstractDhLevel implements IDhLevel
public void unloadBeaconBeamsInPos(long pos)
{
GenericObjectRenderer genericObjectRenderer = this.getGenericRenderer();
+
+ // should always be non-null, but just in case
if (this.beaconBeamRepo != null
&& genericObjectRenderer != null)
{
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java
index 166b0a1df..1f7e19a9b 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java
@@ -60,6 +60,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
public DhClientLevel(AbstractSaveStructure saveStructure, IClientLevelWrapper clientLevelWrapper, @Nullable File fullDataSaveDirOverride, boolean enableRendering)
{
this.levelWrapper = clientLevelWrapper;
+ this.levelWrapper.setParentClientLevel(this);
this.saveStructure = saveStructure;
this.dataFileHandler = new RemoteFullDataSourceProvider(this, saveStructure, fullDataSaveDirOverride);
this.clientside = new ClientLevelModule(this);
@@ -156,10 +157,11 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
@Override
public void close()
{
+ this.levelWrapper.setParentClientLevel(null);
this.clientside.close();
super.close();
this.dataFileHandler.close();
- LOGGER.info("Closed " + DhClientLevel.class.getSimpleName() + " for " + levelWrapper);
+ LOGGER.info("Closed [" + DhClientLevel.class.getSimpleName() + "] for [" + this.levelWrapper + "]");
}
@Override
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java
index 0b950ed39..c6b4c6911 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java
@@ -41,6 +41,10 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel
+ //=============//
+ // constructor //
+ //=============//
+
public DhServerLevel(AbstractSaveStructure saveStructure, IServerLevelWrapper serverLevelWrapper)
{
if (saveStructure.getFullDataFolder(serverLevelWrapper).mkdirs())
@@ -56,6 +60,10 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel
+ //=========//
+ // methods //
+ //=========//
+
public void serverTick() { this.chunkToLodBuilder.tick(); }
@Override
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java
index ea73498bd..420a4a3fa 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericObjectRenderer.java
@@ -19,7 +19,6 @@
package com.seibel.distanthorizons.core.render.renderer;
-import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
@@ -27,12 +26,10 @@ import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegist
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
-import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
-import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.render.glObject.GLState;
import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer;
@@ -234,8 +231,11 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
}
private void addGenericDebugObjects()
{
+ GenericRenderObjectFactory factory = GenericRenderObjectFactory.INSTANCE;
+
+
// single giant box
- IDhApiRenderableBoxGroup singleGiantBoxGroup = this.createForSingleBox(
+ IDhApiRenderableBoxGroup singleGiantBoxGroup = factory.createForSingleBox(
new DhApiRenderableBox(
new DhApiVec3f(0f,0f,0f), new DhApiVec3f(16f,190f,16f),
new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125))
@@ -246,7 +246,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
// single slender box
- IDhApiRenderableBoxGroup singleTallBoxGroup = this.createForSingleBox(
+ IDhApiRenderableBoxGroup singleTallBoxGroup = factory.createForSingleBox(
new DhApiRenderableBox(
new DhApiVec3f(16f,0f,31f), new DhApiVec3f(17f,2000f,32f),
new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125))
@@ -264,7 +264,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
new DhApiVec3f(0f+i,150f+i,24f), new DhApiVec3f(1f+i,151f+i,25f),
new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue())));
}
- IDhApiRenderableBoxGroup absolutePosBoxGroup = this.createAbsolutePositionedGroup(absBoxList);
+ IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(absBoxList);
this.add(absolutePosBoxGroup);
@@ -276,7 +276,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
new DhApiVec3f(0f,0f+i,0f), new DhApiVec3f(1f,1f+i,1f),
new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue())));
}
- IDhApiRenderableBoxGroup relativePosBoxGroup = this.createRelativePositionedGroup(
+ IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup(
new DhApiVec3f(24f, 140f, 24f),
relBoxList);
relativePosBoxGroup.setPreRenderFunc((event) ->
@@ -300,7 +300,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue())));
}
}
- IDhApiRenderableBoxGroup massRelativePosBoxGroup = this.createRelativePositionedGroup(
+ IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup(
new DhApiVec3f(-25f, 140f, 0f),
massRelBoxList);
massRelativePosBoxGroup.setPreRenderFunc((event) ->
@@ -323,29 +323,6 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
-
- //================//
- // group creation //
- //================//
-
- @Override
- public IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox box)
- {
- ArrayList list = new ArrayList<>();
- list.add(box);
- return this.createAbsolutePositionedGroup(list);
- }
-
- @Override
- public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List boxList)
- { return new RenderableBoxGroup(new Vec3f(originBlockPos), boxList, true); }
-
- @Override
- public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList)
- { return new RenderableBoxGroup(new Vec3f(0, 0, 0), boxList, false); }
-
-
-
//==============//
// registration //
//==============//
@@ -355,7 +332,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
{
if (!(iBoxGroup instanceof RenderableBoxGroup))
{
- throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"].");
+ throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"], type received: ["+(iBoxGroup != null ? iBoxGroup.getClass() : "NULL")+"].");
}
RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup;
@@ -493,9 +470,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
this.shader.setUniform(this.instancedShaderOffsetUniform,
new Vec3f(
- boxGroup.originBlockPos.x,
- boxGroup.originBlockPos.y,
- boxGroup.originBlockPos.z
+ boxGroup.getOriginBlockPos().x,
+ boxGroup.getOriginBlockPos().y,
+ boxGroup.getOriginBlockPos().z
));
this.shader.setUniform(this.instancedShaderCameraPosUniform,
@@ -577,7 +554,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight);
this.shader.setUniform(this.blockLightUniform, boxGroup.blockLight);
- for (DhApiRenderableBox box : boxGroup.boxList)
+ for (DhApiRenderableBox box : boxGroup)
{
renderBox(boxGroup, box, transformMatrix, camPos);
}
@@ -591,9 +568,9 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
float originOffsetZ = 0;
if (boxGroup.positionBoxesRelativeToGroupOrigin)
{
- originOffsetX = boxGroup.originBlockPos.x;
- originOffsetY = boxGroup.originBlockPos.y;
- originOffsetZ = boxGroup.originBlockPos.z;
+ originOffsetX = boxGroup.getOriginBlockPos().x;
+ originOffsetY = boxGroup.getOriginBlockPos().y;
+ originOffsetZ = boxGroup.getOriginBlockPos().z;
}
Mat4f boxTransform = Mat4f.createTranslateMatrix(
@@ -640,259 +617,4 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
return LodUtil.formatLog("Generic Obj Count: " + activeCountText + "/" + totalCountText);
}
-
-
- //================//
- // helper classes //
- //================//
-
- private static final class RenderableBoxGroup
- extends AbstractList
- implements IDhApiRenderableBoxGroup, Closeable
- {
- public final static AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0);
-
-
-
- public final long id;
-
- /** If false the boxes will be positioned relative to the level's origin */
- public final boolean positionBoxesRelativeToGroupOrigin;
-
- private final ArrayList boxList;
-
- private final Vec3f originBlockPos;
-
- public int skyLight = 15;
- public int blockLight = 0;
-
- @Nullable
- public Consumer beforeRenderFunc;
-
- private boolean vertexDataDirty = true;
- public boolean active = true;
-
- // instance data
- private int instanceTranslationVbo = 0;
- private int instanceScaleVbo = 0;
- private int instanceColorVbo = 0;
-
-
-
- // setters/getters //
-
- @Override
- public long getId() { return this.id; }
-
- @Override
- public void setOriginBlockPos(DhApiVec3f pos)
- {
- this.originBlockPos.x = pos.x;
- this.originBlockPos.y = pos.y;
- this.originBlockPos.z = pos.z;
- }
-
- @Override
- public DhApiVec3f getOriginBlockPos() { return new DhApiVec3f(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); }
-
-
- @Override
- public void setSkyLight(int skyLight)
- {
- if (skyLight < LodUtil.MIN_MC_LIGHT || skyLight > LodUtil.MAX_MC_LIGHT)
- {
- throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
- }
- this.skyLight = skyLight;
- }
- @Override
- public int getSkyLight() { return this.skyLight; }
-
- @Override
- public void setBlockLight(int blockLight)
- {
- if (blockLight < LodUtil.MIN_MC_LIGHT || blockLight > LodUtil.MAX_MC_LIGHT)
- {
- throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
- }
- this.blockLight = blockLight;
- }
- @Override
- public int getBlockLight() { return this.blockLight; }
-
-
-
- //=============//
- // constructor //
- //=============//
-
- public RenderableBoxGroup(Vec3f originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin)
- {
- // TODO save to database
- // TODO when?
-
- this.id = NEXT_ID_ATOMIC_INT.getAndIncrement();
- this.boxList = new ArrayList<>(boxList);
-
- this.originBlockPos = originBlockPos;
- this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin;
- }
-
-
-
- // methods //
-
- @Override
- public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); }
-
- @Override
- public void setPreRenderFunc(Consumer func) { this.beforeRenderFunc = func; }
-
- @Override
- public void triggerBoxChange() { this.vertexDataDirty = true; }
-
- @Override
- public void setActive(boolean active) { this.active = active; }
- @Override
- public boolean isActive() { return this.active; }
-
- public void preRender(DhApiRenderParam renderEventParam)
- {
- if (this.beforeRenderFunc != null)
- {
- beforeRenderFunc.accept(renderEventParam);
- }
- }
-
-
-
- // overrides //
-
- @Override
- public DhApiRenderableBox get(int index) { return this.boxList.get(index); }
- @Override
- public int size() { return this.boxList.size(); }
- @Override
- public boolean removeIf(Predicate super DhApiRenderableBox> filter) { return this.boxList.removeIf(filter); }
- @Override
- public void replaceAll(UnaryOperator operator) { this.boxList.replaceAll(operator); }
- @Override
- public void sort(Comparator super DhApiRenderableBox> c) { this.boxList.sort(c); }
- @Override
- public void forEach(Consumer super DhApiRenderableBox> action) { this.boxList.forEach(action); }
- @Override
- public Spliterator spliterator() { return this.boxList.spliterator(); }
- @Override
- public Stream stream() { return this.boxList.stream(); }
- @Override
- public Stream parallelStream() { return this.boxList.parallelStream(); }
-
-
-
- //===================//
- // vertex attributes //
- //===================//
-
- /** Does nothing if the vertex data is already up-to-date */
- private void updateVertexAttributeData()
- {
- if (!this.vertexDataDirty)
- {
- return;
- }
- this.vertexDataDirty = false;
-
- if (this.instanceTranslationVbo == 0)
- {
- this.instanceTranslationVbo = GL32.glGenBuffers();
- this.instanceScaleVbo = GL32.glGenBuffers();
- this.instanceColorVbo = GL32.glGenBuffers();
- }
-
- int boxCount = this.size();
-
-
- // transformation / scaling //
-
- float[] translationData = new float[boxCount * 3];
- float[] scalingData = new float[boxCount * 3];
- for (int i = 0; i < boxCount; i++)
- {
- DhApiRenderableBox box = this.get(i);
-
- int dataIndex = i * 3;
-
- translationData[dataIndex] = box.minPos.x;
- translationData[dataIndex + 1] = box.minPos.y;
- translationData[dataIndex + 2] = box.minPos.z;
-
- scalingData[dataIndex] = box.maxPos.x - box.minPos.x;
- scalingData[dataIndex + 1] = box.maxPos.y - box.minPos.y;
- scalingData[dataIndex + 2] = box.maxPos.z - box.minPos.z;
-
- }
-
-
- // colors //
-
- float[] colorData = new float[boxCount * 4];
- for (int i = 0; i < boxCount; i++)
- {
- DhApiRenderableBox box = this.get(i);
- Color color = box.color;
- int colorIndex = i * 4;
- colorData[colorIndex] = color.getRed() / 255.0f;
- colorData[colorIndex + 1] = color.getGreen() / 255.0f;
- colorData[colorIndex + 2] = color.getBlue() / 255.0f;
- colorData[colorIndex + 3] = color.getAlpha() / 255.0f;
- }
-
-
- // Upload transformation matrices
- GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslationVbo);
- GL32.glBufferData(GL32.GL_ARRAY_BUFFER, translationData ,GL32.GL_DYNAMIC_DRAW);
- GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo);
- GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW);
-
- // Upload colors
- GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo);
- GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW);
- }
-
-
-
- //================//
- // base overrides //
- //================//
-
- @Override
- public String toString() { return "ID:["+this.id+"], pos:["+this.originBlockPos.x+","+this.originBlockPos.y+","+this.originBlockPos.z+"], size:["+this.size()+"], active:["+this.active+"]"; }
-
- @Override
- public void close()
- {
- GLProxy.getInstance().queueRunningOnRenderThread(() ->
- {
- if (this.instanceTranslationVbo != 0)
- {
- GL32.glDeleteBuffers(this.instanceTranslationVbo);
- this.instanceTranslationVbo = 0;
- }
-
- if (this.instanceScaleVbo != 0)
- {
- GL32.glDeleteBuffers(this.instanceScaleVbo);
- this.instanceScaleVbo = 0;
- }
-
- if (this.instanceColorVbo != 0)
- {
- GL32.glDeleteBuffers(this.instanceColorVbo);
- this.instanceColorVbo = 0;
- }
- });
- }
-
- }
-
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java
new file mode 100644
index 000000000..bae8c24af
--- /dev/null
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/GenericRenderObjectFactory.java
@@ -0,0 +1,76 @@
+/*
+ * 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.core.render.renderer;
+
+import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
+import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
+import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
+import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
+import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
+import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
+import com.seibel.distanthorizons.core.util.math.Vec3f;
+import org.apache.logging.log4j.Logger;
+
+import java.util.List;
+import java.util.*;
+
+/**
+ * Handles creating {@link DhApiRenderableBox}.
+ *
+ * @see IDhApiCustomRenderRegister
+ * @see DhApiRenderableBox
+ */
+public class GenericRenderObjectFactory implements IDhApiCustomRenderObjectFactory
+{
+ private static final Logger LOGGER = DhLoggerBuilder.getLogger();
+
+ public static final GenericRenderObjectFactory INSTANCE = new GenericRenderObjectFactory();
+
+
+
+ //=============//
+ // constructor //
+ //=============//
+
+ private GenericRenderObjectFactory() { }
+
+
+
+ //================//
+ // group creation //
+ //================//
+
+ @Override
+ public IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox box)
+ {
+ ArrayList list = new ArrayList<>();
+ list.add(box);
+ return this.createAbsolutePositionedGroup(list);
+ }
+
+ @Override
+ public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List boxList)
+ { return new RenderableBoxGroup(new Vec3f(originBlockPos), boxList, true); }
+
+ @Override
+ public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList)
+ { return new RenderableBoxGroup(new Vec3f(0, 0, 0), boxList, false); }
+
+}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java
new file mode 100644
index 000000000..0e87d046e
--- /dev/null
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/RenderableBoxGroup.java
@@ -0,0 +1,268 @@
+package com.seibel.distanthorizons.core.render.renderer;
+
+import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
+import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
+import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
+import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
+import com.seibel.distanthorizons.core.render.glObject.GLProxy;
+import com.seibel.distanthorizons.core.util.LodUtil;
+import com.seibel.distanthorizons.core.util.math.Vec3f;
+import org.jetbrains.annotations.Nullable;
+import org.lwjgl.opengl.GL32;
+
+import java.awt.*;
+import java.io.Closeable;
+import java.util.*;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.UnaryOperator;
+import java.util.stream.Stream;
+
+public class RenderableBoxGroup
+ extends AbstractList
+ implements IDhApiRenderableBoxGroup, Closeable
+ {
+ public final static AtomicInteger NEXT_ID_ATOMIC_INT = new AtomicInteger(0);
+
+
+
+ public final long id;
+
+ /** If false the boxes will be positioned relative to the level's origin */
+ public final boolean positionBoxesRelativeToGroupOrigin;
+
+ private final ArrayList boxList;
+
+ private final Vec3f originBlockPos;
+
+ public int skyLight = 15;
+ public int blockLight = 0;
+
+ @Nullable
+ public Consumer beforeRenderFunc;
+
+ private boolean vertexDataDirty = true;
+ public boolean active = true;
+
+ // instance data
+ public int instanceTranslationVbo = 0;
+ public int instanceScaleVbo = 0;
+ public int instanceColorVbo = 0;
+
+
+
+ // setters/getters //
+
+ @Override
+ public long getId() { return this.id; }
+
+ @Override
+ public void setOriginBlockPos(DhApiVec3f pos)
+ {
+ this.originBlockPos.x = pos.x;
+ this.originBlockPos.y = pos.y;
+ this.originBlockPos.z = pos.z;
+ }
+
+ @Override
+ public DhApiVec3f getOriginBlockPos() { return new DhApiVec3f(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); }
+
+
+ @Override
+ public void setSkyLight(int skyLight)
+ {
+ if (skyLight < LodUtil.MIN_MC_LIGHT || skyLight > LodUtil.MAX_MC_LIGHT)
+ {
+ throw new IllegalArgumentException("Sky light ["+skyLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
+ }
+ this.skyLight = skyLight;
+ }
+ @Override
+ public int getSkyLight() { return this.skyLight; }
+
+ @Override
+ public void setBlockLight(int blockLight)
+ {
+ if (blockLight < LodUtil.MIN_MC_LIGHT || blockLight > LodUtil.MAX_MC_LIGHT)
+ {
+ throw new IllegalArgumentException("Block light ["+blockLight+"] must be between ["+LodUtil.MIN_MC_LIGHT+"] and ["+LodUtil.MAX_MC_LIGHT+"] (inclusive).");
+ }
+ this.blockLight = blockLight;
+ }
+ @Override
+ public int getBlockLight() { return this.blockLight; }
+
+
+
+ //=============//
+ // constructor //
+ //=============//
+
+ public RenderableBoxGroup(Vec3f originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin)
+ {
+ this.id = NEXT_ID_ATOMIC_INT.getAndIncrement();
+ this.boxList = new ArrayList<>(boxList);
+
+ this.originBlockPos = originBlockPos;
+ this.positionBoxesRelativeToGroupOrigin = positionBoxesRelativeToGroupOrigin;
+ }
+
+
+
+ // methods //
+
+ @Override
+ public boolean add(DhApiRenderableBox box) { return this.boxList.add(box); }
+
+ @Override
+ public void setPreRenderFunc(Consumer func) { this.beforeRenderFunc = func; }
+
+ @Override
+ public void triggerBoxChange() { this.vertexDataDirty = true; }
+
+ @Override
+ public void setActive(boolean active) { this.active = active; }
+ @Override
+ public boolean isActive() { return this.active; }
+
+ public void preRender(DhApiRenderParam renderEventParam)
+ {
+ if (this.beforeRenderFunc != null)
+ {
+ beforeRenderFunc.accept(renderEventParam);
+ }
+ }
+
+
+
+ // overrides //
+
+ @Override
+ public DhApiRenderableBox get(int index) { return this.boxList.get(index); }
+ @Override
+ public int size() { return this.boxList.size(); }
+ @Override
+ public boolean removeIf(Predicate super DhApiRenderableBox> filter) { return this.boxList.removeIf(filter); }
+ @Override
+ public void replaceAll(UnaryOperator operator) { this.boxList.replaceAll(operator); }
+ @Override
+ public void sort(Comparator super DhApiRenderableBox> c) { this.boxList.sort(c); }
+ @Override
+ public void forEach(Consumer super DhApiRenderableBox> action) { this.boxList.forEach(action); }
+ @Override
+ public Spliterator spliterator() { return this.boxList.spliterator(); }
+ @Override
+ public Stream stream() { return this.boxList.stream(); }
+ @Override
+ public Stream parallelStream() { return this.boxList.parallelStream(); }
+
+
+
+ //===================//
+ // vertex attributes //
+ //===================//
+
+ /** Does nothing if the vertex data is already up-to-date */
+ public void updateVertexAttributeData()
+ {
+ if (!this.vertexDataDirty)
+ {
+ return;
+ }
+ this.vertexDataDirty = false;
+
+ if (this.instanceTranslationVbo == 0)
+ {
+ this.instanceTranslationVbo = GL32.glGenBuffers();
+ this.instanceScaleVbo = GL32.glGenBuffers();
+ this.instanceColorVbo = GL32.glGenBuffers();
+ }
+
+ int boxCount = this.size();
+
+
+ // transformation / scaling //
+
+ float[] translationData = new float[boxCount * 3];
+ float[] scalingData = new float[boxCount * 3];
+ for (int i = 0; i < boxCount; i++)
+ {
+ DhApiRenderableBox box = this.get(i);
+
+ int dataIndex = i * 3;
+
+ translationData[dataIndex] = box.minPos.x;
+ translationData[dataIndex + 1] = box.minPos.y;
+ translationData[dataIndex + 2] = box.minPos.z;
+
+ scalingData[dataIndex] = box.maxPos.x - box.minPos.x;
+ scalingData[dataIndex + 1] = box.maxPos.y - box.minPos.y;
+ scalingData[dataIndex + 2] = box.maxPos.z - box.minPos.z;
+
+ }
+
+
+ // colors //
+
+ float[] colorData = new float[boxCount * 4];
+ for (int i = 0; i < boxCount; i++)
+ {
+ DhApiRenderableBox box = this.get(i);
+ Color color = box.color;
+ int colorIndex = i * 4;
+ colorData[colorIndex] = color.getRed() / 255.0f;
+ colorData[colorIndex + 1] = color.getGreen() / 255.0f;
+ colorData[colorIndex + 2] = color.getBlue() / 255.0f;
+ colorData[colorIndex + 3] = color.getAlpha() / 255.0f;
+ }
+
+
+ // Upload transformation matrices
+ GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslationVbo);
+ GL32.glBufferData(GL32.GL_ARRAY_BUFFER, translationData ,GL32.GL_DYNAMIC_DRAW);
+ GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo);
+ GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW);
+
+ // Upload colors
+ GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceColorVbo);
+ GL32.glBufferData(GL32.GL_ARRAY_BUFFER, colorData, GL32.GL_DYNAMIC_DRAW);
+ }
+
+
+
+ //================//
+ // base overrides //
+ //================//
+
+ @Override
+ public String toString() { return "ID:["+this.id+"], pos:["+this.originBlockPos.x+","+this.originBlockPos.y+","+this.originBlockPos.z+"], size:["+this.size()+"], active:["+this.active+"]"; }
+
+ @Override
+ public void close()
+ {
+ GLProxy.getInstance().queueRunningOnRenderThread(() ->
+ {
+ if (this.instanceTranslationVbo != 0)
+ {
+ GL32.glDeleteBuffers(this.instanceTranslationVbo);
+ this.instanceTranslationVbo = 0;
+ }
+
+ if (this.instanceScaleVbo != 0)
+ {
+ GL32.glDeleteBuffers(this.instanceScaleVbo);
+ this.instanceScaleVbo = 0;
+ }
+
+ if (this.instanceColorVbo != 0)
+ {
+ GL32.glDeleteBuffers(this.instanceColorVbo);
+ this.instanceColorVbo = 0;
+ }
+ });
+ }
+
+ }
+
\ No newline at end of file
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java b/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java
index d7855be30..bc23212f7 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/world/DhApiWorldProxy.java
@@ -50,10 +50,18 @@ public class DhApiWorldProxy implements IDhApiWorldProxy
+ //=============//
+ // constructor //
+ //=============//
+
private DhApiWorldProxy() { }
+ //=========//
+ // methods //
+ //=========//
+
@Override
public boolean worldLoaded() { return SharedApi.getAbstractDhWorld() != null; }
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java
index 9aef5d00c..17a49bc82 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/world/IClientLevelWrapper.java
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.core.wrapperInterfaces.world;
+import com.seibel.distanthorizons.core.level.DhClientLevel;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
import org.jetbrains.annotations.Nullable;
@@ -41,4 +42,6 @@ public interface IClientLevelWrapper extends ILevelWrapper
@Nullable
IBiomeWrapper getPlainsBiomeWrapper();
+ void setParentClientLevel(DhClientLevel parentClientLevel);
+
}
diff --git a/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java b/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java
index 187a86c41..b297fa03a 100644
--- a/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java
+++ b/core/src/test/java/testItems/worldGeneratorInjection/objects/LevelWrapperTest.java
@@ -20,6 +20,7 @@
package testItems.worldGeneratorInjection.objects;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
+import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiDimensionTypeWrapper;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
@@ -52,4 +53,9 @@ public class LevelWrapperTest implements IDhApiLevelWrapper
@Override
public int getMinHeight() { return IDhApiLevelWrapper.super.getMinHeight(); }
+ @Override
+ public IDhApiCustomRenderRegister getRenderRegister() { return null; }
+
+
+
}