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 4d8b478f8..90bc2c5b8 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,8 +21,14 @@ 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.block.IDhApiBiomeWrapper; +import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBlockColorOverrideEvent; +import com.seibel.distanthorizons.api.objects.DhApiResult; +import com.seibel.distanthorizons.api.objects.data.IDhApiFullDataSource; +import java.awt.*; import java.io.File; /** @@ -90,6 +96,26 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper */ File getDhSaveFolder(); + /** + * Returns the color DH would use for the given block/biome + * pair at the given world position before any API color overrides + * are considered.
+ * API color overrides are ignored to prevent infinite + * loops if this event is triggered inside said API override. + *

+ * + * Returns {@link DhApiResult#success} = false if {@link IDhApiLevelWrapper#getLevelType()} returns a {@link EDhApiLevelType#SERVER_LEVEL} + * (server levels have no concept of textures or colors). + * + * @see DhApiBlockColorOverrideEvent + * @since API 7.0.0 + */ + DhApiResult getBlockColorPreApi( + IDhApiBlockStateWrapper blockStateWrapper, + IDhApiBiomeWrapper biomeWrapper, + int blockWorldPosX, int blockWorldPosY, int blockWorldPosZ, + IDhApiFullDataSource dataSource); + } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockColorOverrideEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockColorOverrideEvent.java index 4258e65d4..8b28c6254 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockColorOverrideEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockColorOverrideEvent.java @@ -19,16 +19,21 @@ package com.seibel.distanthorizons.api.methods.events.abstractEvents; +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.methods.events.interfaces.IDhApiEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; +import com.seibel.distanthorizons.api.objects.data.IDhApiFullDataSource; import com.seibel.distanthorizons.coreapi.util.ColorUtil; /** - * Performance note: this event will be fired thousands of times on concurrent threads, - * make it thread safe and as fast as possible.

+ * Performance note: this event will be fired millions of times on concurrent threads, + * make it thread safe and as fast as possible.
+ * (If every LOD block goes through this event, On a 512 render distance world, + * at the medium quality preset, it will be triggered around 40,000,000 times.) + *

* * This event is fired when DH needs to convert a {@link IDhApiBlockStateWrapper} * into a color for rendering. This event is fired after DH attempts to determine @@ -41,7 +46,7 @@ import com.seibel.distanthorizons.coreapi.util.ColorUtil; * via {@link DhApiBlockStateWrapperCreatedEvent.EventParam#setAllowApiColorOverride(boolean)}. * * @author James Seibel - * @version 2026-04-14 + * @version 2026-05-18 * @since API 6.0.0 * @see IDhApiBlockStateWrapper */ @@ -50,6 +55,7 @@ public abstract class DhApiBlockColorOverrideEvent implements IDhApiEvent event); + //=========================// // internal DH API methods // //=========================// @@ -58,6 +64,7 @@ public abstract class DhApiBlockColorOverrideEvent implements IDhApiEvent event) { this.onBlockColorOverridden(event); } + //==================// // parameter object // //==================// @@ -65,7 +72,9 @@ public abstract class DhApiBlockColorOverrideEvent implements IDhApiEvent - // these constructors are private because the create... methods below are easier to understand + // these constructors are private because the create methods below are easier to understand private DhApiResult(boolean success, String message) { this(success, message, null); } private DhApiResult(boolean success, String message, T payload) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java index 7b23d02e7..c871a2bae 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/data/DhApiTerrainDataRepo.java @@ -19,12 +19,15 @@ package com.seibel.distanthorizons.core.api.external.methods.data; +import com.seibel.distanthorizons.api.interfaces.block.IDhApiBiomeWrapper; +import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataCache; import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; import com.seibel.distanthorizons.api.objects.DhApiResult; import com.seibel.distanthorizons.api.objects.data.DhApiRaycastResult; import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint; import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataRepo; +import com.seibel.distanthorizons.api.objects.data.IDhApiFullDataSource; import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; import com.seibel.distanthorizons.core.api.internal.SharedApi; import com.seibel.distanthorizons.core.dataObjects.fullData.FullDataPointIdMap; @@ -34,6 +37,8 @@ import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; +import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos; +import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable; import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer; import com.seibel.distanthorizons.core.util.DhApiTerrainDataPointUtil; import com.seibel.distanthorizons.core.util.FullDataPointUtil; @@ -42,12 +47,16 @@ import com.seibel.distanthorizons.core.util.RayCastUtil; import com.seibel.distanthorizons.core.util.math.Vec3f; import com.seibel.distanthorizons.core.world.AbstractDhWorld; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; +import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3i; +import com.seibel.distanthorizons.coreapi.util.ColorUtil; import it.unimi.dsi.fastutil.longs.LongArrayList; import com.seibel.distanthorizons.core.logging.DhLogger; import org.jetbrains.annotations.Nullable; @@ -78,17 +87,21 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo //=============// // constructor // //=============// + //region private DhApiTerrainDataRepo() { } + //endregion + //================// // Getter Methods // //================// + //region @Override public DhApiResult getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ, IDhApiTerrainDataCache dataCache) @@ -109,9 +122,12 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo public DhApiResult getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ, IDhApiTerrainDataCache dataCache) { return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, DhSectionPos.encode(detailLevel, posX, posZ), dataCache); } + //endregion + // private getters // + //region /** Returns a single API terrain datapoint that contains the given Y block position */ private static DhApiResult getTerrainDataAtBlockYPos(IDhApiLevelWrapper levelWrapper, long requestedColumnPos, Integer blockYPos, IDhApiTerrainDataCache dataCache) @@ -340,11 +356,14 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo } } + //endregion + //====================// // raycasting methods // //====================// + //region @Override public DhApiResult raycast( @@ -490,11 +509,14 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo return returnList; } + //endregion + //================// // setter methods // //================// + //region @Override public DhApiResult overwriteChunkDataAsync(IDhApiLevelWrapper levelWrapper, Object[] chunkObjectArray) throws ClassCastException @@ -524,20 +546,26 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo return DhApiResult.createSuccess(); } + //endregion + //=============// // API helpers // //=============// + //region @Override public IDhApiTerrainDataCache createSoftCache() { return new DhApiTerrainDataCache(); } + //endregion + //===============// // debug methods // //===============// + //region /** * This method is here for debugging the repo and isn't intended for normal use. @@ -618,5 +646,8 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo } } + //endregion + + } 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 e0bc88e0b..3e69a5aa3 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 @@ -32,7 +32,9 @@ public interface IClientLevelWrapper extends ILevelWrapper @Nullable IServerLevelWrapper tryGetServerSideWrapper(); - int getBlockColor(DhBlockPos pos, IBiomeWrapper biome, FullDataSourceV2 fullDataSource, IBlockStateWrapper blockState); + default int getBlockColor(DhBlockPos pos, IBiomeWrapper biome, FullDataSourceV2 fullDataSource, IBlockStateWrapper blockState) + { return this.getBlockColor(pos, biome, fullDataSource, blockState, true); } + int getBlockColor(DhBlockPos pos, IBiomeWrapper biome, FullDataSourceV2 fullDataSource, IBlockStateWrapper blockState, boolean allowApiOverride); /** @return -1 if there was a problem getting the color */ int getDirtBlockColor(); void clearBlockColorCache();