Add DhApiBlockColorOverrideEvent

This commit is contained in:
James Seibel
2026-04-14 20:35:38 -05:00
parent 1d368e3adc
commit 61eaf43ba0
10 changed files with 184 additions and 9 deletions
@@ -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 <https://www.gnu.org/licenses/>.
*/
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. <Br><Br>
*
* 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.). <Br>
* Using this event will override the tinting config for this block
* unless you re-implement that logic yourself.
* <Br><Br>
*
* 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<DhApiBlockColorOverrideEvent.EventParam>
{
public abstract void blockStateWrapperCreated(DhApiEventParam<EventParam> event);
//=========================//
// internal DH API methods //
//=========================//
@Override
public final void fireEvent(DhApiEventParam<EventParam> 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; }
}
}
@@ -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; }
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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)
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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.
@@ -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;
/**
@@ -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();