Chest GUI API now completed

This commit is contained in:
zontreck 2024-01-02 17:59:10 -07:00
parent 01a6f1ddc7
commit 0fb37b1633
19 changed files with 436 additions and 239 deletions

View file

@ -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. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=GPLv3 mod_license=GPLv3
# The mod version. See https://semver.org/ # 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. # 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. # This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html # See https://maven.apache.org/guides/mini/guide-naming-conventions.html

View file

@ -10,6 +10,7 @@ import java.util.UUID;
import dev.zontreck.ariaslib.util.DelayedExecutorService; import dev.zontreck.ariaslib.util.DelayedExecutorService;
import dev.zontreck.eventsbus.Bus; import dev.zontreck.eventsbus.Bus;
import dev.zontreck.libzontreck.chestgui.ChestGUIRegistry;
import dev.zontreck.libzontreck.currency.Bank; import dev.zontreck.libzontreck.currency.Bank;
import dev.zontreck.libzontreck.currency.CurrencyHelper; import dev.zontreck.libzontreck.currency.CurrencyHelper;
import dev.zontreck.libzontreck.menus.ChestGUIScreen; import dev.zontreck.libzontreck.menus.ChestGUIScreen;
@ -83,6 +84,7 @@ public class LibZontreck {
MinecraftForge.EVENT_BUS.register(new ForgeEventHandlers()); MinecraftForge.EVENT_BUS.register(new ForgeEventHandlers());
MinecraftForge.EVENT_BUS.register(new Commands()); MinecraftForge.EVENT_BUS.register(new Commands());
MinecraftForge.EVENT_BUS.register(new NetworkEvents()); MinecraftForge.EVENT_BUS.register(new NetworkEvents());
MinecraftForge.EVENT_BUS.register(ChestGUIRegistry.class);
Bus.Reset(); Bus.Reset();

View file

@ -1,8 +1,11 @@
package dev.zontreck.libzontreck.chestgui; package dev.zontreck.libzontreck.chestgui;
import dev.zontreck.libzontreck.LibZontreck; import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.events.CloseGUIEvent;
import dev.zontreck.libzontreck.events.OpenGUIEvent; import dev.zontreck.libzontreck.events.OpenGUIEvent;
import dev.zontreck.libzontreck.menus.ChestGUIMenu; 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.util.ServerUtilities;
import dev.zontreck.libzontreck.vectors.Vector2; import dev.zontreck.libzontreck.vectors.Vector2;
import dev.zontreck.libzontreck.vectors.Vector2i; import dev.zontreck.libzontreck.vectors.Vector2i;
@ -59,11 +62,24 @@ public class ChestGUI
{ {
if(LibZontreck.CURRENT_SIDE == LogicalSide.SERVER) 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"))); 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) public boolean isPlayer(UUID ID)
{ {
return player.equals(ID); return player.equals(ID);

View file

@ -18,7 +18,7 @@ public class ChestGUIButton
{ {
private Item icon; private Item icon;
private String name; private String name;
private List<LoreEntry> tooltipInfo; private List<LoreEntry> tooltipInfo = new ArrayList<>();
private Runnable callback; private Runnable callback;
private CompoundTag NBT = new CompoundTag(); private CompoundTag NBT = new CompoundTag();
@ -43,7 +43,7 @@ public class ChestGUIButton
this.position = position; this.position = position;
LoreContainer container = new LoreContainer(existing); LoreContainer container = new LoreContainer(existing);
tooltipInfo = container.miscData.LoreData; tooltipInfo = container.miscData.loreData;
name = existing.getHoverName().getString(); name = existing.getHoverName().getString();
icon = existing.getItem(); icon = existing.getItem();
NBT = existing.getTag(); NBT = existing.getTag();
@ -61,19 +61,17 @@ public class ChestGUIButton
ItemStack ret = new ItemStack(icon,1); ItemStack ret = new ItemStack(icon,1);
ret = ret.setHoverName(ChatHelpers.macro(name)); 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.putInt("slot", getSlotNum());
NBT.put("pos", position.serialize()); NBT.put("pos", position.serialize());
ret.setTag(NBT); ret.setTag(NBT);
LoreContainer cont = new LoreContainer(ret);
cont.clear();
cont.miscData.loreData.addAll(tooltipInfo);
cont.commitLore();
return ret; return ret;
} }

View file

@ -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<UUID, ChestGUI> 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;
}
}

View file

@ -6,6 +6,8 @@ import com.mojang.brigadier.CommandDispatcher;
import dev.zontreck.libzontreck.LibZontreck; import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.chestgui.ChestGUI; import dev.zontreck.libzontreck.chestgui.ChestGUI;
import dev.zontreck.libzontreck.chestgui.ChestGUIButton; 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.CreditsEntry;
import dev.zontreck.libzontreck.util.heads.HeadCache; import dev.zontreck.libzontreck.util.heads.HeadCache;
import dev.zontreck.libzontreck.vectors.Vector2i; import dev.zontreck.libzontreck.vectors.Vector2i;
@ -31,9 +33,11 @@ public class CreditsCommand {
int y = 0; int y = 0;
for(CreditsEntry entry : HeadCache.CREDITS) 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++; y++;
if(y>=9) if(y>=9)

View file

@ -3,18 +3,40 @@ package dev.zontreck.libzontreck.dynamicchest;
import dev.zontreck.libzontreck.LibZontreck; import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.chestgui.ChestGUI; import dev.zontreck.libzontreck.chestgui.ChestGUI;
import dev.zontreck.libzontreck.chestgui.ChestGUIButton; 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.minecraft.world.item.ItemStack;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.time.Instant;
public class ChestGUIReadOnlyStackHandler extends ItemStackHandler public class ChestGUIReadOnlyStackHandler extends ItemStackHandler
{ {
private ChestGUI gui; 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)); super((3*9));
this.gui = gui; this.gui = gui;
this.player = player;
LibZontreck.LOGGER.info("Logical Side : " + LibZontreck.CURRENT_SIDE); LibZontreck.LOGGER.info("Logical Side : " + LibZontreck.CURRENT_SIDE);
@ -43,12 +65,22 @@ public class ChestGUIReadOnlyStackHandler extends ItemStackHandler
@Override @Override
public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { 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; if(btn == null) return ItemStack.EMPTY;
if(validClick(slot))
{
btn.clicked(); btn.clicked();
lastClickTime = Instant.now().getEpochSecond();
lastClickStack = slot;
}
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
} }

View file

@ -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;
}
}

View file

@ -1,5 +1,6 @@
package dev.zontreck.libzontreck.events; package dev.zontreck.libzontreck.events;
import dev.zontreck.libzontreck.chestgui.ChestGUI;
import dev.zontreck.libzontreck.util.ServerUtilities; import dev.zontreck.libzontreck.util.ServerUtilities;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
@ -8,16 +9,17 @@ import net.minecraftforge.eventbus.api.Event;
import java.util.UUID; import java.util.UUID;
@Cancelable
public class OpenGUIEvent extends Event public class OpenGUIEvent extends Event
{ {
private ResourceLocation GUIId; private ResourceLocation GUIId;
private UUID playerID; private UUID playerID;
private final ChestGUI gui;
public OpenGUIEvent(ResourceLocation ID, UUID player) public OpenGUIEvent(ResourceLocation ID, UUID player, ChestGUI gui)
{ {
GUIId = ID; GUIId = ID;
playerID = player; playerID = player;
this.gui = gui;
} }
public boolean matches(ResourceLocation id) public boolean matches(ResourceLocation id)
@ -27,6 +29,10 @@ public class OpenGUIEvent extends Event
public ServerPlayer getPlayer() public ServerPlayer getPlayer()
{ {
return ServerUtilities.getPlayerByID(getPlayer().getStringUUID()); return ServerUtilities.getPlayerByID(playerID.toString());
}
public ChestGUI getGui() {
return gui;
} }
} }

View file

@ -4,69 +4,93 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; 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.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
// Extra container /**
* Represents a container for multiple LoreEntry instances.
*/
public class ExtraLore { public class ExtraLore {
public List<LoreEntry> LoreData = new ArrayList<>(); @SerializedName("extra")
public List<LoreEntry> loreData = new ArrayList<>();
/**
public void save(CompoundTag tag) * Saves the lore entries into a CompoundTag for storage.
{ *
ListTag lores = new ListTag(); * @param tag The CompoundTag to save the entries.
for (LoreEntry loreEntry : LoreData) { */
loreEntry.save(lores); public void save(CompoundTag tag) {
} ListTag lores = saveEntries();
// Extra entry in display:Lore list // Extra entry in display:Lore list
tag.put("extra", lores); 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(); ListTag lores = new ListTag();
for (LoreEntry tag : LoreData) { for (LoreEntry loreEntry : loreData) {
tag.save(lores); lores.add(StringTag.valueOf(loreEntry.saveJson()));
} }
return lores; 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(){ * Generates a JSON string representing the lore entries.
String ret = "{"; *
Iterator<LoreEntry> loreEntries = LoreData.iterator(); * @return The JSON string representing the lore entries.
ret += "\"extra\": ["; */
while(loreEntries.hasNext()) public String saveJson() {
{ Gson gson = new GsonBuilder().setPrettyPrinting().create();
LoreEntry loreEntryx = loreEntries.next(); return gson.toJson(this);
ret += loreEntryx.saveJson();
if(loreEntries.hasNext())
{
ret += ",";
}
}
ret += "],";
ret += "\"text\": \"\"";
ret += "}";
return ret;
} }
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); ListTag tag = tags.getList("extra", CompoundTag.TAG_COMPOUND);
Iterator<Tag> tagsx = tag.iterator(); for (Tag t : tag) {
while(tagsx.hasNext()) CompoundTag ct = (CompoundTag) t;
{ loreData.add(new LoreEntry(ct));
Tag t = tagsx.next();
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
} }
} }

