aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java32
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipEvents.java4
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/mixin/ScreenMixin.java166
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/mixin/TooltipRenderUtilMixin.java120
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/renderer/CheckedBufferSource.java68
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/renderer/CustomItemRenderer.java656
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/renderer/VertexCollector.java79
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/DynamicResourcePack.java59
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/GuiHelper.java5
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/Selectors.java97
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java286
-rw-r--r--src/main/resources/fabric.mod.json4
-rw-r--r--src/main/resources/iceberg.accesswidener9
-rw-r--r--src/main/resources/iceberg.mixins.json5
14 files changed, 1339 insertions, 251 deletions
diff --git a/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java b/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java
index 8218f71..8e3c31b 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java
@@ -1,12 +1,26 @@
package com.anthonyhilyard.iceberg;
+import java.util.List;
+
+import com.anthonyhilyard.iceberg.events.RenderTooltipEvents;
+import com.anthonyhilyard.iceberg.events.RenderTooltipEvents.GatherResult;
+import com.anthonyhilyard.iceberg.util.Tooltips.TitleBreakComponent;
+import com.mojang.datafixers.util.Either;
+
import net.fabricmc.api.ClientModInitializer;
+import net.minecraft.network.chat.FormattedText;
+import net.minecraft.world.InteractionResult;
+import net.minecraft.world.inventory.tooltip.TooltipComponent;
+import net.minecraft.world.item.ItemStack;
public class IcebergClient implements ClientModInitializer
{
@Override
public void onInitializeClient()
{
+ TitleBreakComponent.registerFactory();
+ RenderTooltipEvents.GATHER.register(IcebergClient::onGatherComponentsEventEnd);
+
// Event testing.
// CriterionCallback.EVENT.register((player, advancement, criterion) -> { Loader.LOGGER.info("CriterionCallback: {}, {}, {}", player.getName().getString(), advancement.getId().toString(), criterion); });
// NewItemPickupCallback.EVENT.register((uuid, itemStack) -> { Loader.LOGGER.info("NewItemPickupCallback: {}, {}", uuid.toString(), itemStack.getDisplayName().getString()); });
@@ -23,4 +37,22 @@ public class IcebergClient implements ClientModInitializer
// Loader.LOGGER.info("RenderTooltipEvents.POST: {}, {}, {}, {}, {}, {}, {}, {}, {}", stack.getDisplayName().getString(), components.stream().map(Object::toString).collect(Collectors.joining()), poseStack, x, y, font, width, height, comparison);
// });
}
+
+ public static GatherResult onGatherComponentsEventEnd(ItemStack itemStack, int screenWidth, int screenHeight, List<Either<FormattedText, TooltipComponent>> tooltipElements, int maxWidth, int index)
+ {
+ if (tooltipElements.size() > 1)
+ {
+ // Insert a title break component after the first formattedText component.
+ for (int i = 0; i < tooltipElements.size(); i++)
+ {
+ if (tooltipElements.get(i).left().isPresent())
+ {
+ tooltipElements.add(i + 1, Either.<FormattedText, TooltipComponent>right(new TitleBreakComponent()));
+ break;
+ }
+ }
+ }
+
+ return new GatherResult(InteractionResult.PASS, maxWidth, tooltipElements);
+ }
}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipEvents.java b/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipEvents.java
index 622d3e0..c5a10a8 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipEvents.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipEvents.java
@@ -23,7 +23,7 @@ public final class RenderTooltipEvents
GatherResult result = new GatherResult(InteractionResult.PASS, maxWidth, tooltipElements);
for (RenderTooltipEvents.Gather callback : callbacks)
{
- result = callback.onGather(itemStack, screenWidth, screenHeight, tooltipElements, maxWidth, index);
+ result = callback.onGather(itemStack, screenWidth, screenHeight, result.tooltipElements, result.maxWidth, index);
if (result.result != InteractionResult.PASS)
{
@@ -38,7 +38,7 @@ public final class RenderTooltipEvents
PreExtResult result = new PreExtResult(InteractionResult.PASS, x, y, screenWidth, screenHeight, font);
for (RenderTooltipEvents.PreExt callback : callbacks)
{
- result = callback.onPre(stack, components, poseStack, x, y, screenWidth, screenHeight, font, comparison, index);
+ result = callback.onPre(stack, components, poseStack, result.x, result.y, screenWidth, screenHeight, result.font, comparison, index);
if (result.result != InteractionResult.PASS)
{
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/ScreenMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/ScreenMixin.java
index a797c9f..bc3674f 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/mixin/ScreenMixin.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/ScreenMixin.java
@@ -9,16 +9,12 @@ import com.anthonyhilyard.iceberg.events.RenderTooltipEvents.ColorResult;
import com.anthonyhilyard.iceberg.events.RenderTooltipEvents.PreExtResult;
import com.anthonyhilyard.iceberg.util.Tooltips;
import com.google.common.collect.Lists;
-import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.PoseStack;
-import com.mojang.blaze3d.vertex.Tesselator;
-import com.mojang.math.Matrix4f;
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.Redirect;
import org.spongepowered.asm.mixin.injection.At.Shift;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@@ -29,9 +25,11 @@ import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
+import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner;
+import net.minecraft.client.gui.screens.inventory.tooltip.TooltipRenderUtil;
+import net.minecraft.network.chat.TextColor;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionResult;
-import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
import net.minecraft.world.item.ItemStack;
@@ -60,12 +58,24 @@ public class ScreenMixin extends AbstractContainerEventHandler
}
@Inject(method = "renderTooltip(Lcom/mojang/blaze3d/vertex/PoseStack;Ljava/util/List;Ljava/util/Optional;II)V",
- at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;renderTooltipInternal(Lcom/mojang/blaze3d/vertex/PoseStack;Ljava/util/List;II)V"),
- locals = LocalCapture.CAPTURE_FAILEXCEPTION)
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;renderTooltipInternal(Lcom/mojang/blaze3d/vertex/PoseStack;Ljava/util/List;IILnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;)V",
+ shift = Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
public void renderTooltip(PoseStack poseStack, List<Component> textComponents, Optional<TooltipComponent> itemComponent, int x, int y, CallbackInfo info, List<ClientTooltipComponent> components)
{
Screen self = (Screen)(Object)this;
+ if (self instanceof AbstractContainerScreen<?> containerScreen)
+ {
+ Slot hoveredSlot = containerScreen.hoveredSlot;
+
+ // If the tooltip stack is empty, try to get the stack from the slot under the mouse.
+ // This is needed for the creative inventory screen, which doesn't set the tooltip stack.
+ if (tooltipStack.isEmpty() && hoveredSlot != null)
+ {
+ tooltipStack = hoveredSlot.getItem();
+ }
+ }
+
List<ClientTooltipComponent> newComponents = Tooltips.gatherTooltipComponents(tooltipStack, textComponents, itemComponent, x, self.width, self.height, null, font, -1);
if (newComponents != null && !newComponents.isEmpty())
{
@@ -74,93 +84,65 @@ public class ScreenMixin extends AbstractContainerEventHandler
}
}
- @SuppressWarnings({"unchecked", "deprecation"})
+ @SuppressWarnings("deprecation")
@Inject(method = "renderTooltipInternal", at = @At(value = "HEAD"), cancellable = true)
- private void preRenderTooltipInternal(PoseStack poseStack, List<ClientTooltipComponent> components, int x, int y, CallbackInfo info)
+ private void preRenderTooltipInternal(PoseStack poseStack, List<ClientTooltipComponent> components, int x, int y, ClientTooltipPositioner positioner, CallbackInfo info)
{
- PreExtResult eventResult = null;
Screen self = (Screen)(Object)this;
- if (self instanceof AbstractContainerScreen)
+
+ if (!components.isEmpty())
{
- if (!components.isEmpty())
+ PreExtResult eventResult = null;
+ InteractionResult result = InteractionResult.PASS;
+
+ eventResult = RenderTooltipEvents.PREEXT.invoker().onPre(tooltipStack, components, poseStack, x, y, self.width, self.height, font, false, 0);
+ result = eventResult.result();
+
+ if (result != InteractionResult.PASS)
{
- Slot hoveredSlot = ((AbstractContainerScreen<AbstractContainerMenu>)self).hoveredSlot;
- if (hoveredSlot != null)
- {
- ItemStack tooltipStack = hoveredSlot.getItem();
- InteractionResult result = InteractionResult.PASS;
- eventResult = RenderTooltipEvents.PREEXT.invoker().onPre(tooltipStack, components, poseStack, x, y, self.width, self.height, font, false, 0);
- result = eventResult.result();
-
- if (result != InteractionResult.PASS)
- {
- info.cancel();
- }
-
- // Fire a pre event as well for compatibility.
- result = RenderTooltipEvents.PRE.invoker().onPre(tooltipStack, components, poseStack, x, y, self.width, self.height, -1, font, false);
- if (result != InteractionResult.PASS)
- {
- info.cancel();
- }
- }
+ info.cancel();
}
- }
- }
- @SuppressWarnings("unchecked")
- @Redirect(method = "renderTooltipInternal", at = @At(value = "INVOKE",
- target = "Lnet/minecraft/client/gui/screens/Screen;fillGradient(Lcom/mojang/math/Matrix4f;Lcom/mojang/blaze3d/vertex/BufferBuilder;IIIIIII)V"))
- private void fillGradientProxy(Matrix4f matrix4f, BufferBuilder bufferBuilder, int left, int top, int right, int bottom, int zIndex, int colorStart, int colorEnd)
- {
- Screen self = (Screen)(Object)this;
- ItemStack tooltipStack = ItemStack.EMPTY;
- if (self instanceof AbstractContainerScreen)
- {
- Slot hoveredSlot = ((AbstractContainerScreen<AbstractContainerMenu>)self).hoveredSlot;
-
- if (hoveredSlot != null)
+ // Fire a pre event as well for compatibility.
+ result = RenderTooltipEvents.PRE.invoker().onPre(tooltipStack, components, poseStack, x, y, self.width, self.height, -1, font, false);
+ if (result != InteractionResult.PASS)
{
- tooltipStack = hoveredSlot.getItem();
+ info.cancel();
}
}
- if (tooltipStack == ItemStack.EMPTY)
- {
- // Do standard functionality if this isn't a container screen.
- Screen.fillGradient(matrix4f, bufferBuilder, left, top, right, bottom, zIndex, colorStart, colorEnd);
- }
- else
- {
- // Otherwise do nothing to disable the default calls.
- }
}
- @SuppressWarnings({"unchecked", "deprecation"})
- @Inject(method = "renderTooltipInternal", at = @At(value = "INVOKE",
- target = "Lnet/minecraft/client/gui/screens/Screen;fillGradient(Lcom/mojang/math/Matrix4f;Lcom/mojang/blaze3d/vertex/BufferBuilder;IIIIIII)V", ordinal = 0, shift = Shift.BEFORE),
- locals = LocalCapture.CAPTURE_FAILEXCEPTION)
- private void preFillGradient(PoseStack poseStack, List<ClientTooltipComponent> components, int x, int y, CallbackInfo info,
- int __, int ___, int left, int top, int width, int height, int background, int borderStart, int borderEnd,
- int zIndex, float blitOffset, Tesselator tesselator, BufferBuilder bufferBuilder, Matrix4f matrix4f)
+ @SuppressWarnings("deprecation")
+ @Inject(method = "renderTooltipInternal",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil;renderTooltipBackground(Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil$BlitPainter;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/vertex/BufferBuilder;IIIII)V",
+ ordinal = 0, shift = Shift.BEFORE))
+ private void preFillGradient(PoseStack poseStack, List<ClientTooltipComponent> components, int x, int y, ClientTooltipPositioner positioner, CallbackInfo info)
{
Screen self = (Screen)(Object)this;
- ItemStack tooltipStack = ItemStack.EMPTY;
- if (self instanceof AbstractContainerScreen)
+ ItemStack containerStack = ItemStack.EMPTY;
+ if (self instanceof AbstractContainerScreen<?> containerScreen)
{
- Slot hoveredSlot = ((AbstractContainerScreen<AbstractContainerMenu>)self).hoveredSlot;
-
+ Slot hoveredSlot = containerScreen.hoveredSlot;
if (hoveredSlot != null)
{
- tooltipStack = hoveredSlot.getItem();
+ containerStack = hoveredSlot.getItem();
}
}
- if (tooltipStack != ItemStack.EMPTY)
+ if (containerStack.isEmpty())
{
+ containerStack = tooltipStack;
+ }
+
+ if (!containerStack.isEmpty())
+ {
+ int background = TooltipRenderUtil.BACKGROUND_COLOR;
int backgroundEnd = background;
+ int borderStart = TooltipRenderUtil.BORDER_COLOR_TOP;
+ int borderEnd = TooltipRenderUtil.BORDER_COLOR_BOTTOM;
// Do colors now, sure why not.
- ColorExtResult result = RenderTooltipEvents.COLOREXT.invoker().onColor(tooltipStack, components, poseStack, x, y, font, background, backgroundEnd, borderStart, borderEnd, false, 0);
+ ColorExtResult result = RenderTooltipEvents.COLOREXT.invoker().onColor(containerStack, components, poseStack, x, y, font, background, backgroundEnd, borderStart, borderEnd, false, 0);
if (result != null)
{
background = result.backgroundStart();
@@ -170,7 +152,7 @@ public class ScreenMixin extends AbstractContainerEventHandler
}
// Fire a colors event as well for compatibility.
- ColorResult colorResult = RenderTooltipEvents.COLOR.invoker().onColor(tooltipStack, components, poseStack, x, y, font, background, borderStart, borderEnd, false);
+ ColorResult colorResult = RenderTooltipEvents.COLOR.invoker().onColor(containerStack, components, poseStack, x, y, font, background, borderStart, borderEnd, false);
if (colorResult != null)
{
background = colorResult.background();
@@ -178,35 +160,37 @@ public class ScreenMixin extends AbstractContainerEventHandler
borderEnd = colorResult.borderEnd();
}
- Screen.fillGradient(matrix4f, bufferBuilder, left - 3, top - 4, left + width + 3, top - 3, zIndex, background, background);
- Screen.fillGradient(matrix4f, bufferBuilder, left - 3, top + height + 3, left + width + 3, top + height + 4, zIndex, backgroundEnd, backgroundEnd);
- Screen.fillGradient(matrix4f, bufferBuilder, left - 3, top - 3, left + width + 3, top + height + 3, zIndex, background, backgroundEnd);
- Screen.fillGradient(matrix4f, bufferBuilder, left - 4, top - 3, left - 3, top + height + 3, zIndex, background, backgroundEnd);
- Screen.fillGradient(matrix4f, bufferBuilder, left + width + 3, top - 3, left + width + 4, top + height + 3, zIndex, background, backgroundEnd);
- Screen.fillGradient(matrix4f, bufferBuilder, left - 3, top - 3 + 1, left - 3 + 1, top + height + 3 - 1, zIndex, borderStart, borderEnd);
- Screen.fillGradient(matrix4f, bufferBuilder, left + width + 2, top - 3 + 1, left + width + 3, top + height + 3 - 1, zIndex, borderStart, borderEnd);
- Screen.fillGradient(matrix4f, bufferBuilder, left - 3, top - 3, left + width + 3, top - 3 + 1, zIndex, borderStart, borderStart);
- Screen.fillGradient(matrix4f, bufferBuilder, left - 3, top + height + 2, left + width + 3, top + height + 3, zIndex, borderEnd, borderEnd);
+ Tooltips.currentColors = new Tooltips.TooltipColors(TextColor.fromRgb(background), TextColor.fromRgb(backgroundEnd), TextColor.fromRgb(borderStart), TextColor.fromRgb(borderEnd));
}
}
- @SuppressWarnings({"unchecked", "deprecation"})
+ @SuppressWarnings("deprecation")
@Inject(method = "renderTooltipInternal", at = @At(value = "TAIL"), locals = LocalCapture.CAPTURE_FAILEXCEPTION)
- private void renderTooltipInternal(PoseStack poseStack, List<ClientTooltipComponent> components, int x, int y, CallbackInfo info, int tooltipWidth, int tooltipHeight, int postX, int postY)
+ private void renderTooltipInternal(PoseStack poseStack, List<ClientTooltipComponent> components, int x, int y, ClientTooltipPositioner positioner, CallbackInfo info, int tooltipWidth, int tooltipHeight, int postX, int postY)
{
- if ((Screen)(Object)this instanceof AbstractContainerScreen)
+ Screen self = (Screen)(Object)this;
+ ItemStack containerStack = ItemStack.EMPTY;
+ if (self instanceof AbstractContainerScreen<?> containerScreen)
{
- if (!components.isEmpty())
+ Slot hoveredSlot = containerScreen.hoveredSlot;
+ if (hoveredSlot != null)
{
- Slot hoveredSlot = ((AbstractContainerScreen<AbstractContainerMenu>)(Object)this).hoveredSlot;
- if (hoveredSlot != null)
- {
- ItemStack tooltipStack = hoveredSlot.getItem();
- RenderTooltipEvents.POSTEXT.invoker().onPost(tooltipStack, components, poseStack, postX, postY, font, tooltipWidth, tooltipHeight, false, 0);
- RenderTooltipEvents.POST.invoker().onPost(tooltipStack, components, poseStack, postX, postY, font, tooltipWidth, tooltipHeight, false);
- }
+ containerStack = hoveredSlot.getItem();
}
}
+
+ if (containerStack.isEmpty())
+ {
+ containerStack = tooltipStack;
+ }
+
+ if (!containerStack.isEmpty() && !components.isEmpty())
+ {
+ RenderTooltipEvents.POSTEXT.invoker().onPost(containerStack, components, poseStack, postX, postY, font, tooltipWidth, tooltipHeight, false, 0);
+ RenderTooltipEvents.POST.invoker().onPost(containerStack, components, poseStack, postX, postY, font, tooltipWidth, tooltipHeight, false);
+ }
+
+ tooltipStack = ItemStack.EMPTY;
}
@Override
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/TooltipRenderUtilMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/TooltipRenderUtilMixin.java
new file mode 100644
index 0000000..18ef9e4
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/TooltipRenderUtilMixin.java
@@ -0,0 +1,120 @@
+package com.anthonyhilyard.iceberg.mixin;
+
+import org.joml.Matrix4f;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import com.anthonyhilyard.iceberg.util.Tooltips;
+import com.mojang.blaze3d.vertex.BufferBuilder;
+
+import net.minecraft.client.gui.screens.inventory.tooltip.TooltipRenderUtil;
+import net.minecraft.network.chat.TextColor;
+
+@Mixin(TooltipRenderUtil.class)
+public class TooltipRenderUtilMixin
+{
+ @Unique
+ private static TextColor horizontalLineColor;
+
+ @Shadow
+ @Final
+ private static int BACKGROUND_COLOR;
+
+ @Shadow
+ @Final
+ private static int BORDER_COLOR_TOP;
+
+ @Shadow
+ @Final
+ private static int BORDER_COLOR_BOTTOM;
+
+ @Inject(method = "renderTooltipBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil;renderHorizontalLine(Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil$BlitPainter;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/vertex/BufferBuilder;IIIII)V", shift = At.Shift.BEFORE, ordinal = 0))
+ private static void icebergRenderTooltipBackgroundOne(TooltipRenderUtil.BlitPainter painter, Matrix4f matrix, BufferBuilder bufferbuilder, int x, int y, int width, int height, int z, CallbackInfo info)
+ {
+ horizontalLineColor = Tooltips.currentColors.backgroundColorStart();
+ }
+
+ @Inject(method = "renderTooltipBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil;renderHorizontalLine(Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil$BlitPainter;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/vertex/BufferBuilder;IIIII)V", shift = At.Shift.BEFORE, ordinal = 1))
+ private static void icebergRenderTooltipBackgroundTwo(TooltipRenderUtil.BlitPainter painter, Matrix4f matrix, BufferBuilder bufferbuilder, int x, int y, int width, int height, int z, CallbackInfo info)
+ {
+ horizontalLineColor = Tooltips.currentColors.backgroundColorEnd();
+ }
+
+ @Inject(method = "renderFrameGradient", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil;renderHorizontalLine(Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil$BlitPainter;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/vertex/BufferBuilder;IIIII)V", shift = At.Shift.BEFORE, ordinal = 0))
+ private static void icebergRenderFrameGradientOne(TooltipRenderUtil.BlitPainter painter, Matrix4f matrix, BufferBuilder bufferbuilder, int x, int y, int width, int height, int z, int color1, int color2, CallbackInfo info)
+ {
+ horizontalLineColor = Tooltips.currentColors.borderColorStart();
+ }
+
+ @Inject(method = "renderFrameGradient", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil;renderHorizontalLine(Lnet/minecraft/client/gui/screens/inventory/tooltip/TooltipRenderUtil$BlitPainter;Lorg/joml/Matrix4f;Lcom/mojang/blaze3d/vertex/BufferBuilder;IIIII)V", shift = At.Shift.BEFORE, ordinal = 1))
+ private static void icebergRenderFrameGradientTwo(TooltipRenderUtil.BlitPainter painter, Matrix4f matrix, BufferBuilder bufferbuilder, int x, int y, int width, int height, int z, int color1, int color2, CallbackInfo info)
+ {
+ horizontalLineColor = Tooltips.currentColors.borderColorEnd();
+ }
+
+ @Inject(method = "renderHorizontalLine", at = @At(value = "HEAD"), cancellable = true)
+ private static void icebergRenderHorizontalLine(TooltipRenderUtil.BlitPainter painter, Matrix4f matrix, BufferBuilder bufferbuilder, int x, int y, int width, int z, int color, CallbackInfo info)
+ {
+ if (color != BACKGROUND_COLOR && color != BORDER_COLOR_TOP && color != BORDER_COLOR_BOTTOM)
+ {
+ // Do default behavior so other mods that change colors can still work.
+ }
+ else
+ {
+ // Replace the rendered colors with the ones previously stored.
+ int renderColor = horizontalLineColor.getValue();
+ painter.blit(matrix, bufferbuilder, x, y, x + width, y + 1, z, renderColor, renderColor);
+ info.cancel();
+ }
+ }
+
+ @Inject(method = "renderRectangle", at = @At(value = "HEAD"), cancellable = true)
+ private static void icebergRenderRectangle(TooltipRenderUtil.BlitPainter painter, Matrix4f matrix, BufferBuilder bufferbuilder, int x, int y, int width, int height, int z, int color, CallbackInfo info)
+ {
+ if (color != BACKGROUND_COLOR)
+ {
+ // Do default behavior so other mods that change colors can still work.
+ }
+ else
+ {
+ // Replace the rendered colors with the ones previously stored.
+ painter.blit(matrix, bufferbuilder, x, y, x + width, y + height, z, Tooltips.currentColors.backgroundColorStart().getValue(), Tooltips.currentColors.backgroundColorEnd().getValue());
+ info.cancel();
+ }
+ }
+
+ @Inject(method = "renderVerticalLine", at = @At(value = "HEAD"), cancellable = true)
+ private static void icebergRenderVerticalLine(TooltipRenderUtil.BlitPainter painter, Matrix4f matrix, BufferBuilder bufferbuilder, int x, int y, int height, int z, int color, CallbackInfo info)
+ {
+ if (color != BACKGROUND_COLOR)
+ {
+ // Do default behavior so other mods that change colors can still work.
+ }
+ else
+ {
+ // Replace the rendered colors with the ones previously stored.
+ painter.blit(matrix, bufferbuilder, x, y, x + 1, y + height, z, Tooltips.currentColors.backgroundColorStart().getValue(), Tooltips.currentColors.backgroundColorEnd().getValue());
+ info.cancel();
+ }
+ }
+
+ @Inject(method = "renderVerticalLineGradient", at = @At(value = "HEAD"), cancellable = true)
+ private static void icebergRenderVerticalLineGradient(TooltipRenderUtil.BlitPainter painter, Matrix4f matrix, BufferBuilder bufferbuilder, int x, int y, int height, int z, int startColor, int endColor, CallbackInfo info)
+ {
+ if (startColor != BORDER_COLOR_TOP || endColor != BORDER_COLOR_BOTTOM)
+ {
+ // Do default behavior so other mods that change colors can still work.
+ }
+ else
+ {
+ // Replace the rendered colors with the ones previously stored.
+ painter.blit(matrix, bufferbuilder, x, y, x + 1, y + height, z, Tooltips.currentColors.borderColorStart().getValue(), Tooltips.currentColors.borderColorEnd().getValue());
+ info.cancel();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/anthonyhilyard/iceberg/renderer/CheckedBufferSource.java b/src/main/java/com/anthonyhilyard/iceberg/renderer/CheckedBufferSource.java
new file mode 100644
index 0000000..b8f5fde
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/renderer/CheckedBufferSource.java
@@ -0,0 +1,68 @@
+package com.anthonyhilyard.iceberg.renderer;
+
+import com.mojang.blaze3d.vertex.VertexConsumer;
+
+import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.client.renderer.RenderType;
+
+public final class CheckedBufferSource implements MultiBufferSource
+{
+ private boolean hasRendered = false;
+ private final MultiBufferSource bufferSource;
+
+ public CheckedBufferSource(MultiBufferSource bufferSource)
+ {
+ this.bufferSource = bufferSource;
+ }
+
+ @Override
+ public VertexConsumer getBuffer(RenderType renderType)
+ {
+ final VertexConsumer vertexConsumer = bufferSource.getBuffer(renderType);
+ VertexConsumer vertexConsumerWrap = new VertexConsumer()
+ {
+ @Override
+ public VertexConsumer vertex(double x, double y, double z)
+ {
+ hasRendered = true;
+ return vertexConsumer.vertex(x, y, z);
+ }
+
+ @Override
+ public VertexConsumer color(int r, int g, int b, int a) { return vertexConsumer.color(r, g, b, a); }
+
+ @Override
+ public VertexConsumer uv(float u, float v) { return vertexConsumer.uv(u, v); }
+
+ @Override
+ public VertexConsumer overlayCoords(int x, int y) { return vertexConsumer.overlayCoords(x, y); }
+
+ @Override
+ public VertexConsumer uv2(int u, int v) { return vertexConsumer.uv2(u, v); }
+
+ @Override
+ public VertexConsumer normal(float x, float y, float z) { return vertexConsumer.normal(x, y, z); }
+
+ @Override
+ public void endVertex() { vertexConsumer.endVertex(); }
+
+ @Override
+ public void defaultColor(int r, int g, int b, int a) { vertexConsumer.defaultColor(r, g, b, a); }
+
+ @Override
+ public void unsetDefaultColor() { vertexConsumer.unsetDefaultColor(); }
+ };
+
+ return vertexConsumerWrap;
+ }
+
+ public boolean hasRendered()
+ {
+ return hasRendered;
+ }
+
+ public void reset()
+ {
+ hasRendered = false;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/anthonyhilyard/iceberg/renderer/CustomItemRenderer.java b/src/main/java/com/anthonyhilyard/iceberg/renderer/CustomItemRenderer.java
index b77bb09..c3cc4b5 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/renderer/CustomItemRenderer.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/renderer/CustomItemRenderer.java
@@ -1,50 +1,122 @@
package com.anthonyhilyard.iceberg.renderer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+
+import com.google.common.collect.Maps;
+
+import org.joml.Matrix4f;
+import org.joml.Quaternionf;
+import org.joml.Vector3f;
+
+import org.lwjgl.opengl.GL11;
+
import com.mojang.blaze3d.vertex.PoseStack;
+import com.mojang.blaze3d.vertex.VertexConsumer;
+import com.mojang.datafixers.util.Pair;
+import com.mojang.math.MatrixUtil;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.pipeline.MainTarget;
import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.Lighting;
+import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
+import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.lwjgl.opengl.GL11;
-
+import net.minecraft.CrashReport;
+import net.minecraft.CrashReportCategory;
+import net.minecraft.ReportedException;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.texture.TextureManager;
-
-import com.mojang.blaze3d.platform.GlStateManager.SourceFactor;
-import com.mojang.blaze3d.platform.GlStateManager.DestFactor;
-import com.mojang.math.Matrix4f;
-
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
+import net.minecraft.client.renderer.ItemBlockRenderTypes;
+import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.client.renderer.MultiBufferSource.BufferSource;
import net.minecraft.client.renderer.block.model.ItemTransforms;
+import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType;
+import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelManager;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.server.packs.resources.ReloadableResourceManager;
+import net.minecraft.server.packs.resources.ResourceManager;
+import net.minecraft.tags.ItemTags;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.entity.EquipmentSlot;
+import net.minecraft.world.entity.animal.horse.Horse;
+import net.minecraft.world.entity.decoration.ArmorStand;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.entity.vehicle.AbstractMinecart;
+import net.minecraft.world.entity.vehicle.Boat;
+import net.minecraft.world.entity.vehicle.ChestBoat;
import net.minecraft.world.inventory.InventoryMenu;
+import net.minecraft.world.item.BlockItem;
+import net.minecraft.world.item.BoatItem;
+import net.minecraft.world.item.HorseArmorItem;
+import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.Items;
+import net.minecraft.world.item.MinecartItem;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.EntityBlock;
+import net.minecraft.world.level.block.HalfTransparentBlock;
+import net.minecraft.world.level.block.StainedGlassPaneBlock;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.block.state.properties.BlockStateProperties;
+import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
+
/**
- * An extended ItemRenderer that allows items to be rendered to RenderTarget before drawing to screen.
- * This allows alpha values to be supported properly by all item types, even semi-transparent items.
+ * An extended ItemRenderer with extended functionality, such as allowing items to be rendered to a RenderTarget
+ * before drawing to screen for alpha support, and allowing handheld item models to be rendered into the gui.
*/
public class CustomItemRenderer extends ItemRenderer
{
- @SuppressWarnings("unused")
- private static final Logger LOGGER = LogManager.getLogger();
+ /* Cylindrical bounds for a model. */
+ private record ModelBounds(Vector3f center, float height, float radius) {}
private static RenderTarget iconFrameBuffer = null;
+ private static ArmorStand armorStand = null;
+ private static AbstractMinecart minecart = null;
+ private static Boat boat = null;
+ private static Horse horse = null;
+ private static Pair<Item, CompoundTag> cachedArmorStandItem = null;
+ private static Pair<Item, CompoundTag> cachedHorseArmorItem = null;
+ private static Map<Item, ModelBounds> modelBoundsCache = Maps.newHashMap();
+
+ private static final List<Direction> quadDirections;
+ static {
+ quadDirections = new ArrayList<>(Arrays.asList(Direction.values()));
+ quadDirections.add(null);
+ }
+
private Minecraft mc;
-
+ private final ModelManager modelManager;
+ private final BlockEntityWithoutLevelRenderer blockEntityRenderer;
+
public CustomItemRenderer(TextureManager textureManagerIn, ModelManager modelManagerIn, ItemColors itemColorsIn, BlockEntityWithoutLevelRenderer blockEntityRendererIn, Minecraft mcIn)
{
super(textureManagerIn, modelManagerIn, itemColorsIn, blockEntityRendererIn);
mc = mcIn;
+ modelManager = modelManagerIn;
+ blockEntityRenderer = blockEntityRendererIn;
+ if (mc.getResourceManager() instanceof ReloadableResourceManager resourceManager)
+ {
+ resourceManager.registerReloadListener(this);
+ }
// Initialize the icon framebuffer if needed.
if (iconFrameBuffer == null)
@@ -56,6 +128,515 @@ public class CustomItemRenderer extends ItemRenderer
}
}
+ private void renderGuiModel(ItemStack itemStack, int x, int y, Quaternionf rotation, BakedModel bakedModel)
+ {
+ mc.getTextureManager().getTexture(InventoryMenu.BLOCK_ATLAS).setFilter(false, false);
+ RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS);
+ RenderSystem.enableBlend();
+ RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
+ RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
+
+ PoseStack modelViewStack = RenderSystem.getModelViewStack();
+ modelViewStack.pushPose();
+ modelViewStack.translate(x, y, 100.0f + blitOffset);
+
+ modelViewStack.translate(8.0f, 8.0f, 0.0f);
+ modelViewStack.scale(1.0f, -1.0f, 1.0f);
+ modelViewStack.scale(16.0f, 16.0f, 16.0f);
+ RenderSystem.applyModelViewMatrix();
+
+ BufferSource bufferSource = Minecraft.getInstance().renderBuffers().bufferSource();
+ boolean flatLighting = !bakedModel.usesBlockLight();
+ if (flatLighting) { Lighting.setupForFlatItems(); }
+
+ PoseStack poseStack = new PoseStack();
+ renderModel(itemStack, ItemTransforms.TransformType.GUI, false, poseStack, rotation, bufferSource, LightTexture.FULL_BRIGHT, OverlayTexture.NO_OVERLAY, bakedModel);
+
+ poseStack.popPose();
+ bufferSource.endBatch();
+ RenderSystem.enableDepthTest();
+ if (flatLighting) { Lighting.setupFor3DItems(); }
+
+ modelViewStack.popPose();
+ RenderSystem.applyModelViewMatrix();
+ }
+
+ @SuppressWarnings("deprecation")
+ private void renderEntityModel(Entity entity, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight)
+ {
+ Minecraft minecraft = Minecraft.getInstance();
+ EntityRenderDispatcher entityRenderDispatcher = minecraft.getEntityRenderDispatcher();
+ Lighting.setupForEntityInInventory();
+ RenderSystem.enableDepthTest();
+ RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
+ entityRenderDispatcher.setRenderShadow(false);
+
+ RenderSystem.runAsFancy(() -> entityRenderDispatcher.render(entity, 0.0, 0.0, 0.0, 0.0f, 1.0f, poseStack, bufferSource, packedLight));
+
+ if (bufferSource instanceof BufferSource)
+ {
+ ((BufferSource)bufferSource).endBatch();
+ }
+
+ entityRenderDispatcher.setRenderShadow(true);
+
+ RenderSystem.applyModelViewM