From 61eaf43ba0ece93bb9c61d8f7fa842ceb4c3ae78 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Tue, 14 Apr 2026 20:35:38 -0500 Subject: [PATCH] Add DhApiBlockColorOverrideEvent --- .../DhApiBlockColorOverrideEvent.java | 148 ++++++++++++++++++ .../DhApiBlockStateWrapperCreatedEvent.java | 18 ++- .../coreapi}/util/ColorUtil.java | 12 +- .../render/bufferBuilding/ColumnBox.java | 2 +- .../ColumnRenderBufferBuilder.java | 2 +- .../render/bufferBuilding/LodQuadBuilder.java | 2 +- .../FullDataToRenderDataTransformer.java | 1 + .../distanthorizons/core/util/LodUtil.java | 1 + .../core/util/RenderDataPointUtil.java | 1 + .../block/IBlockStateWrapper.java | 6 + 10 files changed, 184 insertions(+), 9 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockColorOverrideEvent.java rename {core/src/main/java/com/seibel/distanthorizons/core => api/src/main/java/com/seibel/distanthorizons/coreapi}/util/ColorUtil.java (95%) 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 new file mode 100644 index 000000000..742919e2b --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockColorOverrideEvent.java @@ -0,0 +1,148 @@ +/* + * 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 . + */ + +package com.seibel.distanthorizons.api.methods.events.abstractEvents; + +import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; +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.coreapi.util.ColorUtil; + +import java.awt.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Performance note: this event will be fired thousands of times on concurrent threads, + * make it thread safe and as fast as possible.

+ * + * 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 + * the color itself (using the base color, tinting, etc.).
+ * Using this event will override the tinting config for this block + * unless you re-implement that logic yourself. + *

