Chest GUI API now completed
This commit is contained in:
parent
01a6f1ddc7
commit
0fb37b1633
19 changed files with 436 additions and 239 deletions
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -18,7 +18,7 @@ public class ChestGUIButton
|
|||
{
|
||||
private Item icon;
|
||||
private String name;
|
||||
private List<LoreEntry> tooltipInfo;
|
||||
private List<LoreEntry> 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<LoreEntry> LoreData = new ArrayList<>();
|
||||
@SerializedName("extra")
|
||||
public List<LoreEntry> 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<LoreEntry> 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<Tag> 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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<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)+",";
|
||||
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<LoreEntry> list = gson.fromJson(json, new TypeToken<List<LoreEntry>>() {}.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";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -102,11 +102,11 @@ public class HeadCache
|
|||
List<CreditsEntry> 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;
|
||||
|
||||
|
|
Reference in a new issue