diff options
author | CalMWolfs <94038482+CalMWolfs@users.noreply.github.com> | 2023-11-05 00:13:36 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-04 14:13:36 +0100 |
commit | f197b517e5ced58eee13b3f9aef89156575d0540 (patch) | |
tree | b88c8e7b74dfd235519d9f38469b6633575c0689 /src/main | |
parent | df476f63ccde2ff0c17d048e582ffa75e0d66088 (diff) | |
download | NotEnoughUpdates-f197b517e5ced58eee13b3f9aef89156575d0540.tar.gz NotEnoughUpdates-f197b517e5ced58eee13b3f9aef89156575d0540.tar.bz2 NotEnoughUpdates-f197b517e5ced58eee13b3f9aef89156575d0540.zip |
Feature: Sacks page in pv (#891)
* sacks in pv
* fix formatting
* a bit more formatting
* change location to make more sense
* suggested changes
* change colour
* add coloured tooltips
* remove some more magic numbers
Diffstat (limited to 'src/main')
12 files changed, 586 insertions, 33 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java index e59a6a14..20031ec3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java @@ -46,6 +46,10 @@ public class StringUtils { return Integer.parseInt(str); } + public static String shortNumberFormat(int n) { + return shortNumberFormat(n, 0); + } + public static String shortNumberFormat(double n) { return shortNumberFormat(n, 0); } @@ -74,7 +78,9 @@ public class StringUtils { double d = ((long) n / 100) / 10.0; boolean isRound = (d * 10) % 10 == 0; - return d < 1000 ? (isRound || d > 9.99 ? (int) d * 10 / 10 : d + "") + "" + sizeSuffix[iteration] : shortNumberFormat(d, iteration + 1); + return d < 1000 + ? (isRound || d > 9.99 ? (int) d * 10 / 10 : d + "") + "" + sizeSuffix[iteration] + : shortNumberFormat(d, iteration + 1); } public static String removeLastWord(String string, String splitString) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java index 7b21e6a1..0011272f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java @@ -83,7 +83,7 @@ public class BasicPage extends GuiProfileViewerPage { "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODdkODg1YjMyYjBkZDJkNmI3ZjFiNTgyYTM0MTg2ZjhhNTM3M2M0NjU4OWEyNzM0MjMxMzJiNDQ4YjgwMzQ2MiJ9fX0=" ); - private static final LinkedHashMap<String, ItemStack> dungeonsModeIcons = new LinkedHashMap<String, ItemStack>() { + private static final LinkedHashMap<String, ItemStack> pageModeIcon = new LinkedHashMap<String, ItemStack>() { { put( "first_page", @@ -1001,7 +1001,7 @@ public class BasicPage extends GuiProfileViewerPage { int guiLeft = GuiProfileViewer.getGuiLeft(); int guiTop = GuiProfileViewer.getGuiTop(); - int i = onSlotToChangePage(mouseX, mouseY, guiLeft, guiTop); + int i = ProfileViewerUtils.onSlotToChangePage(mouseX, mouseY, guiLeft, guiTop); switch (i) { case 1: onSecondPage = false; @@ -1017,32 +1017,21 @@ public class BasicPage extends GuiProfileViewerPage { return false; } - public int onSlotToChangePage(int mouseX, int mouseY, int guiLeft, int guiTop) { - if (mouseX >= guiLeft - 29 && mouseX <= guiLeft) { - if (mouseY >= guiTop && mouseY <= guiTop + 28) { - return 1; - } else if (mouseY + 28 >= guiTop && mouseY <= guiTop + 28 * 2) { - return 2; - } - } - return 0; - } - public void drawSideButtons() { GlStateManager.enableDepth(); GlStateManager.translate(0, 0, 5); if (onSecondPage) { - Utils.drawPvSideButton(1, dungeonsModeIcons.get("second_page"), true, guiProfileViewer); + Utils.drawPvSideButton(1, pageModeIcon.get("second_page"), true, guiProfileViewer); } else { - Utils.drawPvSideButton(0, dungeonsModeIcons.get("first_page"), true, guiProfileViewer); + Utils.drawPvSideButton(0, pageModeIcon.get("first_page"), true, guiProfileViewer); } GlStateManager.translate(0, 0, -3); GlStateManager.translate(0, 0, -2); if (!onSecondPage) { - Utils.drawPvSideButton(1, dungeonsModeIcons.get("second_page"), false, guiProfileViewer); + Utils.drawPvSideButton(1, pageModeIcon.get("second_page"), false, guiProfileViewer); } else { - Utils.drawPvSideButton(0, dungeonsModeIcons.get("first_page"), false, guiProfileViewer); + Utils.drawPvSideButton(0, pageModeIcon.get("first_page"), false, guiProfileViewer); } GlStateManager.disableDepth(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java index e8e9f171..333ae591 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 NotEnoughUpdates contributors + * Copyright (C) 2022-2023 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * @@ -76,6 +76,7 @@ public class CollectionsPage extends GuiProfileViewerPage { private int page = 0; private int maxPage = 0; + public CollectionsPage(GuiProfileViewer instance) { super(instance); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java index b03c87dd..d53e44d0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 NotEnoughUpdates contributors + * Copyright (C) 2022-2023 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * @@ -74,7 +74,7 @@ public class DungeonPage extends GuiProfileViewerPage { "fa06cb0c471c1c9bc169af270cd466ea701946776056e472ecdaeb49f0f4a4dc", "a435164c05cea299a3f016bbbed05706ebb720dac912ce4351c2296626aecd9a", }; - private static final LinkedHashMap<String, ItemStack> dungeonsModeIcons = new LinkedHashMap<String, ItemStack>() { + private static final LinkedHashMap<String, ItemStack> pageModeIcon = new LinkedHashMap<String, ItemStack>() { { put( "catacombs", @@ -650,17 +650,17 @@ public class DungeonPage extends GuiProfileViewerPage { GlStateManager.enableDepth(); GlStateManager.translate(0, 0, 5); if (onMasterMode) { - Utils.drawPvSideButton(1, dungeonsModeIcons.get("master_catacombs"), true, getInstance()); + Utils.drawPvSideButton(1, pageModeIcon.get("master_catacombs"), true, getInstance()); } else { - Utils.drawPvSideButton(0, dungeonsModeIcons.get("catacombs"), true, getInstance()); + Utils.drawPvSideButton(0, pageModeIcon.get("catacombs"), true, getInstance()); } GlStateManager.translate(0, 0, -3); GlStateManager.translate(0, 0, -2); if (!onMasterMode) { - Utils.drawPvSideButton(1, dungeonsModeIcons.get("master_catacombs"), false, getInstance()); + Utils.drawPvSideButton(1, pageModeIcon.get("master_catacombs"), false, getInstance()); } else { - Utils.drawPvSideButton(0, dungeonsModeIcons.get("catacombs"), false, getInstance()); + Utils.drawPvSideButton(0, pageModeIcon.get("catacombs"), false, getInstance()); } GlStateManager.disableDepth(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java index 5d23eede..c4dc7cd6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 NotEnoughUpdates contributors + * Copyright (C) 2022-2023 NotEnoughUpdates contributors * * This file is part of NotEnoughUpdates. * @@ -24,6 +24,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.miscfeatures.profileviewer.SacksPage; import io.github.moulberry.notenoughupdates.profileviewer.info.QuiverInfo; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; @@ -131,8 +132,35 @@ public class InventoriesPage extends GuiProfileViewerPage { put("intelligence",2f); }}; + private boolean onSacksPage; + private final SacksPage sacksPage; + + private static final LinkedHashMap<String, ItemStack> pageModeIcon = new LinkedHashMap<String, ItemStack>() { + { + put( + "inventories", + Utils.editItemStackInfo( + new ItemStack(Items.painting), + EnumChatFormatting.GRAY + "Inventories", + true + ) + ); + put( + "sacks", + Utils.editItemStackInfo( + NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("LARGE_ENCHANTED_MINING_SACK") + ), + EnumChatFormatting.GRAY + "Sacks", + true + ) + ); + } + }; + public InventoriesPage(GuiProfileViewer instance) { super(instance); + this.sacksPage = new SacksPage(getInstance()); } @Override @@ -140,6 +168,13 @@ public class InventoriesPage extends GuiProfileViewerPage { int guiLeft = GuiProfileViewer.getGuiLeft(); int guiTop = GuiProfileViewer.getGuiTop(); + drawSideButtons(); + + if (onSacksPage) { + sacksPage.drawPage(mouseX, mouseY, partialTicks); + return; + } + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_invs); Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST); getInstance().inventoryTextField.setSize(88, 20); @@ -512,15 +547,31 @@ public class InventoriesPage extends GuiProfileViewerPage { int guiLeft = GuiProfileViewer.getGuiLeft(); int guiTop = GuiProfileViewer.getGuiTop(); - getInstance().inventoryTextField.setSize(88, 20); - if (mouseX > guiLeft + 19 && mouseX < guiLeft + 19 + 88) { - if (mouseY > guiTop + getInstance().sizeY - 26 - 20 && mouseY < guiTop + getInstance().sizeY - 26) { - getInstance().inventoryTextField.mouseClicked(mouseX, mouseY, mouseButton); - getInstance().playerNameTextField.otherComponentClick(); - return true; + if (!onSacksPage) { + getInstance().inventoryTextField.setSize(88, 20); + if (mouseX > guiLeft + 19 && mouseX < guiLeft + 19 + 88) { + if (mouseY > guiTop + getInstance().sizeY - 26 - 20 && mouseY < guiTop + getInstance().sizeY - 26) { + getInstance().inventoryTextField.mouseClicked(mouseX, mouseY, mouseButton); + getInstance().playerNameTextField.otherComponentClick(); + return true; + } } } - return false; + + int i = ProfileViewerUtils.onSlotToChangePage(mouseX, mouseY, guiLeft, guiTop); + switch (i) { + case 1: + onSacksPage = false; + break; + case 2: + onSacksPage = true; + break; + + default: + break; + } + + return sacksPage.mouseClick(mouseX, mouseY, mouseButton); } @Override @@ -844,4 +895,23 @@ public class InventoriesPage extends GuiProfileViewerPage { return 6; } } + + private void drawSideButtons() { + GlStateManager.enableDepth(); + GlStateManager.translate(0, 0, 5); + if (onSacksPage) { + Utils.drawPvSideButton(1, pageModeIcon.get("sacks"), true, getInstance()); + } else { + Utils.drawPvSideButton(0, pageModeIcon.get("inventories"), true, getInstance()); + } + GlStateManager.translate(0, 0, -3); + + GlStateManager.translate(0, 0, -2); + if (!onSacksPage) { + Utils.drawPvSideButton(1, pageModeIcon.get("sacks"), false, getInstance()); + } else { + Utils.drawPvSideButton(0, pageModeIcon.get("inventories"), false, getInstance()); + } + GlStateManager.disableDepth(); + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewerUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewerUtils.java index ef4d5aa9..417ca9e6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewerUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewerUtils.java @@ -294,4 +294,15 @@ public class ProfileViewerUtils { } }); } + + public static int onSlotToChangePage(int mouseX, int mouseY, int guiLeft, int guiTop) { + if (mouseX >= guiLeft - 29 && mouseX <= guiLeft) { + if (mouseY >= guiTop && mouseY <= guiTop + 28) { + return 1; + } else if (mouseY + 28 >= guiTop && mouseY <= guiTop + 28 * 2) { + return 2; + } + } + return 0; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java index c30f869e..59084548 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java @@ -84,6 +84,7 @@ public class Constants { public static JsonObject SBLEVELS; public static JsonObject MUSEUM; public static JsonObject BESTIARY; + public static JsonObject SACKS; private static final ReentrantLock lock = new ReentrantLock(); @@ -111,6 +112,7 @@ public class Constants { SBLEVELS = Utils.getConstant("sblevels", gson); MUSEUM = Utils.getConstant("museum", gson); BESTIARY = Utils.getConstant("bestiary", gson); + SACKS = Utils.getConstant("sacks", gson); parseEssenceCosts(); } catch (Exception ex) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java index f879631e..6d44e4b7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java @@ -1171,6 +1171,10 @@ public class Utils { drawStringCentered(str, Minecraft.getMinecraft().fontRendererObj, x, y, shadow, colour); } + public static void drawStringCentered(String str, int x, int y, boolean shadow, int colour) { + drawStringCentered(str, Minecraft.getMinecraft().fontRendererObj, x, y, shadow, colour); + } + @Deprecated public static void drawStringCentered(String str, FontRenderer fr, float x, float y, boolean shadow, int colour) { int strLen = fr.getStringWidth(str); diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/profileviewer/SacksPage.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/profileviewer/SacksPage.kt new file mode 100644 index 00000000..ebd53c4d --- /dev/null +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/profileviewer/SacksPage.kt @@ -0,0 +1,449 @@ +/* + * Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures.profileviewer + +import com.google.gson.JsonObject +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.core.util.ArrowPagesUtils +import io.github.moulberry.notenoughupdates.core.util.StringUtils +import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewerPage +import io.github.moulberry.notenoughupdates.profileviewer.SkyblockProfiles +import io.github.moulberry.notenoughupdates.util.* +import io.github.moulberry.notenoughupdates.util.hypixelapi.HypixelItemAPI +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.util.ResourceLocation +import org.lwjgl.input.Mouse +import org.lwjgl.opengl.GL11 + + +class SacksPage(pvInstance: GuiProfileViewer) : GuiProfileViewerPage(pvInstance) { + private val manager get() = NotEnoughUpdates.INSTANCE.manager + private val pv_sacks = ResourceLocation("notenoughupdates:pv_sacks.png") + private var sacksJson = Constants.SACKS + private var tooltipToDisplay = listOf<String>() + private var currentProfile: SkyblockProfiles.SkyblockProfile? = null + + private var currentSack = "All" + + private var page = 0 + private var maxPage = 0 + private val arrowsHeight = 180 + private val arrowsXPos = 110 + + private val columns = 7 + private val rows = 4 + private val pageSize = columns * rows + + private var guiLeft = GuiProfileViewer.getGuiLeft() + private var guiTop = GuiProfileViewer.getGuiTop() + private val sackArrayLeft = 168 + private val sackArrayTop = 20 + private val sackGridXSize = 37 + private val sackGridYSize = 41 + private val itemIconSize = 20 + + private val sackContents = mutableMapOf<String, SackInfo>() + private val sackItems = mutableMapOf<String, SackItem>() + private val playerRunes = mutableListOf<String>() + + private val sackPattern = "^RUNE_(?<name>\\w+)_(?<tier>\\d)\$".toPattern() + + override fun drawPage(mouseX: Int, mouseY: Int, partialTicks: Float) { + guiLeft = GuiProfileViewer.getGuiLeft() + guiTop = GuiProfileViewer.getGuiTop() + + MC.textureManager.bindTexture(pv_sacks) + Utils.drawTexturedRect( + guiLeft.toFloat(), + guiTop.toFloat(), + instance.sizeX.toFloat(), + instance.sizeY.toFloat(), + GL11.GL_NEAREST + ) + + val newProfile = selectedProfile + if (newProfile == null) { + Utils.drawStringCentered("§cMissing Profile Data", guiLeft + 250, guiTop + 101, true, 0) + return + } + + if (sacksJson == null) { + Utils.drawStringCentered("§cMissing Repo Data", guiLeft + 250, guiTop + 101, true, 0) + return + } + + if (newProfile != currentProfile) { + getData() + currentProfile = selectedProfile + } + + val currentSackData = sackContents[currentSack] ?: run { + Utils.drawStringCentered("§cApi Info Missing", guiLeft + 250, guiTop + 101, true, 0) + return + } + // after this point everything in the constants json exists and does not need to be checked again except "item" + + val name = if (currentSack == "All") "§2All Sacks" else "§2$currentSack Sack" + Utils.renderShadowedString(name, (guiLeft + 78).toFloat(), (guiTop + 74).toFloat(), 105) + + Utils.renderAlignedString( + "§6Value", + "§f${StringUtils.formatNumber(currentSackData.sackValue.toLong())}", + (guiLeft + 27).toFloat(), + (guiTop + 91).toFloat(), + 102 + ) + + Utils.renderAlignedString( + "§2Items", + "§f${StringUtils.formatNumber(currentSackData.itemCount)}", + (guiLeft + 27).toFloat(), + (guiTop + 108).toFloat(), + 102 + ) + + GlStateManager.enableDepth() + + val sackTypes = sacksJson.getAsJsonObject("sacks") + + val startIndex = page * pageSize + val endIndex = (page + 1) * pageSize + if (currentSack == "All") { + for ((index, entrySet) in sackTypes.entrySet().withIndex()) { + val (sackName, sackData) = entrySet + + if (index < startIndex || index >= endIndex) continue + val adjustedIndex = index - startIndex + + val xIndex = adjustedIndex % columns + val yIndex = adjustedIndex / columns + if (yIndex >= rows) continue + + val data = sackData.asJsonObject + + if (!data.has("item") || !data.get("item").isJsonPrimitive || !data.get("item").asJsonPrimitive.isString) continue + val sackItemName = data.get("item").asString + val itemStack = manager.createItem(sackItemName) + + val x = guiLeft + sackArrayLeft + xIndex * sackGridXSize + val y = guiTop + sackArrayTop + yIndex * sackGridYSize + + MC.textureManager.bindTexture(GuiProfileViewer.pv_elements) + Utils.drawTexturedRect( + (x).toFloat(), + (y).toFloat(), + 20f, + 20f, + 0f, + 20 / 256f, + 0f, + 20 / 256f, + GL11.GL_NEAREST + ) + + val sackInfo = sackContents[sackName] ?: SackInfo(0, 0.0) + Utils.drawStringCentered( + "§6${StringUtils.shortNumberFormat(sackInfo.sackValue.roundToDecimals(0))}", + x + itemIconSize / 2, + y - 4, + true, + 0 + ) + Utils.drawStringCentered( + "§7${StringUtils.shortNumberFormat(sackInfo.itemCount)}", + x + itemIconSize / 2, + y + 26, + true, + 0 + ) + GlStateManager.color(0f, 0f, 0f, 0f) + + if (itemStack != null) { + Utils.drawItemStack(itemStack, x + 2, y + 2) + + if (mouseX > x && mouseX < x + itemIconSize) { + if (mouseY > y && mouseY < y + itemIconSize) { + tooltipToDisplay = createTooltip( + "$sackName Sack", + sackInfo.sackValue, + sackInfo.itemCount, + true + ) + } + } + } else { + println("$sackItemName missing in neu repo") + } + } + } else { + val sackData = sackTypes.get(currentSack).asJsonObject + + val sackContents = sackData.getAsJsonArray("contents") + var sackItemNames = sackContents.map { it.asString }.toList() + if (currentSack == "Rune") { + sackItemNames = playerRunes + } + + for ((index, itemName) in sackItemNames.withIndex()) { + if (index < startIndex || index >= endIndex) continue + val adjustedIndex = index - startIndex + + val xIndex = adjustedIndex % columns + val yIndex = adjustedIndex / columns + if (yIndex >= rows) continue + + val itemStack = manager.createItem(itemName) + + val x = guiLeft + sackArrayLeft + xIndex * sackGridXSize + val y = guiTop + sackArrayTop + yIndex * sackGridYSize + + MC.textureManager.bindTexture(GuiProfileViewer.pv_elements) + Utils.drawTexturedRect( + (x).toFloat(), + (y).toFloat(), + 20f, + 20f, + 0f, + 20 / 256f, + 0f, + 20 / 256f, + GL11.GL_NEAREST + ) + + val itemInfo = sackItems[itemName] ?: SackItem(0, 0.0) + Utils.drawStringCentered( + "§6${StringUtils.shortNumberFormat(itemInfo.value.roundToDecimals(0))}", + x + itemIconSize / 2, + y - 4, + true, + 0 + ) + Utils.drawStringCentered("§7${StringUtils.shortNumberFormat(itemInfo.amount)}", x + 10, y + 26, true, 0) + GlStateManager.color(1f, 1f, 1f, 1f) + + if (itemStack != null) { + val stackName = itemStack.displayName + Utils.drawItemStack(itemStack, x + 2, y + 2) + + if (mouseX > x && mouseX < x + itemIconSize) { + if (mouseY > y && mouseY < y + itemIconSize) { + tooltipToDisplay = createTooltip(stackName, itemInfo.value, itemInfo.amount, false) + } + } + } else { + println("$itemName missing in neu repo") + } + } + val buttonRect = Rectangle(guiLeft + sackArrayLeft, guiTop + arrowsHeight, 80, 15) + RenderUtils.drawFloatingRectWithAlpha( + buttonRect.x, + buttonRect.y, + buttonRect.width, + buttonRect.height, + 100, + true + ) + Utils.renderShadowedString("§2Back", (guiLeft + sackArrayLeft + 40).toFloat(), (guiTop + arrowsHeight + 3).toFloat(), 79) + + if (Mouse.getEventButtonState() && Utils.isWithinRect(mouseX, mouseY, buttonRect)) { + currentSack = "All" + Utils.playPressSound() + page = 0 + maxPage = getPages(currentSack, sackTypes) + } + } + + GlStateManager.color(1f, 1f, 1f, 1f) + ArrowPagesUtils.onDraw(guiLeft, guiTop, intArrayOf(sackArrayLeft + arrowsXPos, arrowsHeight), page, maxPage + 1) + + if (tooltipToDisplay.isNotEmpty()) { + tooltipToDisplay = tooltipToDisplay.map { "§7$it" } + Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, instance.width, instance.height, -1) + tooltipToDisplay = listOf() + } + } + + fun mouseClick(mouseX: Int, mouseY: Int, mouseButton: Int): Boolean { + super.mouseClicked(mouseX, mouseY, mouseButton) + + if (sacksJson == null || sackContents.isEmpty()) { + return false + } + // after this point everything in the constants json exists and does not need to be checked again + + if (currentSack == "All") { + val sackTypes = sacksJson.getAsJsonObject("sacks") + + val startIndex = page * pageSize + val endIndex = (page + 1) * pageSize + + for ((index, sackData) in sackTypes.entrySet().withIndex()) { + val sackName = sackData.key + + if (index < startIndex || index >= endIndex) continue + val adjustedIndex = index - startIndex + + val xIndex = adjustedIndex % columns + val yIndex = adjustedIndex / columns + if (yIndex >= rows) continue + + val x = guiLeft + sackArrayLeft + xIndex * sackGridXSize + val y = guiTop + sackArrayTop + yIndex * sackGridYSize + + if (mouseX > x && mouseX < x + itemIconSize) { + if (mouseY > y && mouseY < y + itemIconSize) { + currentSack = sackName + Utils.playPressSound() + page = 0 + maxPage = getPages(currentSack, sackTypes) + return true + } + } + } + } + + ArrowPagesUtils.onPageSwitchMouse( + guiLeft, + guiTop, + intArrayOf(sackArrayLeft + arrowsXPos, arrowsHeight), + page, + maxPage + 1 + ) { pageChange -> page = pageChange } + + return false + } + + private fun createTooltip(name: String, value: Double, amount: Int, isSack: Boolean): List<String> { + val baseList = mutableListOf( + "§2$name", + "Items Stored: §a${StringUtils.formatNumber(amount)}", + "Total Value: §6${StringUtils.formatNumber(value.toLong())}" + ) + if (isSack) baseList.add("§eClick for more details") + return baseList + } + + private fun getPages(pageName: String, sackTypes: JsonObject): Int { + return when (pageName) { + "All" -> { + sackTypes.entrySet().size / pageSize + } + + "Rune" -> { + playerRunes.size / pageSize + } + + else -> { + val sackData = sackTypes.get(currentSack).asJsonObject + val sackContents = sackData.getAsJsonArray("contents") + sackContents.size() / pageSize + } + } + } + + private fun getData() { + sackContents.clear() + sackItems.clear() + playerRunes.clear() + + if (!sacksJson.has("sacks") || !sacksJson.get("sacks").isJsonObject) return + val sackTypes = sacksJson.getAsJsonObject("sacks") + val selectedProfile = selectedProfile?.profileJson ?: return + + if (!selectedProfile.has("sacks_counts") || !selectedProfile.get("sacks_counts").isJsonObject) return + val sacksInfo = selectedProfile.get("sacks_counts").asJsonObject + + var totalValue = 0.0 + var totalItems = 0 + + for ((sackName, sackData) in sackTypes.entrySet()) { + if (!sackData.isJsonObject) return + val data = sackData.asJsonObject + var sackValue = 0.0 + var sackItemCount = 0 + + if (sackName == "Rune") { + totalItems += getRuneData(sacksInfo) + continue + } + + if (!data.has("contents") || !data.get("contents").isJsonArray) return + val contents = data.getAsJsonArray("contents") + for (item in contents) { + if (!item.isJsonPrimitive || !item.asJsonPrimitive.isString) return + val sackItem = item.asString + + val adjustedName = sackItem.replace("-", ":") + val itemCount = sacksInfo.getIntOrValue(adjustedName, 0) + val itemValue = itemCount * getPrice(sackItem) + + if (sackItem !in sackItems) { + totalValue += itemValue + totalItems += itemCount + } + + sackItems[sackItem] = SackItem(itemCount, itemValue) + sackValue += itemValue + sackItemCount += itemCount + } + sackContents[sackName] = SackInfo(sackItemCount, sackValue) + } + + for ((itemName, _) in sacksInfo.entrySet()) { + val adjustedName = itemName.replace(":", "-") + if (adjustedName.contains(Regex("(RUNE|PERFECT_|MUSHROOM_COLLECTION)"))) continue + if (adjustedName in sackItems) continue + println("$adjustedName missing from repo sacks file!") + } + + sackContents["All"] = SackInfo(totalItems, totalValue) + } + + private fun getPrice(itemName: String): Double { + val npcPrice = HypixelItemAPI.getNPCSellPrice(itemName) ?: 0.0 + val bazaarInfo = manager.auctionManager.getBazaarInfo(itemName) ?: return npcPrice + val buyPrice = bazaarInfo.getDoubleOrValue("curr_buy", 0.0) + val sellPrice = bazaarInfo.getDoubleOrValue("curr_sell", 0.0) + return maxOf(npcPrice, buyPrice, sellPrice) + } + + private fun getRuneData(sacksInfo: JsonObject): Int { + var sackItemCount = 0 + for ((itemName, amount) in sacksInfo.entrySet()) { + if (!amount.isJsonPrimitive || !amount.asJsonPrimitive.isNumber) continue + sackPattern.matchMatcher(itemName) { + val itemAmount = amount.asInt + val name = group("name") + val tier = group("tier") + val neuInternalName = "${name}_RUNE;$tier" + sackItemCount += itemAmount + sackItems[neuInternalName] = SackItem(itemAmount, 1.0 * itemAmount) + playerRunes.add(neuInternalName) + } + } + sackContents["Rune"] = SackInfo(sackItemCount, 1.0 * sackItemCount) + return sackItemCount + } + + data class SackInfo(val itemCount: Int, val sackValue: Double) + data class SackItem(val amount: Int, val value: Double) +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinJsonUtils.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinJsonUtils.kt index 95b6f1ac..ef2eaedf 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinJsonUtils.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinJsonUtils.kt @@ -21,6 +21,7 @@ package io.github.moulberry.notenoughupdates.util import com.google.gson.JsonArray import com.google.gson.JsonElement +import com.google.gson.JsonObject fun Iterable<JsonElement>.toJsonArray(): JsonArray = JsonArray().also { @@ -29,3 +30,18 @@ fun Iterable<JsonElement>.toJsonArray(): JsonArray = JsonArray().also { } } +fun JsonObject.getIntOrValue(key: String, alternative: Int): Int { + return if (has(key) && get(key).isJsonPrimitive && get(key).asJsonPrimitive.isNumber) { + get(key).asInt + } else { + alternative + } +} + +fun JsonObject.getDoubleOrValue(key: String, alternative: Double): Double { + return if (has(key) && get(key).isJsonPrimitive && get(key).asJsonPrimitive.isNumber) { + get(key).asDouble + } else { + alternative + } +} diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinStringUtils.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinStringUtils.kt index d8491167..68b262ee 100644 --- a/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinStringUtils.kt +++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinStringUtils.kt @@ -22,7 +22,12 @@ package io.github.moulberry.notenoughupdates.util import net.minecraft.util.StringUtils import java.awt.Toolkit import java.awt.datatransfer.StringSelection +import java.util.regex.Matcher +import java.util.regex.Pattern fun String.stripControlCodes(): String = StringUtils.stripControlCodes(this) fun String.copyToClipboard() = Toolkit.getDefaultToolkit().systemClipboard.setContents(StringSelection(this), null) + +inline fun <T> Pattern.matchMatcher(text: String, consumer: Matcher.() -> T) = + matcher(text).let { if (it.matches()) consumer(it) else null } diff --git a/src/main/resources/assets/notenoughupdates/pv_sacks.png b/src/main/resources/assets/notenoughupdates/pv_sacks.png Binary files differnew file mode 100644 index 00000000..27b72b4a --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/pv_sacks.png |