+ * + * This event will only trigger for {@link IDhApiBlockStateWrapper}s that have been registered + * via {@link DhApiBlockStateWrapperCreatedEvent.EventParam#setAllowApiColorOverride(boolean)}. + * + * @author James Seibel + * @version 2026-04-14 + * @since API 6.0.0 + * @see IDhApiBlockStateWrapper + */ +public abstract class DhApiBlockColorOverrideEvent implements IDhApiEvent +{ + public abstract void blockStateWrapperCreated(DhApiEventParam event); + + + //=========================// + // internal DH API methods // + //=========================// + + @Override + public final void fireEvent(DhApiEventParam event) { this.blockStateWrapperCreated(event); } + + + //==================// + // parameter object // + //==================// + + public static class EventParam implements IDhApiEventParam + { + private IDhApiLevelWrapper levelWrapper; + private IDhApiBlockStateWrapper blockStateWrapper = null; + private int colorAsInt = -1; + private int blockPosX = 0, blockPosY = 0, blockPosZ = 0; + + + + //=============// + // constructor // + //=============// + + public EventParam() {} + + public void update( + IDhApiLevelWrapper levelWrapper, + IDhApiBlockStateWrapper blockStateWrapper, + int colorAsInt, + int blockPosX, int blockPosY, int blockPosZ) + { + this.levelWrapper = levelWrapper; + this.blockStateWrapper = blockStateWrapper; + this.colorAsInt = colorAsInt; + + this.blockPosX = blockPosX; + this.blockPosY = blockPosY; + this.blockPosZ = blockPosZ; + } + + + + //=================// + // getters/setters // + //=================// + + public IDhApiBlockStateWrapper getBlockStateWrapper() { return this.blockStateWrapper; } + + public IDhApiLevelWrapper getLevelWrapper() { return levelWrapper; } + + public int getColorAsInt() { return this.colorAsInt; } + public int getRed() { return ColorUtil.getRed(this.colorAsInt); } + public int getGreen() { return ColorUtil.getGreen(this.colorAsInt); } + public int getBlue() { return ColorUtil.getBlue(this.colorAsInt); } + public void setColor(int red, int green, int blue) throws IllegalArgumentException + { + ColorUtil.throwIfColorValueOutOfIntRange("red", red); + ColorUtil.throwIfColorValueOutOfIntRange("green", green); + ColorUtil.throwIfColorValueOutOfIntRange("blue", blue); + + this.colorAsInt = ColorUtil.rgbToInt(red, green, blue); + } + + /** @return the block's X value in the world */ + public int getBlockPosX() { return blockPosX; } + /** @return the block's Y value in the world */ + public int getBlockPosY() { return blockPosY; } + /** @return the block's Z value in the world */ + public int getBlockPosZ() { return blockPosZ; } + + + + /** + * Returns the same instance of this event. + * Copying this event isn't supported + * since the internal parameters must be mutated + * by API users in order to be tracked by DH's internal + * logic. + */ + @Override + public EventParam copy() { return this; } + + @Override + public boolean getCopyBeforeFire() { return false; } + + + + } + +} \ No newline at end of file diff --git a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockStateWrapperCreatedEvent.java b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockStateWrapperCreatedEvent.java index 8b0953019..c5de74b30 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockStateWrapperCreatedEvent.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/methods/events/abstractEvents/DhApiBlockStateWrapperCreatedEvent.java @@ -61,11 +61,12 @@ public abstract class DhApiBlockStateWrapperCreatedEvent implements IDhApiEvent< * Note: modifying this object won't change anything * a new wrapper will be created after this event finishes. */ - public final IDhApiBlockStateWrapper blockStateWrapper; + private final IDhApiBlockStateWrapper blockStateWrapper; private boolean overridesSet = false; private EDhApiBlockMaterial blockMaterial = null; private Integer opacity = null; + private Boolean allowApiColorOverride = null; @@ -73,10 +74,7 @@ public abstract class DhApiBlockStateWrapperCreatedEvent implements IDhApiEvent< // constructor // //=============// - public EventParam(IDhApiBlockStateWrapper blockStateWrapper) - { - this.blockStateWrapper = blockStateWrapper; - } + public EventParam(IDhApiBlockStateWrapper blockStateWrapper) { this.blockStateWrapper = blockStateWrapper; } @@ -84,6 +82,8 @@ public abstract class DhApiBlockStateWrapperCreatedEvent implements IDhApiEvent< // getters/setters // //=================// + public IDhApiBlockStateWrapper getBlockStateWrapper() { return this.blockStateWrapper; } + /** if set this will override the value currently set in the given {@link IDhApiBlockStateWrapper} */ public void setBlockMaterial(EDhApiBlockMaterial blockMaterial) { @@ -100,6 +100,14 @@ public abstract class DhApiBlockStateWrapperCreatedEvent implements IDhApiEvent< } public Integer getOpacity() { return this.opacity; } + /** if set to true this {@link IDhApiBlockStateWrapper} will trigger {@link DhApiBlockColorOverrideEvent} */ + public void setAllowApiColorOverride(boolean allowApiColorOverride) + { + this.allowApiColorOverride = allowApiColorOverride; + this.overridesSet = true; + } + public Boolean getAllowApiColorOverride() { return this.allowApiColorOverride; } + /** If true then one or more options for this block were set to be changed */ public boolean getOverridesSet() { return this.overridesSet; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/ColorUtil.java similarity index 95% rename from core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java rename to api/src/main/java/com/seibel/distanthorizons/coreapi/util/ColorUtil.java index 8f5479401..b46910349 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/ColorUtil.java +++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/util/ColorUtil.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.seibel.distanthorizons.core.util; +package com.seibel.distanthorizons.coreapi.util; import java.awt.*; @@ -89,6 +89,16 @@ public class ColorUtil /** @param newBlue should be a value between 0 and 255 */ public static int setBlue(int color, int newBlue) { return (getAlpha(color) << 24) | (getRed(color) << 16) | (getGreen(color) << 8) | newBlue; } + /** @throws IllegalArgumentException if the given int value is out of the range 0 - 255 (exclusive) */ + public static void throwIfColorValueOutOfIntRange(String colorName, int value) throws IllegalArgumentException + { + if (value < 0 + || value > 255) + { + throw new IllegalArgumentException("["+colorName+"] with the value ["+value+"] is out of the expected range 0 - 255 (exclusive)."); + } + } + public static int applyShade(int color, int shade) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java index 726880feb..cfa0082e2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnBox.java @@ -24,7 +24,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.level.IDhClientLevel; import com.seibel.distanthorizons.core.util.objects.pooling.PhantomArrayListCheckout; -import com.seibel.distanthorizons.core.util.ColorUtil; +import com.seibel.distanthorizons.coreapi.util.ColorUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RenderDataPointUtil; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnRenderView; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java index 686262d33..3f4fe08a2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java @@ -31,7 +31,7 @@ import com.seibel.distanthorizons.core.util.objects.pooling.PhantomArrayListChec import com.seibel.distanthorizons.core.util.objects.pooling.PhantomArrayListPool; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; -import com.seibel.distanthorizons.core.util.ColorUtil; +import com.seibel.distanthorizons.coreapi.util.ColorUtil; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.RenderDataPointUtil; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnRenderView; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java index 61450859b..f97f67da3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/LodQuadBuilder.java @@ -30,7 +30,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.logging.DhLogger; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; -import com.seibel.distanthorizons.core.util.ColorUtil; +import com.seibel.distanthorizons.coreapi.util.ColorUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import org.lwjgl.system.MemoryUtil; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java index 12157e112..3af137531 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java @@ -37,6 +37,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrappe import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; +import com.seibel.distanthorizons.coreapi.util.ColorUtil; import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import com.seibel.distanthorizons.core.logging.DhLogger; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java index 5554fc005..a18e89549 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java @@ -22,6 +22,7 @@ package com.seibel.distanthorizons.core.util; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.logging.DhLogger; +import com.seibel.distanthorizons.coreapi.util.ColorUtil; /** * This class holds methods and constants that may be used in multiple places. diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java index 0d7bac19b..3b91954da 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java @@ -24,6 +24,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.core.logging.DhLogger; +import com.seibel.distanthorizons.coreapi.util.ColorUtil; /** diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java index d9caddb31..4cc97245c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/block/IBlockStateWrapper.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.block; import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBlockColorOverrideEvent; import com.seibel.distanthorizons.core.util.LodUtil; import java.awt.*; @@ -59,6 +60,11 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper * IE Iron, diamond, gold, etc. */ boolean isBeaconBaseBlock(); + /** + * if true this block can have its color overridden + * by {@link DhApiBlockColorOverrideEvent} + */ + boolean allowApiColorOverride(); Color getMapColor(); Color getBeaconTintColor();