View file

@ -8,118 +8,84 @@ import net.minecraft.nbt.Tag;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class LoreContainer { public class LoreContainer {
public int loreEntryNumber; private int loreEntryNumber;
public ExtraLore miscData; public ExtraLore miscData = new ExtraLore();
private final ItemStack associatedItem;
private ItemStack associatedItem; public LoreContainer(ItemStack stack) {
associatedItem = stack;
loreEntryNumber = getLoreEntryNumber(stack);
public LoreContainer(CompoundTag container, ItemStack associated) parseExistingLore(stack);
{
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) public void commitLore() {
{ assertLoreExists();
this.associatedItem=stack; CompoundTag tag = associatedItem.getOrCreateTag();
// 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();
CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY); 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); display.put(ItemStack.TAG_LORE, lore);
tag.put(ItemStack.TAG_DISPLAY, display); tag.put(ItemStack.TAG_DISPLAY, display);
associatedItem.setTag(tag); associatedItem.setTag(tag);
} }
private void SetOrUpdateIndex(ListTag lst, int pos, Tag insert) public void clear() {
{ loreEntryNumber = 0;
if(lst.size() <= pos){ 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); lst.add(insert);
// Update the loreEntryNumber loreEntryNumber = lst.size() - 1;
loreEntryNumber = lst.indexOf(insert); } else {
}else lst.set(pos, insert); lst.set(pos, insert);
}
} }
private void AssertLoreExists() private void assertLoreExists() {
{ assertTag();
AssertTag(); assertDisplay();
AssertDisplay(); assertLore();
AssertLore();
} }
private void AssertTag() private void assertTag() {
{ if (!associatedItem.hasTag()) {
if(!associatedItem.hasTag()){
associatedItem.setTag(new CompoundTag()); associatedItem.setTag(new CompoundTag());
} }
} }
private void AssertDisplay() private void assertDisplay() {
{ CompoundTag tag = associatedItem.getOrCreateTag();
CompoundTag tag = associatedItem.getTag();
CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY); CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY);
if(display==null) if (display.isEmpty()) {
{
tag.put(ItemStack.TAG_DISPLAY, new CompoundTag()); tag.put(ItemStack.TAG_DISPLAY, new CompoundTag());
associatedItem.setTag(tag); associatedItem.setTag(tag);
} }
} }
private void AssertLore() private void assertLore() {
{ CompoundTag tag = associatedItem.getOrCreateTag();
CompoundTag tag = associatedItem.getTag();
CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY); CompoundTag display = tag.getCompound(ItemStack.TAG_DISPLAY);
ListTag lore = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING); ListTag lore = display.getList(ItemStack.TAG_LORE, Tag.TAG_STRING);
if (lore.isEmpty()) {
if(lore == null) display.put(ItemStack.TAG_LORE, new ListTag());
{
lore = new ListTag();
display.put(ItemStack.TAG_LORE, lore);
tag.put(ItemStack.TAG_DISPLAY, display);
associatedItem.setTag(tag); 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);
}
} }

