From 0fb37b16338f336d77d60f21dff93bf72dc0a3a6 Mon Sep 17 00:00:00 2001 From: zontreck Date: Tue, 2 Jan 2024 17:59:10 -0700 Subject: [PATCH] Chest GUI API now completed --- gradle.properties | 2 +- .../dev/zontreck/libzontreck/LibZontreck.java | 2 + .../libzontreck/chestgui/ChestGUI.java | 18 ++- .../libzontreck/chestgui/ChestGUIButton.java | 18 +-- .../chestgui/ChestGUIRegistry.java | 33 ++++ .../libzontreck/commands/CreditsCommand.java | 8 +- .../ChestGUIReadOnlyStackHandler.java | 38 ++++- .../libzontreck/events/CloseGUIEvent.java | 19 +++ .../libzontreck/events/OpenGUIEvent.java | 12 +- .../zontreck/libzontreck/lore/ExtraLore.java | 106 ++++++++----- .../libzontreck/lore/LoreContainer.java | 134 +++++++---------- .../zontreck/libzontreck/lore/LoreEntry.java | 141 +++++++++++++++--- .../libzontreck/menus/ChestGUIMenu.java | 10 +- .../libzontreck/networking/ModMessages.java | 19 ++- .../libzontreck/networking/NetworkEvents.java | 1 - .../networking/packets/ChestGUIOpenC2S.java | 47 ------ .../networking/packets/S2CCloseChestGUI.java | 39 +++++ .../libzontreck/util/heads/CreditsEntry.java | 22 +-- .../libzontreck/util/heads/HeadCache.java | 6 +- 19 files changed, 436 insertions(+), 239 deletions(-) create mode 100644 src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIRegistry.java create mode 100644 src/main/java/dev/zontreck/libzontreck/events/CloseGUIEvent.java delete mode 100644 src/main/java/dev/zontreck/libzontreck/networking/packets/ChestGUIOpenC2S.java create mode 100644 src/main/java/dev/zontreck/libzontreck/networking/packets/S2CCloseChestGUI.java diff --git a/gradle.properties b/gradle.properties index d840622..b0a9f82 100644 --- a/gradle.properties +++ b/gradle.properties @@ -53,7 +53,7 @@ mod_name=Zontreck Library Mod # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=GPLv3 # The mod version. See https://semver.org/ -mod_version=1.9.122123.1608 +mod_version=1.10.010224.1758 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/src/main/java/dev/zontreck/libzontreck/LibZontreck.java b/src/main/java/dev/zontreck/libzontreck/LibZontreck.java index 6c69dff..94d8736 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.menus.ChestGUIScreen; @@ -83,6 +84,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(ChestGUIRegistry.class); Bus.Reset(); diff --git a/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUI.java b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUI.java index 1a2bb2c..3bac901 100644 --- a/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUI.java +++ b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUI.java @@ -1,8 +1,11 @@ package dev.zontreck.libzontreck.chestgui; import dev.zontreck.libzontreck.LibZontreck; +import dev.zontreck.libzontreck.events.CloseGUIEvent; import dev.zontreck.libzontreck.events.OpenGUIEvent; import dev.zontreck.libzontreck.menus.ChestGUIMenu; +import dev.zontreck.libzontreck.networking.ModMessages; +import dev.zontreck.libzontreck.networking.packets.S2CCloseChestGUI; import dev.zontreck.libzontreck.util.ServerUtilities; import dev.zontreck.libzontreck.vectors.Vector2; import dev.zontreck.libzontreck.vectors.Vector2i; @@ -59,11 +62,24 @@ public class ChestGUI { if(LibZontreck.CURRENT_SIDE == LogicalSide.SERVER) { - MinecraftForge.EVENT_BUS.post(new OpenGUIEvent(id, player)); + MinecraftForge.EVENT_BUS.post(new OpenGUIEvent(id, player, this)); NetworkHooks.openScreen(ServerUtilities.getPlayerByID(player.toString()), new SimpleMenuProvider(ChestGUIMenu.getServerMenu(this), Component.literal((MenuTitle != "") ? MenuTitle : "No Title"))); } } + /** + * Send a signal to trigger the GUI to close on the server, then send a signal to the client to also close the interface + */ + public void close() + { + if(LibZontreck.CURRENT_SIDE == LogicalSide.SERVER) + { + MinecraftForge.EVENT_BUS.post(new CloseGUIEvent(this, ServerUtilities.getPlayerByID(player.toString()))); + + ModMessages.sendToPlayer(new S2CCloseChestGUI(), ServerUtilities.getPlayerByID(player.toString())); + } + } + public boolean isPlayer(UUID ID) { return player.equals(ID); diff --git a/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIButton.java b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIButton.java index 99ac7b0..88a5984 100644 --- a/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIButton.java +++ b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIButton.java @@ -18,7 +18,7 @@ public class ChestGUIButton { private Item icon; private String name; - private List tooltipInfo; + private List tooltipInfo = new ArrayList<>(); private Runnable callback; private CompoundTag NBT = new CompoundTag(); @@ -43,7 +43,7 @@ public class ChestGUIButton this.position = position; LoreContainer container = new LoreContainer(existing); - tooltipInfo = container.miscData.LoreData; + tooltipInfo = container.miscData.loreData; name = existing.getHoverName().getString(); icon = existing.getItem(); NBT = existing.getTag(); @@ -61,19 +61,17 @@ public class ChestGUIButton 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); + LoreContainer cont = new LoreContainer(ret); + cont.clear(); + + cont.miscData.loreData.addAll(tooltipInfo); + + cont.commitLore(); return ret; } 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..f275180 --- /dev/null +++ b/src/main/java/dev/zontreck/libzontreck/chestgui/ChestGUIRegistry.java @@ -0,0 +1,33 @@ +package dev.zontreck.libzontreck.chestgui; + +import dev.zontreck.libzontreck.events.CloseGUIEvent; +import dev.zontreck.libzontreck.events.OpenGUIEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class ChestGUIRegistry +{ + private static Map GUIS = new HashMap<>(); + + + @SubscribeEvent + public static void onGuiOpen(final OpenGUIEvent event) + { + GUIS.put(event.getPlayer().getUUID(), event.getGui()); + } + + @SubscribeEvent + public static void onGuiClose(final CloseGUIEvent event) + { + GUIS.remove(event.player.getUUID()); + } + + public static ChestGUI get(UUID ID) + { + if(GUIS.containsKey(ID)) return GUIS.get(ID); + return null; + } +} diff --git a/src/main/java/dev/zontreck/libzontreck/commands/CreditsCommand.java b/src/main/java/dev/zontreck/libzontreck/commands/CreditsCommand.java index c6d89c5..10b5943 100644 --- a/src/main/java/dev/zontreck/libzontreck/commands/CreditsCommand.java +++ b/src/main/java/dev/zontreck/libzontreck/commands/CreditsCommand.java @@ -6,6 +6,8 @@ import com.mojang.brigadier.CommandDispatcher; import dev.zontreck.libzontreck.LibZontreck; import dev.zontreck.libzontreck.chestgui.ChestGUI; import dev.zontreck.libzontreck.chestgui.ChestGUIButton; +import dev.zontreck.libzontreck.networking.ModMessages; +import dev.zontreck.libzontreck.networking.packets.S2CCloseChestGUI; import dev.zontreck.libzontreck.util.heads.CreditsEntry; import dev.zontreck.libzontreck.util.heads.HeadCache; import dev.zontreck.libzontreck.vectors.Vector2i; @@ -31,9 +33,11 @@ public class CreditsCommand { int y = 0; for(CreditsEntry entry : HeadCache.CREDITS) { - gui = gui.withButton(new ChestGUIButton(entry.compile(), ()->{}, new Vector2i(x,y))); + gui = gui.withButton(new ChestGUIButton(entry.compile(), ()->{ - LibZontreck.LOGGER.info("Add gui button : " + entry.name); + }, new Vector2i(x,y))); + + //LibZontreck.LOGGER.info("Add gui button : " + entry.name); y++; if(y>=9) diff --git a/src/main/java/dev/zontreck/libzontreck/dynamicchest/ChestGUIReadOnlyStackHandler.java b/src/main/java/dev/zontreck/libzontreck/dynamicchest/ChestGUIReadOnlyStackHandler.java index 39ae504..a0a764e 100644 --- a/src/main/java/dev/zontreck/libzontreck/dynamicchest/ChestGUIReadOnlyStackHandler.java +++ b/src/main/java/dev/zontreck/libzontreck/dynamicchest/ChestGUIReadOnlyStackHandler.java @@ -3,18 +3,40 @@ package dev.zontreck.libzontreck.dynamicchest; import dev.zontreck.libzontreck.LibZontreck; import dev.zontreck.libzontreck.chestgui.ChestGUI; import dev.zontreck.libzontreck.chestgui.ChestGUIButton; +import dev.zontreck.libzontreck.chestgui.ChestGUIRegistry; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraftforge.items.ItemStackHandler; import org.jetbrains.annotations.NotNull; +import java.time.Instant; + public class ChestGUIReadOnlyStackHandler extends ItemStackHandler { private ChestGUI gui; + private Player player; + private long lastClickTime; + private int lastClickStack; - public ChestGUIReadOnlyStackHandler(ChestGUI gui) + public boolean validClick(int slot) + { + if(lastClickStack != slot)return true; + else{ + if(Instant.now().getEpochSecond() > (lastClickTime + 1)) + { + return true; + } + } + + return false; + } + + public ChestGUIReadOnlyStackHandler(ChestGUI gui, Player player) { super((3*9)); this.gui = gui; + this.player = player; + LibZontreck.LOGGER.info("Logical Side : " + LibZontreck.CURRENT_SIDE); @@ -43,11 +65,21 @@ public class ChestGUIReadOnlyStackHandler extends ItemStackHandler @Override public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { - ChestGUIButton btn = gui.buttons.stream().filter(x->x.getSlotNum()==slot).findFirst().orElse(null); + ChestGUI instance = ChestGUIRegistry.get(player.getUUID()); + if(instance==null)return ItemStack.EMPTY; + + + ChestGUIButton btn = instance.buttons.stream().filter(x->x.getSlotNum()==slot).findFirst().orElse(null); if(btn == null) return ItemStack.EMPTY; - btn.clicked(); + if(validClick(slot)) + { + btn.clicked(); + + lastClickTime = Instant.now().getEpochSecond(); + lastClickStack = slot; + } return ItemStack.EMPTY; } diff --git a/src/main/java/dev/zontreck/libzontreck/events/CloseGUIEvent.java b/src/main/java/dev/zontreck/libzontreck/events/CloseGUIEvent.java new file mode 100644 index 0000000..d0a80ea --- /dev/null +++ b/src/main/java/dev/zontreck/libzontreck/events/CloseGUIEvent.java @@ -0,0 +1,19 @@ +package dev.zontreck.libzontreck.events; + +import dev.zontreck.libzontreck.chestgui.ChestGUI; +import dev.zontreck.libzontreck.util.ServerUtilities; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.eventbus.api.Event; + +public class CloseGUIEvent extends Event +{ + public ChestGUI gui; + public Player player; + + public CloseGUIEvent(ChestGUI gui, ServerPlayer player) + { + this.gui = gui; + 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 index 279fe63..c37630f 100644 --- a/src/main/java/dev/zontreck/libzontreck/events/OpenGUIEvent.java +++ b/src/main/java/dev/zontreck/libzontreck/events/OpenGUIEvent.java @@ -1,5 +1,6 @@ package dev.zontreck.libzontreck.events; +import dev.zontreck.libzontreck.chestgui.ChestGUI; import dev.zontreck.libzontreck.util.ServerUtilities; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; @@ -8,16 +9,17 @@ import net.minecraftforge.eventbus.api.Event; import java.util.UUID; -@Cancelable public class OpenGUIEvent extends Event { private ResourceLocation GUIId; private UUID playerID; + private final ChestGUI gui; - public OpenGUIEvent(ResourceLocation ID, UUID player) + public OpenGUIEvent(ResourceLocation ID, UUID player, ChestGUI gui) { GUIId = ID; playerID = player; + this.gui = gui; } public boolean matches(ResourceLocation id) @@ -27,6 +29,10 @@ public class OpenGUIEvent extends Event public ServerPlayer getPlayer() { - return ServerUtilities.getPlayerByID(getPlayer().getStringUUID()); + return ServerUtilities.getPlayerByID(playerID.toString()); + } + + public ChestGUI getGui() { + return gui; } } diff --git a/src/main/java/dev/zontreck/libzontreck/lore/ExtraLore.java b/src/main/java/dev/zontreck/libzontreck/lore/ExtraLore.java index 431f924..6c8cf8e 100644 --- a/src/main/java/dev/zontreck/libzontreck/lore/ExtraLore.java +++ b/src/main/java/dev/zontreck/libzontreck/lore/ExtraLore.java @@ -4,69 +4,93 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; +import dev.zontreck.libzontreck.lore.LoreEntry; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; -// Extra container +/** + * Represents a container for multiple LoreEntry instances. + */ public class ExtraLore { - public List LoreData = new ArrayList<>(); + @SerializedName("extra") + public List loreData = new ArrayList<>(); - - public void save(CompoundTag tag) - { - ListTag lores = new ListTag(); - for (LoreEntry loreEntry : LoreData) { - loreEntry.save(lores); - } + /** + * Saves the lore entries into a CompoundTag for storage. + * + * @param tag The CompoundTag to save the entries. + */ + public void save(CompoundTag tag) { + ListTag lores = saveEntries(); // Extra entry in display:Lore list tag.put("extra", lores); } - public ListTag save(){ + /** + * Saves the lore entries into a ListTag. + * + * @return The ListTag containing saved lore entries. + */ + public ListTag saveEntries() { ListTag lores = new ListTag(); - for (LoreEntry tag : LoreData) { - tag.save(lores); + for (LoreEntry loreEntry : loreData) { + lores.add(StringTag.valueOf(loreEntry.saveJson())); } return lores; } - // This json object is what goes inside the actual item lore. This is not the entry used to save the state - public String saveJson(){ - String ret = "{"; - Iterator loreEntries = LoreData.iterator(); - ret += "\"extra\": ["; - while(loreEntries.hasNext()) - { - LoreEntry loreEntryx = loreEntries.next(); - ret += loreEntryx.saveJson(); - - if(loreEntries.hasNext()) - { - ret += ","; - } - } - ret += "],"; - ret += "\"text\": \"\""; - ret += "}"; - return ret; + /** + * Generates a JSON string representing the lore entries. + * + * @return The JSON string representing the lore entries. + */ + public String saveJson() { + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + return gson.toJson(this); } - public ExtraLore(CompoundTag tags) - { + + /** + * Parses a JSON string to create an ExtraLore object with LoreEntry instances. + * + * @param json The JSON string representing lore entries. + * @return An ExtraLore object created from the JSON string. + */ + public static ExtraLore parseJson(String json) { + Gson gson = new Gson(); + return gson.fromJson(json, ExtraLore.class); + } + + /** + * Constructs an ExtraLore object from a CompoundTag. + * + * @param tags The CompoundTag containing lore entries. + */ + public ExtraLore(CompoundTag tags) { ListTag tag = tags.getList("extra", CompoundTag.TAG_COMPOUND); - Iterator tagsx = tag.iterator(); - while(tagsx.hasNext()) - { - Tag t = tagsx.next(); - CompoundTag ct = (CompoundTag)t; - LoreData.add(new LoreEntry(ct)); + for (Tag t : tag) { + CompoundTag ct = (CompoundTag) t; + loreData.add(new LoreEntry(ct)); } } - public ExtraLore() + public ExtraLore(ListTag tag) { + for(Tag t : tag) + { + loreData.add(LoreEntry.parseJson(t.getAsString())); + } + } + /** + * Constructs an empty ExtraLore object. + */ + public ExtraLore() { + // Empty constructor } } - diff --git a/src/main/java/dev/zontreck/libzontreck/lore/LoreContainer.java b/src/main/java/dev/zontreck/libzontreck/lore/LoreContainer.java index d3e0bdd..be1ad9f 100644 --- a/src/main/java/dev/zontreck/libzontreck/lore/LoreContainer.java +++ b/src/main/java/dev/zontreck/libzontreck/lore/LoreContainer.java @@ -8,118 +8,84 @@ import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; public class LoreContainer { - public int loreEntryNumber; - public ExtraLore miscData; + private int loreEntryNumber; + public ExtraLore miscData = new ExtraLore(); + private final ItemStack associatedItem; - private ItemStack associatedItem; - - - public LoreContainer(CompoundTag container, ItemStack associated) - { - loreEntryNumber = container.getInt("pos"); - miscData = new ExtraLore(container.getCompound("state")); - - this.associatedItem = associated; - } - public void save(CompoundTag tag) - { - tag.putInt("pos", loreEntryNumber); - miscData.save(tag); + public LoreContainer(ItemStack stack) { + associatedItem = stack; + loreEntryNumber = getLoreEntryNumber(stack); + parseExistingLore(stack); } - public LoreContainer(ItemStack stack) - { - this.associatedItem=stack; - // Set the loreentrynumber appropriately, and insert a blank entry to hold it's position - CompoundTag display = stack.getOrCreateTag().getCompound(ItemStack.TAG_DISPLAY); - ListTag loreEntries = null; - if(display!= null) - { - loreEntries = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING); - if(loreEntries==null) - { - loreEntryNumber=0; - }else { - loreEntryNumber = loreEntries.size(); // This will be the next position - } - }else { - loreEntryNumber=0; - } - - miscData = new ExtraLore(); - LoreEntry blank = new LoreEntry(); - blank.text = ChatColor.WHITE + "Nothing to see here"; - - miscData.LoreData.add(blank); - - commitLore(); - - } - - public void commitLore() - { - AssertLoreExists(); - - // Set the Lore - CompoundTag tag = associatedItem.getTag(); + public void commitLore() { + assertLoreExists(); + CompoundTag tag = associatedItem.getOrCreateTag(); CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY); - ListTag lore = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING); + ListTag lore = miscData.saveEntries(); - // Set the lore entry - SetOrUpdateIndex(lore, loreEntryNumber, StringTag.valueOf(miscData.saveJson())); display.put(ItemStack.TAG_LORE, lore); tag.put(ItemStack.TAG_DISPLAY, display); associatedItem.setTag(tag); - - } - private void SetOrUpdateIndex(ListTag lst, int pos, Tag insert) - { - if(lst.size() <= pos){ + public void clear() { + loreEntryNumber = 0; + miscData.loreData.clear(); + CompoundTag tag = associatedItem.getOrCreateTag().getCompound(ItemStack.TAG_DISPLAY); + tag.remove(ItemStack.TAG_LORE); + commitLore(); + } + + private void setOrUpdateIndex(ListTag lst, int pos, Tag insert) { + if (lst.size() <= pos) { lst.add(insert); - // Update the loreEntryNumber - loreEntryNumber = lst.indexOf(insert); - }else lst.set(pos, insert); + loreEntryNumber = lst.size() - 1; + } else { + lst.set(pos, insert); + } } - private void AssertLoreExists() - { - AssertTag(); - AssertDisplay(); - AssertLore(); + private void assertLoreExists() { + assertTag(); + assertDisplay(); + assertLore(); } - private void AssertTag() - { - if(!associatedItem.hasTag()){ + private void assertTag() { + if (!associatedItem.hasTag()) { associatedItem.setTag(new CompoundTag()); } } - private void AssertDisplay() - { - CompoundTag tag = associatedItem.getTag(); + private void assertDisplay() { + CompoundTag tag = associatedItem.getOrCreateTag(); CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY); - if(display==null) - { + if (display.isEmpty()) { tag.put(ItemStack.TAG_DISPLAY, new CompoundTag()); associatedItem.setTag(tag); } } - private void AssertLore() - { - CompoundTag tag = associatedItem.getTag(); + private void assertLore() { + CompoundTag tag = associatedItem.getOrCreateTag(); CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY); ListTag lore = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING); - - if(lore == null) - { - lore = new ListTag(); - display.put(ItemStack.TAG_LORE, lore); - tag.put(ItemStack.TAG_DISPLAY, display); + if (lore.isEmpty()) { + display.put(ItemStack.TAG_LORE, new ListTag()); associatedItem.setTag(tag); } } + + private int getLoreEntryNumber(ItemStack stack) { + CompoundTag display = stack.getOrCreateTag().getCompound(ItemStack.TAG_DISPLAY); + ListTag loreEntries = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING); + return (loreEntries != null) ? loreEntries.size() : 0; + } + + private void parseExistingLore(ItemStack stack) { + CompoundTag display = stack.getOrCreateTag().getCompound(ItemStack.TAG_DISPLAY); + ListTag loreEntries = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING); + miscData = new ExtraLore(loreEntries); + } } diff --git a/src/main/java/dev/zontreck/libzontreck/lore/LoreEntry.java b/src/main/java/dev/zontreck/libzontreck/lore/LoreEntry.java index 582f1eb..0ad9d8f 100644 --- a/src/main/java/dev/zontreck/libzontreck/lore/LoreEntry.java +++ b/src/main/java/dev/zontreck/libzontreck/lore/LoreEntry.java @@ -1,17 +1,89 @@ package dev.zontreck.libzontreck.lore; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; -public class LoreEntry -{ +import java.util.ArrayList; +import java.util.List; + +public class LoreEntry { + + /** + * Builder pattern for creating a LoreEntry object. + */ + public static class Builder { + private boolean bold; + private boolean italic; + private boolean underlined; + private boolean strikethrough; + private boolean obfuscated; + private String color = ""; + private String text = ""; + + public Builder bold(boolean bold) { + this.bold = bold; + return this; + } + + public Builder italic(boolean italic) { + this.italic = italic; + return this; + } + + public Builder underlined(boolean underlined) { + this.underlined = underlined; + return this; + } + + public Builder strikethrough(boolean strikethrough) { + this.strikethrough = strikethrough; + return this; + } + + public Builder obfuscated(boolean obfuscated) { + this.obfuscated = obfuscated; + return this; + } + + public Builder color(String color) { + this.color = color; + return this; + } + + public Builder text(String text) { + this.text = text; + return this; + } + + public LoreEntry build() { + return new LoreEntry(this); + } + } + public boolean bold; public boolean italic; public boolean underlined; public boolean strikethrough; public boolean obfuscated; - public String color=""; - public String text=""; + public String color = ""; + public String text = ""; + + /** + * Constructs a LoreEntry object from a Builder + */ + LoreEntry(Builder builder) { + bold = builder.bold; + italic = builder.italic; + underlined = builder.underlined; + strikethrough = builder.strikethrough; + obfuscated = builder.obfuscated; + color = builder.color; + text = builder.text; + } + public LoreEntry (CompoundTag tag) { @@ -25,7 +97,12 @@ public class LoreEntry text = tag.getString("text"); } - public void save(ListTag parentTag){ + /** + * Saves the lore attributes into a ListTag for storage. + * + * @param parentTag The parent ListTag to save the attributes. + */ + public void save(ListTag parentTag) { CompoundTag tag = new CompoundTag(); tag.putBoolean("bold", bold); tag.putBoolean("italic", italic); @@ -38,30 +115,46 @@ public class LoreEntry parentTag.add(tag); } - private String bool2str(boolean a){ - if(a)return "true"; - else return "false"; + /** + * Generates a JSON string representing the lore entry. + * + * @return The JSON string representing the lore entry. + */ + public String saveJson() { + List list = new ArrayList<>(); + list.add(this); + + Gson gson = new GsonBuilder().setPrettyPrinting().create(); + return gson.toJson(list); } - // Only json saving is available. - // The NBT Variant should be saved to the mod's custom tag container due to the way lore must be formatted - public String saveJson() - { - - String obj = "{"; - obj += "\"bold\": " + bool2str(bold)+","; - obj += "\"italic\": " + bool2str(italic)+","; - obj += "\"underlined\": "+bool2str(underlined)+","; - obj += "\"strikethrough\": "+bool2str(strikethrough)+","; - obj += "\"obfuscated\": "+bool2str(obfuscated)+","; - obj += "\"color\": \""+color+"\","; - obj += "\"text\": \""+text+"\""; - obj += "}"; + /** + * Parses a JSON string to create a LoreEntry object. + * + * @param json The JSON string representing lore attributes. + * @return A LoreEntry object created from the JSON string. + */ - return obj; + public static LoreEntry parseJson(String json) { + Gson gson = new Gson(); + List list = gson.fromJson(json, new TypeToken>() {}.getType()); + if (list != null && !list.isEmpty()) { + return list.get(0); + } + + return null; } - public LoreEntry(){} + + /** + * Converts a boolean value to its string representation. + * + * @param a The boolean value to convert. + * @return The string representation of the boolean. + */ + private String bool2str(boolean a) { + return a ? "true" : "false"; + } } diff --git a/src/main/java/dev/zontreck/libzontreck/menus/ChestGUIMenu.java b/src/main/java/dev/zontreck/libzontreck/menus/ChestGUIMenu.java index c7b74dc..65e40a0 100644 --- a/src/main/java/dev/zontreck/libzontreck/menus/ChestGUIMenu.java +++ b/src/main/java/dev/zontreck/libzontreck/menus/ChestGUIMenu.java @@ -11,6 +11,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerListener; import net.minecraft.world.inventory.MenuConstructor; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.ItemStack; @@ -22,6 +23,7 @@ public class ChestGUIMenu extends AbstractContainerMenu { public final ChestGUI gui; public final ItemStackHandler slots; + public final Player player; public ChestGUIMenu(int id, Inventory playerInv, FriendlyByteBuf buf) { @@ -33,13 +35,15 @@ public class ChestGUIMenu extends AbstractContainerMenu super(ModMenuTypes.CHEST_GUI_MENU.get(), id); this.gui = gui; + this.player = player; - slots = new ChestGUIReadOnlyStackHandler(gui); + slots = new ChestGUIReadOnlyStackHandler(gui, player); int slotSize = 18; - int startX = 15; - int startY = 15; + int startX = 16; + int startY = 16; + for (int row = 0; row < 3; row++) { diff --git a/src/main/java/dev/zontreck/libzontreck/networking/ModMessages.java b/src/main/java/dev/zontreck/libzontreck/networking/ModMessages.java index ec110e0..9d47f08 100644 --- a/src/main/java/dev/zontreck/libzontreck/networking/ModMessages.java +++ b/src/main/java/dev/zontreck/libzontreck/networking/ModMessages.java @@ -2,8 +2,9 @@ package dev.zontreck.libzontreck.networking; import dev.zontreck.libzontreck.LibZontreck; import dev.zontreck.libzontreck.events.RegisterPacketsEvent; -import dev.zontreck.libzontreck.networking.packets.ChestGUIOpenC2S; import dev.zontreck.libzontreck.networking.packets.IPacket; +import dev.zontreck.libzontreck.networking.packets.S2CCloseChestGUI; +import dev.zontreck.libzontreck.networking.packets.S2CPlaySoundPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.common.MinecraftForge; @@ -45,11 +46,17 @@ public class ModMessages { packet.register(net); } - net.messageBuilder(ChestGUIOpenC2S.class, PACKET_ID.getAndIncrement(), NetworkDirection.PLAY_TO_SERVER) - .decoder(ChestGUIOpenC2S::new) - .encoder(ChestGUIOpenC2S::toBytes) - .consumerMainThread(ChestGUIOpenC2S::handle) - .add(); + net.messageBuilder(S2CPlaySoundPacket.class, PACKET_ID.getAndIncrement(), NetworkDirection.PLAY_TO_CLIENT) + .decoder(S2CPlaySoundPacket::new) + .encoder(S2CPlaySoundPacket::toBytes) + .consumerMainThread(S2CPlaySoundPacket::handle) + .add(); + + net.messageBuilder(S2CCloseChestGUI.class, PACKET_ID.getAndIncrement(), NetworkDirection.PLAY_TO_CLIENT) + .decoder(S2CCloseChestGUI::new) + .encoder(S2CCloseChestGUI::toBytes) + .consumerMainThread(S2CCloseChestGUI::handle) + .add(); } diff --git a/src/main/java/dev/zontreck/libzontreck/networking/NetworkEvents.java b/src/main/java/dev/zontreck/libzontreck/networking/NetworkEvents.java index ad473f9..13ef44a 100644 --- a/src/main/java/dev/zontreck/libzontreck/networking/NetworkEvents.java +++ b/src/main/java/dev/zontreck/libzontreck/networking/NetworkEvents.java @@ -12,7 +12,6 @@ public class NetworkEvents public void onRegisterPackets(RegisterPacketsEvent ev) { ev.packets.add(new S2CWalletUpdatedPacket()); - ev.packets.add(new S2CPlaySoundPacket()); ev.packets.add(new S2CWalletInitialSyncPacket()); } } diff --git a/src/main/java/dev/zontreck/libzontreck/networking/packets/ChestGUIOpenC2S.java b/src/main/java/dev/zontreck/libzontreck/networking/packets/ChestGUIOpenC2S.java deleted file mode 100644 index aa92c96..0000000 --- a/src/main/java/dev/zontreck/libzontreck/networking/packets/ChestGUIOpenC2S.java +++ /dev/null @@ -1,47 +0,0 @@ -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; - -/** - * To be used by first-party and third-party mods to assemble a menu - * NOTE: Without the server, only the credits menu will be able to be opened, which is the only built-in menu utilizing this system. - */ -public class ChestGUIOpenC2S { - private CompoundTag data; - - public ChestGUIOpenC2S(OpenGUIRequest request) - { - data = request.serialize(); - } - - public ChestGUIOpenC2S(FriendlyByteBuf buf) - { - data = buf.readAnySizeNbt(); - } - - public void toBytes(FriendlyByteBuf buf) - { - buf.writeNbt(data); - } - - public boolean handle(Supplier supplier) - { - NetworkEvent.Context ctx = supplier.get(); - - 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/packets/S2CCloseChestGUI.java b/src/main/java/dev/zontreck/libzontreck/networking/packets/S2CCloseChestGUI.java new file mode 100644 index 0000000..60021d1 --- /dev/null +++ b/src/main/java/dev/zontreck/libzontreck/networking/packets/S2CCloseChestGUI.java @@ -0,0 +1,39 @@ +package dev.zontreck.libzontreck.networking.packets; + +import dev.zontreck.libzontreck.chestgui.ChestGUI; +import dev.zontreck.libzontreck.menus.ChestGUIScreen; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.network.NetworkEvent; + +import java.util.function.Supplier; + +public class S2CCloseChestGUI +{ + + public S2CCloseChestGUI() + { + + } + + public S2CCloseChestGUI(FriendlyByteBuf buf) + { + + } + + public void toBytes(FriendlyByteBuf buf) + { + + } + + public void handle(Supplier supplier) + { + NetworkEvent.Context ctx = supplier.get(); + + ctx.enqueueWork(()->{ + // Close the GUI + if(Minecraft.getInstance().screen instanceof ChestGUIScreen) + Minecraft.getInstance().setScreen(null); + }); + } +} diff --git a/src/main/java/dev/zontreck/libzontreck/util/heads/CreditsEntry.java b/src/main/java/dev/zontreck/libzontreck/util/heads/CreditsEntry.java index e1946a6..d65ae03 100644 --- a/src/main/java/dev/zontreck/libzontreck/util/heads/CreditsEntry.java +++ b/src/main/java/dev/zontreck/libzontreck/util/heads/CreditsEntry.java @@ -1,6 +1,7 @@ package dev.zontreck.libzontreck.util.heads; import dev.zontreck.libzontreck.chat.ChatColor; +import dev.zontreck.libzontreck.lore.ExtraLore; import dev.zontreck.libzontreck.lore.LoreContainer; import dev.zontreck.libzontreck.lore.LoreEntry; import dev.zontreck.libzontreck.util.heads.HeadCache.HeadCacheItem; @@ -29,16 +30,17 @@ public class CreditsEntry { ItemStack stack = player.getAsItem(); stack.setHoverName(Component.literal(name)); LoreContainer contain = new LoreContainer(stack); - contain.miscData.LoreData.clear(); - LoreEntry entry = new LoreEntry(); - entry.text = ChatColor.doColors("!Dark_Purple!Role: "+role + "\n"); - entry.bold=true; - entry.italic=true; - contain.miscData.LoreData.add(entry); - entry = new LoreEntry(); - entry.text = ChatColor.doColors("!White!About: !Dark_Green!"+description + "\n"); - entry.italic=true; - contain.miscData.LoreData.add(entry); + contain.clear(); + LoreEntry.Builder builder = new LoreEntry.Builder(); + builder = builder.text(ChatColor.doColors("!Dark_Purple!Role: "+role + "\n")) + .bold(true) + .italic(true); + contain.miscData.loreData.add(builder.build()); + + builder = new LoreEntry.Builder().italic(true) + .text(ChatColor.doColors("!White!About: !Dark_Green!"+description + "\n")); + + contain.miscData.loreData.add(builder.build()); contain.commitLore(); diff --git a/src/main/java/dev/zontreck/libzontreck/util/heads/HeadCache.java b/src/main/java/dev/zontreck/libzontreck/util/heads/HeadCache.java index 7aaabdf..416a59f 100644 --- a/src/main/java/dev/zontreck/libzontreck/util/heads/HeadCache.java +++ b/src/main/java/dev/zontreck/libzontreck/util/heads/HeadCache.java @@ -102,11 +102,11 @@ public class HeadCache List creds = new ArrayList<>(); creds.add( - new CreditsEntry(HeadUtilities.cachedLookup("zontreck"), "Aria (zontreck)", "Developer", "Aria is the primary developer and project maintainer")); + new CreditsEntry(HeadUtilities.cachedLookup("zontreck"), "Aria (zontreck)", "Developer, Designer, Artist", "Aria is the primary developer and project maintainer")); creds.add( - new CreditsEntry(HeadUtilities.cachedLookup("PossumTheWarrior"), "PossumTheWarrior", "Tester", "Poss has helped to test the mods from very early on")); + new CreditsEntry(HeadUtilities.cachedLookup("PossumTheWarrior"), "PossumTheWarrior", "Tester, Adviser, Designer, Artist", "Poss has helped to test the mods from very early on. Poss has also contributed the artwork and mob model for the Possum")); creds.add( - new CreditsEntry(HeadUtilities.cachedLookup("GemMD"), "GemMD", "Adviser", "GemMD has provided advice on marketing and development decisions for various mods")); + new CreditsEntry(HeadUtilities.cachedLookup("GemMD"), "GemMD", "Tester, Adviser, Designer", "GemMD has provided advice on marketing and development decisions for various mods")); CREDITS = creds;