aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/anthonyhilyard
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/anthonyhilyard')
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java26
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/IcebergServer.java19
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/Loader.java70
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/events/CriterionEvent.java38
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvent.java57
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/mixin/EntityMixin.java66
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/mixin/PlayerAdvancementsMixin.java31
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/renderer/CustomItemRenderer.java129
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/Easing.java107
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/ItemColor.java38
10 files changed, 581 insertions, 0 deletions
diff --git a/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java b/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java
new file mode 100644
index 0000000..3a860a2
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java
@@ -0,0 +1,26 @@
+package com.anthonyhilyard.iceberg;
+
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
+import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
+
+@Mod.EventBusSubscriber(modid = Loader.MODID, bus = Bus.MOD, value = Dist.CLIENT)
+public class IcebergClient
+{
+ public IcebergClient()
+ {
+ }
+
+ public void onClientSetup(FMLClientSetupEvent event)
+ {
+ event.enqueueWork(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+
+ }
+ });
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/IcebergServer.java b/src/main/java/com/anthonyhilyard/iceberg/IcebergServer.java
new file mode 100644
index 0000000..c5baa64
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/IcebergServer.java
@@ -0,0 +1,19 @@
+package com.anthonyhilyard.iceberg;
+
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
+import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
+
+@Mod.EventBusSubscriber(modid = Loader.MODID, bus = Bus.MOD, value = Dist.DEDICATED_SERVER)
+public class IcebergServer
+{
+ public IcebergServer()
+ {
+ }
+
+ public void onServerStarting(FMLServerStartingEvent event)
+ {
+
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/Loader.java b/src/main/java/com/anthonyhilyard/iceberg/Loader.java
new file mode 100644
index 0000000..b41595f
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/Loader.java
@@ -0,0 +1,70 @@
+package com.anthonyhilyard.iceberg;
+
+import com.anthonyhilyard.iceberg.events.CriterionEvent;
+import com.anthonyhilyard.iceberg.events.EntityFluidEvent;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import net.minecraftforge.api.distmarker.Dist;
+import net.minecraftforge.eventbus.api.SubscribeEvent;
+import net.minecraftforge.fml.ExtensionPoint;
+import net.minecraftforge.fml.ModLoadingContext;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
+import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
+import net.minecraftforge.fml.loading.FMLEnvironment;
+import net.minecraftforge.fml.network.FMLNetworkConstants;
+
+@Mod(Loader.MODID)
+public class Loader
+{
+ public static final String MODID = "iceberg";
+ public static final Logger LOGGER = LogManager.getLogger(MODID);
+
+ public Loader()
+ {
+ if (FMLEnvironment.dist == Dist.CLIENT)
+ {
+ IcebergClient mod = new IcebergClient();
+ FMLJavaModLoadingContext.get().getModEventBus().addListener(mod::onClientSetup);
+ }
+ else
+ {
+ new IcebergServer();
+ }
+ ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true));
+ }
+
+ @SubscribeEvent
+ public void onCommonSetup(FMLCommonSetupEvent event)
+ {
+
+ }
+
+ // Event testing.
+ //
+ // @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.FORGE)
+ // public static class AdvancementEvents
+ // {
+ // @SubscribeEvent
+ // public static void onCriterion(final CriterionEvent event)
+ // {
+ // LOGGER.info("{} gained {} for {}!", event.getPlayer().getName().getString(), event.getCriterionKey(), event.getAdvancement().getId().toString());
+ // }
+
+ // @SubscribeEvent
+ // public static void onFluidEntered(final EntityFluidEvent.Entered event)
+ // {
+ // LOGGER.info("{} entered {}!", event.getEntity().getName().getString(), event.getFluid().getRegistryName().toString());
+ // }
+
+ // @SubscribeEvent
+ // public static void onFluidExited(final EntityFluidEvent.Exited event)
+ // {
+ // LOGGER.info("{} exited {}!", event.getEntity().getName().getString(), event.getFluid().getRegistryName().toString());
+ // }
+ // }
+
+} \ No newline at end of file
diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/CriterionEvent.java b/src/main/java/com/anthonyhilyard/iceberg/events/CriterionEvent.java
new file mode 100644
index 0000000..8148b9b
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/events/CriterionEvent.java
@@ -0,0 +1,38 @@
+package com.anthonyhilyard.iceberg.events;
+
+import net.minecraftforge.event.entity.player.AdvancementEvent;
+import net.minecraft.advancements.Advancement;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraftforge.common.MinecraftForge;
+
+/**
+ * This event is fired when a player is granted an advancement criterion.
+ * <br>
+ * This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.<br>
+ * <br>
+ * This event does not have a result. {@link HasResult}<br>
+ * <br>
+ * This event is fired on the {@link MinecraftForge#EVENT_BUS}.
+ */
+public class CriterionEvent extends AdvancementEvent
+{
+ private final Advancement advancement;
+ private final String criterionKey;
+
+ public CriterionEvent(PlayerEntity player, Advancement advancement, String criterionKey)
+ {
+ super(player, advancement);
+ this.advancement = advancement;
+ this.criterionKey = criterionKey;
+ }
+
+ public Advancement getAdvancement()
+ {
+ return advancement;
+ }
+
+ public String getCriterionKey()
+ {
+ return criterionKey;
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvent.java b/src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvent.java
new file mode 100644
index 0000000..aa91fa5
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvent.java
@@ -0,0 +1,57 @@
+package com.anthonyhilyard.iceberg.events;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.fluid.Fluid;
+import net.minecraftforge.event.entity.EntityEvent;
+
+public class EntityFluidEvent extends EntityEvent
+{
+ private final Fluid fluid;
+
+ private EntityFluidEvent(Entity entity, Fluid fluid)
+ {
+ super(entity);
+ this.fluid = fluid;
+ }
+
+ public Fluid getFluid()
+ {
+ return fluid;
+ }
+
+ /**
+ * This event is fired when an entity enters a fluid to at least eye-level.
+ * If this is a player, they will see the "submerged in fluid" effect at this point.
+ * <br>
+ * This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.<br>
+ * <br>
+ * This event does not have a result. {@link HasResult}<br>
+ * <br>
+ * This event is fired on the {@link MinecraftForge#EVENT_BUS}.
+ */
+ public static class Entered extends EntityFluidEvent
+ {
+ public Entered(Entity entity, Fluid fluid)
+ {
+ super(entity, fluid);
+ }
+ }
+
+ /**
+ * This event is fired when an entity was previously submerged in a fluid to at least eye-level and no longer are.
+ * If this is a player, they will no longer see the "submerged in fluid" effect at this point.
+ * <br>
+ * This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.<br>
+ * <br>
+ * This event does not have a result. {@link HasResult}<br>
+ * <br>
+ * This event is fired on the {@link MinecraftForge#EVENT_BUS}.
+ */
+ public static class Exited extends EntityFluidEvent
+ {
+ public Exited(Entity entity, Fluid fluid)
+ {
+ super(entity, fluid);
+ }
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/EntityMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/EntityMixin.java
new file mode 100644
index 0000000..f4ca091
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/EntityMixin.java
@@ -0,0 +1,66 @@
+package com.anthonyhilyard.iceberg.mixin;
+
+import java.util.Objects;
+
+import com.anthonyhilyard.iceberg.events.EntityFluidEvent;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.At.Shift;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import net.minecraft.entity.Entity;
+import net.minecraft.fluid.Fluid;
+import net.minecraft.tags.ITag;
+import net.minecraftforge.common.MinecraftForge;
+
+@Mixin(Entity.class)
+public class EntityMixin extends net.minecraftforge.common.capabilities.CapabilityProvider<Entity>
+{
+ private Fluid previousFluidOnEyes = null;
+
+ @Shadow
+ protected ITag<Fluid> fluidOnEyes;
+
+ protected EntityMixin(Class<Entity> baseClass) { super(baseClass); }
+
+ @Inject(method = "updateFluidOnEyes", at = @At(value = "RETURN"))
+ public void onUpdateFluidOnEyes(CallbackInfo callbackInfo)
+ {
+ if (fluidOnEyes != null && fluidOnEyes.getValues().size() > 0)
+ {
+ previousFluidOnEyes = fluidOnEyes.getValues().get(0);
+ }
+ else if (previousFluidOnEyes != null)
+ {
+ // We were submerged in a fluid that we no longer are.
+ if (previousFluidOnEyes != null)
+ {
+ MinecraftForge.EVENT_BUS.post(new EntityFluidEvent.Exited((Entity)(Object)this, previousFluidOnEyes));
+ }
+ previousFluidOnEyes = null;
+ }
+ }
+
+ @Inject(method = "updateFluidOnEyes",
+ at = @At(value = "FIELD", target = "Lnet/minecraft/entity/Entity;fluidOnEyes:Lnet/minecraft/tags/ITag;", ordinal = 1, shift = Shift.AFTER))
+ public void onUpdateFluidOnEyeAssign(CallbackInfo callbackInfo)
+ {
+ Fluid currentFluid = null;
+ if (fluidOnEyes != null && fluidOnEyes.getValues().size() > 0)
+ {
+ currentFluid = fluidOnEyes.getValues().get(0);
+ }
+
+ if (!Objects.equals(previousFluidOnEyes, currentFluid))
+ {
+ // We are now submerged in a fluid that doesn't match the previous one.
+ if (currentFluid != null)
+ {
+ MinecraftForge.EVENT_BUS.post(new EntityFluidEvent.Entered((Entity)(Object)this, currentFluid));
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/PlayerAdvancementsMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/PlayerAdvancementsMixin.java
new file mode 100644
index 0000000..b27b219
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/PlayerAdvancementsMixin.java
@@ -0,0 +1,31 @@
+package com.anthonyhilyard.iceberg.mixin;
+
+import com.anthonyhilyard.iceberg.events.CriterionEvent;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
+
+import net.minecraft.advancements.Advancement;
+import net.minecraft.advancements.PlayerAdvancements;
+import net.minecraft.entity.player.ServerPlayerEntity;
+import net.minecraftforge.common.MinecraftForge;
+
+@Mixin(PlayerAdvancements.class)
+public class PlayerAdvancementsMixin
+{
+ @Shadow
+ private ServerPlayerEntity player;
+
+ @Inject(method = "award", at = @At(value = "TAIL"), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
+ public void onAward(Advancement advancement, String criterionKey, CallbackInfoReturnable<Boolean> callbackInfo, boolean success)
+ {
+ if (success)
+ {
+ MinecraftForge.EVENT_BUS.post(new CriterionEvent(player, advancement, criterionKey));
+ }
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/renderer/CustomItemRenderer.java b/src/main/java/com/anthonyhilyard/iceberg/renderer/CustomItemRenderer.java
new file mode 100644
index 0000000..29ce7d0
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/renderer/CustomItemRenderer.java
@@ -0,0 +1,129 @@
+package com.anthonyhilyard.iceberg.renderer;
+
+import com.mojang.blaze3d.matrix.MatrixStack;
+import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
+import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
+import com.mojang.blaze3d.systems.RenderSystem;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.lwjgl.opengl.GL11;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.AbstractGui;
+import net.minecraft.client.renderer.IRenderTypeBuffer;
+import net.minecraft.client.renderer.ItemRenderer;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.client.renderer.color.ItemColors;
+import net.minecraft.client.renderer.model.IBakedModel;
+import net.minecraft.client.renderer.model.ItemCameraTransforms;
+import net.minecraft.client.renderer.model.ModelManager;
+import net.minecraft.client.renderer.texture.AtlasTexture;
+import net.minecraft.client.renderer.texture.OverlayTexture;
+import net.minecraft.client.renderer.texture.TextureManager;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.item.ItemStack;
+
+/**
+ * An extended ItemRenderer that allows items to be rendered to framebuffer before drawing to screen.
+ * This allows alpha values to be supported properly by all item types, even semi-transparent items.
+ */
+public class CustomItemRenderer extends ItemRenderer
+{
+ @SuppressWarnings("unused")
+ private static final Logger LOGGER = LogManager.getLogger();
+
+ private static Framebuffer iconFrameBuffer = null;
+ private Minecraft mc;
+
+ public CustomItemRenderer(TextureManager textureManagerIn, ModelManager modelManagerIn, ItemColors itemColorsIn, Minecraft mcIn)
+ {
+ super(textureManagerIn, modelManagerIn, itemColorsIn);
+ mc = mcIn;
+
+ // Initialize the icon framebuffer if needed.
+ if (iconFrameBuffer == null)
+ {
+ // Use 96 x 96 pixels for the icon frame buffer so at 1.5 scale we get 4x resolution (for smooth icons on larger gui scales).
+ iconFrameBuffer = new Framebuffer(96, 96, true, Minecraft.ON_OSX);
+ iconFrameBuffer.setClearColor(0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void renderItemModelIntoGUIWithAlpha(ItemStack stack, int x, int y, float alpha)
+ {
+ IBakedModel bakedModel = mc.getItemRenderer().getModel(stack, null, null);
+ Framebuffer lastFrameBuffer = mc.getMainRenderTarget();
+
+ // Bind the icon framebuffer so we can render to texture.
+ iconFrameBuffer.clear(Minecraft.ON_OSX);
+ iconFrameBuffer.bindWrite(true);
+
+ RenderSystem.clear(GL11.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX);
+ RenderSystem.matrixMode(GL11.GL_PROJECTION);
+ RenderSystem.pushMatrix();
+ RenderSystem.loadIdentity();
+ RenderSystem.ortho(0.0D, iconFrameBuffer.width, iconFrameBuffer.height, 0.0D, 1000.0D, 3000.0D);
+ RenderSystem.matrixMode(GL11.GL_MODELVIEW);
+ RenderSystem.pushMatrix();
+ RenderSystem.loadIdentity();
+ RenderSystem.translatef(0.0F, 0.0F, -2000.0F);
+ RenderHelper.setupFor3DItems();
+
+ mc.getTextureManager().bind(AtlasTexture.LOCATION_BLOCKS);
+ mc.getTextureManager().getTexture(AtlasTexture.LOCATION_BLOCKS).setFilter(false, false);
+ RenderSystem.enableRescaleNormal();
+ RenderSystem.enableAlphaTest();
+ RenderSystem.defaultAlphaFunc();
+ RenderSystem.enableBlend();
+ RenderSystem.blendFuncSeparate(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ONE_MINUS_SRC_ALPHA);
+ RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
+ RenderSystem.translatef(48.0f, 48.0f, 150.0f + this.blitOffset);
+ RenderSystem.scalef(1.0f, -1.0f, 1.0f);
+ RenderSystem.scalef(96.0f, 96.0f, 96.0f);
+ MatrixStack matrixStack = new MatrixStack();
+ IRenderTypeBuffer.Impl renderBuffer = Minecraft.getInstance().renderBuffers().bufferSource();
+ boolean isSideLit = !bakedModel.usesBlockLight();
+ if (isSideLit)
+ {
+ RenderHelper.setupForFlatItems();
+ }
+
+ render(stack, ItemCameraTransforms.TransformType.GUI, false, matrixStack, renderBuffer, 0xF000F0, OverlayTexture.NO_OVERLAY, bakedModel);
+ renderBuffer.endBatch();
+ RenderSystem.enableDepthTest();
+ if (isSideLit)
+ {
+ RenderHelper.setupFor3DItems();
+ }
+
+ RenderSystem.disableRescaleNormal();
+ RenderSystem.popMatrix();
+ RenderSystem.matrixMode(GL11.GL_PROJECTION);
+ RenderSystem.popMatrix();
+ RenderSystem.matrixMode(GL11.GL_MODELVIEW);
+
+ // Rebind the previous framebuffer, if there was one.
+ if (lastFrameBuffer != null)
+ {
+ lastFrameBuffer.bindWrite(true);
+
+ // Blit from the texture we just rendered to, respecting the alpha value given.
+ iconFrameBuffer.bindRead();
+ RenderSystem.enableAlphaTest();
+ RenderSystem.enableBlend();
+ RenderSystem.defaultBlendFunc();
+ RenderSystem.defaultAlphaFunc();
+ RenderSystem.disableCull();
+ RenderSystem.color4f(1.0f, 1.0f, 1.0f, alpha);
+ RenderSystem.scalef(1.0f, -1.0f, 1.0f);
+
+ AbstractGui.blit(new MatrixStack(), x, y - 18, 16, 16, 0, 0, iconFrameBuffer.width, iconFrameBuffer.height, iconFrameBuffer.width, iconFrameBuffer.height);
+ }
+ else
+ {
+ iconFrameBuffer.unbindWrite();
+ }
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/Easing.java b/src/main/java/com/anthonyhilyard/iceberg/util/Easing.java
new file mode 100644
index 0000000..da41927
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/util/Easing.java
@@ -0,0 +1,107 @@
+package com.anthonyhilyard.iceberg.util;
+
+/**
+ * Helper functions for smooth easing/interpolation. If you need linear, use net.minecraft.util.math.MathHelper.lerp instead.
+ */
+public final class Easing
+{
+ public static enum EasingType
+ {
+ None, // Produces step-wise interpolation.
+ Quad,
+ Cubic
+ }
+
+ public static enum EasingDirection
+ {
+ In,
+ Out,
+ InOut
+ }
+
+ public static float Ease(float a, float b, float t)
+ {
+ return Ease(a, b, t, EasingType.Quad);
+ }
+
+ public static float Ease(float a, float b, float t, EasingType type)
+ {
+ return Ease(a, b, t, type, EasingDirection.InOut);
+ }
+
+ public static float Ease(float a, float b, float t, EasingType type, EasingDirection direction)
+ {
+ switch (type)
+ {
+ case None:
+ default:
+ return None(a, b, t);
+ case Quad:
+ return Quad(a, b, t, direction);
+ case Cubic:
+ return Cubic(a, b, t, direction);
+ }
+ }
+
+ private static float None(float a, float b, float t)
+ {
+ if (t < 0.5f)
+ {
+ return a;
+ }
+ else
+ {
+ return b;
+ }
+ }
+
+ private static float Quad(float a, float b, float t, EasingDirection direction)
+ {
+ switch (direction)
+ {
+ case In:
+ return a + (b - a) * t * t;
+ case Out:
+ return a + (b - a) * (1.0f - (1.0f - t) * (1.0f - t));
+ case InOut:
+ default:
+ {
+ t *= 2.0f;
+ if (t < 1.0f)
+ {
+ return a + (b - a) * 0.5f * t * t;
+ }
+ else
+ {
+ t -= 2.0f;
+ return a + (a - b) * 0.5f * (t * t - 2.0f);
+ }
+ }
+ }
+ }
+
+ private static float Cubic(float a, float b, float t, EasingDirection direction)
+ {
+ switch (direction)
+ {
+ case In:
+ return a + (b - a) * t * t * t;
+ case Out:
+ return a + (b - a) * (1.0f - (1.0f - t) * (1.0f - t) * (1.0f - t));
+ case InOut:
+ default:
+ {
+ t *= 2.0f;
+ if (t < 1.0f)
+ {
+ return a + (b - a) * 0.5f * t * t * t;
+ }
+ else
+ {
+ t -= 2.0f;
+ return a + (b - a) * 0.5f * (t * t * t + 2.0f);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/ItemColor.java b/src/main/java/com/anthonyhilyard/iceberg/util/ItemColor.java
new file mode 100644
index 0000000..a4625aa
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/util/ItemColor.java
@@ -0,0 +1,38 @@
+package com.anthonyhilyard.iceberg.util;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.text.Color;
+
+public class ItemColor
+{
+ public static Color getColorForItem(ItemStack item, Color defaultColor)
+ {
+ Color result = null;
+
+ // Color based on rarity value.
+ result = item.getDisplayName().getStyle().getColor();
+
+ // Some mods override the getName() method of the Item class, so grab that color if it's there.
+ if (item.getItem() != null &&
+ item.getItem().getName(item) != null &&
+ item.getItem().getName(item).getStyle() != null &&
+ item.getItem().getName(item).getStyle().getColor() != null)
+ {
+ result = item.getItem().getName(item).getStyle().getColor();
+ }
+
+ // Finally, if the item has a special hover name color (Stored in NBT), use that.
+ if (!item.getHoverName().getStyle().isEmpty() && item.getHoverName().getStyle().getColor() != null)
+ {
+ result = item.getHoverName().getStyle().getColor();
+ }
+
+ // Fallback to the default color if we somehow haven't found a single valid color.
+ if (result == null)
+ {
+ result = defaultColor;
+ }
+
+ return result;
+ }
+}