aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCalMWolfs <94038482+CalMWolfs@users.noreply.github.com>2023-11-05 00:13:36 +1100
committerGitHub <noreply@github.com>2023-11-04 14:13:36 +0100
commitf197b517e5ced58eee13b3f9aef89156575d0540 (patch)
treeb88c8e7b74dfd235519d9f38469b6633575c0689
parentdf476f63ccde2ff0c17d048e582ffa75e0d66088 (diff)
downloadNotEnoughUpdates-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
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java8
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java23
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java3
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java12
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java86
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewerUtils.java11
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java4
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/profileviewer/SacksPage.kt449
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinJsonUtils.kt16
-rw-r--r--src/main/kotlin/io/github/moulberry/notenoughupdates/util/KotlinStringUtils.kt5
-rw-r--r--src/main/resources/assets/notenoughupdates/pv_sacks.pngbin0 -> 1518 bytes
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
new file mode 100644
index 00000000..27b72b4a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/pv_sacks.png
Binary files differ