aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/Loader.java6
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupEvent.java41
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeEventFactoryMixin.java31
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/network/IcebergNetworkProtocol.java30
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/network/NewItemPickupEventPacket.java45
-rw-r--r--src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java207
-rw-r--r--src/main/resources/iceberg.mixins.json7
7 files changed, 365 insertions, 2 deletions
diff --git a/src/main/java/com/anthonyhilyard/iceberg/Loader.java b/src/main/java/com/anthonyhilyard/iceberg/Loader.java
index b1ff65a..38aa9c1 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/Loader.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/Loader.java
@@ -1,5 +1,7 @@
package com.anthonyhilyard.iceberg;
+import com.anthonyhilyard.iceberg.network.IcebergNetworkProtocol;
+
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -31,6 +33,10 @@ public class Loader
{
new IcebergServer();
}
+
+ // Register the network protocol.
+ IcebergNetworkProtocol.register();
+
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true));
}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupEvent.java b/src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupEvent.java
new file mode 100644
index 0000000..a758769
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupEvent.java
@@ -0,0 +1,41 @@
+package com.anthonyhilyard.iceberg.events;
+
+import net.minecraftforge.event.entity.player.PlayerEvent;
+
+import java.util.UUID;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.MinecraftForge;
+
+/**
+ * This event is fired right before a player picks up a new item. Unlike EntityItemPickupEvent, this event fires on the logical client.
+ * <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 NewItemPickupEvent extends PlayerEvent
+{
+ private final ItemStack itemStack;
+
+ public NewItemPickupEvent(PlayerEntity player, ItemStack itemStack)
+ {
+ super(player);
+ this.itemStack = itemStack;
+ }
+
+ @SuppressWarnings("resource")
+ public NewItemPickupEvent(UUID playerUUID, ItemStack itemStack)
+ {
+ this(Minecraft.getInstance().level.getPlayerByUUID(playerUUID), itemStack);
+ }
+
+ public ItemStack getItemStack()
+ {
+ return itemStack;
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeEventFactoryMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeEventFactoryMixin.java
new file mode 100644
index 0000000..a530465
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeEventFactoryMixin.java
@@ -0,0 +1,31 @@
+package com.anthonyhilyard.iceberg.mixin;
+
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import net.minecraft.entity.item.ItemEntity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.entity.player.ServerPlayerEntity;
+import net.minecraftforge.event.ForgeEventFactory;
+import net.minecraftforge.fml.loading.FMLEnvironment;
+import net.minecraftforge.fml.network.PacketDistributor;
+
+import com.anthonyhilyard.iceberg.network.IcebergNetworkProtocol;
+import com.anthonyhilyard.iceberg.network.NewItemPickupEventPacket;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(ForgeEventFactory.class)
+public class ForgeEventFactoryMixin
+{
+ @Inject(method = { "onItemPickup(Lnet/minecraft/entity/item/ItemEntity;Lnet/minecraft/entity/player/PlayerEntity;)I" },
+ at = { @At("HEAD") }, remap = false)
+ private static void onItemPickup(ItemEntity entityItem, PlayerEntity player, CallbackInfoReturnable<Integer> info)
+ {
+ if (player instanceof ServerPlayerEntity && FMLEnvironment.dist.isDedicatedServer())
+ {
+ IcebergNetworkProtocol.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity)player), new NewItemPickupEventPacket(player.getUUID(), entityItem.getItem()));
+ }
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/network/IcebergNetworkProtocol.java b/src/main/java/com/anthonyhilyard/iceberg/network/IcebergNetworkProtocol.java
new file mode 100644
index 0000000..d0dd1c8
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/network/IcebergNetworkProtocol.java
@@ -0,0 +1,30 @@
+package com.anthonyhilyard.iceberg.network;
+
+import com.anthonyhilyard.iceberg.Loader;
+
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.fml.network.NetworkRegistry;
+import net.minecraftforge.fml.network.simple.SimpleChannel;
+
+public class IcebergNetworkProtocol
+{
+ private static final String NETWORK_PROTOCOL_VERSION = "1";
+
+ public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel(
+ new ResourceLocation(Loader.MODID, "main"), () -> NETWORK_PROTOCOL_VERSION,
+ NETWORK_PROTOCOL_VERSION::equals, NETWORK_PROTOCOL_VERSION::equals
+ );
+
+ public static final void register()
+ {
+ int messageID = 0;
+
+ CHANNEL.registerMessage(
+ messageID++,
+ NewItemPickupEventPacket.class,
+ NewItemPickupEventPacket::encode,
+ NewItemPickupEventPacket::decode,
+ NewItemPickupEventPacket::handle
+ );
+ }
+}
diff --git a/src/main/java/com/anthonyhilyard/iceberg/network/NewItemPickupEventPacket.java b/src/main/java/com/anthonyhilyard/iceberg/network/NewItemPickupEventPacket.java
new file mode 100644
index 0000000..23df08b
--- /dev/null
+++ b/src/main/java/com/anthonyhilyard/iceberg/network/NewItemPickupEventPacket.java
@@ -0,0 +1,45 @@
+package com.anthonyhilyard.iceberg.network;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.network.PacketBuffer;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.fml.network.NetworkEvent;
+
+import java.util.UUID;
+import java.util.function.Supplier;
+
+import com.anthonyhilyard.iceberg.events.NewItemPickupEvent;
+
+
+public final class NewItemPickupEventPacket
+{
+ private final UUID playerUUID;
+ private final ItemStack item;
+
+ public NewItemPickupEventPacket(final UUID playerUUID, final ItemStack item)
+ {
+ this.playerUUID = playerUUID;
+ this.item = item;
+ }
+
+ public static void encode(final NewItemPickupEventPacket msg, final PacketBuffer packetBuffer)
+ {
+ packetBuffer.writeUUID(msg.playerUUID);
+ packetBuffer.writeItem(msg.item);
+ }
+
+ public static NewItemPickupEventPacket decode(final PacketBuffer packetBuffer)
+ {
+ return new NewItemPickupEventPacket(packetBuffer.readUUID(), packetBuffer.readItem());
+ }
+
+ public static void handle(final NewItemPickupEventPacket msg, final Supplier<NetworkEvent.Context> contextSupplier)
+ {
+ final NetworkEvent.Context context = contextSupplier.get();
+ context.enqueueWork(() -> {
+ MinecraftForge.EVENT_BUS.post(new NewItemPickupEvent(msg.playerUUID, msg.item));
+ });
+ context.setPacketHandled(true);
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java
index 3761fc5..69039db 100644
--- a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java
+++ b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java
@@ -3,18 +3,225 @@ package com.anthonyhilyard.iceberg.util;
import java.util.ArrayList;
import java.util.List;
+import javax.annotation.Nonnull;
+
import com.mojang.blaze3d.matrix.MatrixStack;
+import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Rectangle2d;
+import net.minecraft.client.renderer.Tessellator;
import net.minecraft.item.ItemStack;
+import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.text.ITextProperties;
+import net.minecraft.util.text.LanguageMap;
import net.minecraft.util.text.Style;
import net.minecraftforge.client.event.RenderTooltipEvent;
import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.fml.client.gui.GuiUtils;
public class Tooltips
{
+ public static class TooltipInfo
+ {
+ private int tooltipWidth = 0;
+ private int titleLines = 1;
+ private FontRenderer font;
+ private List<? extends ITextProperties> lines = new ArrayList<>();
+
+ public TooltipInfo(List<? extends ITextProperties> lines, FontRenderer font)
+ {
+ this.lines = lines;
+ this.font = font;
+ }
+
+ public int getTooltipWidth() { return tooltipWidth; }
+ public int getTitleLines() { return titleLines; }
+ public FontRenderer getFont() { return font; }
+ public List<? extends ITextProperties> getLines() { return lines; }
+
+ public void setFont(FontRenderer font) { this.font = font; }
+
+ public int getMaxLineWidth()
+ {
+ int textWidth = 0;
+ for (ITextProperties textLine : lines)
+ {
+ int textLineWidth = font.width(textLine);
+ if (textLineWidth > textWidth)
+ {
+ textWidth = textLineWidth;
+ }
+ }
+ return textWidth;
+ }
+
+ public void wrap(int maxWidth)
+ {
+ tooltipWidth = 0;
+ List<ITextProperties> wrappedLines = new ArrayList<>();
+ for (int i = 0; i < lines.size(); i++)
+ {
+ ITextProperties textLine = lines.get(i);
+ List<ITextProperties> wrappedLine = font.getSplitter().splitLines(textLine, maxWidth, Style.EMPTY);
+ if (i == 0)
+ {
+ titleLines = wrappedLine.size();
+ }
+
+ for (ITextProperties line : wrappedLine)
+ {
+ int lineWidth = font.width(line);
+ if (lineWidth > tooltipWidth)
+ {
+ tooltipWidth = lineWidth;
+ }
+ wrappedLines.add(line);
+ }
+ }
+
+ lines = wrappedLines;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public static void renderItemTooltip(@Nonnull final ItemStack stack, MatrixStack mStack, TooltipInfo info,
+ Rectangle2d rect, int screenWidth, int screenHeight,
+ int backgroundColor, int borderColorStart, int borderColorEnd)
+ {
+ if (info.getLines().isEmpty())
+ {
+ return;
+ }
+
+ int rectX = rect.getX() - 8;
+ int rectY = rect.getY() + 18;
+ int maxTextWidth = rect.getWidth() - 8;
+
+ RenderTooltipEvent.Pre event = new RenderTooltipEvent.Pre(stack, info.getLines(), mStack, rectX, rectY, screenWidth, screenHeight, maxTextWidth, info.getFont());
+ if (MinecraftForge.EVENT_BUS.post(event))
+ {
+ return;
+ }
+
+ rectX = event.getX();
+ rectY = event.getY();
+ screenWidth = event.getScreenWidth();
+ screenHeight = event.getScreenHeight();
+ maxTextWidth = event.getMaxWidth();
+ info.setFont(event.getFontRenderer());
+
+ RenderSystem.disableRescaleNormal();
+ RenderSystem.disableDepthTest();
+ int tooltipTextWidth = info.getMaxLineWidth();
+
+ boolean needsWrap = false;
+
+ int tooltipX = rectX + 12;
+ if (tooltipX + tooltipTextWidth + 4 > screenWidth)
+ {
+ tooltipX = rectX - 16 - tooltipTextWidth;
+ if (tooltipX < 4) // if the tooltip doesn't fit on the screen
+ {
+ if (rectX > screenWidth / 2)
+ {
+ tooltipTextWidth = rectX - 12 - 8;
+ }
+ else
+ {
+ tooltipTextWidth = screenWidth - 16 - rectX;
+ }
+ needsWrap = true;
+ }
+ }
+
+ if (maxTextWidth > 0 && tooltipTextWidth > maxTextWidth)
+ {
+ tooltipTextWidth = maxTextWidth;
+ needsWrap = true;
+ }
+
+ if (needsWrap)
+ {
+ info.wrap(tooltipTextWidth);
+ tooltipTextWidth = info.getTooltipWidth();
+ tooltipX = rectX + 12;
+ }
+
+ int tooltipY = rectY - 12;
+ int tooltipHeight = 8;
+
+ if (info.getLines().size() > 1)
+ {
+ tooltipHeight += (info.getLines().size() - 1) * 10;
+ if (info.getLines().size() > info.getTitleLines())
+ {
+ tooltipHeight += 2; // gap between title lines and next lines
+ }
+ }
+
+ if (tooltipY < 4)
+ {
+ tooltipY = 4;
+ }
+ else if (tooltipY + tooltipHeight + 4 > screenHeight)
+ {
+ tooltipY = screenHeight - tooltipHeight - 4;
+ }
+
+ final int zLevel = 400;
+ RenderTooltipEvent.Color colorEvent = new RenderTooltipEvent.Color(stack, info.getLines(), mStack, tooltipX, tooltipY, info.getFont(), backgroundColor, borderColorStart, borderColorEnd);
+ MinecraftForge.EVENT_BUS.post(colorEvent);
+ backgroundColor = colorEvent.getBackground();
+ borderColorStart = colorEvent.getBorderStart();
+ borderColorEnd = colorEvent.getBorderEnd();
+
+ mStack.pushPose();
+ Matrix4f mat = mStack.last().pose();
+
+ GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 4, tooltipX + tooltipTextWidth + 3, tooltipY - 3, backgroundColor, backgroundColor);
+ GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY + tooltipHeight + 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 4, backgroundColor, backgroundColor);
+ GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor);
+ GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 4, tooltipY - 3, tooltipX - 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor);
+ GuiUtils.drawGradientRect(mat, zLevel, tooltipX + tooltipTextWidth + 3, tooltipY - 3, tooltipX + tooltipTextWidth + 4, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor);
+ GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 3 + 1, tooltipX - 3 + 1, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd);
+ GuiUtils.drawGradientRect(mat, zLevel, tooltipX + tooltipTextWidth + 2, tooltipY - 3 + 1, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd);
+ GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY - 3 + 1, borderColorStart, borderColorStart);
+ GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY + tooltipHeight + 2, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, borderColorEnd, borderColorEnd);
+
+ MinecraftForge.EVENT_BUS.post(new RenderTooltipEvent.PostBackground(stack, info.getLines(), mStack, tooltipX, tooltipY, info.getFont(), tooltipTextWidth, tooltipHeight));
+
+ IRenderTypeBuffer.Impl renderType = IRenderTypeBuffer.immediate(Tessellator.getInstance().getBuilder());
+ mStack.translate(0.0D, 0.0D, zLevel);
+
+ int tooltipTop = tooltipY;
+
+ for (int lineNumber = 0; lineNumber < info.getLines().size(); ++lineNumber)
+ {
+ ITextProperties line = info.getLines().get(lineNumber);
+ if (line != null)
+ {
+ info.getFont().drawInBatch(LanguageMap.getInstance().getVisualOrder(line), (float)tooltipX, (float)tooltipY, -1, true, mat, renderType, false, 0, 15728880);
+ }
+
+ if (lineNumber + 1 == info.getTitleLines())
+ {
+ tooltipY += 2;
+ }
+
+ tooltipY += 10;
+ }
+
+ renderType.endBatch();
+ mStack.popPose();
+
+ MinecraftForge.EVENT_BUS.post(new RenderTooltipEvent.PostText(stack, info.getLines(), mStack, tooltipX, tooltipTop, info.getFont(), tooltipTextWidth, tooltipHeight));
+
+ RenderSystem.enableDepthTest();
+ RenderSystem.enableRescaleNormal();
+ }
+
public static Rectangle2d calculateRect(final ItemStack stack, MatrixStack mStack, List<? extends ITextProperties> textLines, int mouseX, int mouseY,
int screenWidth, int screenHeight, int maxTextWidth, FontRenderer font)
{
diff --git a/src/main/resources/iceberg.mixins.json b/src/main/resources/iceberg.mixins.json
index 41b5589..9dfa917 100644
--- a/src/main/resources/iceberg.mixins.json
+++ b/src/main/resources/iceberg.mixins.json
@@ -4,8 +4,11 @@
"compatibilityLevel": "JAVA_8",
"refmap": "iceberg.refmap.json",
"mixins": [
- "PlayerAdvancementsMixin",
- "EntityMixin"
+ "EntityMixin",
+ "PlayerAdvancementsMixin"
+ ],
+ "server": [
+ "ForgeEventFactoryMixin"
],
"injectors": {
"defaultRequire": 1