View file

@ -1,17 +1,89 @@
package dev.zontreck.libzontreck.lore; 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.CompoundTag;
import net.minecraft.nbt.ListTag; 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 bold;
public boolean italic; public boolean italic;
public boolean underlined; public boolean underlined;
public boolean strikethrough; public boolean strikethrough;
public boolean obfuscated; public boolean obfuscated;
public String color=""; public String color = "";
public String text=""; 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) public LoreEntry (CompoundTag tag)
{ {
@ -25,7 +97,12 @@ public class LoreEntry
text = tag.getString("text"); 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(); CompoundTag tag = new CompoundTag();
tag.putBoolean("bold", bold); tag.putBoolean("bold", bold);
tag.putBoolean("italic", italic); tag.putBoolean("italic", italic);
@ -38,30 +115,46 @@ public class LoreEntry
parentTag.add(tag); parentTag.add(tag);
} }
private String bool2str(boolean a){ /**
if(a)return "true"; * Generates a JSON string representing the lore entry.
else return "false"; *
* @return The JSON string representing the lore entry.
*/
public String saveJson() {
List<LoreEntry> 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)+","; * Parses a JSON string to create a LoreEntry object.
obj += "\"italic\": " + bool2str(italic)+","; *
obj += "\"underlined\": "+bool2str(underlined)+","; * @param json The JSON string representing lore attributes.
obj += "\"strikethrough\": "+bool2str(strikethrough)+","; * @return A LoreEntry object created from the JSON string.
obj += "\"obfuscated\": "+bool2str(obfuscated)+","; */
obj += "\"color\": \""+color+"\",";
obj += "\"text\": \""+text+"\"";
obj += "}";
public static LoreEntry parseJson(String json) {
Gson gson = new Gson();
List<LoreEntry> list = gson.fromJson(json, new TypeToken<List<LoreEntry>>() {}.getType());
return obj; if (list != null && !list.isEmpty()) {
return list.get(0);
} }
public LoreEntry(){} return null;
}
/**
* 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";
}
} }

View file

@ -11,6 +11,7 @@ import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerListener;
import net.minecraft.world.inventory.MenuConstructor; import net.minecraft.world.inventory.MenuConstructor;
import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -22,6 +23,7 @@ public class ChestGUIMenu extends AbstractContainerMenu
{ {
public final ChestGUI gui; public final ChestGUI gui;
public final ItemStackHandler slots; public final ItemStackHandler slots;
public final Player player;
public ChestGUIMenu(int id, Inventory playerInv, FriendlyByteBuf buf) public ChestGUIMenu(int id, Inventory playerInv, FriendlyByteBuf buf)
{ {
@ -33,13 +35,15 @@ public class ChestGUIMenu extends AbstractContainerMenu
super(ModMenuTypes.CHEST_GUI_MENU.get(), id); super(ModMenuTypes.CHEST_GUI_MENU.get(), id);
this.gui = gui; this.gui = gui;
this.player = player;
slots = new ChestGUIReadOnlyStackHandler(gui); slots = new ChestGUIReadOnlyStackHandler(gui, player);
int slotSize = 18; int slotSize = 18;
int startX = 15; int startX = 16;
int startY = 15; int startY = 16;
for (int row = 0; row < 3; row++) for (int row = 0; row < 3; row++)
{ {

View file

@ -2,8 +2,9 @@ package dev.zontreck.libzontreck.networking;
import dev.zontreck.libzontreck.LibZontreck; import dev.zontreck.libzontreck.LibZontreck;
import dev.zontreck.libzontreck.events.RegisterPacketsEvent; 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.IPacket;
import dev.zontreck.libzontreck.networking.packets.S2CCloseChestGUI;
import dev.zontreck.libzontreck.networking.packets.S2CPlaySoundPacket;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
@ -45,10 +46,16 @@ public class ModMessages {
packet.register(net); packet.register(net);
} }
net.messageBuilder(ChestGUIOpenC2S.class, PACKET_ID.getAndIncrement(), NetworkDirection.PLAY_TO_SERVER) net.messageBuilder(S2CPlaySoundPacket.class, PACKET_ID.getAndIncrement(), NetworkDirection.PLAY_TO_CLIENT)
.decoder(ChestGUIOpenC2S::new) .decoder(S2CPlaySoundPacket::new)
.encoder(ChestGUIOpenC2S::toBytes) .encoder(S2CPlaySoundPacket::toBytes)
.consumerMainThread(ChestGUIOpenC2S::handle) .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(); .add();
} }

View file

@ -12,7 +12,6 @@ public class NetworkEvents
public void onRegisterPackets(RegisterPacketsEvent ev) public void onRegisterPackets(RegisterPacketsEvent ev)
{ {
ev.packets.add(new S2CWalletUpdatedPacket()); ev.packets.add(new S2CWalletUpdatedPacket());
ev.packets.add(new S2CPlaySoundPacket());
ev.packets.add(new S2CWalletInitialSyncPacket()); ev.packets.add(new S2CWalletInitialSyncPacket());
} }
} }

View file

@ -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<NetworkEvent.Context> 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;
}
}

View file

@ -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<NetworkEvent.Context> supplier)
{
NetworkEvent.Context ctx = supplier.get();
ctx.enqueueWork(()->{
// Close the GUI
if(Minecraft.getInstance().screen instanceof ChestGUIScreen)
Minecraft.getInstance().setScreen(null);
});
}
}

View file

@ -1,6 +1,7 @@
package dev.zontreck.libzontreck.util.heads; package dev.zontreck.libzontreck.util.heads;
import dev.zontreck.libzontreck.chat.ChatColor; import dev.zontreck.libzontreck.chat.ChatColor;
import dev.zontreck.libzontreck.lore.ExtraLore;
import dev.zontreck.libzontreck.lore.LoreContainer; import dev.zontreck.libzontreck.lore.LoreContainer;
import dev.zontreck.libzontreck.lore.LoreEntry; import dev.zontreck.libzontreck.lore.LoreEntry;
import dev.zontreck.libzontreck.util.heads.HeadCache.HeadCacheItem; import dev.zontreck.libzontreck.util.heads.HeadCache.HeadCacheItem;
@ -29,16 +30,17 @@ public class CreditsEntry {
ItemStack stack = player.getAsItem(); ItemStack stack = player.getAsItem();
stack.setHoverName(Component.literal(name)); stack.setHoverName(Component.literal(name));
LoreContainer contain = new LoreContainer(stack); LoreContainer contain = new LoreContainer(stack);
contain.miscData.LoreData.clear(); contain.clear();
LoreEntry entry = new LoreEntry(); LoreEntry.Builder builder = new LoreEntry.Builder();
entry.text = ChatColor.doColors("!Dark_Purple!Role: "+role + "\n"); builder = builder.text(ChatColor.doColors("!Dark_Purple!Role: "+role + "\n"))
entry.bold=true; .bold(true)
entry.italic=true; .italic(true);
contain.miscData.LoreData.add(entry); contain.miscData.loreData.add(builder.build());
entry = new LoreEntry();
entry.text = ChatColor.doColors("!White!About: !Dark_Green!"+description + "\n"); builder = new LoreEntry.Builder().italic(true)
entry.italic=true; .text(ChatColor.doColors("!White!About: !Dark_Green!"+description + "\n"));
contain.miscData.LoreData.add(entry);
contain.miscData.loreData.add(builder.build());
contain.commitLore(); contain.commitLore();

View file

@ -102,11 +102,11 @@ public class HeadCache
List<CreditsEntry> creds = new ArrayList<>(); List<CreditsEntry> creds = new ArrayList<>();
creds.add( 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( 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( 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; CREDITS = creds;