From a8048391a0f9a3304b176f1049a14a2cd2e1d681 Mon Sep 17 00:00:00 2001 From: zontreck Date: Sun, 31 Dec 2023 05:24:21 -0700 Subject: [PATCH] Start adding a chest gui system --- .../dev/zontreck/libzontreck/LibZontreck.java | 2 + .../libzontreck/chestgui/ChestGUI.java | 90 +++++++++++++++ .../libzontreck/chestgui/ChestGUIButton.java | 104 ++++++++++++++++++ .../chestgui/ChestGUIRegistry.java | 34 ++++++ .../events/GUIButtonClickedEvent.java | 21 ++++ .../libzontreck/events/OpenGUIEvent.java | 32 ++++++ .../libzontreck/networking/ModMessages.java | 6 + .../packets/C2SChestGUIButtonClicked.java | 55 +++++++++ .../networking/packets/ChestGUIOpenC2S.java | 4 + .../networking/structures/OpenGUIRequest.java | 25 ++--- 10 files changed, 357 insertions(+), 16 deletions(-) create mode 100644 src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUI.java create mode 100644 src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIButton.java create mode 100644 src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIRegistry.java create mode 100644 src/main/java/dev/zontreck/libzontreck/events/GUIButtonClickedEvent.java create mode 100644 src/main/java/dev/zontreck/libzontreck/events/OpenGUIEvent.java create mode 100644 src/main/java/dev/zontreck/libzontreck/networking/packets/C2SChestGUIButtonClicked.java diff --git a/src/main/java/dev/zontreck/libzontreck/LibZontreck.java b/src/main/java/dev/zontreck/libzontreck/LibZontreck.java index a22b09d..13300b1 100644 --- a/src/main/java/dev/zontreck/libzontreck/LibZontreck.java +++ b/src/main/java/dev/zontreck/libzontreck/LibZontreck.java @@ -10,6 +10,7 @@ import java.util.UUID; import dev.zontreck.ariaslib.util.DelayedExecutorService; import dev.zontreck.eventsbus.Bus; +import dev.zontreck.libzontreck.chestgui.ChestGUIRegistry; import dev.zontreck.libzontreck.currency.Bank; import dev.zontreck.libzontreck.currency.CurrencyHelper; import dev.zontreck.libzontreck.networking.NetworkEvents; @@ -80,6 +81,7 @@ public class LibZontreck { MinecraftForge.EVENT_BUS.register(new ForgeEventHandlers()); MinecraftForge.EVENT_BUS.register(new Commands()); MinecraftForge.EVENT_BUS.register(new NetworkEvents()); + MinecraftForge.EVENT_BUS.register(new ChestGUIRegistry()); Bus.Reset(); diff --git a/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUI.java b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUI.java new file mode 100644 index 0000000..86595e1 --- /dev/null +++ b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUI.java @@ -0,0 +1,90 @@ +package dev.zontreck.libzontreck.chestgui; + +import dev.zontreck.libzontreck.LibZontreck; +import dev.zontreck.libzontreck.networking.packets.ChestGUIOpenC2S; +import dev.zontreck.libzontreck.vectors.Vector2; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraftforge.fml.LogicalSide; +import net.minecraftforge.items.ItemStackHandler; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ChestGUI +{ + private ItemStackHandler container = new ItemStackHandler((9*3)); + private String MenuTitle; + private UUID player; + private List buttons = new ArrayList<>(); + private ResourceLocation id; + public ChestGUI withButton(ChestGUIButton button) + { + buttons.add(button); + container.setStackInSlot(button.getSlotNum(), button.buildIcon()); + + return this; + } + + public ChestGUI withTitle(String title) + { + MenuTitle = title; + + return this; + } + + public static ChestGUI builder() + { + return new ChestGUI(); + } + + public ChestGUI withPlayer(UUID id) + { + player=id; + return this; + } + + /** + * Open the GUI on the client + */ + public void open() + { + if(LibZontreck.CURRENT_SIDE == LogicalSide.SERVER) + { + + } + } + + public boolean isPlayer(UUID ID) + { + return player.equals(ID); + } + + public ChestGUI withGUIId(ResourceLocation id) + { + this.id = id; + return this; + } + + public boolean matches(ResourceLocation id) + { + return this.id.equals(id); + } + + public void handleButtonClicked(int slot, Vector2 pos, Item item) { + for(ChestGUIButton button : buttons) + { + if(button.getSlotNum() == slot) + { + if(button.buildIcon().getItem() == item) + { + button.clicked(); + return; + } + } + } + } +} diff --git a/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIButton.java b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIButton.java new file mode 100644 index 0000000..e0c9942 --- /dev/null +++ b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIButton.java @@ -0,0 +1,104 @@ +package dev.zontreck.libzontreck.chestgui; + +import dev.zontreck.libzontreck.lore.LoreContainer; +import dev.zontreck.libzontreck.lore.LoreEntry; +import dev.zontreck.libzontreck.util.ChatHelpers; +import dev.zontreck.libzontreck.vectors.Vector2; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +public class ChestGUIButton +{ + private Item icon; + private String name; + private List tooltipInfo; + + private Runnable callback; + private CompoundTag NBT = new CompoundTag(); + + /** + * Position is Row (X), Column (Y) + */ + private Vector2 position; + + public ChestGUIButton(Item icon, String name, Runnable callback, Vector2 position) + { + this.icon = icon; + this.name = name; + this.callback = callback; + this.position = position; + tooltipInfo = new ArrayList<>(); + } + + public ChestGUIButton(ItemStack existing, Runnable callback, Vector2 position) + { + this.callback = callback; + this.position = position; + + LoreContainer container = new LoreContainer(existing); + tooltipInfo = container.miscData.LoreData; + name = existing.getHoverName().getString(); + icon = existing.getItem(); + NBT = existing.getTag(); + + } + + public ChestGUIButton withNBT(CompoundTag tag) + { + this.NBT = tag; + return this; + } + + public ItemStack buildIcon() + { + ItemStack ret = new ItemStack(icon,1); + ret = ret.setHoverName(ChatHelpers.macro(name)); + + LoreContainer cont = new LoreContainer(ret); + + for (LoreEntry str : tooltipInfo) + { + cont.miscData.LoreData.add(str); + } + + cont.commitLore(); + + NBT.putInt("slot", getSlotNum()); + NBT.put("pos", position.serialize()); + + ret.setTag(NBT); + + return ret; + } + + /** + * Adds a line to the Lore (Tooltip) of the button + * @param line The line to add + * @return ChestGUIButton instance + */ + public ChestGUIButton withInfo(LoreEntry line) + { + tooltipInfo.add(line); + + return this; + } + + /** + * Returns the slot number in the 32 item grid + * @return Slot number from vector (row, column) + */ + public int getSlotNum() + { + return (int) Math.floor((position.x * 9) + position.y); + } + + public void clicked() + { + callback.run(); + } +} diff --git a/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIRegistry.java b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIRegistry.java new file mode 100644 index 0000000..eaec6d1 --- /dev/null +++ b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIRegistry.java @@ -0,0 +1,34 @@ +package dev.zontreck.libzontreck.chestgui; + +import dev.zontreck.libzontreck.events.GUIButtonClickedEvent; +import dev.zontreck.libzontreck.vectors.Vector2; +import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +import java.util.ArrayList; +import java.util.List; + +public class ChestGUIRegistry +{ + public static List ActiveGUIs = new ArrayList<>(); + + @SubscribeEvent + public void onChestGUIButtonClicked(GUIButtonClickedEvent event) + { + for(ChestGUI gui : ActiveGUIs) + { + if(gui.isPlayer(event.player)) + { + if(gui.matches(event.id)) + { + // Handle the click now + CompoundTag tag = event.stack.getTag(); + Vector2 pos = new Vector2(tag.getCompound("pos")); + int slot = tag.getInt("slot"); + gui.handleButtonClicked(slot, pos, event.stack.getItem()); + } + + } + } + } +} diff --git a/src/main/java/dev/zontreck/libzontreck/events/GUIButtonClickedEvent.java b/src/main/java/dev/zontreck/libzontreck/events/GUIButtonClickedEvent.java new file mode 100644 index 0000000..8a8e186 --- /dev/null +++ b/src/main/java/dev/zontreck/libzontreck/events/GUIButtonClickedEvent.java @@ -0,0 +1,21 @@ +package dev.zontreck.libzontreck.events; + +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.eventbus.api.Event; + +import java.util.UUID; + +public class GUIButtonClickedEvent extends Event +{ + public ResourceLocation id; + public ItemStack stack; + public UUID player; + + public GUIButtonClickedEvent(ItemStack stack, ResourceLocation id, UUID player) + { + this.id = id; + this.stack = stack; + this.player = player; + } +} diff --git a/src/main/java/dev/zontreck/libzontreck/events/OpenGUIEvent.java b/src/main/java/dev/zontreck/libzontreck/events/OpenGUIEvent.java new file mode 100644 index 0000000..279fe63 --- /dev/null +++ b/src/main/java/dev/zontreck/libzontreck/events/OpenGUIEvent.java @@ -0,0 +1,32 @@ +package dev.zontreck.libzontreck.events; + +import dev.zontreck.libzontreck.util.ServerUtilities; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.eventbus.api.Cancelable; +import net.minecraftforge.eventbus.api.Event; + +import java.util.UUID; + +@Cancelable +public class OpenGUIEvent extends Event +{ + private ResourceLocation GUIId; + private UUID playerID; + + public OpenGUIEvent(ResourceLocation ID, UUID player) + { + GUIId = ID; + playerID = player; + } + + public boolean matches(ResourceLocation id) + { + return GUIId.equals(id); + } + + public ServerPlayer getPlayer() + { + return ServerUtilities.getPlayerByID(getPlayer().getStringUUID()); + } +} diff --git a/src/main/java/dev/zontreck/libzontreck/networking/ModMessages.java b/src/main/java/dev/zontreck/libzontreck/networking/ModMessages.java index 624682d..a8e5875 100644 --- a/src/main/java/dev/zontreck/libzontreck/networking/ModMessages.java +++ b/src/main/java/dev/zontreck/libzontreck/networking/ModMessages.java @@ -2,6 +2,7 @@ package dev.zontreck.libzontreck.networking; import dev.zontreck.libzontreck.LibZontreck; import dev.zontreck.libzontreck.events.RegisterPacketsEvent; +import dev.zontreck.libzontreck.networking.packets.C2SChestGUIButtonClicked; import dev.zontreck.libzontreck.networking.packets.ChestGUIOpenC2S; import dev.zontreck.libzontreck.networking.packets.IPacket; import net.minecraft.resources.ResourceLocation; @@ -51,6 +52,11 @@ public class ModMessages { .consumerMainThread(ChestGUIOpenC2S::handle) .add(); + net.messageBuilder(C2SChestGUIButtonClicked.class, PACKET_ID.getAndIncrement(), NetworkDirection.PLAY_TO_SERVER) + .decoder(C2SChestGUIButtonClicked::new) + .encoder(C2SChestGUIButtonClicked::toBytes) + .consumerMainThread(C2SChestGUIButtonClicked::handle) + .add(); } diff --git a/src/main/java/dev/zontreck/libzontreck/networking/packets/C2SChestGUIButtonClicked.java b/src/main/java/dev/zontreck/libzontreck/networking/packets/C2SChestGUIButtonClicked.java new file mode 100644 index 0000000..dfafd8e --- /dev/null +++ b/src/main/java/dev/zontreck/libzontreck/networking/packets/C2SChestGUIButtonClicked.java @@ -0,0 +1,55 @@ +package dev.zontreck.libzontreck.networking.packets; + +import dev.zontreck.libzontreck.events.GUIButtonClickedEvent; +import dev.zontreck.libzontreck.vectors.Vector2; +import net.minecraft.client.Minecraft; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.network.NetworkEvent; + +import java.util.UUID; +import java.util.function.Supplier; + +public class C2SChestGUIButtonClicked +{ + private ItemStack stack; + private ResourceLocation id; + private UUID player; + + public C2SChestGUIButtonClicked(ItemStack stack, ResourceLocation id) + { + this.stack = stack; + + this.id = id; + player = Minecraft.getInstance().player.getUUID(); + } + + public C2SChestGUIButtonClicked(FriendlyByteBuf buf) + { + stack = buf.readItem(); + id = buf.readResourceLocation(); + } + + public void toBytes(FriendlyByteBuf buf) + { + buf.writeItem(stack); + buf.writeResourceLocation(id); + } + + public boolean handle(Supplier ctx) + { + NetworkEvent.Context context = ctx.get(); + + context.enqueueWork(()->{ + // We're on the server now. + + MinecraftForge.EVENT_BUS.post(new GUIButtonClickedEvent(stack, id, player)); + }); + + return true; + } +} diff --git a/src/main/java/dev/zontreck/libzontreck/networking/packets/ChestGUIOpenC2S.java b/src/main/java/dev/zontreck/libzontreck/networking/packets/ChestGUIOpenC2S.java index bf69280..aa92c96 100644 --- a/src/main/java/dev/zontreck/libzontreck/networking/packets/ChestGUIOpenC2S.java +++ b/src/main/java/dev/zontreck/libzontreck/networking/packets/ChestGUIOpenC2S.java @@ -2,9 +2,11 @@ package dev.zontreck.libzontreck.networking.packets; import java.util.function.Supplier; +import dev.zontreck.libzontreck.events.OpenGUIEvent; import dev.zontreck.libzontreck.networking.structures.OpenGUIRequest; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.network.NetworkEvent; /** @@ -36,6 +38,8 @@ public class ChestGUIOpenC2S { ctx.enqueueWork(()->{ // We are on the server! OpenGUIRequest req = new OpenGUIRequest(data); + + MinecraftForge.EVENT_BUS.post(new OpenGUIEvent(req.ID, req.playerID)); }); return true; diff --git a/src/main/java/dev/zontreck/libzontreck/networking/structures/OpenGUIRequest.java b/src/main/java/dev/zontreck/libzontreck/networking/structures/OpenGUIRequest.java index be0c60d..689beaa 100644 --- a/src/main/java/dev/zontreck/libzontreck/networking/structures/OpenGUIRequest.java +++ b/src/main/java/dev/zontreck/libzontreck/networking/structures/OpenGUIRequest.java @@ -7,37 +7,30 @@ import java.util.UUID; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; public class OpenGUIRequest { - public List options = new ArrayList<>(); - public String GUITitle; + public ResourceLocation ID; public UUID playerID; public OpenGUIRequest(CompoundTag tag) { - ListTag items = tag.getList("items", Tag.TAG_COMPOUND); + CompoundTag tags = tag.getCompound("id"); - for(Tag tags : items) - { - ItemStack is = ItemStack.of((CompoundTag)tags); - options.add(is); - } - - GUITitle = tag.getString("title"); + ID = new ResourceLocation(tags.getString("mod"), tags.getString("id")); playerID = tag.getUUID("player"); } public CompoundTag serialize() { CompoundTag tag = new CompoundTag(); - tag.putString("title", GUITitle); tag.putUUID("player", playerID); - ListTag lst = new ListTag(); - for (ItemStack itemStack : options) { - lst.add(itemStack.serializeNBT()); - } - tag.put("items", lst); + CompoundTag tags = new CompoundTag(); + tags.putString("mod", ID.getNamespace()); + tags.putString("id", ID.getPath()); + + tag.put("id", tags); return tag; }