From 61c53c0054431e75826d071dfb363406b5763195 Mon Sep 17 00:00:00 2001 From: NopoTheGamer <40329022+NopoTheGamer@users.noreply.github.com> Date: Fri, 23 Sep 2022 23:33:16 +1000 Subject: [PATCH] Pet overlay fixes (#290) * fixed pet overlay going to level 100 * fixed transparent pet and equip overlay not using the special texture fixed pet overlay showing a pet when you remove your pet * made pet overlay show the current stats of your pet * Fixed pet overlay showing Until level 100.0 * Fixed pet stats not showing decimal * Made pet overlay show xp to next level * 2.1.md slight smile * Try to generify pet lore replacements a tiny bit Also move pets page to use the same code as the pet overlay Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Co-authored-by: nea --- Update Notes/2.1.md | 1 + .../notenoughupdates/NEUManager.java | 3 +- .../listener/ItemTooltipListener.java | 72 +++-- .../miscfeatures/PetInfoOverlay.java | 9 +- .../overlays/EquipmentOverlay.java | 11 +- .../profileviewer/PetsPage.java | 266 ++-------------- .../util/ItemResolutionQuery.java | 7 + .../notenoughupdates/util/ItemUtils.java | 284 +++++++++++++++++- 8 files changed, 368 insertions(+), 285 deletions(-) diff --git a/Update Notes/2.1.md b/Update Notes/2.1.md index 99b2eef0d7..1c623928d7 100644 --- a/Update Notes/2.1.md +++ b/Update Notes/2.1.md @@ -157,6 +157,7 @@ - Fixed skill average calculation to include carpentry in /peek - whalker - Fixed middle clicking on pets not registering pet swap - nopo - Fixed middle clicking on an item with no id searching for it - nopo +- Fixed pets with decimal stats not showing in pv - nopo ### **Other:** diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 92e2cfd649..62b2411132 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -1380,7 +1380,7 @@ public HashMap getLoreReplacements(String petname, String tier, float statMax = entry.getValue().getAsFloat(); float statMin = min.get("statNums").getAsJsonObject().get(entry.getKey()).getAsFloat(); float val = statMin * minMix + statMax * maxMix; - String statStr = (statMin > 0 ? "+" : "") + (int) Math.floor(val); + String statStr = (statMin > 0 ? "+" : "") + removeUnusedDecimal(Math.floor(val * 10) / 10); replacements.put(entry.getKey(), statStr); } } @@ -1457,6 +1457,7 @@ public ItemStack jsonToStack(JsonObject json, boolean useCache, boolean useRepla } public ItemStack jsonToStack(JsonObject json, boolean useCache, boolean useReplacements, boolean copyStack) { + if (useReplacements) useCache = false; if (json == null) return new ItemStack(Items.painting, 1, 10); String internalname = json.get("internalname").getAsString(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java index c522e70ae8..d89e886f76 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java @@ -55,7 +55,6 @@ import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -67,7 +66,7 @@ import java.util.regex.Pattern; public class ItemTooltipListener { - private static final String petToolTipRegex = + public static final String petToolTipRegex = "((Farming)|(Combat)|(Fishing)|(Mining)|(Foraging)|(Enchanting)|(Alchemy)) ((Mount)|(Pet)|(Morph)).*"; private final NotEnoughUpdates neu; private final Pattern xpLevelPattern = Pattern.compile("(.*) (\\xA7e(.*)\\xA76/\\xA7e(.*))"); @@ -711,45 +710,44 @@ public void onItemTooltipLow(ItemTooltipEvent event) { } private void petToolTipXPExtendPetMenu(ItemTooltipEvent event) { - if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) { - //7 is just a random number i chose, prob no pets with less lines than 7 - if (event.toolTip.size() > 7) { - if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { - GuiProfileViewer.PetLevel petLevel; - - int xpLine = -1; - for (int i = event.toolTip.size() - 1; i >= 0; i--) { - Matcher matcher = xpLevelPattern.matcher(event.toolTip.get(i)); - if (matcher.matches()) { - xpLine = i; - event.toolTip.set(xpLine, matcher.group(1)); - break; - } else if (event.toolTip.get(i).matches("MAX LEVEL")) { - return; - } - } + if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) return; + //7 is just a random number i chose, prob no pets with less lines than 7 + if (event.toolTip.size() < 7) return; + if (event.itemStack.getTagCompound().hasKey("NEUHIDEPETTOOLTIP")) return; + if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) { + GuiProfileViewer.PetLevel petLevel; + + int xpLine = -1; + for (int i = event.toolTip.size() - 1; i >= 0; i--) { + Matcher matcher = xpLevelPattern.matcher(event.toolTip.get(i)); + if (matcher.matches()) { + xpLine = i; + event.toolTip.set(xpLine, matcher.group(1)); + break; + } else if (event.toolTip.get(i).matches("MAX LEVEL")) { + return; + } + } - PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack( - event.itemStack.getTagCompound() - ); - if (pet == null) { - return; - } - petLevel = pet.petLevel; + PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack( + event.itemStack.getTagCompound() + ); + if (pet == null) { + return; + } + petLevel = pet.petLevel; - if (petLevel == null || xpLine == -1) { - return; - } + if (petLevel == null || xpLine == -1) { + return; + } - event.toolTip.add( - xpLine + 1, - EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petLevel.levelXp) + - EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + - myFormatter.format(petLevel.currentLevelRequirement) - ); + event.toolTip.add( + xpLine + 1, + EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petLevel.levelXp) + + EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + + myFormatter.format(petLevel.currentLevelRequirement) + ); - } - } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java index 14a136a28d..499448fa72 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java @@ -133,10 +133,11 @@ public static class Pet { public String petXpType; public String petItem; public String skin; + public int candyUsed; public String getPetId(boolean withoutBoost) { - return petType + ";" + (withoutBoost ? rarity.petId - 1 : rarity.petId); - + boolean shouldDecreaseRarity = withoutBoost && "PET_ITEM_TIER_BOOST".equals(petItem); + return petType + ";" + (shouldDecreaseRarity ? rarity.petId - 1 : rarity.petId); } } @@ -466,10 +467,10 @@ private List createStringsForPet(Pet currentPet, boolean secondPet) { float remainingMax = currentPet.petLevel.maxXP - currentPet.petLevel.totalXp; if (remaining > 0) { if (xpGain < 1000) { - etaMaxStr = EnumChatFormatting.AQUA + "Until L" + currentPet.petLevel.maxLevel + ": " + + etaMaxStr = EnumChatFormatting.AQUA + "Until L" + (int) currentPet.petLevel.maxLevel + ": " + EnumChatFormatting.YELLOW + "N/A"; } else { - etaMaxStr = EnumChatFormatting.AQUA + "Until L" + currentPet.petLevel.maxLevel + ": " + + etaMaxStr = EnumChatFormatting.AQUA + "Until L" + (int) currentPet.petLevel.maxLevel + ": " + EnumChatFormatting.YELLOW + Utils.prettyTime((long) (remainingMax) * 1000 * 60 * 60 / (long) xpGain); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java index 2d3175b59b..d64dbe014c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java @@ -106,7 +106,7 @@ public ResourceLocation getCustomEquipmentTexture(boolean isPetRendering) { case 2: return ARMOR_DISPLAY_DARK; case 3: - return isPetRendering ? ARMOR_DISPLAY_TRANSPARENT_PET : ARMOR_DISPLAY_TRANSPARENT; + return NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 3 && isPetRendering ? ARMOR_DISPLAY_TRANSPARENT_PET : ARMOR_DISPLAY_TRANSPARENT; case 4: return ARMOR_DISPLAY_FSR; } @@ -191,7 +191,7 @@ public void renderEquipmentGui(GuiInventory guiScreen, int mouseX, int mouseY, i int overlayLeft = container.getGuiLeft() - ARMOR_OVERLAY_OVERHAND_WIDTH; int overlayTop = container.getGuiTop(); - ResourceLocation equipmentTexture = getCustomEquipmentTexture(isRenderingPet); + ResourceLocation equipmentTexture = getCustomEquipmentTexture(shouldRenderPets); Minecraft.getMinecraft().getTextureManager().bindTexture(equipmentTexture); Utils.drawTexturedRect(overlayLeft, overlayTop, ARMOR_OVERLAY_WIDTH, ARMOR_OVERLAY_HEIGHT, GL11.GL_NEAREST); @@ -243,7 +243,10 @@ private ItemStack getRepoPetStack() { NEUManager manager = NotEnoughUpdates.INSTANCE.manager; PetInfoOverlay.Pet currentPet = PetInfoOverlay.getCurrentPet(); if (currentPet == null) return null; - ItemStack item = manager.createItem(currentPet.getPetId(false)); + + ItemStack item = ItemUtils.createPetItemstackFromPetInfo(currentPet); + item = ItemUtils.petToolTipXPExtendPetOverlay(item); + if (item != null) { return item; } @@ -259,7 +262,7 @@ private void updateGuiInfo(GuiScreen screen) { slot4 = getWardrobeSlot(37); } - if (screen instanceof GuiChest) { + if (screen instanceof GuiChest || screen instanceof GuiInventory) { petStack = getRepoPetStack(); } if ((!(screen instanceof GuiInventory) && !(screen instanceof GuiInvButtonEditor)) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java index 25751ab808..cb85bf7971 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java @@ -22,22 +22,17 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.ItemUtils; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.init.Items; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.JsonToNBT; -import net.minecraft.nbt.NBTException; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTTagString; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Mouse; @@ -46,11 +41,7 @@ import java.awt.*; import java.io.IOException; import java.util.ArrayList; -import java.util.Base64; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.UUID; public class PetsPage extends GuiProfileViewerPage { @@ -91,7 +82,8 @@ public void drawPage(int mouseX, int mouseY, float partialTicks) { String panoramaIdentifier = "day"; if (SBInfo.getInstance().currentTimeDate != null) { - if (SBInfo.getInstance().currentTimeDate.getHours() <= 6 || SBInfo.getInstance().currentTimeDate.getHours() >= 20) { + if (SBInfo.getInstance().currentTimeDate.getHours() <= 6 || + SBInfo.getInstance().currentTimeDate.getHours() >= 20) { panoramaIdentifier = "night"; } } @@ -123,201 +115,22 @@ public void drawPage(int mouseX, int mouseY, float partialTicks) { } }); for (JsonObject pet : sortedPets) { - String petname = pet.get("type").getAsString(); - String tier = pet.get("tier").getAsString(); - String heldItem = Utils.getElementAsString(pet.get("heldItem"), null); - String skin = Utils.getElementAsString(pet.get("skin"), null); - int candy = pet.get("candyUsed").getAsInt(); - JsonObject heldItemJson = heldItem == null ? null : NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(heldItem); - String tierNum = GuiProfileViewer.MINION_RARITY_TO_NUM.get(tier); - float exp = pet.get("exp").getAsFloat(); - if (tierNum == null) continue; - - if ( - pet.has("heldItem") && - !pet.get("heldItem").isJsonNull() && - pet.get("heldItem").getAsString().equals("PET_ITEM_TIER_BOOST") - ) { - tierNum = "" + (Integer.parseInt(tierNum) + 1); - } - - GuiProfileViewer.PetLevel levelObj = GuiProfileViewer.getPetLevel(petname, tier, exp); - - float level = levelObj.level; - float currentLevelRequirement = levelObj.currentLevelRequirement; - float maxXP = levelObj.maxXP; - pet.addProperty("level", level); - pet.addProperty("currentLevelRequirement", currentLevelRequirement); - pet.addProperty("maxXP", maxXP); - - JsonObject petItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(petname + ";" + tierNum); - ItemStack stack; - if (petItem == null) { - stack = getQuestionmarkSkull(); - NBTTagCompound display = new NBTTagCompound(); - if (stack.getTagCompound() != null && stack.getTagCompound().hasKey("display")) { - display = stack.getTagCompound().getCompoundTag("display"); - } - NBTTagList lore = new NBTTagList(); - lore.appendTag(new NBTTagString(EnumChatFormatting.RED + "This pet is not saved in the repository")); - lore.appendTag(new NBTTagString("")); - lore.appendTag(new NBTTagString(EnumChatFormatting.RED + "If you expected it to be there please send a message in")); - lore.appendTag( - new NBTTagString( - EnumChatFormatting.RED.toString() + - EnumChatFormatting.BOLD + - "#neu-support " + - EnumChatFormatting.RESET + - EnumChatFormatting.RED + - "on " + - EnumChatFormatting.BOLD + - "discord.gg/moulberry" - ) - ); - - display.setTag("Lore", lore); - NBTTagCompound tag = stack.getTagCompound() != null ? stack.getTagCompound() : new NBTTagCompound(); - tag.setTag("display", display); - stack.setTagCompound(tag); - } else { - stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(petItem, false, false); - HashMap replacements = NotEnoughUpdates.INSTANCE.manager.getLoreReplacements( - petname, - tier, - (int) Math.floor(level) - ); - - if (heldItem != null) { - HashMap petStatBoots = GuiProfileViewer.PET_STAT_BOOSTS.get(heldItem); - HashMap petStatBootsMult = GuiProfileViewer.PET_STAT_BOOSTS_MULT.get(heldItem); - if (petStatBoots != null) { - for (Map.Entry entryBoost : petStatBoots.entrySet()) { - try { - float value = Float.parseFloat(replacements.get(entryBoost.getKey())); - replacements.put(entryBoost.getKey(), String.valueOf((int) Math.floor(value + entryBoost.getValue()))); - } catch (Exception ignored) {} - } - } - if (petStatBootsMult != null) { - for (Map.Entry entryBoost : petStatBootsMult.entrySet()) { - try { - float value = Float.parseFloat(replacements.get(entryBoost.getKey())); - replacements.put(entryBoost.getKey(), String.valueOf((int) Math.floor(value * entryBoost.getValue()))); - } catch (Exception ignored) {} - } - } - } - - NBTTagCompound tag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound(); - if (tag.hasKey("display", 10)) { - NBTTagCompound display = tag.getCompoundTag("display"); - if (display.hasKey("Lore", 9)) { - NBTTagList newLore = new NBTTagList(); - NBTTagList lore = display.getTagList("Lore", 8); - HashMap blankLocations = new HashMap<>(); - for (int j = 0; j < lore.tagCount(); j++) { - String line = lore.getStringTagAt(j); - if (line.trim().isEmpty()) { - blankLocations.put(blankLocations.size(), j); - } - for (Map.Entry replacement : replacements.entrySet()) { - line = line.replace("{" + replacement.getKey() + "}", replacement.getValue()); - } - newLore.appendTag(new NBTTagString(line)); - } - Integer secondLastBlank = blankLocations.get(blankLocations.size() - 2); - if (skin != null) { - JsonObject petSkin = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("PET_SKIN_" + skin); - if (petSkin != null) { - try { - NBTTagCompound nbt = JsonToNBT.getTagFromJson(petSkin.get("nbttag").getAsString()); - tag.setTag("SkullOwner", nbt.getTag("SkullOwner")); - String name = petSkin.get("displayname").getAsString(); - if (name != null) { - name = Utils.cleanColour(name); - newLore.set(0, new NBTTagString(newLore.get(0).toString().replace("\"", "") + ", " + name)); - } - } catch (NBTException e) { - e.printStackTrace(); - } - } - } - for (int i = 0; i < newLore.tagCount(); i++) { - String cleaned = Utils.cleanColour(newLore.get(i).toString()); - if (cleaned.equals("\"Right-click to add this pet to\"")) { - newLore.removeTag(i + 1); - newLore.removeTag(i); - secondLastBlank = i - 1; - break; - } - } - NBTTagList temp = new NBTTagList(); - for (int i = 0; i < newLore.tagCount(); i++) { - temp.appendTag(newLore.get(i)); - if (secondLastBlank != null && i == secondLastBlank) { - if (heldItem != null) { - temp.appendTag( - new NBTTagString( - EnumChatFormatting.GOLD + "Held Item: " + heldItemJson.get("displayname").getAsString() - ) - ); - int blanks = 0; - JsonArray heldItemLore = heldItemJson.get("lore").getAsJsonArray(); - for (int k = 0; k < heldItemLore.size(); k++) { - String heldItemLine = heldItemLore.get(k).getAsString(); - if (heldItemLine.trim().isEmpty()) { - blanks++; - } else if (blanks == 2) { - temp.appendTag(new NBTTagString(heldItemLine)); - } else if (blanks > 2) { - break; - } - } - temp.appendTag(new NBTTagString()); - } - if (candy != 0) { - temp.appendTag(new NBTTagString(EnumChatFormatting.GREEN + "(" + candy + "/10) Pet Candy Used")); - temp.appendTag(new NBTTagString()); - } - temp.removeTag(temp.tagCount() - 1); - } - } - newLore = temp; - display.setTag("Lore", newLore); - } - if (display.hasKey("Name", 8)) { - String displayName = display.getString("Name"); - for (Map.Entry replacement : replacements.entrySet()) { - displayName = displayName.replace("{" + replacement.getKey() + "}", replacement.getValue()); - } - display.setTag("Name", new NBTTagString(displayName)); - } - tag.setTag("display", display); - } - - // Adds the missing pet fields to the tag - NBTTagCompound extraAttributes = new NBTTagCompound(); - JsonObject petInfo = new JsonObject(); - if(tag.hasKey("ExtraAttributes", 10)) { - extraAttributes = tag.getCompoundTag("ExtraAttributes"); - if (extraAttributes.hasKey("petInfo", 8)) { - petInfo = new JsonParser().parse(extraAttributes.getString("petInfo")).getAsJsonObject(); - } - } - petInfo.addProperty("exp", exp); - petInfo.addProperty("tier", tier); - petInfo.addProperty("type", petname); - if (heldItem != null) { - petInfo.addProperty("heldItem", heldItem); - } - if (skin != null) { - petInfo.addProperty("skin", skin); - } - extraAttributes.setString("petInfo", petInfo.toString()); - tag.setTag("ExtraAttributes", extraAttributes); - stack.setTagCompound(tag); - } - sortedPetsStack.add(stack); + PetInfoOverlay.Pet parsedPet = new PetInfoOverlay.Pet(); + parsedPet.petType = pet.get("type").getAsString(); + parsedPet.rarity = PetInfoOverlay.Rarity.valueOf(pet.get("tier").getAsString()); + parsedPet.petLevel = GuiProfileViewer.getPetLevel( + parsedPet.petType, + parsedPet.rarity.name(), + pet.get("exp").getAsFloat() + ); + parsedPet.petXpType = "unknown"; + parsedPet.petItem = Utils.getElementAsString(pet.get("heldItem"), null); + parsedPet.skin = Utils.getElementAsString(pet.get("skin"), null); + parsedPet.candyUsed = pet.get("candyUsed").getAsInt(); + sortedPetsStack.add(ItemUtils.createPetItemstackFromPetInfo(parsedPet)); + pet.addProperty("level", parsedPet.petLevel.level); + pet.addProperty("currentLevelRequirement", parsedPet.petLevel.currentLevelRequirement); + pet.addProperty("maxXP", parsedPet.petLevel.maxXP); } } @@ -396,7 +209,11 @@ public void drawPage(int mouseX, int mouseY, float partialTicks) { ); } - for (int i = petsPage * 20; i < Math.min(petsPage * 20 + 20, Math.min(sortedPetsStack.size(), sortedPets.size())); i++) { + for ( + int i = petsPage * 20; + i < Math.min(petsPage * 20 + 20, Math.min(sortedPetsStack.size(), sortedPets.size())); + i++ + ) { JsonObject pet = sortedPets.get(i); ItemStack stack = sortedPetsStack.get(i); @@ -433,7 +250,7 @@ public void drawPage(int mouseX, int mouseY, float partialTicks) { if (selectedPet >= 0) { ItemStack petStack; if (sortedPetsStack.size() <= selectedPet) { - petStack = getQuestionmarkSkull(); + petStack = ItemUtils.createQuestionMarkSkull("§cInvalid pet selection"); } else { petStack = sortedPetsStack.get(selectedPet); } @@ -441,7 +258,8 @@ public void drawPage(int mouseX, int mouseY, float partialTicks) { JsonObject pet = sortedPets.get(selectedPet); int x = guiLeft + 280; - float y = guiTop + 67 + 15 * (float) Math.sin(((getInstance().currentTime - getInstance().startTime) / 800f) % (2 * Math.PI)); + float y = guiTop + 67 + 15 * (float) Math.sin( + ((getInstance().currentTime - getInstance().startTime) / 800f) % (2 * Math.PI)); int displayLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(display); int halfDisplayLen = displayLen / 2; @@ -568,32 +386,4 @@ public void resetCache() { sortedPetsStack = null; selectedPet = -1; } - - private ItemStack getQuestionmarkSkull() { - String textureLink = "bc8ea1f51f253ff5142ca11ae45193a4ad8c3ab5e9c6eec8ba7a4fcb7bac40"; - - String b64Decoded = "{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + textureLink + "\"}}}"; - String b64Encoded = new String(Base64.getEncoder().encode(b64Decoded.getBytes())); - - ItemStack stack = new ItemStack(Items.skull, 1, 3); - NBTTagCompound nbt = new NBTTagCompound(); - NBTTagCompound skullOwner = new NBTTagCompound(); - NBTTagCompound properties = new NBTTagCompound(); - NBTTagList textures = new NBTTagList(); - NBTTagCompound textures_0 = new NBTTagCompound(); - - String uuid = UUID.nameUUIDFromBytes(b64Encoded.getBytes()).toString(); - skullOwner.setString("Id", uuid); - skullOwner.setString("Name", uuid); - - textures_0.setString("Value", b64Encoded); - textures.appendTag(textures_0); - - properties.setTag("textures", textures); - skullOwner.setTag("Properties", properties); - nbt.setTag("SkullOwner", skullOwner); - stack.setTagCompound(nbt); - stack.setStackDisplayName(EnumChatFormatting.RED + "Unknown Pet"); - return stack; - } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java index 75086b1fd3..4d3b464597 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java @@ -138,6 +138,13 @@ public ItemStack resolveToItemStack() { return manager.jsonToStack(jsonObject); } + @Nullable + public ItemStack resolveToItemStack(boolean useReplacements) { + JsonObject jsonObject = resolveToItemListJson(); + if (jsonObject == null) return null; + return manager.jsonToStack(jsonObject, false, useReplacements); + } + // private boolean isBazaar(IInventory chest) { if (chest.getDisplayName().getFormattedText().startsWith("Bazaar ➜ ")) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java index c7c7d4b645..a8f6e960b5 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java @@ -20,16 +20,31 @@ package io.github.moulberry.notenoughupdates.util; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.listener.ItemTooltipListener; +import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.JsonToNBT; +import net.minecraft.nbt.NBTException; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MathHelper; +import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.Map; +import java.util.function.BiFunction; public class ItemUtils { @@ -58,6 +73,14 @@ public static ItemStack getCoinItemStack(long coinAmount) { return skull; } + public static ItemStack createQuestionMarkSkull(String label) { + return Utils.createSkull( + label, + "00000000-0000-0000-0000-000000000000", + "bc8ea1f51f253ff5142ca11ae45193a4ad8c3ab5e9c6eec8ba7a4fcb7bac40" + ); + } + public static NBTTagCompound getOrCreateTag(ItemStack is) { if (is.hasTagCompound()) return is.getTagCompound(); NBTTagCompound nbtTagCompound = new NBTTagCompound(); @@ -120,8 +143,267 @@ public static String fixEnchantId(String enchId, boolean useId) { return enchId; } + /** + * Mutates baseValues + */ + public static void modifyReplacement( + Map baseValues, + Map modifiers, + BiFunction mapper + ) { + if (modifiers == null || baseValues == null) return; + for (Map.Entry modifier : modifiers.entrySet()) { + String baseValue = baseValues.get(modifier.getKey()); + if (baseValue == null) continue; + try { + baseValues.put(modifier.getKey(), mapper.apply(baseValue, modifier.getValue())); + } catch (Exception e) { + System.out.println("Exception during replacement mapping: "); + e.printStackTrace(); + } + } + } + + public static String applyReplacements(Map replacements, String text) { + for (Map.Entry replacement : replacements.entrySet()) { + String search = "{" + replacement.getKey() + "}"; + text = text.replace(search, replacement.getValue()); + } + return text; + } + + public static ItemStack createPetItemstackFromPetInfo(PetInfoOverlay.Pet currentPet) { + JsonObject pet = NotEnoughUpdates.INSTANCE.manager.getJsonForItem(NotEnoughUpdates.INSTANCE.manager.createItem( + currentPet.getPetId(false))); + String petname = currentPet.petType; + String tier = Utils.getRarityFromInt(currentPet.rarity.petId).toUpperCase(); + String heldItem = currentPet.petItem; + String skin = currentPet.skin; + JsonObject heldItemJson = heldItem == null ? null : NotEnoughUpdates.INSTANCE.manager.getItemInformation().get( + heldItem); + String petId = currentPet.getPetId(false); + float exp = currentPet.petLevel.totalXp; + + GuiProfileViewer.PetLevel levelObj = GuiProfileViewer.getPetLevel(petname, tier, exp); + + float level = levelObj.level; + float currentLevelRequirement = levelObj.currentLevelRequirement; + float maxXP = levelObj.maxXP; + pet.addProperty("level", level); + pet.addProperty("currentLevelRequirement", currentLevelRequirement); + pet.addProperty("maxXP", maxXP); + + ItemStack petItemstack = NotEnoughUpdates.INSTANCE.manager + .createItemResolutionQuery() + .withKnownInternalName(petId) + .resolveToItemStack(false); + if (petItemstack == null) { + petItemstack = ItemUtils.createQuestionMarkSkull(EnumChatFormatting.RED + "Unknown Pet"); + appendLore(petItemstack, Arrays.asList( + "§cThis pet is not saved in the repository", + "", + "§cIf you expected it to be there please send a message in", + "§c§l#neu-support §r§con §ldiscord.gg/moulberry" + )); + } + Map replacements = NotEnoughUpdates.INSTANCE.manager.getLoreReplacements( + petname, + tier, + MathHelper.floor_float(level) + ); + + if (heldItem != null) { + modifyReplacement(replacements, GuiProfileViewer.PET_STAT_BOOSTS.get(heldItem), (original, modifier) -> + "" + MathHelper.floor_float(Float.parseFloat(original) + modifier)); + modifyReplacement(replacements, GuiProfileViewer.PET_STAT_BOOSTS_MULT.get(heldItem), (original, modifier) -> + "" + MathHelper.floor_float(Float.parseFloat(original) * modifier)); + } + + NBTTagCompound tag = getOrCreateTag(petItemstack); + if (tag.hasKey("display", 10)) { + NBTTagCompound displayTag = tag.getCompoundTag("display"); + if (displayTag.hasKey("Lore", 9)) { + List newLore = new ArrayList<>(); + NBTTagList lore = displayTag.getTagList("Lore", 8); + int secondLastBlankLine = -1, lastBlankLine = -1; + for (int j = 0; j < lore.tagCount(); j++) { + String line = lore.getStringTagAt(j); + if (line.trim().isEmpty()) { + secondLastBlankLine = lastBlankLine; + lastBlankLine = j; + } + line = applyReplacements(replacements, line); + newLore.add(line); + } + if (skin != null) { + JsonObject petSkin = NotEnoughUpdates.INSTANCE.manager + .createItemResolutionQuery() + .withKnownInternalName("PET_SKIN_" + skin) + .resolveToItemListJson(); + if (petSkin != null) { + try { + NBTTagCompound nbt = JsonToNBT.getTagFromJson(petSkin.get("nbttag").getAsString()); + tag.setTag("SkullOwner", nbt.getTag("SkullOwner")); + String name = petSkin.get("displayname").getAsString(); + if (name != null) { + name = Utils.cleanColour(name); + newLore.set(0, newLore.get(0) + ", " + name); + } + } catch (NBTException e) { + e.printStackTrace(); + } + } + } + for (int i = 0; i < newLore.size(); i++) { + String cleaned = Utils.cleanColour(newLore.get(i)); + if (cleaned.equals("Right-click to add this pet to")) { + newLore.remove(i + 1); + newLore.remove(i); + secondLastBlankLine = i - 1; + break; + } + } + if (secondLastBlankLine != -1) { + List petItemLore = new ArrayList<>(); + if (heldItem != null) { + petItemLore.add(EnumChatFormatting.GOLD + "Held Item: " + heldItemJson.get("displayname").getAsString()); + List heldItemLore = JsonUtils.getJsonArrayOrEmpty(heldItemJson, "lore", JsonElement::getAsString); + int blanks = 0; + for (String heldItemLoreLine : heldItemLore) { + if (heldItemLoreLine.trim().isEmpty()) { + blanks++; + } else if (blanks == 2) { + petItemLore.add(heldItemLoreLine); + } else if (blanks > 2) { + break; + } + } + } + if (currentPet.candyUsed > 0) { + if (petItemLore.size() > 0) { + petItemLore.add(""); + } + petItemLore.add("§a(" + currentPet.candyUsed + "/10) Pet Candy Used"); + } + newLore.addAll(secondLastBlankLine + 1, petItemLore); + } + NBTTagList temp = new NBTTagList(); + for (String loreLine : newLore) { + temp.appendTag(new NBTTagString(loreLine)); + } + displayTag.setTag("Lore", temp); + } + + if (displayTag.hasKey("Name", 8)) { + String displayName = displayTag.getString("Name"); + displayName = applyReplacements(replacements, displayName); + displayTag.setTag("Name", new NBTTagString(displayName)); + } + tag.setTag("display", displayTag); + } + + // Adds the missing pet fields to the tag + NBTTagCompound extraAttributes = new NBTTagCompound(); + JsonObject petInfo = new JsonObject(); + if (tag.hasKey("ExtraAttributes", 10)) { + extraAttributes = tag.getCompoundTag("ExtraAttributes"); + if (extraAttributes.hasKey("petInfo", 8)) { + petInfo = new JsonParser().parse(extraAttributes.getString("petInfo")).getAsJsonObject(); + } + } + petInfo.addProperty("exp", exp); + petInfo.addProperty("tier", tier); + petInfo.addProperty("type", petname); + if (heldItem != null) { + petInfo.addProperty("heldItem", heldItem); + } + if (skin != null) { + petInfo.addProperty("skin", skin); + } + extraAttributes.setString("petInfo", petInfo.toString()); + tag.setTag("ExtraAttributes", extraAttributes); + petItemstack.setTagCompound(tag); + return petItemstack; + } + + private static final DecimalFormat decimalFormatter = new DecimalFormat("#,###,###.###"); + + public static ItemStack petToolTipXPExtendPetOverlay(ItemStack stack) { + NBTTagCompound tag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound(); + if (tag.hasKey("display", 10)) { + NBTTagCompound display = tag.getCompoundTag("display"); + if (display.hasKey("Lore", 9)) { + NBTTagList lore = display.getTagList("Lore", 8); + if (Utils.cleanColour(lore.getStringTagAt(0)).matches(ItemTooltipListener.petToolTipRegex) && + lore.tagCount() > 7) { + + GuiProfileViewer.PetLevel petLevel; + + PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack( + stack.getTagCompound() + ); + if (pet == null) return stack; + petLevel = pet.petLevel; + if (petLevel == null) return stack; + + NBTTagList newLore = new NBTTagList(); + int maxLvl = 100; + if (Constants.PETS != null && Constants.PETS.has("custom_pet_leveling") && + Constants.PETS.getAsJsonObject("custom_pet_leveling").has(pet.petType.toUpperCase()) && + Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(pet.petType.toUpperCase()).has( + "max_level")) { + maxLvl = + Constants.PETS + .getAsJsonObject("custom_pet_leveling") + .getAsJsonObject(pet.petType.toUpperCase()) + .get("max_level") + .getAsInt(); + } + for (int i = 0; i < lore.tagCount(); i++) { + if (i == lore.tagCount() - 2) { + newLore.appendTag(new NBTTagString("")); + if (petLevel.level >= maxLvl) { + newLore.appendTag(new NBTTagString( + EnumChatFormatting.AQUA + "" + EnumChatFormatting.BOLD + "MAX LEVEL")); + } else { + double levelPercent = (Math.round(petLevel.levelPercentage * 1000) / 10.0); + newLore.appendTag(new NBTTagString( + EnumChatFormatting.GRAY + "Progress to Level " + (int) (petLevel.level + 1) + ": " + + EnumChatFormatting.YELLOW + levelPercent + "%")); + StringBuilder sb = new StringBuilder(); + + for (int j = 0; j < 20; j++) { + if (j < (levelPercent / 5)) { + sb.append(EnumChatFormatting.DARK_GREEN); + } else { + sb.append(EnumChatFormatting.GRAY); + } + sb.append("-"); + } + newLore.appendTag(new NBTTagString(sb.toString())); + newLore.appendTag(new NBTTagString( + EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + + decimalFormatter.format(petLevel.levelXp) + + EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW + + decimalFormatter.format(petLevel.currentLevelRequirement) + )); + } + } + newLore.appendTag(lore.get(i)); + } + display.setTag("Lore", newLore); + tag.setTag("display", display); + } + } + } + stack.setTagCompound(tag); + return stack; + } + public static boolean isSoulbound(ItemStack item) { return ItemUtils.getLore(item).stream() - .anyMatch(line -> line.equals("§8§l* §8Co-op Soulbound §8§l*") || line.equals("§8§l* Soulbound §8§l*")); + .anyMatch(line -> line.equals("§8§l* §8Co-op Soulbound §8§l*") || + line.equals("§8§l* Soulbound §8§l*")); } + }