/* * Copyright (C) 2022 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * * NotEnoughUpdates is free software: you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * NotEnoughUpdates is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with NotEnoughUpdates. If not, see . */ package io.github.moulberry.notenoughupdates.profileviewer; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; 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.PetLeveling; import io.github.moulberry.notenoughupdates.util.Rectangle; 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.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import java.awt.*; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer.pv_elements; public class PetsPage extends GuiProfileViewerPage { public static final ResourceLocation pv_pets = new ResourceLocation("notenoughupdates:pv_pets.png"); private static final int COLLS_XCOUNT = 5; private static final int COLLS_YCOUNT = 4; private static final float COLLS_XPADDING = (190 - COLLS_XCOUNT * 20) / (float) (COLLS_XCOUNT + 1); private static final float COLLS_YPADDING = (202 - COLLS_YCOUNT * 20) / (float) (COLLS_YCOUNT + 1); private static final Rectangle switchSortingMethodButton = new Rectangle(180, 8, 16, 16); private boolean sortPetsAlphabetically = false; private List sortedPets = null; private List sortedPetsStack = null; private int selectedPet = -1; private int petsPage = 0; public PetsPage(GuiProfileViewer instance) { super(instance); } @Override public void drawPage(int mouseX, int mouseY, float partialTicks) { int guiLeft = GuiProfileViewer.getGuiLeft(); int guiTop = GuiProfileViewer.getGuiTop(); JsonObject petsJson = Constants.PETS; if (petsJson == null) { return; } SkyblockProfiles.SkyblockProfile selectedProfile = getSelectedProfile(); if (selectedProfile == null) { return; } JsonObject petsInfo = selectedProfile.getPetsInfo(); if (petsInfo == null) { return; } String location = null; JsonObject status = GuiProfileViewer.getProfile().getPlayerStatus(); if (status != null && status.has("mode")) { location = status.get("mode").getAsString(); } getInstance().backgroundRotation += (getInstance().currentTime - getInstance().lastTime) / 400f; getInstance().backgroundRotation %= 360; String panoramaIdentifier = "day"; if (SBInfo.getInstance().currentTimeDate != null) { if (SBInfo.getInstance().currentTimeDate.getHours() <= 6 || SBInfo.getInstance().currentTimeDate.getHours() >= 20) { panoramaIdentifier = "night"; } } JsonArray pets = petsInfo.get("pets").getAsJsonArray(); if (sortedPets == null) { sortPets(pets); } renderSortingButton(guiLeft, guiTop); Panorama.drawPanorama( -getInstance().backgroundRotation, guiLeft + 212, guiTop + 44, 81, 108, -0.37f, 0.6f, Panorama.getPanoramasForLocation(location == null ? "dynamic" : location, panoramaIdentifier) ); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_pets); Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST); Utils.drawStringCentered(EnumChatFormatting.DARK_PURPLE + "Pets", guiLeft + 100, guiTop + 14, true, 4210752); GlStateManager.color(1, 1, 1, 1); JsonElement activePetElement = petsInfo.get("active_pet"); if (selectedPet == -1 && activePetElement != null && activePetElement.isJsonObject()) { JsonObject active = activePetElement.getAsJsonObject(); for (int i = 0; i < sortedPets.size(); i++) { if (sortedPets.get(i) == active) { selectedPet = i; break; } } } boolean leftHovered = false; boolean rightHovered = false; if (Mouse.isButtonDown(0)) { if (mouseY > guiTop + 6 && mouseY < guiTop + 22) { if (mouseX > guiLeft + 100 - 20 - 12 && mouseX < guiLeft + 100 - 20) { leftHovered = true; } else if (mouseX > guiLeft + 100 + 20 && mouseX < guiLeft + 100 + 20 + 12) { rightHovered = true; } } } Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.resource_packs); if (petsPage > 0) { Utils.drawTexturedRect( guiLeft + 100 - 15 - 12, guiTop + 6, 12, 16, 29 / 256f, 53 / 256f, !leftHovered ? 0 : 32 / 256f, !leftHovered ? 32 / 256f : 64 / 256f, GL11.GL_NEAREST ); } if (petsPage < Math.ceil(pets.size() / 20f) - 1) { Utils.drawTexturedRect( guiLeft + 100 + 15, guiTop + 6, 12, 16, 5 / 256f, 29 / 256f, !rightHovered ? 0 : 32 / 256f, !rightHovered ? 32 / 256f : 64 / 256f, GL11.GL_NEAREST ); } 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); if (pet != null) { { NBTTagCompound tag = stack.getTagCompound(); tag.setBoolean("DisablePetExp", true); stack.setTagCompound(tag); } int xIndex = (i % 20) % COLLS_XCOUNT; int yIndex = (i % 20) / COLLS_XCOUNT; float x = 5 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex; float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex; Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements); if (i == selectedPet) { GlStateManager.color(1, 185 / 255f, 0, 1); } else { GlStateManager.color(1, 1, 1, 1); } Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST); Utils.drawItemStack(stack, guiLeft + (int) x + 2, guiTop + (int) y + 2, true); if (mouseX > guiLeft + x && mouseX < guiLeft + x + 20) { if (mouseY > guiTop + y && mouseY < guiTop + y + 20) { getInstance().tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); } } } } if (selectedPet >= 0) { ItemStack petStack; if (sortedPetsStack.size() <= selectedPet) { petStack = ItemUtils.createQuestionMarkSkull("§cInvalid pet selection"); } else { petStack = sortedPetsStack.get(selectedPet); } String display = petStack.getDisplayName(); 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)); int displayLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(display); int halfDisplayLen = displayLen / 2; GlStateManager.pushMatrix(); GlStateManager.translate(x, y, 0); GuiScreen.drawRect(-halfDisplayLen - 1 - 28, -1, halfDisplayLen + 1 - 28, 8, new Color(0, 0, 0, 100).getRGB()); Minecraft.getMinecraft().fontRendererObj.drawString(display, -halfDisplayLen - 28, 0, 0, true); GlStateManager.enableDepth(); GlStateManager.translate(-55, 0, 0); GlStateManager.scale(3.5f, 3.5f, 1); Utils.drawItemStack(petStack, 0, 0); GlStateManager.popMatrix(); float level = pet.get("level").getAsFloat(); float currentLevelRequirement = pet.get("currentLevelRequirement").getAsFloat(); float percentageToNextLevel = pet.get("percentageToNextLevel").getAsFloat(); float exp = pet.get("exp").getAsFloat(); float maxXP = pet.get("maxXP").getAsFloat(); String[] split = display.split("] "); String colouredName = split[split.length - 1]; Utils.renderAlignedString( colouredName, EnumChatFormatting.WHITE + "Level " + (int) Math.floor(level), guiLeft + 319, guiTop + 28, 98 ); //Utils.drawStringCenteredScaledMaxWidth(, Minecraft.getMinecraft().fontRendererObj, guiLeft+368, guiTop+28+4, true, 98, 0); //renderAlignedString(display, EnumChatFormatting.YELLOW+"[LVL "+Math.floor(level)+"]", guiLeft+319, guiTop+28, 98); getInstance().renderBar(guiLeft + 319, guiTop + 38, 98, (float) Math.floor(level) / 100f); Utils.renderAlignedString( EnumChatFormatting.YELLOW + "To Next LVL", EnumChatFormatting.WHITE.toString() + (int) (percentageToNextLevel * 100) + "%", guiLeft + 319, guiTop + 46, 98 ); getInstance().renderBar(guiLeft + 319, guiTop + 56, 98, percentageToNextLevel); Utils.renderAlignedString( EnumChatFormatting.YELLOW + "To Max LVL", EnumChatFormatting.WHITE.toString() + Math.min(100, (int) (exp / maxXP * 100)) + "%", guiLeft + 319, guiTop + 64, 98 ); getInstance().renderBar(guiLeft + 319, guiTop + 74, 98, exp / maxXP); Utils.renderAlignedString( EnumChatFormatting.YELLOW + "Total XP", EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(exp), guiLeft + 319, guiTop + 125, 98 ); Utils.renderAlignedString( EnumChatFormatting.YELLOW + "Current LVL XP", EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(percentageToNextLevel * currentLevelRequirement), guiLeft + 319, guiTop + 143, 98 ); Utils.renderAlignedString( EnumChatFormatting.YELLOW + "Required LVL XP", EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(currentLevelRequirement), guiLeft + 319, guiTop + 161, 98 ); } } private void renderSortingButton(int guiLeft, int guiTop) { Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); Utils.drawTexturedRect( switchSortingMethodButton.getX() + guiLeft - 2, switchSortingMethodButton.getY() + guiTop - 2, 20, 20, 20 / 256f, 0, 20 / 256f, 0, GL11.GL_NEAREST ); ItemStack itemStack = new ItemStack(Blocks.hopper); Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI( itemStack, switchSortingMethodButton.getX() + guiLeft, switchSortingMethodButton.getY() + guiTop ); int mouseX = Utils.getMouseX() - guiLeft; int mouseY = Utils.getMouseY() - guiTop; if (switchSortingMethodButton.contains(mouseX, mouseY)) { getInstance().tooltipToDisplay = Arrays.asList( EnumChatFormatting.GREEN + "Sort", "", (sortPetsAlphabetically ? EnumChatFormatting.GRAY + " " : EnumChatFormatting.DARK_AQUA + "▶") + " Pet Exp", (!sortPetsAlphabetically ? EnumChatFormatting.GRAY + " " : EnumChatFormatting.DARK_AQUA + "▶") + " Alphabetical", "", EnumChatFormatting.YELLOW + "Click to switch!" ); } } private void sortPets(JsonArray pets) { sortedPets = new ArrayList<>(); sortedPetsStack = new ArrayList<>(); for (int i = 0; i < pets.size(); i++) { sortedPets.add(pets.get(i).getAsJsonObject()); } sortedPets.sort((pet1, pet2) -> { String petType1 = pet1.get("type").getAsString(); String tier1 = pet1.get("tier").getAsString(); String tierNum1 = GuiProfileViewer.RARITY_TO_NUM.get(tier1); if (tierNum1 == null) return 1; int tierNum1I = Integer.parseInt(tierNum1); if ("PET_ITEM_TIER_BOOST".equals(Utils.getElementAsString(pet1.get("heldItem"), null))) { PetInfoOverlay.Pet parsedPet = new PetInfoOverlay.Pet(); PetInfoOverlay.Rarity tier = PetInfoOverlay.Rarity.valueOf(pet1.get("tier").getAsString()); parsedPet.petType = pet1.get("type").getAsString(); parsedPet.rarity = tier; if (Utils.canPetBeTierBoosted(parsedPet, tier.nextRarity())) { tierNum1I += 1; } } float exp1 = pet1.get("exp").getAsFloat(); String petType2 = pet2.get("type").getAsString(); String tier2 = pet2.get("tier").getAsString(); String tierNum2 = GuiProfileViewer.RARITY_TO_NUM.get(tier2); if (tierNum2 == null) return -1; int tierNum2I = Integer.parseInt(tierNum2); if ("PET_ITEM_TIER_BOOST".equals(Utils.getElementAsString(pet2.get("heldItem"), null))) { PetInfoOverlay.Pet parsedPet = new PetInfoOverlay.Pet(); PetInfoOverlay.Rarity tier = PetInfoOverlay.Rarity.valueOf(pet2.get("tier").getAsString()); parsedPet.petType = pet2.get("type").getAsString(); parsedPet.rarity = tier; if (Utils.canPetBeTierBoosted(parsedPet, tier.nextRarity())) { tierNum2I += 1; } } float exp2 = pet2.get("exp").getAsFloat(); if (tierNum1I != tierNum2I) { return tierNum2I - tierNum1I; } else if (sortPetsAlphabetically && petType1.compareTo(petType2) != 0) { return petType1.compareTo(petType2); } else { return (int) (exp2 - exp1); } }); for (JsonObject pet : sortedPets) { PetInfoOverlay.Pet parsedPet = new PetInfoOverlay.Pet(); parsedPet.petType = pet.get("type").getAsString(); parsedPet.rarity = PetInfoOverlay.Rarity.valueOf(pet.get("tier").getAsString()); parsedPet.petItem = Utils.getElementAsString(pet.get("heldItem"), null); if ("PET_ITEM_TIER_BOOST".equals(parsedPet.petItem)) { PetInfoOverlay.Rarity nextRarity = parsedPet.rarity.nextRarity(); if (Utils.canPetBeTierBoosted(parsedPet, nextRarity)) parsedPet.rarity = nextRarity; } parsedPet.petLevel = PetLeveling.getPetLevelingForPet( parsedPet.petType, parsedPet.rarity ).getPetLevel(pet.get("exp").getAsFloat()); parsedPet.petXpType = "unknown"; parsedPet.skin = Utils.getElementAsString(pet.get("skin"), null); parsedPet.candyUsed = pet.get("candyUsed").getAsInt(); sortedPetsStack.add(ItemUtils.createPetItemstackFromPetInfo(parsedPet)); pet.addProperty("level", parsedPet.petLevel.getCurrentLevel()); pet.addProperty("currentLevelRequirement", parsedPet.petLevel.getExpRequiredForNextLevel()); pet.addProperty("maxXP", parsedPet.petLevel.getExpRequiredForMaxLevel()); pet.addProperty("percentageToNextLevel", parsedPet.petLevel.getPercentageToNextLevel()); } } @Override public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { if (sortedPets == null) return false; for (int i = petsPage * 20; i < Math.min(petsPage * 20 + 20, sortedPets.size()); i++) { int xIndex = (i % 20) % COLLS_XCOUNT; int yIndex = (i % 20) / COLLS_XCOUNT; float x = 5 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex; float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex; int guiLeft = GuiProfileViewer.getGuiLeft(); int guiTop = GuiProfileViewer.getGuiTop(); if (mouseX > guiLeft + x && mouseX < guiLeft + x + 20) { if (mouseY > guiTop + y && mouseY < guiTop + y + 20) { selectedPet = i; return true; } } } return false; } @Override public void mouseReleased(int mouseX, int mouseY, int mouseButton) { int guiLeft = GuiProfileViewer.getGuiLeft(); int guiTop = GuiProfileViewer.getGuiTop(); if (mouseY > guiTop + 6 && mouseY < guiTop + 22) { if (mouseX > guiLeft + 100 - 15 - 12 && mouseX < guiLeft + 100 - 20) { if (petsPage > 0) { petsPage--; } } else if (mouseX > guiLeft + 100 + 15 && mouseX < guiLeft + 100 + 20 + 12) { if (sortedPets != null && petsPage < Math.ceil(sortedPets.size() / 20f) - 1) { petsPage++; } } } if (switchSortingMethodButton.contains(mouseX - guiLeft, mouseY - guiTop)) { sortPetsAlphabetically = !sortPetsAlphabetically; // Causes the pets to be sorted again next frame, this time taking into account the new sorting preference. resetCache(); Utils.playPressSound(); } } @Override public void resetCache() { petsPage = 0; sortedPets = null; sortedPetsStack = null; selectedPet = -1; } }