diff options
101 files changed, 9139 insertions, 6368 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 5e58389d..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: Bug report -about: Help Moulberry pinpoint problems. -title: '[Bug] Title' -labels: '' -assignees: '' - ---- - -<!-- -Before you begin check if the bug already been reported. -And also ensure you are using the latest version. - - -If you are unsure about these requirements or need general support, -please join the discord server at discord.gg/moulberry ---> - -<!-- This is asking for the mod version for example 1.7.3-REL --> -**Mod Version:** - -<!-- Provide a clear and concise description of what the bug is. --> -**Describe the bug** - -<!-- Steps to reproduce the behavior --> -**To Reproduce** -1. -2. - -<!-- A clear and concise description of what you expected to happen. --> -**Expected behavior** - -<!-- Add screenshots, crash logs etc. --> -**Attachments**
\ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..0063ceed --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: NEU Support + url: https://discord.gg/moulberry + about: "Please ask for support in #neu-support on Moulberry's discord." + - name: Report security vulnerabilities + url: https://discord.gg/moulberry + about: "If you wish to discuss a bug *with security implications* privately, please open a ticket in Moulberry's discord using /new in #bot-commands" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a5fa2b6a..e7c4b379 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,7 +28,7 @@ ## Logging into Hypixel in a development environment -Use [DevAuth](https://github.com/DJtheRedstoner/DevAuth). Download the `forge-legacy` version, and put it into the `run/mods` folder. Then follow the configuration instructions in the [DevAuth README](https://github.com/DJtheRedstoner/DevAuth#configuration-file) +Use [DevAuth](https://github.com/DJtheRedstoner/DevAuth). You do **not** need to download the jar, just follow the configuration instructions in the [DevAuth README](https://github.com/DJtheRedstoner/DevAuth#configuration-file) ## Hot Reloading @@ -74,6 +74,7 @@ public static final int HOTFIX_VERSION_ID = 0; /* Reset the HOTFIX_VERSION_ID ba "pre_version": "0.0", /* Reset to 0.0 */ "pre_version_id": 0, /* Reset to 0 */ "update_link": "https://github.com/NotEnoughUpdates/NotEnoughUpdates/releases/tag/<VERSIONNAME>", /* Change download link to the github release */ + "update_direct": "https://github.com/NotEnoughUpdates/NotEnoughUpdates/releases/download/<VERSIONNAME>/NotEnoughUpdates-<VERSIONNAME>.jar", /* Change direct link to a direct download link */ } ``` @@ -104,7 +105,8 @@ public static final int PRE_VERSION_ID = 1; /* Increment the PRE_VERSION_ID */ "pre_update_msg": "§7§m§l--------------------§5§l[§c§lNEU§5§l]§7§m§l--------------------\n\n§7A new pre-release, v§52.0-PRE{pre_version}§7, is now available!\n ", /* Update the version name. Remove old patch notes; Optionally add in a short new patch note. */ "pre_version": "0.0", /* Set to a new string (preferably increase the major version every time, except for hotfixes on the prerelease stream) */ "pre_version_id": 0, /* Set to PRE_VERSION_ID from java */ - "update_link": "https://github.com/NotEnoughUpdates/NotEnoughUpdates/releases/tag/<VERSIONNAME>", /* Change download link to the github release */ + "pre_update_link": "https://github.com/NotEnoughUpdates/NotEnoughUpdates/releases/tag/<VERSIONNAME>", /* Change download link to the github release */ + "pre_update_direct": "https://github.com/NotEnoughUpdates/NotEnoughUpdates/releases/download/<VERSIONNAME>/NotEnoughUpdates-<VERSIONNAME>.jar", /* Change direct link to a direct download link */ } ``` @@ -136,6 +138,7 @@ public static final int HOTFIX_VERSION_ID = 1; /* Increment the HOTFIX_VERSION_I "version_id": 20100, /* Same as version */ "update_msg": "§7§m§l--------------------§6§l[§c§lNEU§6§l]§7§m§l--------------------\n\n§7A new version, v§6{version}§7, is now available!\n ", /* Update the version name. Don't remove old patch notes; Optionally add in a short new patch note. Indicate that there is a hotfix present */ "update_link": "https://github.com/NotEnoughUpdates/NotEnoughUpdates/releases/tag/<VERSIONNAME>", /* Change download link to the github release */ + "update_direct": "https://github.com/NotEnoughUpdates/NotEnoughUpdates/releases/download/<VERSIONNAME>/NotEnoughUpdates-<VERSIONNAME>.jar", /* Change direct link to a direct download link */ } ``` @@ -0,0 +1,34 @@ +# FAQ For NEU + +## What is this feature? + +### Equipment Overlay +![Equipment Overlay](https://cdn.discordapp.com/attachments/756532125443817594/1006792213432389752/unknown.png) + +This overlay shows the current equipment of the player +#### It doesn't fit in with my texture pack !!!!! +[If you go to /neu equipment you can change the style of the overlay](https://cdn.discordapp.com/attachments/756532125443817594/1006796222415245413/unknown.png) +This also applies to the pet inventory overlay + + +## What does this mean? + +### Missing Repo Data +![Missing Repo Data](https://cdn.discordapp.com/attachments/756532125443817594/1006805696639143987/unknown.png) + +If you get this popup you need to update your repo data. +As the popup says, you can try `/neuresetrepo` but if that doesn't resolve the issue go to [#neu-support](https://discord.gg/moulberry) and ask for help + +## How do I? + +### Turn on fairy soul waypoints +You can either [run `/neusouls`](https://cdn.discordapp.com/attachments/756532125443817594/1006808649471103046/unknown.png) for the help menu or [turn on the option in the first page of `/neu`](https://cdn.discordapp.com/attachments/756532125443817594/1006808594743840778/unknown.png) + +### Help I accidentally turned off the custom storage gui +![enable storage gui](https://cdn.discordapp.com/attachments/756532125443817594/1006810880794710046/unknown.png) + +Simply go to `/neu storage` and turn on the first option + +### Move a GUI element +![Edit gui](https://cdn.discordapp.com/attachments/756532125443817594/1006811543356317797/unknown.png) +Go to the second tab of `/neu` and here you will have all the gui elements you can move diff --git a/Update Notes/2.1.md b/Update Notes/2.1.md index 6e4dd71f..90ebbf87 100644 --- a/Update Notes/2.1.md +++ b/Update Notes/2.1.md @@ -16,8 +16,7 @@ - Added wishing compass solver that shows target coordinates, structure, and integrates with Skytils waypoints - CraftyOldMiner - Improved metal detector logic to solve using a single position in most cases using known locations based on Keeper coordinates - CraftyOldMiner - Added support for official Hypixel wiki, can be toggled in /neu misc - DeDiamondPro -- Added a calculator (/neucalc help), that also works in the auction house / bazaar - nea89o -- Added Minion Helper - hannibal2, Eisengolem & Alea1337 +- Added a calculator (/neucalc help), that also works in the auction house / bazaar - nea89 - Added and fixed various things in the profile viewer: - [Added hotm tab](https://media.discordapp.net/attachments/659613194066722833/991115131507441724/unknown.png) - nopo - Big thanks to kwev1n for some math and jani for the texture @@ -28,7 +27,7 @@ - Added equipment - nopo - Added blaze slayer level and kills - nopo - Added social level - nopo - - Added various new collections and minions - nopo + - Added various new collections and minions - nopo & CrypticPlasma & hannibal2 - Added mastermode catacombs xp to level calculator - nopo - Added profile viewer settings to /neu - nopo - Added an unknown icon if neu doesn't recognize your profile type - nopo @@ -36,6 +35,8 @@ - Fixed minion tiers crafted by coop members not showing up in /pv - Lulonaut - Fixed crash in /pv when the player had a pet that is not saved in the repo - Lulonaut - Added senither and lily weight - CrypticPlasma + - Added the Quiver Info when hovering in inventory tab over Arrows display - Lulonaut + - Added the Magical Power Info when hovering in inventory tab over Accessory Bag display - Lulonaut ### **Minor Changes:** @@ -102,9 +103,13 @@ - Added Fishing Timer over bobber - nea89 - Added [Auction Profit Viewer Overlay](https://cdn.discordapp.com/attachments/848901833119629332/993191851400101918/176946124-28ddf336-1ec7-460b-b22a-5fe2733b46a3.png) - efefury - Added Trophy Reward Overlay - hannibal2 +- Add Auto-Updater (linux only) - nea89 - Added power stone feature - hannibal2 - Added abiphone warning - hannibal2 -- Added blur limit at 100 - nopo +- Added blur limit to map at 100 - nopo +- Added bazaar sacks profit feature - hannibal2 +- Added an option to disable etherwarp overlay when TP is denied - hannibal2 + ### **Bug Fixes:** @@ -130,6 +135,7 @@ - Fixed some vanilla Minecraft keybinds not working in NEU GUIs - nopo - Fixed crash with spamming remove enchant in /neuec - nopo - Fixed missing enchants not working with shiny items - nopo +- Fixed golden dragon not working in pet overlay - CrypticPlasma ### **Other:** diff --git a/build.gradle.kts b/build.gradle.kts index 54c9e92f..6e88fb3b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,10 @@ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>. */ + import java.io.ByteArrayOutputStream +import java.nio.charset.StandardCharsets +import java.util.* plugins { idea @@ -92,21 +95,29 @@ repositories { mavenCentral() mavenLocal() maven("https://repo.spongepowered.org/maven/") + maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") maven("https://jitpack.io") } +val shadowImplementation by configurations.creating { + configurations.implementation.get().extendsFrom(this) +} + dependencies { minecraft("com.mojang:minecraft:1.8.9") mappings("de.oceanlabs.mcp:mcp_stable:22-1.8.9") forge("net.minecraftforge:forge:1.8.9-11.15.1.2318-1.8.9") - implementation("org.spongepowered:mixin:0.7.11-SNAPSHOT") + shadowImplementation("org.spongepowered:mixin:0.7.11-SNAPSHOT") { + isTransitive = false // Dependencies of mixin are already bundled by minecraft + } annotationProcessor("org.spongepowered:mixin:0.8.4-SNAPSHOT") - implementation("com.fasterxml.jackson.core:jackson-core:2.13.1") - implementation("info.bliki.wiki:bliki-core:3.1.0") + shadowImplementation("info.bliki.wiki:bliki-core:3.1.0") testImplementation("org.junit.jupiter:junit-jupiter:5.8.2") testAnnotationProcessor("org.spongepowered:mixin:0.8.4-SNAPSHOT") // modImplementation("io.github.notenoughupdates:MoulConfig:0.0.1") + + modRuntimeOnly("me.djtheredstoner:DevAuth-forge-legacy:1.1.0") } @@ -133,6 +144,7 @@ tasks.withType(Jar::class) { this["MixinConfigs"] = "mixins.notenoughupdates.json" this["FMLCorePluginContainsFMLMod"] = "true" this["ForceLoadAsMod"] = "true" + this["Manifest-Version"] = "1.0" } } @@ -140,35 +152,42 @@ val remapJar by tasks.named<net.fabricmc.loom.task.RemapJarTask>("remapJar") { archiveClassifier.set("dep") from(tasks.shadowJar) input.set(tasks.shadowJar.get().archiveFile) + doLast { + println("Jar name: ${archiveFile.get().asFile}") + } } tasks.shadowJar { archiveClassifier.set("dep-dev") - exclude( - "module-info.class", "LICENSE.txt" - ) + configurations = listOf(shadowImplementation) + exclude("**/module-info.class", "LICENSE.txt") dependencies { - include(dependency("org.spongepowered:mixin")) - - include(dependency("commons-io:commons-io")) - include(dependency("org.apache.commons:commons-lang3")) - include(dependency("com.fasterxml.jackson.core:jackson-databind:2.10.2")) - include(dependency("com.fasterxml.jackson.core:jackson-annotations:2.10.2")) - include(dependency("com.fasterxml.jackson.core:jackson-core:2.10.2")) - - include(dependency("info.bliki.wiki:bliki-core:3.1.0")) - include(dependency("org.slf4j:slf4j-api:1.7.18")) - include(dependency("org.luaj:luaj-jse:3.0.1")) + exclude { + it.moduleGroup.startsWith("org.apache.") || it.moduleName in + listOf("logback-classic", "commons-logging", "commons-codec", "logback-core") + } } fun relocate(name: String) = relocate(name, "io.github.moulberry.notenoughupdates.deps.$name") - relocate("com.fasterxml.jackson") - relocate("org.eclipse") - relocate("org.slf4j") } tasks.assemble.get().dependsOn(remapJar) +val generateBuildFlags by tasks.creating { + outputs.upToDateWhen { false } + val t = layout.buildDirectory.file("buildflags.properties") + outputs.file(t) + val props = project.properties.filter { (name, value) -> name.startsWith("neu.buildflags.") } + doLast { + val p = Properties() + p.putAll(props) + t.get().asFile.writer(StandardCharsets.UTF_8).use { + p.store(it, "Store build time configuration for NEU") + } + } +} + tasks.processResources { + from(generateBuildFlags) filesMatching("mcmod.info") { expand( "version" to project.version, "mcversion" to "1.8.9" diff --git a/gradle.properties b/gradle.properties index 87c0a7c6..f596b2d7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,6 @@ org.gradle.jvmargs=-Xmx2G loom.platform=forge +# NEU Buildflags. Please keep these flags in a commented out form while checked into version control. +# See BuildFlags.java for usages of these values. +# Build with Pronouns in PV by default +# neu.buildflags.pronouns=true diff --git a/src/main/java/io/github/moulberry/notenoughupdates/BuildFlags.java b/src/main/java/io/github/moulberry/notenoughupdates/BuildFlags.java new file mode 100644 index 00000000..d997d980 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/BuildFlags.java @@ -0,0 +1,72 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * For storage of compile-time configuration flags + */ +public class BuildFlags { + + private static final Properties properties = new Properties(); + + static { + try { + properties.load(BuildFlags.class.getResourceAsStream("/buildflags.properties")); + } catch (IOException | NullPointerException e) { + System.out.println("Failed to load build properties: " + e); + } + } + + private static boolean getBuildFlag(String flag) { + return Boolean.parseBoolean(properties.getProperty("neu.buildflags." + flag)); + } + + public static Map<String, Boolean> getAllFlags() { + return Holder.ALL_FLAGS; + } + + public static final boolean ENABLE_PRONOUNS_IN_PV_BY_DEFAULT = getBuildFlag("pronouns"); + + private static class Holder { + static Map<String, Boolean> ALL_FLAGS = new HashMap<>(); + + static { + for (Field declaredField : BuildFlags.class.getDeclaredFields()) { + if (Boolean.TYPE.equals(declaredField.getType()) + && (declaredField.getModifiers() & Modifier.STATIC) != 0) { + try { + declaredField.setAccessible(true); + ALL_FLAGS.put(declaredField.getName(), (Boolean) declaredField.get(null)); + } catch (IllegalAccessException | ClassCastException | SecurityException e) { + System.err.println("Failed to access BuildFlag: " + e); + } + } + } + } + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java index 06321b53..3911396f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java @@ -110,11 +110,11 @@ public class CustomItems { * SHAAAAAAAAAAAAAAAAAAME */ - private static JsonObject create(String internalname, String itemid, String displayname, String... lore) { + private static JsonObject create(String internalname, String itemid, String displayName, String... lore) { JsonObject json = new JsonObject(); json.addProperty("itemid", itemid); json.addProperty("internalname", internalname); - json.addProperty("displayname", EnumChatFormatting.RED + displayname); + json.addProperty("displayname", EnumChatFormatting.RED + displayName); JsonArray jsonlore = new JsonArray(); for (String line : lore) { jsonlore.add(new JsonPrimitive(EnumChatFormatting.GRAY + line)); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index 4d8f3967..407e6852 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -29,7 +29,6 @@ import io.github.moulberry.notenoughupdates.auction.APIManager; import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent; import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; import io.github.moulberry.notenoughupdates.miscgui.KatSitterOverlay; -import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; import io.github.moulberry.notenoughupdates.recipes.CraftingOverlay; import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe; import io.github.moulberry.notenoughupdates.recipes.Ingredient; @@ -781,14 +780,14 @@ public class NEUManager { if (itemMc != null) { itemid = itemMc.getRegistryName(); } - String displayname = display.getString("Name"); + String displayName = display.getString("Name"); String[] info = new String[0]; String clickcommand = ""; JsonObject item = new JsonObject(); item.addProperty("internalname", internalname); item.addProperty("itemid", itemid); - item.addProperty("displayname", displayname); + item.addProperty("displayname", displayName); if (tag != null && tag.hasKey("ExtraAttributes", 10)) { NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); @@ -949,8 +948,7 @@ public class NEUManager { if (!usagesMap.containsKey(internalName)) return false; List<NeuRecipe> usages = getAvailableUsagesFor(internalName); if (usages.isEmpty()) return false; - Minecraft.getMinecraft().displayGuiScreen( - new GuiItemRecipe(usages, this)); + NotEnoughUpdates.INSTANCE.openGui = (new GuiItemRecipe(usages, this)); return true; } @@ -958,8 +956,7 @@ public class NEUManager { if (!recipesMap.containsKey(internalName)) return false; List<NeuRecipe> recipes = getAvailableRecipesFor(internalName); if (recipes.isEmpty()) return false; - Minecraft.getMinecraft().displayGuiScreen( - new GuiItemRecipe(recipes, this)); + NotEnoughUpdates.INSTANCE.openGui = (new GuiItemRecipe(recipes, this)); return true; } @@ -1111,7 +1108,7 @@ public class NEUManager { * json files representing skyblock item data. */ public JsonObject createItemJson( - String internalname, String itemid, String displayname, String[] lore, + String internalname, String itemid, String displayName, String[] lore, String crafttext, String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag ) { @@ -1119,7 +1116,7 @@ public class NEUManager { new JsonObject(), internalname, itemid, - displayname, + displayName, lore, crafttext, infoType, @@ -1131,7 +1128,7 @@ public class NEUManager { } public JsonObject createItemJson( - JsonObject base, String internalname, String itemid, String displayname, String[] lore, + JsonObject base, String internalname, String itemid, String displayName, String[] lore, String crafttext, String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag ) { @@ -1142,7 +1139,7 @@ public class NEUManager { JsonObject json = gson.fromJson(gson.toJson(base, JsonObject.class), JsonObject.class); json.addProperty("internalname", internalname); json.addProperty("itemid", itemid); - json.addProperty("displayname", displayname); + json.addProperty("displayname", displayName); json.addProperty("crafttext", crafttext); json.addProperty("clickcommand", clickcommand); json.addProperty("damage", damage); @@ -1168,14 +1165,14 @@ public class NEUManager { } public boolean writeItemJson( - String internalname, String itemid, String displayname, String[] lore, String crafttext, + String internalname, String itemid, String displayName, String[] lore, String crafttext, String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag ) { return writeItemJson( new JsonObject(), internalname, itemid, - displayname, + displayName, lore, crafttext, infoType, @@ -1187,14 +1184,14 @@ public class NEUManager { } public boolean writeItemJson( - JsonObject base, String internalname, String itemid, String displayname, String[] lore, + JsonObject base, String internalname, String itemid, String displayName, String[] lore, String crafttext, String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag ) { JsonObject json = createItemJson( base, internalname, itemid, - displayname, + displayName, lore, crafttext, infoType, @@ -1487,11 +1484,11 @@ public class NEUManager { if (useReplacements) { replacements = getLoreReplacements(stack.getTagCompound(), -1); - String displayname = json.get("displayname").getAsString(); + String displayName = json.get("displayname").getAsString(); for (Map.Entry<String, String> entry : replacements.entrySet()) { - displayname = displayname.replace("{" + entry.getKey() + "}", entry.getValue()); + displayName = displayName.replace("{" + entry.getKey() + "}", entry.getValue()); } - stack.setStackDisplayName(displayname); + stack.setStackDisplayName(displayName); } if (json.has("lore")) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index e51f118e..19f5a780 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -813,7 +813,7 @@ public class NEUOverlay extends Gui { /** * Handles the mouse input, cancelling the forge event if a NEU gui element is clicked. */ - public boolean mouseInput() { + public synchronized boolean mouseInput() { if (disabled) { return false; } @@ -1483,7 +1483,7 @@ public class NEUOverlay extends Gui { * Returns an index-able array containing the elements in searchedItems. * Whenever searchedItems is updated in updateSearch(), the array is recreated here. */ - public List<JsonObject> getSearchedItems() { + public synchronized List<JsonObject> getSearchedItems() { if (searchedItems == null) { updateSearch(); return new ArrayList<>(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index c604fd86..3a2fa7ef 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -57,6 +57,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.SunTzu; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBlockSounds; import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.DwarvenMinesTextures; +import io.github.moulberry.notenoughupdates.miscfeatures.updater.AutoUpdater; import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay; import io.github.moulberry.notenoughupdates.miscgui.InventoryStorageSelector; import io.github.moulberry.notenoughupdates.miscgui.SignCalculator; @@ -112,8 +113,8 @@ import java.util.Set; public class NotEnoughUpdates { public static final String MODID = "notenoughupdates"; public static final String VERSION = "2.1.0-REL"; - public static final int VERSION_ID = 20000; - public static final int PRE_VERSION_ID = 1; + public static final int VERSION_ID = 20100; + public static final int PRE_VERSION_ID = 0; public static final int HOTFIX_VERSION_ID = 0; /** * Registers the biomes for the crystal hollows here so optifine knows they exists @@ -173,6 +174,7 @@ public class NotEnoughUpdates { public Commands commands; public boolean packDevEnabled = false; public Color[][] colourMap = null; + public AutoUpdater autoUpdater = new AutoUpdater(this); private File configFile; private long lastChatMessage = 0; private long secondLastChatMessage = 0; @@ -240,10 +242,6 @@ public class NotEnoughUpdates { config.apiKey = null; } - if (config.dungeonMap.dmEnable && - !NotEnoughUpdates.INSTANCE.config.hidden.dev) { - config.dungeonMap.dmEnable = false; - } //add the trophy fishing tab to the config if (config.profileViewer.pageLayout.size() == 8) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java index 29b5f4a5..c3999fb6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java @@ -59,6 +59,8 @@ import java.util.TreeMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Consumer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class APIManager { private final NEUManager manager; @@ -409,6 +411,7 @@ public class APIManager { int page = pagesToDownload.pop(); getPageFromAPI(page); } catch (NoSuchElementException ignored) { + return; } //Weird race condition? } } @@ -701,6 +704,16 @@ public class APIManager { ); } + private static final Pattern BAZAAR_ENCHANTMENT_PATTERN = Pattern.compile("ENCHANTMENT_(\\D*)_(\\d+)"); + + public String transformHypixelBazaarToNEUItemId(String hypixelId) { + Matcher matcher = BAZAAR_ENCHANTMENT_PATTERN.matcher(hypixelId); + if (matcher.matches()) { + return matcher.group(1) + ";" + matcher.group(2); + } + return hypixelId.replace(":", "-"); + } + public void updateBazaar() { manager.hypixelApi.getHypixelApiAsync( NotEnoughUpdates.INSTANCE.config.apiData.apiKey, @@ -737,7 +750,7 @@ public class APIManager { } } - bazaarJson.add(entry.getKey().replace(":", "-"), productInfo); + bazaarJson.add(transformHypixelBazaarToNEUItemId(entry.getKey()), productInfo); } } GuiPriceGraph.addToCache(bazaarJson, true); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java index f0ef1ec6..7b4542d0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java @@ -133,6 +133,8 @@ public class CustomAH extends Gui { public int guiLeft = -1; public int guiTop = -1; + private String lastSearch = ""; + private final Category CATEGORY_SWORD = new Category("sword", "Swords", "diamond_sword"); private final Category CATEGORY_ARMOR = new Category("armor", "Armor", "diamond_chestplate"); private final Category CATEGORY_BOWS = new Category("bow", "Bows", "bow"); @@ -275,7 +277,11 @@ public class CustomAH extends Gui { } public void setSearch(String search) { - searchField.setText(search); + if (search == null) { + searchField.setText(lastSearch); + } else { + searchField.setText(search); + } updateSearch(); } @@ -1487,8 +1493,15 @@ public class CustomAH extends Gui { auctionIdsNew.add(entry.getKey()); } } + if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.saveLastSearch) { + lastSearch = ""; + } } else { String query = searchField.getText(); + + if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.saveLastSearch) { + lastSearch = query; + } Set<String> dontMatch = new HashSet<>(); HashSet<String> allMatch = new HashSet<>(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java index b152bc09..fcb2aaf9 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java @@ -19,6 +19,7 @@ package io.github.moulberry.notenoughupdates.commands; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.dev.DevTestCommand; import io.github.moulberry.notenoughupdates.commands.dev.DiagCommand; import io.github.moulberry.notenoughupdates.commands.dev.DungeonWinTestCommand; @@ -41,6 +42,8 @@ import io.github.moulberry.notenoughupdates.commands.misc.CalculatorCommand; import io.github.moulberry.notenoughupdates.commands.misc.CalendarCommand; import io.github.moulberry.notenoughupdates.commands.misc.CosmeticsCommand; import io.github.moulberry.notenoughupdates.commands.misc.CustomizeCommand; +import io.github.moulberry.notenoughupdates.commands.misc.PronounsCommand; +import io.github.moulberry.notenoughupdates.commands.misc.UpdateCommand; import io.github.moulberry.notenoughupdates.commands.profile.CataCommand; import io.github.moulberry.notenoughupdates.commands.profile.PeekCommand; import io.github.moulberry.notenoughupdates.commands.profile.PvCommand; @@ -94,6 +97,8 @@ public class Commands { ClientCommandHandler.instance.registerCommand(new AhCommand()); ClientCommandHandler.instance.registerCommand(new CalculatorCommand()); ClientCommandHandler.instance.registerCommand(new CalendarCommand()); + ClientCommandHandler.instance.registerCommand(new UpdateCommand(NotEnoughUpdates.INSTANCE)); + ClientCommandHandler.instance.registerCommand(new PronounsCommand()); // Fairy Soul Commands ClientCommandHandler.instance.registerCommand(new FairySouls.FairySoulsCommand()); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java index 473bcc9d..aa5cd903 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java @@ -19,6 +19,7 @@ package io.github.moulberry.notenoughupdates.commands.dev; +import io.github.moulberry.notenoughupdates.BuildFlags; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.core.config.GuiPositionEditor; @@ -29,6 +30,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.Locati import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.SpecialBlockZone; import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph; import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; +import io.github.moulberry.notenoughupdates.util.PronounDB; import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.TabListUtils; import io.github.moulberry.notenoughupdates.util.Utils; @@ -44,6 +46,7 @@ import net.minecraftforge.common.MinecraftForge; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; public class DevTestCommand extends ClientCommandBase { @@ -122,6 +125,14 @@ public class DevTestCommand extends ClientCommandBase { " with the mode " + gamemode)); } + if (args.length >= 1 && args[0].equalsIgnoreCase("buildflags")) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "BuildFlags: \n" + + BuildFlags.getAllFlags().entrySet().stream() + .map(it -> " + " + it.getKey() + " - " + it.getValue()) + .collect(Collectors.joining("\n")))); + return; + } if (args.length >= 1 && args[0].equalsIgnoreCase("pricetest")) { if (args.length == 1) { NotEnoughUpdates.INSTANCE.manager.auctionManager.updateBazaar(); @@ -167,6 +178,10 @@ public class DevTestCommand extends ClientCommandBase { Utils.addChatMessage(EnumChatFormatting.AQUA + "I would never search"); return; } + if (args.length == 1 && args[0].equalsIgnoreCase("bluehair")) { + PronounDB.test(); + return; + } if (args.length == 2 && args[0].equalsIgnoreCase("openGui")) { try { NotEnoughUpdates.INSTANCE.openGui = (GuiScreen) Class.forName(args[1]).newInstance(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java index 5e3bd9b1..27faa1ce 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java @@ -48,8 +48,13 @@ public class AhCommand extends ClientCommandBase { NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.clearSearch(); NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.updateSearch(); - if (args.length > 0) + if (args.length > 0) { NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.setSearch(StringUtils.join(args, " ")); + } else { + if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.saveLastSearch) { + NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.setSearch(null); + } + } } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java index 916ce072..b01f106b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java @@ -26,8 +26,8 @@ import net.minecraft.command.ICommandSender; import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; -import java.text.DecimalFormat; import java.math.BigDecimal; +import java.text.DecimalFormat; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -50,7 +50,7 @@ public class CalculatorCommand extends ClientCommandBase { "§eFor Example §b/neucalc 3m*7k§e.\n" + "§eYou can also use suffixes (k, m, b, t, s)§e.\n" + "§eThe \"s\" suffix acts as 64.\n" + - "§eTurn on Sign Calculator in /neu misc to also support this in sign popups.\n")); + "§eTurn on Sign Calculator in /neu misc to also support this in sign popups and the neu search bar.\n")); return; } String source = String.join(" ", args); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java new file mode 100644 index 00000000..1d4e3e3c --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java @@ -0,0 +1,93 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.commands.misc; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import io.github.moulberry.notenoughupdates.util.MinecraftExecutor; +import io.github.moulberry.notenoughupdates.util.PronounDB; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiNewChat; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; + +import java.util.Optional; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +public class PronounsCommand extends ClientCommandBase { + public PronounsCommand() { + super("neupronouns"); + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return "/neupronouns <username> [platform]"; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + switch (args.length) { + case 1: + fetchPronouns("minecraft", args[0]); + break; + case 2: + fetchPronouns(args[1], args[0]); + break; + default: + sender.addChatMessage(new ChatComponentText("§4" + getCommandUsage(sender))); + } + } + + private void fetchPronouns(String platform, String user) { + GuiNewChat nc = Minecraft.getMinecraft().ingameGUI.getChatGUI(); + int id = new Random().nextInt(); + nc.printChatMessageWithOptionalDeletion(new ChatComponentText("§e[NEU] Fetching Pronouns..."), id); + + CompletableFuture<Optional<PronounDB.PronounChoice>> pronouns; + if ("minecraft".equals(platform)) { + CompletableFuture<UUID> c = new CompletableFuture<>(); + NotEnoughUpdates.profileViewer.getPlayerUUID(user, uuidString -> { + if (uuidString == null) { + c.completeExceptionally(new NullPointerException()); + } else { + c.complete(Utils.parseDashlessUUID(uuidString)); + } + }); + pronouns = c.thenApplyAsync(PronounDB::getPronounsFor); + } else { + pronouns = CompletableFuture.supplyAsync(() -> PronounDB.getPronounsFor(platform, user)); + } + pronouns.handleAsync((pronounChoice, throwable) -> { + if (throwable != null || !pronounChoice.isPresent()) { + nc.printChatMessageWithOptionalDeletion(new ChatComponentText("§e[NEU] §4Failed to fetch pronouns."), id); + return null; + } + PronounDB.PronounChoice betterPronounChoice = pronounChoice.get(); + nc.printChatMessageWithOptionalDeletion(new ChatComponentText("§e[NEU] Pronouns for §b" + user + " §eon §b" + platform + "§e:"), id); + betterPronounChoice.render().forEach(it -> nc.printChatMessage(new ChatComponentText("§e[NEU] §a" + it))); + return null; + }, MinecraftExecutor.INSTANCE); + + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java new file mode 100644 index 00000000..36443b27 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java @@ -0,0 +1,96 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.commands.misc; + +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.util.ChatComponentText; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public class UpdateCommand extends ClientCommandBase { + NotEnoughUpdates neu; + + public UpdateCommand(NotEnoughUpdates neu) { + super("neuupdate"); + this.neu = neu; + } + + @Override + public List<String> getCommandAliases() { + return Arrays.asList("neuupdates", "enoughupdates"); + } + + public void displayHelp(ICommandSender sender) { + sender.addChatMessage(new ChatComponentText( + "" + + "§e[NEU] §b/neuupdate help - View help.\n" + + "§e[NEU] §b/neuupdate check - Check for updates.\n" + + "§e[NEU] §b/neuupdate url <url> - Load an update from an direct download URL.\n" + + " §cONLY DO THIS WITH TRUSTED URLS OR IT MIGHT RESULT IN A RAT!\n" + + "§e[NEU] §b/neuupdate fromartifact <url> - Load an update from an artifact.\n" + + " §cIf you don't know what this is, don't use it.\n" + + "" + )); + + } + + @Override + public void processCommand(ICommandSender sender, String[] args) throws CommandException { + if ((args.length == 1 && Objects.equals(args[0], "help")) || args.length == 0) { + displayHelp(sender); + return; + } + switch (args[0].toLowerCase().intern()) { + case "check": + neu.autoUpdater.displayUpdateMessageIfOutOfDate(); + break; + case "url": + if (args.length != 2) { + sender.addChatMessage(new ChatComponentText("§e[NEU] §cPlease provide an URL")); + } + URL url; + try { + url = new URL(args[1]); + } catch (MalformedURLException e) { + e.printStackTrace(); + sender.addChatMessage(new ChatComponentText("§e[NEU] §cInvalid URL")); + return; + } + neu.autoUpdater.updateFromURL(url); + break; + case "scheduledownload": + neu.autoUpdater.scheduleDownload(); + break; + case "updatemodes": + sender.addChatMessage(new ChatComponentText("§e[NEU] §bTo ensure we do not accidentally corrupt your mod folder, we can only offer support for autoupdates on system with certain capabilities for file deletions (specifically unix systems). You can still manually update your files")); + break; + default: + displayHelp(sender); + + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java index 2336eea2..77f685e1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java @@ -19,11 +19,11 @@ package io.github.moulberry.notenoughupdates.commands.profile; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.commands.ClientCommandBase; import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.command.CommandException; @@ -35,16 +35,19 @@ import net.minecraft.util.EnumChatFormatting; import org.apache.commons.lang3.text.WordUtils; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; public class PeekCommand extends ClientCommandBase { private ScheduledExecutorService peekCommandExecutorService = null; + private ScheduledFuture<?> peekScheduledFuture = null; public PeekCommand() { super("peek"); @@ -69,23 +72,23 @@ public class PeekCommand extends ClientCommandBase { } else { profile.resetCache(); - if (peekCommandExecutorService == null || peekCommandExecutorService.isShutdown()) { + if (peekCommandExecutorService == null) { peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor(); - } else { + } + + if (peekScheduledFuture != null && !peekScheduledFuture.isDone()) { Utils.addChatMessage( EnumChatFormatting.RED + "[PEEK] New peek command run, cancelling old one."); - peekCommandExecutorService.shutdownNow(); - peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor(); + peekScheduledFuture.cancel(true); } Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText( EnumChatFormatting.YELLOW + "[PEEK] Getting the player's Skyblock profile(s)..."), id); long startTime = System.currentTimeMillis(); - peekCommandExecutorService.schedule(new Runnable() { + peekScheduledFuture = peekCommandExecutorService.schedule(new Runnable() { public void run() { if (System.currentTimeMillis() - startTime > 10 * 1000) { - Minecraft.getMinecraft().ingameGUI .getChatGUI() .printChatMessageWithOptionalDeletion(new ChatComponentText( @@ -103,7 +106,7 @@ public class PeekCommand extends ClientCommandBase { PlayerStats.Stats stats = profile.getStats(null); if (stats == null) return; - JsonObject skill = profile.getSkillInfo(null); + Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(null); Minecraft.getMinecraft().ingameGUI .getChatGUI() @@ -112,26 +115,23 @@ public class PeekCommand extends ClientCommandBase { Utils.getElementAsString(profile.getHypixelProfile().get("displayname"), name) + "'s Info " + EnumChatFormatting.STRIKETHROUGH + "-=-"), id); - if (skill == null) { - Utils.addChatMessage(EnumChatFormatting.YELLOW + "Skills api disabled!"); + if (skyblockInfo == null) { + Utils.addChatMessage(EnumChatFormatting.YELLOW + "Skills API disabled!"); } else { float totalSkillLVL = 0; float totalSkillCount = 0; - for (Map.Entry<String, JsonElement> entry : skill.entrySet()) { - if (entry.getKey().startsWith("level_skill")) { - if (entry.getKey().contains("runecrafting")) continue; - if (entry.getKey().contains("carpentry")) continue; - totalSkillLVL += entry.getValue().getAsFloat(); - totalSkillCount++; - } + List<String> skills = Arrays.asList("taming", "mining", "foraging", "enchanting", "farming", "combat", "fishing", "alchemy"); + for (String skillName : skills) { + totalSkillLVL += skyblockInfo.get(skillName).level; + totalSkillCount++; } - float combat = Utils.getElementAsFloat(skill.get("level_skill_combat"), 0); - float zombie = Utils.getElementAsFloat(skill.get("level_slayer_zombie"), 0); - float spider = Utils.getElementAsFloat(skill.get("level_slayer_spider"), 0); - float wolf = Utils.getElementAsFloat(skill.get("level_slayer_wolf"), 0); - float enderman = Utils.getElementAsFloat(skill.get("level_slayer_enderman"), 0); + float combat = skyblockInfo.get("combat").level; + float zombie = skyblockInfo.get("zombie").level; + float spider = skyblockInfo.get("spider").level; + float wolf = skyblockInfo.get("wolf").level; + float enderman = skyblockInfo.get("enderman").level; float avgSkillLVL = totalSkillLVL / totalSkillCount; @@ -172,7 +172,7 @@ public class PeekCommand extends ClientCommandBase { overallScore += enderman * enderman / 81f; overallScore += avgSkillLVL / 20f; - int cata = (int) Utils.getElementAsFloat(skill.get("level_skill_catacombs"), 0); + int cata = (int) skyblockInfo.get("catacombs").level; EnumChatFormatting cataPrefix = cata > 15 ? (cata > 25 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) : EnumChatFormatting.RED; @@ -278,7 +278,7 @@ public class PeekCommand extends ClientCommandBase { peekCommandExecutorService.shutdownNow(); } else { - peekCommandExecutorService.schedule(this, 200, TimeUnit.MILLISECONDS); + peekScheduledFuture = peekCommandExecutorService.schedule(this, 200, TimeUnit.MILLISECONDS); } } }, 200, TimeUnit.MILLISECONDS); 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 b0b6e2db..2b6f7fc7 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 @@ -23,6 +23,9 @@ import com.google.common.collect.Sets; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.Set; public class StringUtils { @@ -64,6 +67,14 @@ public class StringUtils { return Integer.parseInt(str); } + public static String urlEncode(String something) { + try { + return URLEncoder.encode(something, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); // UTF 8 should always be present + } + } + public static String removeLastWord(String string, String splitString) { try { String[] split = string.split(splitString); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java new file mode 100644 index 00000000..8e0f24b9 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java @@ -0,0 +1,85 @@ +package io.github.moulberry.notenoughupdates.envcheck; + +import javax.swing.*; +import java.lang.reflect.Field; +import java.util.Objects; + +public class EnvironmentScan { + + static Class<?> tryGetClass(String name) { + try { + return Class.forName(name); + } catch (ClassNotFoundException e) { + return null; + } + } + + static Object tryGetField(Class<?> clazz, Object inst, String name) { + if (clazz == null) return null; + try { + Field declaredField = clazz.getDeclaredField(name); + return declaredField.get(inst); + } catch (NoSuchFieldException | IllegalAccessException ignored) { + } + return null; + } + + + static boolean isAtLeast(Object left, int right) { + if (left instanceof Integer) { + return (Integer) left >= right; + } + return false; + } + + static boolean shouldCheckOnce = true; + + static void checkEnvironmentOnce() { + if (shouldCheckOnce) checkEnvironment(); + } + + + static void checkEnvironment() { + shouldCheckOnce = false; + checkForgeEnvironment(); + } + + static void checkForgeEnvironment() { + Class<?> forgeVersion = tryGetClass("net.minecraftforge.common.ForgeVersion"); + if (forgeVersion == null + || !Objects.equals(tryGetField(forgeVersion, null, "majorVersion"), 11) + || !Objects.equals(tryGetField(forgeVersion, null, "minorVersion"), 15) + || !isAtLeast(tryGetField(forgeVersion, null, "revisionVersion"), 1) + || !Objects.equals(tryGetField(forgeVersion, null, "mcVersion"), "1.8.9") + ) { + + System.out.printf("Forge Version : %s%nMajor : %s%nMinor : %s%nRevision : %s%nMinecraft : %s%n", + forgeVersion, + tryGetField(forgeVersion, null, "majorVersion"), + tryGetField(forgeVersion, null, "minorVersion"), + tryGetField(forgeVersion, null, "revisionVersion"), + tryGetField(forgeVersion, null, "mcVersion") + ); + missingOrOutdatedForgeError(); + } + } + + static void missingOrOutdatedForgeError() { + showErrorMessage( + "You just launched NotEnoughUpdates with the wrong (or no) modloader installed.", + "", + "NotEnoughUpdates only works in Minecraft 1.8.9, with Forge 11.15.1+", + "Please relaunch NotEnoughUpdates in the correct environment.", + "If you are using Minecraft 1.8.9 with Forge 11.15.1+ installed, please contact support.", + "Click OK to launch anyways." + ); + } + + + public static void showErrorMessage(String... messages) { + String message = String.join("\n", messages); + JOptionPane.showMessageDialog( + null, message, "NotEnoughUpdates - Problematic System Configuration", JOptionPane.ERROR_MESSAGE + ); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/envcheck/FabricEntrypoint.java b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/FabricEntrypoint.java new file mode 100644 index 00000000..4a70fca3 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/FabricEntrypoint.java @@ -0,0 +1,26 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.envcheck; + +public class FabricEntrypoint { + static { + EnvironmentScan.checkForgeEnvironment(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/envcheck/NEUMixinConfigPlugin.java b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/NEUMixinConfigPlugin.java new file mode 100644 index 00000000..44e24ff4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/NEUMixinConfigPlugin.java @@ -0,0 +1,46 @@ +package io.github.moulberry.notenoughupdates.envcheck; + +import org.spongepowered.asm.lib.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.List; +import java.util.Set; + +public class NEUMixinConfigPlugin implements IMixinConfigPlugin { + + static { + EnvironmentScan.checkEnvironmentOnce(); + } + + @Override + public void onLoad(String mixinPackage) { + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + return true; + } + + @Override + public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) { + } + + @Override + public List<String> getMixins() { + return null; + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java index ff0e5f13..9dc8d8b0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java @@ -89,9 +89,23 @@ public class NEUItemEditor extends GuiScreen { } catch (NBTException ignored) { } } - nbtTag.getCompoundTag("ExtraAttributes").removeTag("uuid"); - nbtTag.getCompoundTag("ExtraAttributes").removeTag("timestamp"); + NBTTagCompound extraAttributes = nbtTag.getCompoundTag("ExtraAttributes"); + extraAttributes.removeTag("uuid"); + extraAttributes.removeTag("timestamp"); + if (extraAttributes.hasKey("petInfo")) { + try { + NBTTagCompound petInfo = JsonToNBT.getTagFromJson(extraAttributes.getString("petInfo")); + + petInfo.removeTag("\"heldItem\""); + petInfo.setString("\"exp\"", "0.0"); + petInfo.setString("\"candyUsed\"", "0"); + petInfo.removeTag("\"uuid\""); + + extraAttributes.setString("petInfo", petInfo.toString()); + } catch (NBTException ignored) { + } + } savedRepoItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().getOrDefault(internalName, null); internalName = internalName == null ? "" : internalName; @@ -103,8 +117,8 @@ public class NEUItemEditor extends GuiScreen { this.itemId = addTextFieldWithSupplier(itemid, NO_SPACE); options.add(new GuiElementText("Display name: ", Color.WHITE.getRGB())); - String displayname = item.has("displayname") ? item.get("displayname").getAsString() : ""; - this.displayName = addTextFieldWithSupplier(displayname, COLOUR); + String displayName = item.has("displayname") ? item.get("displayname").getAsString() : ""; + this.displayName = addTextFieldWithSupplier(displayName, COLOUR); options.add(new GuiElementText("Lore: ", Color.WHITE.getRGB())); JsonElement loreElement = getItemInfo("lore"); @@ -161,7 +175,7 @@ public class NEUItemEditor extends GuiScreen { rightOptions.add(new GuiElementButton("Remove enchants", Color.RED.getRGB(), () -> { nbtTag.removeTag("ench"); - nbtTag.getCompoundTag("ExtraAttributes").removeTag("enchantments"); + extraAttributes.removeTag("enchantments"); })); rightOptions.add(new GuiElementButton( "Add enchant glint", 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 14df3926..f3ed8e7c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java @@ -26,7 +26,6 @@ import com.google.gson.JsonPrimitive; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import io.github.moulberry.notenoughupdates.ItemPriceInformation; -import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.MiscUtils; import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; @@ -73,7 +72,7 @@ public class ItemTooltipListener { private final NotEnoughUpdates neu; private final Pattern xpLevelPattern = Pattern.compile("(.*) (\\xA7e(.*)\\xA76/\\xA7e(.*))"); private final HashSet<String> percentStats = new HashSet<>(); - DecimalFormat myFormatter = new DecimalFormat("###,###.###"); + DecimalFormat myFormatter = new DecimalFormat("#,###,###.###"); private String currentRarity = "COMMON"; private boolean copied = false; private boolean showReforgeStoneStats = true; @@ -791,8 +790,7 @@ public class ItemTooltipListener { } PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack( - event.itemStack.getDisplayName(), - NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(event.itemStack.getTagCompound()) + event.itemStack.getTagCompound() ); if (pet == null) { return; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java index 0add19f5..7435d941 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java @@ -19,7 +19,6 @@ package io.github.moulberry.notenoughupdates.listener; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; @@ -45,7 +44,6 @@ import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.Utils; import io.github.moulberry.notenoughupdates.util.XPInformation; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.event.ClickEvent; import net.minecraft.init.Items; @@ -58,9 +56,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import org.lwjgl.input.Keyboard; -import java.io.File; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -80,73 +76,6 @@ public class NEUEventListener { this.neu = neu; } - private void displayUpdateMessage(JsonObject updateJson, String updateMessage, String downloadLink) { - int firstWidth = -1; - - for (String line : Iterables.concat(Arrays.asList(updateMessage.split("\n")), Arrays.asList("Download here"))) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - boolean isDownloadLink = line.equals("Download here"); - int width = fr.getStringWidth(line); - if (firstWidth == -1) { - firstWidth = width; - } - int missingLen = firstWidth - width; - if (missingLen > 0) { - StringBuilder sb = new StringBuilder(missingLen / 4 / 2 +line.length()); - for (int i = 0; i < missingLen / 4 / 2; i++) { /* fr.getCharWidth(' ') == 4 */ - sb.append(" "); - } - sb.append(line); - line = sb.toString(); - } - ChatComponentText cp = new ChatComponentText(line); - if (isDownloadLink) - cp.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, downloadLink)); - Minecraft.getMinecraft().thePlayer.addChatMessage(cp); - } - neu.displayLinks(updateJson, firstWidth); - NotificationHandler.displayNotification(Arrays.asList( - "§eThere is a new version of NotEnoughUpdates available.", - "§eCheck the chat for more information" - ), true); - } - - private void displayUpdateMessageIfOutOfDate() { - File repo = neu.manager.repoLocation; - if (repo.exists()) { - File updateJson = new File(repo, "update.json"); - try { - JsonObject o = neu.manager.getJsonFromFile(updateJson); - - int fullReleaseVersion = - o.has("version_id") && o.get("version_id").isJsonPrimitive() ? o.get("version_id").getAsInt() : -1; - int preReleaseVersion = - o.has("version_id") && o.get("version_id").isJsonPrimitive() ? o.get("version_id").getAsInt() : -1; - int hotfixVersion = - o.has("hotfix_id") && o.get("hotfix_id").isJsonPrimitive() ? o.get("hotfix_id").getAsInt() : -1; - - boolean hasFullReleaseAvailableForUpgrade = fullReleaseVersion > NotEnoughUpdates.VERSION_ID; - boolean hasHotfixAvailableForUpgrade = - fullReleaseVersion == NotEnoughUpdates.VERSION_ID && hotfixVersion > NotEnoughUpdates.HOTFIX_VERSION_ID; - boolean hasPreReleaseAvailableForUpdate = - fullReleaseVersion == NotEnoughUpdates.VERSION_ID && preReleaseVersion > NotEnoughUpdates.PRE_VERSION_ID; - - int updateChannel = NotEnoughUpdates.INSTANCE.config.notifications.updateChannel; /* 1 = Full, 2 = Pre */ - if (hasFullReleaseAvailableForUpgrade || (hasHotfixAvailableForUpgrade && updateChannel == 1)) { - displayUpdateMessage(o, o.get("update_msg").getAsString(), o.get("update_link").getAsString()); - } else if (hasPreReleaseAvailableForUpdate && updateChannel == 2) { - displayUpdateMessage(o, o.get("pre_update_msg").getAsString(), o.get("pre_update_link").getAsString()); - } - } catch (Exception e) { - e.printStackTrace(); - Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( - "§e[NEU] §cThere has been an error checking for updates. Check the log or join the discord for more information.").setChatStyle( - Utils.createClickStyle( - ClickEvent.Action.OPEN_URL, "https://discord.gg/moulberry"))); - } - } - } - @SubscribeEvent public void onWorldLoad(WorldEvent.Unload event) { NotEnoughUpdates.INSTANCE.saveConfig(); @@ -266,7 +195,7 @@ public class NEUEventListener { joinedSB = true; if (NotEnoughUpdates.INSTANCE.config.notifications.updateChannel != 0) { - displayUpdateMessageIfOutOfDate(); + NotEnoughUpdates.INSTANCE.autoUpdater.displayUpdateMessageIfOutOfDate(); } if (NotEnoughUpdates.INSTANCE.config.notifications.doRamNotif) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java index b6d89dd1..bfe0cfd7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java @@ -23,6 +23,7 @@ import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonPrimitive; @@ -140,6 +141,7 @@ public class RenderListener { private String correctingItem; private boolean typing; private HashMap<String, String> cachedDefinitions; + private boolean inDungeonPage = false; public RenderListener(NotEnoughUpdates neu) { this.neu = neu; @@ -346,6 +348,7 @@ public class RenderListener { NotificationHandler.renderNotification(); } + inDungeonPage = false; if ((NotificationHandler.shouldRenderOverlay(event.gui) || event.gui instanceof CustomAHGui) && neu.isOnSkyblock()) { ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); @@ -533,6 +536,12 @@ public class RenderListener { x -= 25; } } + if (inDungeonPage) { + if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && + y < guiTop + 100) { + x += 185; + } + } GlStateManager.color(1, 1, 1, 1f); @@ -661,6 +670,13 @@ public class RenderListener { } } + if (inDungeonPage) { + if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && + y < guiTop + 100) { + x += 185; + } + } + if (x - guiLeft >= 85 && x - guiLeft <= 115 && y - guiTop >= 4 && y - guiTop <= 25) { disableCraftingText = true; } @@ -708,7 +724,6 @@ public class RenderListener { private void renderDungeonChestOverlay(GuiScreen gui) { if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 3) return; - if (gui instanceof GuiChest && NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc != 2) { try { int xSize = ((AccessorGuiContainer) gui).getXSize(); @@ -720,8 +735,9 @@ public class RenderListener { IInventory lower = cc.getLowerChestInventory(); ItemStack rewardChest = lower.getStackInSlot(31); - if (rewardChest != null && rewardChest.getDisplayName().endsWith( - EnumChatFormatting.GREEN + "Open Reward Chest")) { + this.inDungeonPage = rewardChest != null && rewardChest.getDisplayName().endsWith( + EnumChatFormatting.GREEN + "Open Reward Chest"); + if (inDungeonPage) { int chestCost = 0; try { String line6 = Utils.cleanColour(neu.manager.getLoreFromNBT(rewardChest.getTagCompound())[6]); @@ -917,6 +933,21 @@ public class RenderListener { 160 ); } + JsonObject mayorJson = SBInfo.getInstance().getMayorJson(); + JsonElement mayor = mayorJson.get("mayor"); + if (mayorJson.has("mayor") && mayor != null && mayor.getAsJsonObject().has("name") && + mayor.getAsJsonObject().get("name").getAsString().equals("Derpy") + && NotEnoughUpdates.INSTANCE.config.dungeons.shouldWarningDerpy) { + Utils.drawStringScaled( + EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "shMayor Derpy active!", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + xSize + 4 + 10, + guiTop + 85, + true, + 0, + 1.3f + ); + } } } catch (Exception e) { e.printStackTrace(); @@ -1087,6 +1118,12 @@ public class RenderListener { x -= 25; } } + if (inDungeonPage) { + if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && + y < guiTop + 100) { + x += 185; + } + } if (mouseX >= x && mouseX <= x + 18 && mouseY >= y && mouseY <= y + 18) { if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) { @@ -1253,22 +1290,22 @@ public class RenderListener { try { JsonObject newNPC = new JsonObject(); - String displayname = lower.getDisplayName().getUnformattedText(); + String displayName = lower.getDisplayName().getUnformattedText(); File file = new File( Minecraft.getMinecraft().mcDataDir.getAbsolutePath(), "config" + File.separator + "notenoughupdates" + File.separator + "repo" + File.separator + "npc" + File.separator + - displayname.toUpperCase().replace(" ", "_") + ".json" + displayName.toUpperCase().replace(" ", "_") + ".json" ); newNPC.add("itemid", new JsonPrimitive("minecraft:skull")); - newNPC.add("displayname", new JsonPrimitive("§9" + displayname + " (NPC)")); + newNPC.add("displayname", new JsonPrimitive("§9" + displayName + " (NPC)")); newNPC.add("nbttag", new JsonPrimitive("TODO")); newNPC.add("damage", new JsonPrimitive(3)); JsonArray newArray = new JsonArray(); newArray.add(new JsonPrimitive("")); newNPC.add("lore", newArray); - newNPC.add("internalname", new JsonPrimitive(displayname.toUpperCase().replace(" ", "_") + "_NPC")); + newNPC.add("internalname", new JsonPrimitive(displayName.toUpperCase().replace(" ", "_") + "_NPC")); newNPC.add("clickcommand", new JsonPrimitive("viewrecipe")); newNPC.add("modver", new JsonPrimitive(NotEnoughUpdates.VERSION)); newNPC.add("infoType", new JsonPrimitive("WIKI_URL")); @@ -1359,7 +1396,7 @@ public class RenderListener { ) { writer.write(gson.toJson(newNPC)); Utils.addChatMessage( - EnumChatFormatting.AQUA + "Parsed and saved: " + EnumChatFormatting.WHITE + displayname); + EnumChatFormatting.AQUA + "Parsed and saved: " + EnumChatFormatting.WHITE + displayName); } } catch (IOException ignored) { Utils.addChatMessage(EnumChatFormatting.RED + "Error while writing file."); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java index 75584662..254c891a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java @@ -24,7 +24,7 @@ import io.github.moulberry.notenoughupdates.core.GuiElement; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; 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.Gui; import net.minecraft.client.gui.ScaledResolution; @@ -56,8 +56,7 @@ public class AbiphoneWarning extends GuiElement { return false; } - if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && - SBInfo.getInstance().lastOpenContainerName.startsWith("Abiphone ")) { + if (Utils.getOpenChestName().startsWith("Abiphone ")) { return true; } else { showWarning = false; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java index 0d2d863d..3bd674dd 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java @@ -24,7 +24,6 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.GuiElement; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; -import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; @@ -67,8 +66,7 @@ public class AuctionBINWarning extends GuiElement { return false; } - if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && - SBInfo.getInstance().lastOpenContainerName.startsWith("Create BIN Auction")) { + if (Utils.getOpenChestName().startsWith("Create BIN Auction")) { return true; } else { sellingTooltip = null; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionSortModeWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionSortModeWarning.java index 97e32749..8ac0151a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionSortModeWarning.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionSortModeWarning.java @@ -23,7 +23,6 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; -import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.inventory.GuiChest; @@ -41,9 +40,8 @@ public class AuctionSortModeWarning { private boolean isAuctionBrowser() { return NotEnoughUpdates.INSTANCE.config.ahTweaks.enableSortWarning && - Minecraft.getMinecraft().currentScreen instanceof GuiChest && - (SBInfo.getInstance().lastOpenContainerName.startsWith("Auctions Browser") || - SBInfo.getInstance().lastOpenContainerName.startsWith("Auctions: \"")); + (Utils.getOpenChestName().startsWith("Auctions Browser") || + Utils.getOpenChestName().startsWith("Auctions: \"")); } public void onPostGuiRender() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BazaarSacksProfit.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BazaarSacksProfit.java index 51ec28dd..084fd03f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BazaarSacksProfit.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BazaarSacksProfit.java @@ -58,13 +58,12 @@ public class BazaarSacksProfit { private final Map<String, Integer> prices = new HashMap<>(); private final Map<String, String> names = new HashMap<>(); private final List<String> invalidNames = new ArrayList<>(); + private boolean dirty = true; @SubscribeEvent public void onGuiOpen(GuiOpenEvent event) { showSellOrderPrice = false; - prices.clear(); - names.clear(); - invalidNames.clear(); + dirty = true; } @SubscribeEvent(priority = EventPriority.LOW) @@ -82,7 +81,12 @@ public class BazaarSacksProfit { } pressedShiftLast = shift; - if (prices.isEmpty()) { + if (dirty) { + dirty = false; + prices.clear(); + names.clear(); + invalidNames.clear(); + out: for (String line : ItemUtils.getLore(itemStack)) { if (line.contains("§7x ")) { @@ -96,8 +100,8 @@ public class BazaarSacksProfit { String internalName = entry.getKey(); JsonObject object = entry.getValue(); if (object.has("displayname")) { - String displayname = object.get("displayname").getAsString(); - if (displayname.equals(bazaarName)) { + String name = object.get("displayname").getAsString(); + if (name.equals(bazaarName)) { prices.put(internalName, amount); names.put(internalName, bazaarName); continue out; @@ -146,6 +150,7 @@ public class BazaarSacksProfit { map.put("§a" + formatter.format(amount) + "§7x §f" + name + " §7for §6" + priceFormat + " coins", extraPrice); } + event.toolTip.add(4, ""); if (showSellOrderPrice) { event.toolTip.add(4, "§7Sell order price: §6" + formatter.format(totalPrice)); } else { @@ -153,14 +158,18 @@ public class BazaarSacksProfit { } event.toolTip.add(4, ""); + event.toolTip.removeIf(line -> line.equals("§5§o")); + int index = 4; for (String name : invalidNames) { - event.toolTip.add(4, name + " §cMissing repo data!"); + index++; + event.toolTip.add(4, name + " §c[NEU] Missing Repo data!"); } for (String text : TrophyRewardOverlay.sortByValue(map).keySet()) { + index++; event.toolTip.add(4, text); } + event.toolTip.add(index, ""); - event.toolTip.add(""); if (!showSellOrderPrice) { event.toolTip.add("§8[Press SHIFT to show sell order price]"); } else { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java index ca9a92cb..c77a4b39 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java @@ -273,6 +273,7 @@ public class CustomItemEffects { private boolean usingEtherwarp = false; private RaycastResult etherwarpRaycast = null; private int lastEtherwarpUse = 0; + private String denyTpReason = null; @SubscribeEvent public void onOverlayDrawn(RenderGameOverlayEvent.Post event) { @@ -281,40 +282,50 @@ public class CustomItemEffects { ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem(); String heldInternal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(held); - if (usingEtherwarp && NotEnoughUpdates.INSTANCE.config.itemOverlays.enableEtherwarpHelperOverlay) { - String denyTpReason = null; + WorldClient world = Minecraft.getMinecraft().theWorld; + if (usingEtherwarp) { + denyTpReason = null; if (etherwarpRaycast == null) { denyTpReason = "Too far!"; } else { BlockPos pos = etherwarpRaycast.pos; - if (!etherwarpRaycast.state.getBlock().isCollidable() || - etherwarpRaycast.state.getBlock().getCollisionBoundingBox( - Minecraft.getMinecraft().theWorld, - etherwarpRaycast.pos, - etherwarpRaycast.state - ) == null) { + Block block = etherwarpRaycast.state.getBlock(); + if (!block.isCollidable() || + //Don't allow teleport at this block + block == Blocks.carpet || block == Blocks.skull || + block.getCollisionBoundingBox(world, etherwarpRaycast.pos, etherwarpRaycast.state) == null && + //Allow teleport at this block + block != Blocks.wall_sign && block != Blocks.standing_sign) { denyTpReason = "Not solid!"; } else { - WorldClient world = Minecraft.getMinecraft().theWorld; - Block above = world.getBlockState(pos.add(0, 1, 0)).getBlock(); - if (above != Blocks.air && above.isCollidable() && - above.getCollisionBoundingBox(Minecraft.getMinecraft().theWorld, pos.add(0, 1, 0), - world.getBlockState(pos.add(0, 1, 0)) - ) != null || - world.getBlockState(pos.add(0, 2, 0)).getBlock() != Blocks.air) { + BlockPos blockPosAbove = pos.add(0, 1, 0); + Block blockAbove = world.getBlockState(blockPosAbove).getBlock(); + + Block twoBlockAbove = world.getBlockState(pos.add(0, 2, 0)).getBlock(); + if (blockAbove != Blocks.air && + //Allow teleport to the block below this block + blockAbove != Blocks.carpet && blockAbove != Blocks.skull && blockAbove.isCollidable() && + blockAbove.getCollisionBoundingBox(world, blockPosAbove, world.getBlockState(blockPosAbove)) != null || + //Don't allow teleport to the block below this block + blockAbove == Blocks.wall_sign || block == Blocks.standing_sign || + //Allow teleport to the block 2 blocks below this block + twoBlockAbove != Blocks.air && twoBlockAbove != Blocks.double_plant && twoBlockAbove != Blocks.carpet && + blockAbove != Blocks.skull) { denyTpReason = "No air above!"; } } } - if (denyTpReason != null) { - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - Utils.drawStringCentered(EnumChatFormatting.RED + "Can't TP: " + denyTpReason, - Minecraft.getMinecraft().fontRendererObj, - scaledResolution.getScaledWidth() / 2f, scaledResolution.getScaledHeight() / 2f + 10, true, 0 - ); - GlStateManager.color(1, 1, 1, 1); + if (NotEnoughUpdates.INSTANCE.config.itemOverlays.enableEtherwarpHelperOverlay) { + if (denyTpReason != null) { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + Utils.drawStringCentered(EnumChatFormatting.RED + "Can't TP: " + denyTpReason, + Minecraft.getMinecraft().fontRendererObj, + scaledResolution.getScaledWidth() / 2f, scaledResolution.getScaledHeight() / 2f + 10, true, 0 + ); + GlStateManager.color(1, 1, 1, 1); + } } } @@ -326,7 +337,7 @@ public class CustomItemEffects { Minecraft.getMinecraft().objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK && onPrivateIsland) { - IBlockState hover = Minecraft.getMinecraft().theWorld.getBlockState( + IBlockState hover = world.getBlockState( Minecraft.getMinecraft().objectMouseOver.getBlockPos().offset( Minecraft.getMinecraft().objectMouseOver.sideHit, 1)); if (hover.getBlock() == Blocks.air) { @@ -338,14 +349,14 @@ public class CustomItemEffects { TreeMap<Float, Set<BlockPos>> candidatesOldSorted = new TreeMap<>(); IBlockState match = - Minecraft.getMinecraft().theWorld.getBlockState(Minecraft.getMinecraft().objectMouseOver.getBlockPos()); + world.getBlockState(Minecraft.getMinecraft().objectMouseOver.getBlockPos()); Item matchItem = Item.getItemFromBlock(match.getBlock()); if (matchItem != null) { ItemStack matchStack = new ItemStack(matchItem, 1, match .getBlock() .getDamageValue( - Minecraft.getMinecraft().theWorld, + world, Minecraft.getMinecraft().objectMouseOver.getBlockPos() ) ); @@ -603,7 +614,8 @@ public class CustomItemEffects { double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) event.partialTicks; double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) event.partialTicks; - if (tick - lastEtherwarpUse > 10) { + //Don't need to wait 10 ticks when zoom is disabled + if (tick - lastEtherwarpUse > 10 || !NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpZoom) { boolean aotv = Minecraft.getMinecraft().thePlayer.isSneaking() && (heldInternal.equals("ASPECT_OF_THE_VOID") || heldInternal.equals("ASPECT_OF_THE_END")); if (aotv || heldInternal.equals("ETHERWARP_CONDUIT")) { @@ -632,20 +644,30 @@ public class CustomItemEffects { if (etherwarpRaycast != null && NotEnoughUpdates.INSTANCE.config.itemOverlays.enableEtherwarpBlockOverlay) { - AxisAlignedBB bb = etherwarpRaycast.state.getBlock().getSelectedBoundingBox( - Minecraft.getMinecraft().theWorld, - etherwarpRaycast.pos - ) - .expand(0.01D, 0.01D, 0.01D).offset(-d0, -d1, -d2); - drawFilledBoundingBox(bb, 1f, NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpHighlightColour); + if (denyTpReason == null || !NotEnoughUpdates.INSTANCE.config.itemOverlays.disableOverlayWhenFailed) { + AxisAlignedBB box = etherwarpRaycast.state.getBlock().getSelectedBoundingBox( + Minecraft.getMinecraft().theWorld, + etherwarpRaycast.pos + ); + AxisAlignedBB bb = box.expand(0.01D, 0.01D, 0.01D).offset(-d0, -d1, -d2); + drawFilledBoundingBox( + bb, + 1f, + NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpHighlightColour + ); - GlStateManager.disableDepth(); - drawOutlineBoundingBox(bb, 2f, NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpHighlightColour); - GlStateManager.enableDepth(); + GlStateManager.disableDepth(); + drawOutlineBoundingBox( + bb, + 2f, + NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpHighlightColour + ); + GlStateManager.enableDepth(); - GlStateManager.depthMask(true); - GlStateManager.enableTexture2D(); - GlStateManager.disableBlend(); + GlStateManager.depthMask(true); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } if (NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpZoom) { float distFactor = 1 - diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java index 1032fe16..6b541256 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java @@ -96,20 +96,14 @@ public class EnchantingSolvers { return; } - if (event.gui instanceof GuiChest) { - GuiChest chest = (GuiChest) event.gui; - ContainerChest container = (ContainerChest) chest.inventorySlots; - String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); - String lower = containerName.toLowerCase(); - - if (!lower.contains("stakes")) { - if (lower.startsWith("chronomatron")) { - currentSolver = SolverType.CHRONOMATRON; - } else if (lower.startsWith("ultrasequencer")) { - currentSolver = SolverType.ULTRASEQUENCER; - } else if (lower.startsWith("superpairs")) { - currentSolver = SolverType.SUPERPAIRS; - } + String openChestName = Utils.getOpenChestName(); + if (!openChestName.contains("Stakes")) { + if (openChestName.startsWith("Chronomatron")) { + currentSolver = SolverType.CHRONOMATRON; + } else if (openChestName.startsWith("Ultrasequencer")) { + currentSolver = SolverType.ULTRASEQUENCER; + } else if (openChestName.startsWith("Superpairs")) { + currentSolver = SolverType.SUPERPAIRS; } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java index 3e37b522..077054a4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java @@ -38,7 +38,6 @@ import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.inventory.ContainerChest; import net.minecraft.item.ItemStack; import net.minecraft.util.BlockPos; -import net.minecraft.util.ChatComponentText; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.Vec3i; import net.minecraftforge.client.event.RenderWorldLastEvent; @@ -389,7 +388,7 @@ public class Navigation { && NotEnoughUpdates.INSTANCE.config.misc.untrackCloseWaypoints && island.equals(SBInfo.getInstance().mode)) { EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; - if (thePlayer.getDistanceSq(position) < 16) + if (thePlayer != null && thePlayer.getDistanceSq(position) < 16) untrackWaypoint(); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NewApiKeyHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NewApiKeyHelper.java new file mode 100644 index 00000000..6036d93b --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NewApiKeyHelper.java @@ -0,0 +1,43 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.play.client.C01PacketChatMessage; +import net.minecraft.util.ChatComponentText; + +public class NewApiKeyHelper { + private static final NewApiKeyHelper INSTANCE = new NewApiKeyHelper(); + + public static NewApiKeyHelper getInstance() { + return INSTANCE; + } + + public void hookPacketChatMessage(C01PacketChatMessage packet) { + String message = packet.getMessage().toLowerCase(); + if (message.equals("/api new")) return; + + if (message.replace(" ", "").startsWith("/apinew")) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "§e[NotEnoughUpdates] §7You just executed §c" + packet.getMessage() + + "§7. Did you mean to execute §e/api new§7?")); + } + } +} 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 344f21aa..fcb42d73 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java @@ -22,7 +22,6 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import com.google.common.collect.Lists; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonNull; import com.google.gson.JsonObject; @@ -52,7 +51,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumChatFormatting; import net.minecraftforge.client.event.ClientChatReceivedEvent; -import net.minecraftforge.event.entity.player.ItemTooltipEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -63,11 +61,10 @@ import org.lwjgl.util.vector.Vector2f; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; @@ -78,18 +75,17 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; public class PetInfoOverlay extends TextOverlay { private static final Pattern XP_BOOST_PATTERN = Pattern.compile( "PET_ITEM_(COMBAT|FISHING|MINING|FORAGING|ALL|FARMING)_(SKILL|SKILLS)_BOOST_(COMMON|UNCOMMON|RARE|EPIC)"); private static final Pattern PET_CONTAINER_PAGE = Pattern.compile("\\((\\d)/(\\d)\\) Pets"); - private static final Pattern PET_NAME_PATTERN = Pattern.compile("\u00a77\\[Lvl \\d+] \u00a7(.+)"); - private static final Pattern XP_LINE_PATTERN = Pattern.compile( - "-------------------- (\\d+(?:,\\d+)*(?:\\.\\d+)?)/(\\d+(?:\\.\\d+)?[B|M|k]?)"); private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); @@ -109,10 +105,10 @@ public class PetInfoOverlay extends TextOverlay { LEGENDARY(20, 4, 5, EnumChatFormatting.GOLD), MYTHIC(20, 5, 5, EnumChatFormatting.LIGHT_PURPLE); - public int petOffset; - public EnumChatFormatting chatFormatting; - public int petId; - public int beastcreatMultiplyer; + public final int petOffset; + public final EnumChatFormatting chatFormatting; + public final int petId; + public final int beastcreatMultiplyer; Rarity(int petOffset, int petId, int beastcreatMultiplyer, EnumChatFormatting chatFormatting) { this.chatFormatting = chatFormatting; @@ -136,10 +132,9 @@ public class PetInfoOverlay extends TextOverlay { public GuiProfileViewer.PetLevel petLevel; public String petXpType; public String petItem; + public String skin; } - private static long lastXpGain = 0; - public static class PetConfig { public HashMap<Integer, Pet> petMap = new HashMap<>(); @@ -168,7 +163,7 @@ public class PetInfoOverlay extends TextOverlay { public static void loadConfig(File file) { try ( BufferedReader reader = new BufferedReader(new InputStreamReader( - new FileInputStream(file), + Files.newInputStream(file.toPath()), StandardCharsets.UTF_8 )) ) { @@ -185,7 +180,7 @@ public class PetInfoOverlay extends TextOverlay { file.createNewFile(); try ( BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(file), + Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8 )) ) { @@ -247,13 +242,8 @@ public class PetInfoOverlay extends TextOverlay { } private static Pet getClosestPet(String petType, int petId, String petItem, float petLevel) { - Set<Pet> pets = new HashSet<Pet>() {{ - for (Pet pet : config.petMap.values()) { - if (pet.petType.equals(petType) && pet.rarity.petId == petId) { - add(pet); - } - } - }}; + Set<Pet> pets = config.petMap.values().stream().filter(pet -> pet.petType.equals(petType) && pet.rarity.petId == petId).collect( + Collectors.toSet()); if (pets.isEmpty()) { return null; @@ -263,15 +253,7 @@ public class PetInfoOverlay extends TextOverlay { return pets.iterator().next(); } - String searchItem = petItem; - - Set<Pet> itemMatches = new HashSet<>(); - for (Pet pet : pets) { - if ((searchItem == null && pet.petItem == null) || - (searchItem != null && searchItem.equals(pet.petItem))) { - itemMatches.add(pet); - } - } + Set<Pet> itemMatches = pets.stream().filter(pet -> Objects.equals(petItem, pet.petItem)).collect(Collectors.toSet()); if (itemMatches.size() == 1) { return itemMatches.iterator().next(); @@ -292,15 +274,11 @@ public class PetInfoOverlay extends TextOverlay { } } - if (closestPet != null) { - return closestPet; - } else { - return pets.iterator().next(); - } + return closestPet; } private static void getAndSetPet(ProfileViewer.Profile profile) { - JsonObject skillInfo = profile.getSkillInfo(profile.getLatestProfile()); + Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(profile.getLatestProfile()); JsonObject invInfo = profile.getInventoryInfo(profile.getLatestProfile()); JsonObject profileInfo = profile.getProfileInformation(profile.getLatestProfile()); if (invInfo != null && profileInfo != null) { @@ -339,7 +317,8 @@ public class PetInfoOverlay extends TextOverlay { } } } - if (skillInfo != null) config.tamingLevel = skillInfo.get("level_skill_taming").getAsInt(); + if (skyblockInfo != null) config.tamingLevel = (int) skyblockInfo.get("taming").level; + //JsonObject petObject = profile.getPetsInfo(profile.getLatestProfile()); /*JsonObject petsJson = Constants.PETS; if(petsJson != null) { @@ -460,7 +439,7 @@ public class PetInfoOverlay extends TextOverlay { String etaStr = null; String etaMaxStr = null; - if (currentPet.petLevel.level < 100) { + if (currentPet.petLevel.level < currentPet.petLevel.maxLevel) { float remaining = currentPet.petLevel.currentLevelRequirement - currentPet.petLevel.levelXp; if (remaining > 0) { if (xpGain < 1000) { @@ -472,14 +451,14 @@ public class PetInfoOverlay extends TextOverlay { } } - if (currentPet.petLevel.level < 99 || !NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText.contains(6)) { + if (currentPet.petLevel.level < (currentPet.petLevel.maxLevel - 1) || !NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText.contains(6)) { float remainingMax = currentPet.petLevel.maxXP - currentPet.petLevel.totalXp; if (remaining > 0) { if (xpGain < 1000) { - etaMaxStr = EnumChatFormatting.AQUA + "Until L100: " + + etaMaxStr = EnumChatFormatting.AQUA + "Until L" + currentPet.petLevel.maxLevel + ": " + EnumChatFormatting.YELLOW + "N/A"; } else { - etaMaxStr = EnumChatFormatting.AQUA + "Until L100: " + + etaMaxStr = EnumChatFormatting.AQUA + "Until L" + currentPet.petLevel.maxLevel + ": " + EnumChatFormatting.YELLOW + Utils.prettyTime((long) (remainingMax) * 1000 * 60 * 60 / (long) xpGain); } } @@ -564,78 +543,7 @@ public class PetInfoOverlay extends TextOverlay { } } - private static GuiProfileViewer.PetLevel getMaxLevel(JsonArray levels, int offset) { - float xpTotal = 0; - float level = 1; - float currentLevelRequirement = 0; - - for (int i = offset; i < offset + 99; i++) { - currentLevelRequirement = levels.get(i).getAsFloat(); - xpTotal += currentLevelRequirement; - level += 1; - } - - if (level <= 0) { - level = 1; - } else if (level > 100) { - level = 100; - } - GuiProfileViewer.PetLevel levelObj = new GuiProfileViewer.PetLevel(); - levelObj.level = level; - levelObj.currentLevelRequirement = currentLevelRequirement; - levelObj.maxXP = xpTotal; - levelObj.levelPercentage = 1; - levelObj.levelXp = currentLevelRequirement - 5; - levelObj.totalXp = xpTotal - 5; - return levelObj; - } - - private static GuiProfileViewer.PetLevel getLevel( - JsonArray levels, - int offset, - float xpThisLevel, - int xpMaxThisLevel - ) { - float xpTotal = 0; - float level = 1; - float currentLevelRequirement = 0; - float exp = xpThisLevel; - - boolean addLevel = true; - - for (int i = offset; i < offset + 99; i++) { - if (addLevel) { - currentLevelRequirement = levels.get(i).getAsFloat(); - xpTotal += currentLevelRequirement; - - if (currentLevelRequirement >= xpMaxThisLevel) { - addLevel = false; - } else { - exp += currentLevelRequirement; - level += 1; - } - } else { - xpTotal += levels.get(i).getAsFloat(); - } - } - - level += xpThisLevel / currentLevelRequirement; - if (level <= 0) { - level = 1; - } else if (level > 100) { - level = 100; - } - GuiProfileViewer.PetLevel levelObj = new GuiProfileViewer.PetLevel(); - levelObj.level = level; - levelObj.currentLevelRequirement = currentLevelRequirement; - levelObj.maxXP = xpTotal; - levelObj.levelPercentage = xpThisLevel / currentLevelRequirement; - levelObj.levelXp = xpThisLevel; - levelObj.totalXp = exp; - return levelObj; - } - - public static Pet getPetFromStack(String name, String[] lore) { + public static Pet getPetFromStack(NBTTagCompound tag) { if (Constants.PETS == null || Constants.PETS.get("pet_levels") == null || Constants.PETS.get("pet_levels") instanceof JsonNull) { Utils.showOutdatedRepoNotification(); @@ -646,124 +554,43 @@ public class PetInfoOverlay extends TextOverlay { Rarity rarity = null; String heldItem = null; GuiProfileViewer.PetLevel level = null; - - Matcher petNameMatcher = PET_NAME_PATTERN.matcher(name); - if (petNameMatcher.matches()) { - String petStringMatch = petNameMatcher.group(1); - - char colChar = petStringMatch.charAt(0); - EnumChatFormatting col = EnumChatFormatting.RESET; - for (EnumChatFormatting formatting : EnumChatFormatting.values()) { - if (formatting.toString().equals("\u00a7" + colChar)) { - col = formatting; - break; + String skin = null; + + if (tag != null && tag.hasKey("ExtraAttributes")) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + if (ea.hasKey("petInfo")) { + JsonObject petInfo = new JsonParser().parse(ea.getString("petInfo")).getAsJsonObject(); + petType = petInfo.get("type").getAsString(); + rarity = Rarity.valueOf(petInfo.get("tier").getAsString()); + level = GuiProfileViewer. getPetLevel( + petType, + rarity.name(), + Utils.getElementAsFloat(petInfo.get("exp"), 0) // Should only default if from item list and repo missing exp:0 + ); + if (petInfo.has("heldItem")) { + heldItem = petInfo.get("heldItem").getAsString(); } - } - - rarity = Rarity.COMMON; - if (col != EnumChatFormatting.RESET) { - rarity = Rarity.getRarityFromColor(col); - } - - petType = Utils.cleanColour(petStringMatch.substring(1)) - .replaceAll("[^\\w ]", "").trim() - .replace(" ", "_").toUpperCase(); - } - if (petType == null || rarity == null) { - return null; - } - - for (String line : lore) { - Matcher xpLineMatcher = XP_LINE_PATTERN.matcher(Utils.cleanColour(line)); - if (line.startsWith("\u00a76Held Item: ")) { - String after = line.substring("\u00a76Held Item: ".length()); - - if (itemMap == null) { - itemMap = new HashMap<>(); - - for (Map.Entry<String, JsonObject> entry : NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .entrySet()) { - boolean petItem = false; - - if (entry.getKey().startsWith("PET_ITEM_")) { - petItem = true; - } else { - ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(entry.getValue()); - if (stack.hasTagCompound()) { - String[] itemLore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound()); - - for (String itemLoreLine : itemLore) { - if (itemLoreLine.contains("PET ITEM")) { - petItem = true; - break; - } - } - } - } - - if (petItem) { - ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(entry.getValue()); - itemMap.put(stack.getDisplayName().replace("\u00a7f\u00a7f", ""), entry.getKey()); - } - } - } - - if (itemMap.containsKey(after)) { - heldItem = itemMap.get(after); - } - } else if (xpLineMatcher.matches()) { - String xpThisLevelS = xpLineMatcher.group(1); - String xpMaxThisLevelS = xpLineMatcher.group(2).toLowerCase(); - - try { - float xpThisLevel = Float.parseFloat(xpThisLevelS.replace(",", "")); - - int mutiplier = 1; - char end = xpMaxThisLevelS.charAt(xpMaxThisLevelS.length() - 1); - if (end < '0' || end > '9') { - xpMaxThisLevelS = xpMaxThisLevelS.substring(0, xpMaxThisLevelS.length() - 1); - - switch (end) { - case 'k': - mutiplier = 1000; - break; - case 'm': - mutiplier = 1000000; - break; - case 'b': - mutiplier = 1000000000; - break; - } - } - int xpMaxThisLevel = (int) (Float.parseFloat(xpMaxThisLevelS) * mutiplier); - - level = getLevel( - Constants.PETS.get("pet_levels").getAsJsonArray(), - rarity.petOffset, - xpThisLevel, - xpMaxThisLevel - ); - } catch (NumberFormatException ignored) { + if (petInfo.has("skin")) { + skin = "PET_SKIN_" + petInfo.get("skin").getAsString(); } - } else if (line.equals("\u00a7b\u00a7lMAX LEVEL")) { - level = getMaxLevel(Constants.PETS.get("pet_levels").getAsJsonArray(), rarity.petOffset); } } - if (level != null) { - Pet pet = new Pet(); - pet.petItem = heldItem; - pet.petLevel = level; - pet.rarity = rarity; - pet.petType = petType; - JsonObject petTypes = Constants.PETS.get("pet_types").getAsJsonObject(); - pet.petXpType = - petTypes.has(pet.petType) ? petTypes.get(pet.petType.toUpperCase()).getAsString().toLowerCase() : "unknown"; - return pet; + if (petType == null) { + return null; } - return null; + Pet pet = new Pet(); + pet.petItem = heldItem; + pet.petLevel = level; + pet.rarity = rarity; + pet.petType = petType; + JsonObject petTypes = Constants.PETS.get("pet_types").getAsJsonObject(); + pet.petXpType = + petTypes.has(pet.petType) ? petTypes.get(pet.petType.toUpperCase()).getAsString().toLowerCase() : "unknown"; + pet.skin = skin; + + return pet; } private static final HashMap<Integer, Integer> removeMap = new HashMap<>(); @@ -837,7 +664,7 @@ public class PetInfoOverlay extends TextOverlay { } } else { String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound()); - Pet pet = getPetFromStack(stack.getDisplayName(), lore); + Pet pet = getPetFromStack(stack.getTagCompound()); if (pet != null) { config.petMap.put(petIndex, pet); @@ -886,7 +713,7 @@ public class PetInfoOverlay extends TextOverlay { float petXp = petInfoObject.get("exp").getAsFloat(); - double petLevel = XPInformation.getInstance().getPetLevel(name, petXp, rarityString); + double petLevel = GuiProfileViewer.getPetLevel(name, rarityString, petXp).level; int index = getClosestPetIndex(name, rarity, "", (float) petLevel); if (index != config.selectedPet) { clearPet(); @@ -954,8 +781,7 @@ public class PetInfoOverlay extends TextOverlay { if (currentPet.rarity.petId == 5) { mythicRarity = 4; } - JsonObject petItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get( - currentPet.petType + ";" + mythicRarity); + JsonObject petItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(currentPet.skin != null ? currentPet.skin : (currentPet.petType + ";" + mythicRarity)); if (petItem != null) { Vector2f position = getPosition(overlayWidth, overlayHeight); int x = (int) position.x; @@ -972,8 +798,7 @@ public class PetInfoOverlay extends TextOverlay { Pet currentPet2 = getCurrentPet2(); if (currentPet2 != null) { - JsonObject petItem2 = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get( - currentPet2.petType + ";" + currentPet2.rarity.petId); + JsonObject petItem2 = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(currentPet2.skin != null ? currentPet2.skin : (currentPet2.petType + ";" + currentPet2.rarity.petId)); if (petItem2 != null) { Vector2f position = getPosition(overlayWidth, overlayHeight); int x = (int) position.x; @@ -1067,8 +892,7 @@ public class PetInfoOverlay extends TextOverlay { } else { setCurrentPet(newSelected); - String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound()); - Pet pet = getPetFromStack(stack.getDisplayName(), lore); + Pet pet = getPetFromStack(stack.getTagCompound()); if (pet != null) { config.petMap.put(config.selectedPet, pet); } @@ -1079,7 +903,7 @@ public class PetInfoOverlay extends TextOverlay { } public static float getXpGain(Pet pet, float xp, String xpType) { - if (pet.petLevel.level >= 100) return 0; + if (pet.petLevel.level >= pet.petLevel.maxLevel) return 0; if (validXpTypes == null) validXpTypes = Lists.newArrayList("mining", "foraging", "enchanting", "farming", "combat", "fishing", "alchemy"); @@ -1113,8 +937,6 @@ public class PetInfoOverlay extends TextOverlay { public void updatePetLevels() { HashMap<String, XPInformation.SkillInfo> skillInfoMap = XPInformation.getInstance().getSkillInfoMap(); - long currentTime = System.currentTimeMillis(); - float totalGain = 0; Pet currentPet = getCurrentPet(); @@ -1128,7 +950,6 @@ public class PetInfoOverlay extends TextOverlay { if (skillXpLast <= 0) { skillInfoMapLast.put(entry.getKey(), skillXp); } else if (skillXp > skillXpLast) { - lastXpGain = currentTime; float deltaXp = skillXp - skillXpLast; @@ -1172,7 +993,7 @@ public class PetInfoOverlay extends TextOverlay { JsonObject petsJson = Constants.PETS; if (currentPet != null && petsJson != null) { currentPet.petLevel = GuiProfileViewer.getPetLevel( - currentPet.petItem, + currentPet.petType, currentPet.rarity.name(), currentPet.petLevel.totalXp ); @@ -1202,48 +1023,6 @@ public class PetInfoOverlay extends TextOverlay { } private int lastLevelHovered = 0; - private String lastItemHovered = null; - - private static HashMap<String, String> itemMap = null; - - @SubscribeEvent(priority = EventPriority.HIGHEST, receiveCanceled = true) - public void onTooltip(ItemTooltipEvent event) { - for (String line : event.toolTip) { - if (line.startsWith("\u00a7o\u00a77[Lvl ")) { - lastItemHovered = null; - - String after = line.substring("\u00a7o\u00a77[Lvl ".length()); - if (after.contains("]")) { - String levelStr = after.split("]")[0]; - - try { - lastLevelHovered = Integer.parseInt(levelStr.trim()); - } catch (Exception ignored) { - } - } - } else if (line.startsWith("\u00a75\u00a7o\u00a76Held Item: ")) { - String after = line.substring("\u00a75\u00a7o\u00a76Held Item: ".length()); - - if (itemMap == null) { - itemMap = new HashMap<>(); - - for (Map.Entry<String, JsonObject> entry : NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .entrySet()) { - if (entry.getKey().equals("ALL_SKILLS_SUPER_BOOST") || - XP_BOOST_PATTERN.matcher(entry.getKey()).matches()) { - ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(entry.getValue()); - itemMap.put(stack.getDisplayName(), entry.getKey()); - } - } - } - - if (itemMap.containsKey(after)) { - lastItemHovered = itemMap.get(after); - } - } - } - } private static final Pattern AUTOPET_EQUIP = Pattern.compile( "\u00a7cAutopet \u00a7eequipped your \u00a77\\[Lvl (\\d+)] \u00a7(.{2,})\u00a7e! \u00a7a\u00a7lVIEW RULE\u00a7r"); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java index e62e572d..975bbe6e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java @@ -23,15 +23,13 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.util.ItemUtils; +import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.inventory.Container; -import net.minecraft.inventory.ContainerChest; -import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; +import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.event.entity.player.ItemTooltipEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; @@ -43,7 +41,8 @@ import java.util.Locale; public class PowerStoneStatsDisplay { private static PowerStoneStatsDisplay instance = null; - NumberFormat format = NumberFormat.getInstance(Locale.US); + private final NumberFormat format = NumberFormat.getInstance(Locale.US); + private boolean dirty = true; public static PowerStoneStatsDisplay getInstance() { if (instance == null) { @@ -54,14 +53,12 @@ public class PowerStoneStatsDisplay { @SubscribeEvent public void onTick(TickEvent event) { - GuiScreen currentScreen = Minecraft.getMinecraft().currentScreen; - if (currentScreen == null) return; - if (!(currentScreen instanceof GuiChest)) return; - ContainerChest container = (ContainerChest) ((GuiChest) currentScreen).inventorySlots; - IInventory menu = container.getLowerChestInventory(); - String title = menu.getDisplayName().getUnformattedText(); + if (!dirty) return; - if (!title.equals("SkyBlock Menu")) return; + if (!Utils.getOpenChestName().equals("SkyBlock Menu")) { + dirty = false; + return; + } EntityPlayerSP p = Minecraft.getMinecraft().thePlayer; Container openContainer = p.openContainer; @@ -78,12 +75,20 @@ public class PowerStoneStatsDisplay { NEUConfig.HiddenProfileSpecific configProfileSpecific = NotEnoughUpdates.INSTANCE.config.getProfileSpecific(); if (configProfileSpecific == null) return; configProfileSpecific.magicalPower = Integer.parseInt(rawNumber); + dirty = false; } } } } @SubscribeEvent + public void onGuiOpen(GuiOpenEvent event) { + if (event.gui != null) { + dirty = true; + } + } + + @SubscribeEvent public void onItemTooltipLow(ItemTooltipEvent event) { if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.powerStoneStats) return; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java new file mode 100644 index 00000000..e7ada16f --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java @@ -0,0 +1,257 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures.updater; + +import com.google.common.collect.Iterables; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSyntaxException; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.util.NotificationHandler; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.event.ClickEvent; +import net.minecraft.event.HoverEvent; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatStyle; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.fml.common.Loader; +import org.apache.commons.lang3.SystemUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class AutoUpdater { + + NotEnoughUpdates neu; + + public AutoUpdater(NotEnoughUpdates neu) { + this.neu = neu; + } + + public void logProgress(String str) { + logProgress(new ChatComponentText(str)); + } + + public void logProgress(IChatComponent chatComponent) { + Minecraft.getMinecraft().addScheduledTask(() -> { + IChatComponent chatComponent1 = new ChatComponentText(""); + chatComponent1.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.AQUA)); + chatComponent1.appendSibling(chatComponent); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§e[NEU-AutoUpdater] ").appendSibling( + chatComponent1)); + }); + } + + public UpdateLoader getUpdateLoader(URL url) { + if (SystemUtils.IS_OS_UNIX) { + return new LinuxBasedUpdater(this, url); + } + if (Loader.isModLoaded("skyblockclientupdater") && SCUCompatUpdater.IS_ENABLED) { + return SCUCompatUpdater.tryCreate(this, url); + } + return null; + } + + UpdateLoader updateLoader; + + public void updateFromURL(URL url) { + if (updateLoader != null) { + logProgress( + "There is already an update in progress, so the auto updater cannot process this update (as it might already be installed or is currently being downloaded). Please restart your client to install another update"); + return; + } + if (!"https".equals(url.getProtocol())) { + logProgress("§cInvalid protocol in url: " + url + ". Only https is a valid protocol."); + return; + } + updateLoader = getUpdateLoader(url); + if (updateLoader == null) { + logProgress(new ChatComponentText( + "Your system does not support auto updates. Please download this update manually. Click here to read more about auto update compatibility (or the link above for manual downloads)") + .setChatStyle( + new ChatStyle() + .setChatHoverEvent(new HoverEvent( + HoverEvent.Action.SHOW_TEXT, + new ChatComponentText("Click here to read about auto update modalities") + )) + .setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/neuupdate updatemodes")) + )); + return; + } + updateLoader.greet(); + logProgress(new ChatComponentText("[Start download now]") + .setChatStyle(new ChatStyle() + .setColor(EnumChatFormatting.GREEN) + .setChatHoverEvent(new HoverEvent( + HoverEvent.Action.SHOW_TEXT, + new ChatComponentText("Click to start download.") + )) + .setChatClickEvent(new ClickEvent( + ClickEvent.Action.RUN_COMMAND, + "/neuupdate scheduleDownload" + )))); + } + + public void scheduleDownload() { + if (updateLoader == null) { + logProgress("§cNo update found. Try running /neuupdate check first"); + return; + } + if (updateLoader.getState() != UpdateLoader.State.NOTHING) { + logProgress("§cUpdate download already started. No need to start the download again."); + return; + } + logProgress("Download started."); + updateLoader.scheduleDownload(); + } + + private void displayUpdateMessage( + JsonObject updateJson, + String updateMessage, + String downloadLink, + String directDownload + ) { + int firstWidth = -1; + + for (String line : Iterables.concat(Arrays.asList(updateMessage.split("\n")), Arrays.asList("Download here"))) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + boolean isDownloadLink = line.equals("Download here"); + int width = fr.getStringWidth(line); + if (firstWidth == -1) { + firstWidth = width; + } + int missingLen = firstWidth - width; + if (missingLen > 0) { + StringBuilder sb = new StringBuilder(missingLen / 4 / 2 + line.length()); + for (int i = 0; i < missingLen / 4 / 2; i++) { /* fr.getCharWidth(' ') == 4 */ + sb.append(" "); + } + sb.append(line); + line = sb.toString(); + } + ChatComponentText cp = new ChatComponentText(line); + if (isDownloadLink) + cp.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, downloadLink)); + Minecraft.getMinecraft().thePlayer.addChatMessage(cp); + } + neu.displayLinks(updateJson, firstWidth); + NotificationHandler.displayNotification(Arrays.asList( + "", + "§eThere is a new version of NotEnoughUpdates available.", + "§eCheck the chat for more information" + ), true); + try { + if (directDownload != null) + updateFromURL(new URL(directDownload)); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + public void displayUpdateMessageIfOutOfDate() { + File repo = neu.manager.repoLocation; + File updateJson = new File(repo, "update.json"); + if (updateJson.exists()) { + try { + JsonObject o = neu.manager.getJsonFromFile(updateJson); + + int fullReleaseVersion = + o.has("version_id") && o.get("version_id").isJsonPrimitive() ? o.get("version_id").getAsInt() : -1; + int preReleaseVersion = + o.has("version_id") && o.get("version_id").isJsonPrimitive() ? o.get("version_id").getAsInt() : -1; + int hotfixVersion = + o.has("hotfix_id") && o.get("hotfix_id").isJsonPrimitive() ? o.get("hotfix_id").getAsInt() : -1; + + boolean hasFullReleaseAvailableForUpgrade = fullReleaseVersion > NotEnoughUpdates.VERSION_ID; + boolean hasHotfixAvailableForUpgrade = + fullReleaseVersion == NotEnoughUpdates.VERSION_ID && hotfixVersion > NotEnoughUpdates.HOTFIX_VERSION_ID; + boolean hasPreReleaseAvailableForUpdate = + fullReleaseVersion == NotEnoughUpdates.VERSION_ID && preReleaseVersion > NotEnoughUpdates.PRE_VERSION_ID; + + int updateChannel = NotEnoughUpdates.INSTANCE.config.notifications.updateChannel; /* 1 = Full, 2 = Pre */ + if (hasFullReleaseAvailableForUpgrade || (hasHotfixAvailableForUpgrade && updateChannel == 1)) { + displayUpdateMessage( + o, + o.get("update_msg").getAsString(), + o.get("update_link").getAsString(), + o.has("update_direct") ? o.get("update_direct").getAsString() : null + ); + } else if (hasPreReleaseAvailableForUpdate && updateChannel == 2) { + displayUpdateMessage( + o, + o.get("pre_update_msg").getAsString(), + o.get("pre_update_link").getAsString(), + o.has("pre_update_direct") ? o.get("pre_update_direct").getAsString() : null + ); + } + } catch (Exception e) { + e.printStackTrace(); + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText( + "§e[NEU] §cThere has been an error checking for updates. Check the log or join the discord for more information.").setChatStyle( + Utils.createClickStyle( + ClickEvent.Action.OPEN_URL, "https://discord.gg/moulberry"))); + } + } + } + + private boolean validateMcModInfo(JsonArray array) { + if (array.size() != 1) return false; + JsonElement jsonElement = array.get(0); + if (!jsonElement.isJsonObject()) return false; + JsonObject jsonObject = jsonElement.getAsJsonObject(); + if (!jsonObject.has("modid")) return false; + JsonElement modid = jsonObject.get("modid"); + if (!modid.isJsonPrimitive()) return false; + JsonPrimitive primitive = modid.getAsJsonPrimitive(); + if (!primitive.isString()) return false; + return "notenoughupdates".equals(primitive.getAsString()); + } + + public boolean isNeuJar(File sus) { + try (ZipFile zipFile = new ZipFile(sus)) { + ZipEntry entry = zipFile.getEntry("mcmod.info"); + if (entry == null) { + return false; + } + try (InputStream inputStream = zipFile.getInputStream(entry)) { + JsonArray jsonArray = neu.manager.gson.fromJson( + new InputStreamReader(inputStream), + JsonArray.class + ); + return validateMcModInfo(jsonArray); + } + } catch (IOException | JsonSyntaxException e) { + e.printStackTrace(); + } + return false; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/LinuxBasedUpdater.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/LinuxBasedUpdater.java new file mode 100644 index 00000000..3118b135 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/LinuxBasedUpdater.java @@ -0,0 +1,47 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures.updater; + +import java.io.File; +import java.net.URL; +import java.util.List; + +class LinuxBasedUpdater /* Based on what? */ extends UpdateLoader { + + LinuxBasedUpdater(AutoUpdater updater, URL url) { + super(updater, url); + } + + @Override + public void greet() { + updater.logProgress( + "Welcome Aristocrat! Your superior linux system configuration is supported for NEU auto updates."); + } + + @Override + public void deleteFiles(List<File> toDelete) { + for (File toDel : toDelete) { + if (!toDel.delete()) { + updater.logProgress("§cCould not delete old version of NEU: " + toDel + ". Please manually delete file."); + state = State.FAILED; + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SCUCompatUpdater.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SCUCompatUpdater.java new file mode 100644 index 00000000..3cb600cb --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SCUCompatUpdater.java @@ -0,0 +1,100 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures.updater; + +import java.io.File; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URL; +import java.util.List; + +/* + * Legal considerations: Skyblock Client Updater is licensed under the GNU AGPL v3.0 or later (with modifications). + * https://github.com/My-Name-Is-Jeff/SkyblockClient-Updater/blob/main/LICENSE + * + * However, even tho the AGPL License does not allow conveying covered work in combination with LGPL licensed code + * (such as our own), we do not perceive ourselves as conveying neither an unmodified version of Skyblock Client Updater + * nor a work based on Skyblock Client Updater (modified work) since our work is usable and functional in its entirety + * without presence of Skyblock Client Updater and is not to be distributed along a copy of Skyblock Client Updater + * unless that combined work is licensed with respect of both the LGPL and the AGPL, therefore is not adapting any part + * of Skyblock Client Updater unless already part of a whole distribution. + * + * In case the Copyright owner (Lily aka My-Name-Is-Jeff on Github) disagrees, we are willing to take down this module + * (or only convey this component of our work under a pure GPL license) with or without them providing legal grounds + * for this request. However, due to them not being able to be reached for comment, we will include this + * component for the time being. + * */ +public class SCUCompatUpdater extends UpdateLoader { + + public static final boolean IS_ENABLED = false; + + private SCUCompatUpdater(AutoUpdater updater, URL url) { + super(updater, url); + } + + @Override + public void greet() { + updater.logProgress("Skyblock Client Updater compatibility layer loaded."); + } + + @Override + public void deleteFiles(List<File> toDelete) { + try { + for (File f : toDelete) + ReflectionHolder.deleteFileOnShutdownHandle.invoke(ReflectionHolder.updateCheckerInstance, f, ""); + } catch (Throwable e) { + e.printStackTrace(); + updater.logProgress("Invoking SCU failed. Check the log for more info."); + state = State.FAILED; + } + } + + static class ReflectionHolder { + static boolean isSCUFullyPresent = false; + static Class<?> updateChecker; + static Object updateCheckerInstance; + static Method deleteFileOnShutdown; + static MethodHandle deleteFileOnShutdownHandle; + + static { + try { + updateChecker = Class.forName("mynameisjeff.skyblockclientupdater.utils.UpdateChecker"); + Field instanceField = updateChecker.getDeclaredField("INSTANCE"); + instanceField.setAccessible(true); + updateCheckerInstance = instanceField.get(null); + deleteFileOnShutdown = updateChecker.getDeclaredMethod("deleteFileOnShutdown", File.class, String.class); + deleteFileOnShutdownHandle = MethodHandles.publicLookup().unreflect(deleteFileOnShutdown); + isSCUFullyPresent = true; + } catch (NoSuchFieldException | ClassNotFoundException | IllegalAccessException | NoSuchMethodException e) { + e.printStackTrace(); + } + } + } + + public static UpdateLoader tryCreate(AutoUpdater updater, URL url) { + if (!ReflectionHolder.isSCUFullyPresent) { + updater.logProgress("§cFound Skyclient Updater Mod, however our hooks did not function properly."); + return null; + } + return new SCUCompatUpdater(updater, url); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/UpdateLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/UpdateLoader.java new file mode 100644 index 00000000..1a1a8504 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/UpdateLoader.java @@ -0,0 +1,141 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.miscfeatures.updater; + +import io.github.moulberry.notenoughupdates.util.NetUtils; +import net.minecraft.client.Minecraft; +import org.apache.commons.io.IOUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; + +abstract class UpdateLoader { + + enum State { + NOTHING, DOWNLOAD_STARTED, DOWNLOAD_FINISHED, INSTALLED, FAILED + } + + URL url; + AutoUpdater updater; + + State state = State.NOTHING; + + UpdateLoader(AutoUpdater updater, URL url) { + this.url = url; + this.updater = updater; + } + + public State getState() { + return state; + } + + public void setState(State state) { + this.state = state; + } + + public URL getUrl() { + return url; + } + + public void scheduleDownload() { + state = State.DOWNLOAD_STARTED; + try { + NetUtils.downloadAsync(url, File.createTempFile("NotEnoughUpdates-update", ".jar")) + .handle( + (f, exc) -> { + if (exc != null) { + state = State.FAILED; + updater.logProgress("§cError while downloading. Check your logs for more info."); + exc.printStackTrace(); + return null; + } + state = State.DOWNLOAD_FINISHED; + + updater.logProgress("Download completed. Trying to install"); + launchUpdate(f); + return null; + }); + } catch (IOException e) { + state = State.FAILED; + updater.logProgress("§cError while creating download. Check your logs for more info."); + e.printStackTrace(); + } + } + + public abstract void greet(); + + public void launchUpdate(File file) { + + if (state != State.DOWNLOAD_FINISHED) { + updater.logProgress("§cUpdate is invalid state " + state + " to start update."); + state = State.FAILED; + return; + } + File mcDataDir = new File(Minecraft.getMinecraft().mcDataDir, "mods"); + if (!mcDataDir.exists() || !mcDataDir.isDirectory() || !mcDataDir.canRead()) { + updater.logProgress("§cCould not find mods folder. Searched: " + mcDataDir); + state = State.FAILED; + return; + } + ArrayList<File> toDelete = new ArrayList<>(); + File[] modFiles = mcDataDir.listFiles(); + if (modFiles == null) { + updater.logProgress("§cCould not list minecraft mod folder (" + mcDataDir + ")"); + state = State.FAILED; + return; + } + for (File sus : modFiles) { + if (sus.getName().endsWith(".jar")) { + if (updater.isNeuJar(sus)) { + updater.logProgress("Found old NEU file: " + sus + ". Deleting later."); + toDelete.add(sus); + } + } + } + File dest = new File(mcDataDir, file.getName()); + try ( + InputStream i = Files.newInputStream(file.toPath()); + OutputStream o = Files.newOutputStream(dest.toPath()); + ) { + IOUtils.copyLarge(i, o); + } catch (IOException e) { + e.printStackTrace(); + updater.logProgress( + "§cFailed to copy release JAR. Not making any changes to your mod folder. Consult your logs for more info."); + state = State.FAILED; + } + deleteFiles(toDelete); + if (state != State.FAILED) { + state = State.INSTALLED; + updater.logProgress("Update successful. Thank you for your time."); + return; + } + updater.logProgress("§cFailure to delete some files. Please delte the old NEU version manually from your mods folder."); + } + + public abstract void deleteFiles(List<File> toDelete); + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java index 513252dc..b6c3e763 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java @@ -875,7 +875,7 @@ public class AccessoryBagOverlay { private static boolean inAccessoryBag = false; public static boolean isInAccessoryBag() { - return inAccessoryBag; + return inAccessoryBag && NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay; } public static void renderOverlay() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java index 7bd11ecf..0a1e5b81 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java @@ -85,13 +85,13 @@ public class GuiItemRecipe extends GuiScreen { if (!tabs.contains(recipe.getType())) tabs.add(recipe.getType()); } + changeRecipe(0, 0); } @Override public void initGui() { this.guiLeft = (width - this.xSize) / 2; this.guiTop = (height - this.ySize) / 2; - changeRecipe(0, 0); } public NeuRecipe getCurrentRecipe() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/KatSitterOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/KatSitterOverlay.java index b22ff11f..62aba35b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/KatSitterOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/KatSitterOverlay.java @@ -22,8 +22,8 @@ package io.github.moulberry.notenoughupdates.miscgui; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; import io.github.moulberry.notenoughupdates.util.Utils; -import io.github.moulberry.notenoughupdates.util.XPInformation; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.inventory.GuiChest; @@ -69,8 +69,8 @@ public class KatSitterOverlay { boolean nextRarityPresent = katSlot.getStack() != null && katSlot.getStack().getItem() != Item.getItemFromBlock( Blocks.barrier) && upgradedRarity != null; renderPetInformation( - (int) XPInformation.getInstance().getPetLevel(petId, xp, rarity), - nextRarityPresent ? (int) XPInformation.getInstance().getPetLevel(petId, xp, upgradedRarity) : null, + (int) GuiProfileViewer.getPetLevel(petId, rarity, (float) xp).level, + nextRarityPresent ? (int) GuiProfileViewer.getPetLevel(petId, upgradedRarity, (float) xp).level : null, gui ); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java index 98efa381..7e6b991c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java @@ -1266,8 +1266,8 @@ public class StorageOverlay extends GuiElement { if (fastRender) { fontRendererObj.drawString( - "Fast render does not work with Storage overlay.", - sizeX / 2 - fontRendererObj.getStringWidth("Fast render does not work with Storage overlay.") / 2, + "Fast render and antialiasing do not work with Storage overlay.", + sizeX / 2 - fontRendererObj.getStringWidth("Fast render and antialiasing do not work with Storage overlay.") / 2, -10, 0xFFFF0000 ); @@ -2308,10 +2308,11 @@ public class StorageOverlay extends GuiElement { NotEnoughUpdates.INSTANCE.config.storageGUI.enableStorageGUI3) { this.fastRender = true; NotificationHandler.displayNotification(Lists.newArrayList( - "\u00a74Fast Render Warning", - "\u00a77Due to the way fast render works, it's not compatible with NEU.", - "\u00a77Please disable fast render in your options under", - "\u00a77ESC > Options > Video Settings > Performance > Fast Render", + "\u00a74Warning", + "\u00a77Due to the way fast render and antialiasing work, they're not compatible with NEU.", + "\u00a77Please disable fast render and antialiasing in your options under", + "\u00a77ESC > Options > Video Settings > Performance > \u00A7cFast Render", + "\u00a77ESC > Options > Video Settings > Quality > \u00A7cAntialiasing", "\u00a77This can't be fixed.", "\u00a77", "\u00a77Press X on your keyboard to close this notification" diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java index a3a65dce..540a6dee 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java @@ -31,7 +31,6 @@ import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.inventory.GuiChest; -import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.inventory.Container; import net.minecraft.inventory.ContainerChest; @@ -78,7 +77,6 @@ public class TrophyRewardOverlay { @SubscribeEvent(priority = EventPriority.LOW) public void onItemTooltipLow(ItemTooltipEvent event) { if (!inTrophyFishingInventory()) return; - if (!NotEnoughUpdates.INSTANCE.config.fishing.trophyRewardTooltips) return; ItemStack itemStack = event.itemStack; if (itemStack == null) return; @@ -100,7 +98,6 @@ public class TrophyRewardOverlay { @SubscribeEvent(priority = EventPriority.LOWEST) public void onDrawBackground(GuiScreenEvent.BackgroundDrawnEvent event) { if (!inTrophyFishingInventory()) return; - if (!NotEnoughUpdates.INSTANCE.config.fishing.trophyRewardOverlay) return; GuiScreen screen = Minecraft.getMinecraft().currentScreen; if (!(screen instanceof GuiChest)) return; @@ -276,6 +273,7 @@ public class TrophyRewardOverlay { public static boolean inTrophyFishingInventory() { if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return false; + if (!NotEnoughUpdates.INSTANCE.config.fishing.trophyRewardOverlay) return false; Minecraft minecraft = Minecraft.getMinecraft(); if (minecraft == null || minecraft.thePlayer == null) return false; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java index 3bc92a9c..06512fa8 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java @@ -95,8 +95,8 @@ public abstract class MixinGuiContainer extends GuiScreen { NBTTagCompound tag = eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound(); if (tag.hasKey("SkullOwner") && tag.getCompoundTag("SkullOwner").hasKey("Name")) { String tagName = tag.getCompoundTag("SkullOwner").getString("Name"); - String displayname = Utils.cleanColour(cc.inventorySlots.get(22).getStack().getDisplayName()); - if (tagName.equals(displayname.substring(displayname.length() - tagName.length()))) { + String displayName = Utils.cleanColour(cc.inventorySlots.get(22).getStack().getDisplayName()); + if (tagName.equals(displayName.substring(displayName.length() - tagName.length()))) { ci.cancel(); this.zLevel = 100.0F; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java index abc8c2a2..0b33609d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java @@ -25,12 +25,14 @@ import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper; import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns; import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff; +import io.github.moulberry.notenoughupdates.miscfeatures.NewApiKeyHelper; import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager; import io.github.moulberry.notenoughupdates.util.SBInfo; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.network.Packet; +import net.minecraft.network.play.client.C01PacketChatMessage; import net.minecraft.network.play.client.C0EPacketClickWindow; import net.minecraft.network.play.server.S23PacketBlockChange; import net.minecraft.network.play.server.S2DPacketOpenWindow; @@ -124,11 +126,14 @@ public class MixinNetHandlerPlayClient { ItemCooldowns.processBlockChangePacket(packetIn); } - @Inject(method = "addToSendQueue", at = @At("HEAD")) + @Inject(method = "addToSendQueue", at = @At("HEAD"), cancellable = true) public void addToSendQueue(Packet packet, CallbackInfo ci) { if (packet instanceof C0EPacketClickWindow) { StorageManager.getInstance().clientSendWindowClick((C0EPacketClickWindow) packet); } + if (packet instanceof C01PacketChatMessage) { + NewApiKeyHelper.getInstance().hookPacketChatMessage((C01PacketChatMessage) packet); + } } @Inject(method = "handlePlayerListHeaderFooter", at = @At("HEAD")) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java index fead6780..e080db7d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java @@ -114,6 +114,15 @@ public class Dungeons { @ConfigAccordionId(id = 1) public boolean useKismetOnDungeonProfit = true; + @Expose + @ConfigOption( + name = "Warning if Derpy active", + desc = "Shows a warning if the mayor Derpy is active" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean shouldWarningDerpy = true; + @ConfigOption( name = "Dungeon Win Overlay", desc = "" diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ItemOverlays.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ItemOverlays.java index 7cf56c96..5fde76a5 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ItemOverlays.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ItemOverlays.java @@ -234,6 +234,15 @@ public class ItemOverlays { @Expose @ConfigOption( + name = "Disable overlay when fail", + desc = "Don't display the etherwarp block overlay when you can't TP to the block" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 7) + public boolean disableOverlayWhenFailed = false; + + @Expose + @ConfigOption( name = "Highlight Colour", desc = "Change the colour of the etherwarp target block outline" ) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/NeuAuctionHouse.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/NeuAuctionHouse.java index 44f3454a..6c55fd09 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/NeuAuctionHouse.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/NeuAuctionHouse.java @@ -24,7 +24,8 @@ import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditor import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider; import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption; -public class NeuAuctionHouse { +public class +NeuAuctionHouse { @Expose @ConfigOption( name = "Enable NeuAH", @@ -61,4 +62,12 @@ public class NeuAuctionHouse { ) @ConfigEditorBoolean public boolean priceFiltering = false; + + @Expose + @ConfigOption( + name = "Save Last Search", + desc = "Saving the last query when closing the neuah" + ) + @ConfigEditorBoolean + public boolean saveLastSearch = true; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java index 98d429d0..85ad2093 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java @@ -36,6 +36,14 @@ public class Notifications { @Expose @ConfigOption( + name = "Missing repo warning", + desc = "Warning when repo data is missing or out of date" + ) + @ConfigEditorBoolean + public boolean outdatedRepo = true; + + @Expose + @ConfigOption( name = "RAM Warning", desc = "Warning when game starts with lots of RAM allocated\n" + "\u00a7cBefore disabling this, please seriously read the message. If you complain about FPS issues without listening to the warning, that's your fault." diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java index ee1abf46..673e1015 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java @@ -20,7 +20,12 @@ package io.github.moulberry.notenoughupdates.options.seperateSections; import com.google.gson.annotations.Expose; -import io.github.moulberry.notenoughupdates.core.config.annotations.*; +import io.github.moulberry.notenoughupdates.BuildFlags; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorFSR; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption; import java.util.ArrayList; import java.util.Arrays; @@ -81,4 +86,12 @@ public class ProfileViewer { ) @ConfigEditorBoolean public boolean alwaysShowBingoTab = false; + + @Expose + @ConfigOption( + name = "Show Pronouns in /pv", + desc = "Shows the pronouns of a player in /pv. Data sourced from pronoundb.org" + ) + @ConfigEditorBoolean + public boolean showPronounsInPv = BuildFlags.ENABLE_PRONOUNS_IN_PV_BY_DEFAULT; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SkillOverlays.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SkillOverlays.java index 54e17fcf..8b7002f9 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SkillOverlays.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SkillOverlays.java @@ -75,7 +75,7 @@ public class SkillOverlays { exampleText = { "\u00a7bCounter: \u00a7e37,547,860", "\u00a7bCrops/m: \u00a7e38.29", - "\u00a7bFarm: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%", + "\u00a7bFarming: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%", "\u00a7bCurrent XP: \u00a7e6,734", "\u00a7bRemaining XP: \u00a7e3,265", "\u00a7bXP/h: \u00a7e238,129", @@ -145,7 +145,7 @@ public class SkillOverlays { exampleText = { "\u00a7bCompact: \u00a7e547,860", "\u00a7bBlocks/m: \u00a7e38.29", - "\u00a7bMine: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%", + "\u00a7bMining: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%", "\u00a7bCurrent XP: \u00a7e6,734", "\u00a7bRemaining XP: \u00a7e3,265", "\u00a7bXP/h: \u00a7e238,129", diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java index e0e2c2d3..8ff3218a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java @@ -27,7 +27,6 @@ import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiEditSign; import io.github.moulberry.notenoughupdates.options.NEUConfigEditor; import io.github.moulberry.notenoughupdates.util.Constants; -import io.github.moulberry.notenoughupdates.util.SBInfo; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; @@ -59,7 +58,8 @@ public class AuctionSearchOverlay { private static final ResourceLocation SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED = new ResourceLocation( "notenoughupdates:auc_search/ah_search_overlay_tab_completed.png"); private static final ResourceLocation STAR = new ResourceLocation("notenoughupdates:auc_search/star.png"); - private static final ResourceLocation MASTER_STAR = new ResourceLocation("notenoughupdates:auc_search/master_star.png"); + private static final ResourceLocation MASTER_STAR = + new ResourceLocation("notenoughupdates:auc_search/master_star.png"); private static final ResourceLocation STAR_BOARD = new ResourceLocation("notenoughupdates:auc_search/star_board.png"); private static final GuiElementTextField textField = new GuiElementTextField("", 200, 20, 0); @@ -106,9 +106,7 @@ public class AuctionSearchOverlay { return false; } - String lastContainer = SBInfo.getInstance().lastOpenContainerName; - - if (lastContainer == null) return false; + String lastContainer = Utils.getLastOpenChestName(); if (!lastContainer.equals("Auctions Browser") && !lastContainer.startsWith("Auctions: ")) return false; TileEntitySign tes = ((AccessorGuiEditSign) Minecraft.getMinecraft().currentScreen).getTileSign(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/OverlayManager.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/OverlayManager.java index d73c71dc..fef11a45 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/OverlayManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/OverlayManager.java @@ -100,7 +100,7 @@ public class OverlayManager { List<String> farmingDummy = Lists.newArrayList( "\u00a7bCounter: \u00a7e37,547,860", "\u00a7bCrops/m: \u00a7e38.29", - "\u00a7bFarm: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%", + "\u00a7bFarming: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%", "\u00a7bCurrent XP: \u00a7e6,734", "\u00a7bRemaining XP: \u00a7e3,265", "\u00a7bXP/h: \u00a7e238,129", @@ -122,7 +122,7 @@ public class OverlayManager { List<String> miningSkillDummy = Lists.newArrayList( "\u00a7bCompact: \u00a7e547,860", "\u00a7bBlocks/m: \u00a7e38.29", - "\u00a7bMine: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%", + "\u00a7bMining: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%", "\u00a7bCurrent XP: \u00a7e6,734", "\u00a7bRemaining XP: \u00a7e3,265", "\u00a7bXP/h: \u00a7e238,129", diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java new file mode 100644 index 00000000..dcbcb9e4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java @@ -0,0 +1,840 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer; + +import com.google.common.base.Splitter; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mojang.authlib.GameProfile; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.profileviewer.weight.lily.LilyWeight; +import io.github.moulberry.notenoughupdates.profileviewer.weight.senither.SenitherWeight; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.PronounDB; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EnumPlayerModelParts; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; + +import static io.github.moulberry.notenoughupdates.util.Utils.roundToNearestInt; + +public class BasicPage extends GuiProfileViewerPage { + + private static final ResourceLocation pv_basic = new ResourceLocation("notenoughupdates:pv_basic.png"); + private static final ExecutorService profileLoader = Executors.newFixedThreadPool(1); + public EntityOtherPlayerMP entityPlayer = null; + private ResourceLocation playerLocationSkin = null; + private ResourceLocation playerLocationCape = null; + private String skinType = null; + private boolean loadingProfile = false; + + private int backgroundClickedX = -1; + + public BasicPage(GuiProfileViewer instance) { + super(instance); + } + + @Override + public void drawPage(int mouseX, int mouseY, float partialTicks) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + ProfileViewer.Profile profile = GuiProfileViewer.getProfile(); + String profileId = GuiProfileViewer.getProfileId(); + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + String location = null; + JsonObject status = profile.getPlayerStatus(); + if (status != null && status.has("mode")) { + location = status.get("mode").getAsString(); + } + + int extraRotation = 0; + if (Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) { + if (backgroundClickedX == -1) { + if (mouseX > guiLeft + 23 && mouseX < guiLeft + 23 + 81) { + if (mouseY > guiTop + 44 && mouseY < guiTop + 44 + 108) { + backgroundClickedX = mouseX; + } + } + } + } else { + if (backgroundClickedX != -1) { + getInstance().backgroundRotation += mouseX - backgroundClickedX; + backgroundClickedX = -1; + } + } + if (backgroundClickedX == -1) { + getInstance().backgroundRotation += (getInstance().currentTime - getInstance().lastTime) / 400f; + } else { + extraRotation = mouseX - backgroundClickedX; + } + getInstance().backgroundRotation %= 360; + + String panoramaIdentifier = "day"; + if (SBInfo.getInstance().currentTimeDate != null) { + if (SBInfo.getInstance().currentTimeDate.getHours() <= 6 || + SBInfo.getInstance().currentTimeDate.getHours() >= 20) { + panoramaIdentifier = "night"; + } + } + + Panorama.drawPanorama( + -getInstance().backgroundRotation - extraRotation, + guiLeft + 23, + guiTop + 44, + 81, + 108, + 0.37f, + 0.8f, + Panorama.getPanoramasForLocation(location == null ? "unknown" : location, panoramaIdentifier) + ); + + if (Utils.isWithinRect(mouseX, mouseY, guiLeft + 23, guiTop + 44, 81, 108)) { + Optional<PronounDB.PronounChoice> pronounChoice = + GuiProfileViewer.pronouns + .peekValue() + .flatMap(it -> it); // Flatten: First optional is whether it loaded, second optional is whether it was successful + if (pronounChoice.isPresent()) { + PronounDB.PronounChoice pronouns = pronounChoice.get(); + if (pronouns.isConsciousChoice()) { + getInstance().tooltipToDisplay = pronouns.render(); + } + } + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_basic); + Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST); + + if (entityPlayer != null && profile.getHypixelProfile() != null) { + String playerName = null; + if (profile.getHypixelProfile().has("prefix")) { + playerName = Utils.getElementAsString(profile.getHypixelProfile().get("prefix"), "") + " " + + entityPlayer.getName(); + } else { + String rank = Utils.getElementAsString( + profile.getHypixelProfile().get("rank"), + Utils.getElementAsString(profile.getHypixelProfile().get("newPackageRank"), "NONE") + ); + String monthlyPackageRank = Utils.getElementAsString( + profile.getHypixelProfile().get("monthlyPackageRank"), + "NONE" + ); + if (!rank.equals("YOUTUBER") && !monthlyPackageRank.equals("NONE")) { + rank = monthlyPackageRank; + } + EnumChatFormatting rankPlusColorECF = EnumChatFormatting.getValueByName( + Utils.getElementAsString(profile.getHypixelProfile().get("rankPlusColor"), "GOLD") + ); + String rankPlusColor = EnumChatFormatting.GOLD.toString(); + if (rankPlusColorECF != null) { + rankPlusColor = rankPlusColorECF.toString(); + } + + JsonObject misc = Constants.MISC; + if (misc != null) { + if (misc.has("ranks")) { + String rankName = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".tag"), null); + String rankColor = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".color"), "7"); + String rankPlus = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".plus"), ""); + + String name = entityPlayer.getName(); + + if (misc.has("special_bois")) { + JsonArray special_bois = misc.get("special_bois").getAsJsonArray(); + for (int i = 0; i < special_bois.size(); i++) { + if (special_bois.get(i).getAsString().equals(profile.getUuid())) { + name = Utils.chromaString(name); + break; + } + } + } + + playerName = EnumChatFormatting.GRAY + name; + if (rankName != null) { + playerName = + "\u00A7" + rankColor + "[" + rankName + rankPlusColor + rankPlus + "\u00A7" + rankColor + "] " + name; + } + } + } + } + if (playerName != null) { + int rankPrefixLen = fr.getStringWidth(playerName); + int halfRankPrefixLen = rankPrefixLen / 2; + + int x = guiLeft + 63; + int y = guiTop + 54; + + GuiScreen.drawRect( + x - halfRankPrefixLen - 1, + y - 1, + x + halfRankPrefixLen + 1, + y + 8, + new Color(0, 0, 0, 64).getRGB() + ); + + fr.drawString(playerName, x - halfRankPrefixLen, y, 0, true); + } + } + + long networth = profile.getNetWorth(profileId); + if (networth > 0) { + Utils.drawStringCentered( + EnumChatFormatting.GREEN + "Net Worth: " + EnumChatFormatting.GOLD + + GuiProfileViewer.numberFormat.format(networth), + fr, + guiLeft + 63, + guiTop + 38, + true, + 0 + ); + try { + double networthInCookies = + ( + networth / + NotEnoughUpdates.INSTANCE.manager.auctionManager + .getBazaarInfo("BOOSTER_COOKIE") + .get("avg_buy") + .getAsDouble() + ); + String networthIRLMoney = Long.toString(Math.round(((networthInCookies * 325) / 675) * 4.99)); + if ( + mouseX > guiLeft + 8 && + mouseX < guiLeft + 8 + fr.getStringWidth("Net Worth: " + GuiProfileViewer.numberFormat.format(networth)) + ) { + if (mouseY > guiTop + 32 && mouseY < guiTop + 32 + fr.FONT_HEIGHT) { + getInstance().tooltipToDisplay = new ArrayList<>(); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GREEN + + "Net worth in IRL money: " + + EnumChatFormatting.DARK_GREEN + + "$" + + EnumChatFormatting.GOLD + + networthIRLMoney + ); + getInstance().tooltipToDisplay.add(""); + if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { + getInstance().tooltipToDisplay.add(EnumChatFormatting.RED + "This is calculated using the current"); + getInstance().tooltipToDisplay.add( + EnumChatFormatting.RED + "price of booster cookies on bazaar and the price"); + getInstance().tooltipToDisplay.add( + EnumChatFormatting.RED + "for cookies using gems, then the price of gems"); + getInstance().tooltipToDisplay.add( + EnumChatFormatting.RED + "is where we get the amount of IRL money you"); + getInstance().tooltipToDisplay.add( + EnumChatFormatting.RED + "theoretically have on skyblock in net worth."); + } else { + getInstance().tooltipToDisplay.add(EnumChatFormatting.GRAY + "[SHIFT for Info]"); + } + if (!NotEnoughUpdates.INSTANCE.config.hidden.dev) { + getInstance().tooltipToDisplay.add(""); + getInstance().tooltipToDisplay.add(EnumChatFormatting.RED + "THIS IS IN NO WAY ENDORSING IRL TRADING!"); + } + } + } + } catch (Exception ignored) { + } + } + + if (status != null) { + JsonElement onlineElement = Utils.getElement(status, "online"); + boolean online = onlineElement != null && onlineElement.isJsonPrimitive() && onlineElement.getAsBoolean(); + String statusStr = online ? EnumChatFormatting.GREEN + "ONLINE" : EnumChatFormatting.RED + "OFFLINE"; + String locationStr = null; + if (profile.getUuid().equals("20934ef9488c465180a78f861586b4cf")) { + locationStr = "Ignoring DMs"; + } else if (profile.getUuid().equals("b876ec32e396476ba1158438d83c67d4")) { + statusStr = EnumChatFormatting.LIGHT_PURPLE + "Long live Potato King"; + ItemStack potato_crown = NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("POTATO_CROWN") + ); + potato_crown.addEnchantment(Enchantment.unbreaking, 1656638942); // this number may be useful + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI( + new ItemStack(Items.potato), + guiLeft + 35, + guiTop + 160 + ); + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(potato_crown, guiLeft + 50, guiTop + 162); + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI( + new ItemStack(Items.potato), + guiLeft + 63, + guiTop + 160 + ); + } else if (online) { + locationStr = NotEnoughUpdates.INSTANCE.navigation.getNameForAreaModeOrUnknown(location); + } + if (locationStr != null) { + statusStr += EnumChatFormatting.GRAY + " - " + EnumChatFormatting.GREEN + locationStr; + } + + Utils.drawStringCentered(statusStr, fr, guiLeft + 63, guiTop + 160, true, 0); + } + + if (entityPlayer == null) { + if (!loadingProfile || ((ThreadPoolExecutor) profileLoader).getActiveCount() == 0) { + loadingProfile = true; + UUID playerUUID = UUID.fromString(niceUuid(profile.getUuid())); + + profileLoader.submit(() -> { + GameProfile fakeProfile = Minecraft + .getMinecraft() + .getSessionService() + .fillProfileProperties(new GameProfile(playerUUID, "CoolGuy123"), false); + entityPlayer = + new EntityOtherPlayerMP(Minecraft.getMinecraft().theWorld, fakeProfile) { + public ResourceLocation getLocationSkin() { + return playerLocationSkin == null + ? DefaultPlayerSkin.getDefaultSkin(this.getUniqueID()) + : playerLocationSkin; + } + + public ResourceLocation getLocationCape() { + return playerLocationCape; + } + + public String getSkinType() { + return skinType == null ? DefaultPlayerSkin.getSkinType(this.getUniqueID()) : skinType; + } + }; + entityPlayer.setAlwaysRenderNameTag(false); + entityPlayer.setCustomNameTag(""); + }); + } + } else { + entityPlayer.refreshDisplayName(); + byte b = 0; + for (EnumPlayerModelParts part : EnumPlayerModelParts.values()) { + b |= part.getPartMask(); + } + entityPlayer.getDataWatcher().updateObject(10, b); + } + + JsonObject profileInfo = profile.getProfileInformation(profileId); + if (profileInfo == null) return; + + Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(profileId); + JsonObject inventoryInfo = profile.getInventoryInfo(profileId); + + if (entityPlayer != null) { + if (backgroundClickedX != -1 && Mouse.isButtonDown(1)) { + Arrays.fill(entityPlayer.inventory.armorInventory, null); + } else { + if (inventoryInfo != null && inventoryInfo.has("inv_armor")) { + JsonArray items = inventoryInfo.get("inv_armor").getAsJsonArray(); + if (items != null && items.size() == 4) { + for (int i = 0; i < entityPlayer.inventory.armorInventory.length; i++) { + JsonElement itemElement = items.get(i); + if (itemElement != null && itemElement.isJsonObject()) { + entityPlayer.inventory.armorInventory[i] = + NotEnoughUpdates.INSTANCE.manager.jsonToStack(itemElement.getAsJsonObject(), false); + } + } + } + } else { + Arrays.fill(entityPlayer.inventory.armorInventory, null); + } + } + if (entityPlayer.getUniqueID().toString().equals("ae6193ab-494a-4719-b6e7-d50392c8f012")) { + entityPlayer.inventory.armorInventory[3] = + NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("SMALL_BACKPACK") + ); + } + } + + if (entityPlayer != null && playerLocationSkin == null) { + try { + Minecraft + .getMinecraft() + .getSkinManager() + .loadProfileTextures( + entityPlayer.getGameProfile(), + (type, location1, profileTexture) -> { + switch (type) { + case SKIN: + playerLocationSkin = location1; + skinType = profileTexture.getMetadata("model"); + + if (skinType == null) { + skinType = "default"; + } + + break; + case CAPE: + playerLocationCape = location1; + } + }, + false + ); + } catch (Exception ignored) { + } + } + + GlStateManager.color(1, 1, 1, 1); + JsonObject petsInfo = profile.getPetsInfo(profileId); + if (petsInfo != null) { + JsonElement activePetElement = petsInfo.get("active_pet"); + if (activePetElement != null && activePetElement.isJsonObject()) { + JsonObject activePet = activePetElement.getAsJsonObject(); + + String type = activePet.get("type").getAsString(); + + for (int i = 0; i < 4; i++) { + JsonObject item = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(type + ";" + i); + if (item != null) { + int x = guiLeft + 20; + float y = + guiTop + + 82 + + 15 * + (float) Math.sin(((getInstance().currentTime - getInstance().startTime) / 800f) % (2 * Math.PI)); + GlStateManager.translate(x, y, 0); + ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false); + + //Remove extra attributes so no CIT + NBTTagCompound stackTag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound(); + stackTag.removeTag("ExtraAttributes"); + stack.setTagCompound(stackTag); + + GlStateManager.scale(1.5f, 1.5f, 1); + GlStateManager.enableDepth(); + Utils.drawItemStack(stack, 0, 0); + GlStateManager.scale(1 / 1.5f, 1 / 1.5f, 1); + GlStateManager.translate(-x, -y, 0); + break; + } + } + } + } + if (entityPlayer != null) { + drawEntityOnScreen( + guiLeft + 63, + guiTop + 128 + 7, + 36, + guiLeft + 63 - mouseX, + guiTop + 129 - mouseY, + entityPlayer + ); + } + + PlayerStats.Stats stats = profile.getStats(profileId); + + if (stats != null) { + Splitter splitter = Splitter.on(" ").omitEmptyStrings().limit(2); + for (int i = 0; i < PlayerStats.defaultStatNames.length; i++) { + String statName = PlayerStats.defaultStatNames[i]; + //if (statName.equals("mining_fortune") || statName.equals("mining_speed")) continue; + String statNamePretty = PlayerStats.defaultStatNamesPretty[i]; + + int val = Math.round(stats.get(statName)); + + GlStateManager.color(1, 1, 1, 1); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate( + GL11.GL_SRC_ALPHA, + GL11.GL_ONE_MINUS_SRC_ALPHA, + GL11.GL_ONE, + GL11.GL_ONE_MINUS_SRC_ALPHA + ); + Utils.renderAlignedString( + statNamePretty, + EnumChatFormatting.WHITE.toString() + val, + guiLeft + 132, + guiTop + 21 + 11f * i, + 80 + ); + + if (mouseX > guiLeft + 132 && mouseX < guiLeft + 212) { + if (mouseY > guiTop + 21 + 11f * i && mouseY < guiTop + 37 + 11f * i) { + List<String> split = splitter.splitToList(statNamePretty); + PlayerStats.Stats baseStats = PlayerStats.getBaseStats(); + getInstance().tooltipToDisplay = new ArrayList<>(); + getInstance().tooltipToDisplay.add(statNamePretty); + int base = Math.round(baseStats.get(statName)); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GRAY + + "Base " + + split.get(1) + + ": " + + EnumChatFormatting.GREEN + + base + + " " + + split.get(0) + ); + int passive = Math.round(profile.getPassiveStats(profileId).get(statName) - baseStats.get(statName)); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GRAY + + "Passive " + + split.get(1) + + " Bonus: +" + + EnumChatFormatting.YELLOW + + passive + + " " + + split.get(0) + ); + int itemBonus = Math.round(stats.get(statName) - profile.getPassiveStats(profileId).get(statName)); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GRAY + + "Item " + + split.get(1) + + " Bonus: +" + + EnumChatFormatting.DARK_PURPLE + + itemBonus + + " " + + split.get(0) + ); + int finalStat = Math.round(stats.get(statName)); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GRAY + + "Final " + + split.get(1) + + ": +" + + EnumChatFormatting.RED + + finalStat + + " " + + split.get(0) + ); + } + } + } + } else { + Utils.drawStringCentered( + EnumChatFormatting.RED + "Skill/Inv/Coll", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 172, + guiTop + 101 - 10, + true, + 0 + ); + Utils.drawStringCentered( + EnumChatFormatting.RED + "APIs not", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 172, + guiTop + 101, + true, + 0 + ); + Utils.drawStringCentered( + EnumChatFormatting.RED + "enabled!", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 172, + guiTop + 101 + 10, + true, + 0 + ); + } + + if (skyblockInfo != null) { + int position = 0; + for (Map.Entry<String, ItemStack> entry : ProfileViewer.getSkillToSkillDisplayMap().entrySet()) { + if (entry.getValue() == null || entry.getKey() == null) { + position++; + continue; + } + + int yPosition = position % 8; + int xPosition = position / 8; + + String skillName = entry.getValue().getDisplayName(); + + float level = skyblockInfo.get(entry.getKey()).level; + int levelFloored = (int) Math.floor(level); + + int x = guiLeft + 237 + 86 * xPosition; + int y = guiTop + 24 + 21 * yPosition; + + Utils.renderAlignedString(skillName, EnumChatFormatting.WHITE.toString() + levelFloored, x + 14, y - 4, 60); + + if (skyblockInfo.get(entry.getKey()).maxed) { + getInstance().renderGoldBar(x, y + 6, 80); + } else { + getInstance().renderBar(x, y + 6, 80, level % 1); + } + + if (mouseX > x && mouseX < x + 80) { + if (mouseY > y - 4 && mouseY < y + 13) { + getInstance().tooltipToDisplay = new ArrayList<>(); + getInstance().tooltipToDisplay.add(skillName); + if (skyblockInfo.get(entry.getKey()).maxed) { + getInstance().tooltipToDisplay.add( + EnumChatFormatting.GRAY + "Progress: " + EnumChatFormatting.GOLD + "MAXED!"); + } else { + int maxXp = (int) skyblockInfo.get(entry.getKey()).maxXpForLevel; + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GRAY + + "Progress: " + + EnumChatFormatting.DARK_PURPLE + + GuiProfileViewer.shortNumberFormat(Math.round((level % 1) * maxXp), 0) + + "/" + + GuiProfileViewer.shortNumberFormat(maxXp, 0) + ); + } + String totalXpS = GuiProfileViewer.numberFormat.format((int) skyblockInfo.get(entry.getKey()).totalXp); + getInstance() + .tooltipToDisplay.add(EnumChatFormatting.GRAY + "Total XP: " + EnumChatFormatting.DARK_PURPLE + totalXpS); + } + } + + GL11.glTranslatef((x), (y - 6f), 0); + GL11.glScalef(0.7f, 0.7f, 1); + Utils.drawItemStackLinear(entry.getValue(), 0, 0); + GL11.glScalef(1 / 0.7f, 1 / 0.7f, 1); + GL11.glTranslatef(-(x), -(y - 6f), 0); + + position++; + } + } else { + Utils.drawStringCentered( + EnumChatFormatting.RED + "Skills API not enabled!", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 322, + guiTop + 101, + true, + 0 + ); + } + + renderWeight(mouseX, mouseY, skyblockInfo, profileInfo); + } + + @Override + public void resetCache() { + entityPlayer = null; + playerLocationSkin = null; + playerLocationCape = null; + skinType = null; + } + + private String niceUuid(String uuidStr) { + if (uuidStr.length() != 32) return uuidStr; + + return ( + uuidStr.substring(0, 8) + + "-" + + uuidStr.substring(8, 12) + + "-" + + uuidStr.substring(12, 16) + + "-" + + uuidStr.substring(16, 20) + + "-" + + uuidStr.substring(20, 32) + ); + } + + private void renderWeight( + int mouseX, + int mouseY, + Map<String, ProfileViewer.Level> skyblockInfo, + JsonObject profileInfo + ) { + if (skyblockInfo == null) { + return; + } + + if (Constants.WEIGHT == null || Utils.getElement(Constants.WEIGHT, "lily.skills.overall") == null || + !Utils.getElement(Constants.WEIGHT, "lily.skills.overall").isJsonPrimitive()) { + Utils.showOutdatedRepoNotification(); + return; + } + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + SenitherWeight senitherWeight = new SenitherWeight(skyblockInfo); + LilyWeight lilyWeight = new LilyWeight(skyblockInfo, profileInfo); + + Utils.drawStringCentered( + EnumChatFormatting.GREEN + + "Senither Weight: " + + EnumChatFormatting.GOLD + + GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight.getTotalWeight().getRaw())), + fr, + guiLeft + 63, + guiTop + 18, + true, + 0 + ); + + int textWidth = fr.getStringWidth( + "Senither Weight: " + + GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight.getTotalWeight().getRaw())) + ); + if (mouseX > guiLeft + 63 - textWidth / 2 && mouseX < guiLeft + 63 + textWidth / 2) { + if (mouseY > guiTop + 12 && mouseY < guiTop + 12 + fr.FONT_HEIGHT) { + getInstance().tooltipToDisplay = new ArrayList<>(); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GREEN + + "Skills: " + + EnumChatFormatting.GOLD + + GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight + .getSkillsWeight() + .getWeightStruct() + .getRaw())) + ); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GREEN + + "Slayer: " + + EnumChatFormatting.GOLD + + GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight + .getSlayerWeight() + .getWeightStruct() + .getRaw())) + ); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GREEN + + "Dungeons: " + + EnumChatFormatting.GOLD + + GuiProfileViewer.numberFormat.format( + roundToNearestInt(senitherWeight.getDungeonsWeight().getWeightStruct().getRaw()) + ) + ); + } + } + + Utils.drawStringCentered( + EnumChatFormatting.GREEN + + "Lily Weight: " + + EnumChatFormatting.GOLD + + GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight.getTotalWeight().getRaw())), + fr, + guiLeft + 63, + guiTop + 28, + true, + 0 + ); + + int fontWidth = fr.getStringWidth( + "Lily Weight: " + GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight.getTotalWeight().getRaw())) + ); + if (mouseX > guiLeft + 63 - fontWidth / 2 && mouseX < guiLeft + 63 + fontWidth / 2) { + if (mouseY > guiTop + 22 && mouseY < guiTop + 22 + fr.FONT_HEIGHT) { + getInstance().tooltipToDisplay = new ArrayList<>(); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GREEN + + "Skills: " + + EnumChatFormatting.GOLD + + GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight + .getSkillsWeight() + .getWeightStruct() + .getRaw())) + ); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GREEN + + "Slayer: " + + EnumChatFormatting.GOLD + + GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight + .getSlayerWeight() + .getWeightStruct() + .getRaw())) + ); + getInstance() + .tooltipToDisplay.add( + EnumChatFormatting.GREEN + + "Dungeons: " + + EnumChatFormatting.GOLD + + GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight + .getDungeonsWeight() + .getWeightStruct() + .getRaw())) + ); + } + } + } + + private void drawEntityOnScreen(int posX, int posY, int scale, float mouseX, float mouseY, EntityLivingBase ent) { + GlStateManager.enableColorMaterial(); + GlStateManager.pushMatrix(); + GlStateManager.translate((float) posX, (float) posY, 50.0F); + GlStateManager.scale((float) (-scale), (float) scale, (float) scale); + GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F); + float renderYawOffset = ent.renderYawOffset; + float f1 = ent.rotationYaw; + float f2 = ent.rotationPitch; + float f3 = ent.prevRotationYawHead; + float f4 = ent.rotationYawHead; + GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F); + RenderHelper.enableStandardItemLighting(); + GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F); + GlStateManager.rotate(25, 1.0F, 0.0F, 0.0F); + ent.renderYawOffset = (float) Math.atan(mouseX / 40.0F) * 20.0F; + ent.rotationYaw = (float) Math.atan(mouseX / 40.0F) * 40.0F; + ent.rotationPitch = -((float) Math.atan(mouseY / 40.0F)) * 20.0F; + ent.rotationYawHead = ent.rotationYaw; + ent.prevRotationYawHead = ent.rotationYaw; + RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager(); + rendermanager.setPlayerViewY(180.0F); + rendermanager.setRenderShadow(false); + rendermanager.renderEntityWithPosYaw(ent, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F); + + ent.renderYawOffset = renderYawOffset; + ent.rotationYaw = f1; + ent.rotationPitch = f2; + ent.prevRotationYawHead = f3; + ent.rotationYawHead = f4; + GlStateManager.popMatrix(); + RenderHelper.disableStandardItemLighting(); + GlStateManager.disableRescaleNormal(); + GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); + GlStateManager.disableTexture2D(); + GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BingoPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BingoPage.java index dfcbb007..dfa92730 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BingoPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BingoPage.java @@ -40,13 +40,19 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -public class BingoPage { +public class BingoPage extends GuiProfileViewerPage { + private static final ResourceLocation BINGO_GUI_TEXTURE = new ResourceLocation("notenoughupdates:pv_bingo_tab.png"); - private static long lastResourceRequest; - private static List<JsonObject> bingoGoals = null; - private static int currentEventId; + private long lastResourceRequest; + private List<JsonObject> bingoGoals = null; + private int currentEventId; + + public BingoPage(GuiProfileViewer instance) { + super(instance); + } - public static void renderPage(int mouseX, int mouseY) { + @Override + public void drawPage(int mouseX, int mouseY, float partialTicks) { processBingoResources(); JsonObject bingoInfo = GuiProfileViewer.getProfile().getBingoInformation(); @@ -147,20 +153,22 @@ public class BingoPage { personalGoalsString = EnumChatFormatting.AQUA + "Personal Goals: " + EnumChatFormatting.GOLD + "20/20"; } else { personalGoalsString = - EnumChatFormatting.AQUA + "Personal Goals: " + EnumChatFormatting.WHITE + completedGoals.size() + - EnumChatFormatting.GOLD + "/" + EnumChatFormatting.WHITE + 20; + EnumChatFormatting.AQUA + + "Personal Goals: " + + EnumChatFormatting.WHITE + + completedGoals.size() + + EnumChatFormatting.GOLD + + "/" + + EnumChatFormatting.WHITE + + 20; } - Utils.drawStringF(totalPointsString, Minecraft.getMinecraft().fontRendererObj, - guiLeft + 22, guiTop + 19, true, 0 - ); - Utils.drawStringF(personalGoalsString, Minecraft.getMinecraft().fontRendererObj, - guiLeft + 22, guiTop + 31, true, 0 - ); + Utils.drawStringF(totalPointsString, Minecraft.getMinecraft().fontRendererObj, guiLeft + 22, guiTop + 19, true, 0); + Utils.drawStringF(personalGoalsString, Minecraft.getMinecraft().fontRendererObj, guiLeft + 22, guiTop + 31, true, 0); GlStateManager.enableLighting(); } - private static boolean isCommunityGoalFinished(JsonObject goal) { + private boolean isCommunityGoalFinished(JsonObject goal) { JsonArray tiers = goal.get("tiers").getAsJsonArray(); int totalTiers = tiers.size(); long progress = goal.get("progress").getAsLong(); @@ -175,7 +183,7 @@ public class BingoPage { return finalTier == totalTiers; } - private static String generateProgressIndicator(double progress, double goal) { + private String generateProgressIndicator(double progress, double goal) { int totalFields = 20; int filled; double percentage = progress / goal * 100; @@ -196,7 +204,7 @@ public class BingoPage { return stringBuilder.toString(); } - private static List<String> getTooltip(JsonObject goal, boolean completed, boolean communityGoal) { + private List<String> getTooltip(JsonObject goal, boolean completed, boolean communityGoal) { List<String> tooltip = new ArrayList<>(); if (communityGoal) { //get current tier @@ -211,9 +219,7 @@ public class BingoPage { } finalTier++; } - double nextTier = finalTier < totalTiers ? tiers.get(totalTiers - 1).getAsLong() : tiers - .get(finalTier - 1) - .getAsLong(); + double nextTier = finalTier < totalTiers ? tiers.get(totalTiers - 1).getAsLong() : tiers.get(finalTier - 1).getAsLong(); int progressToNextTier = (int) Math.round(progress / nextTier * 100); if (progressToNextTier > 100) progressToNextTier = 100; String progressBar = generateProgressIndicator(progress, nextTier); @@ -226,21 +232,35 @@ public class BingoPage { tooltip.add(EnumChatFormatting.DARK_GRAY + "Community Goal"); tooltip.add(""); tooltip.add( - EnumChatFormatting.GRAY + "Progress to " + name + " " + nextTierNum + ": " + EnumChatFormatting.YELLOW + - progressToNextTier + EnumChatFormatting.GOLD + "%"); - tooltip.add(progressBar + EnumChatFormatting.YELLOW + " " + progressString + EnumChatFormatting.GOLD + "/" + - EnumChatFormatting.YELLOW + nextTierString); + EnumChatFormatting.GRAY + + "Progress to " + + name + + " " + + nextTierNum + + ": " + + EnumChatFormatting.YELLOW + + progressToNextTier + + EnumChatFormatting.GOLD + + "%" + ); + tooltip.add( + progressBar + + EnumChatFormatting.YELLOW + + " " + + progressString + + EnumChatFormatting.GOLD + + "/" + + EnumChatFormatting.YELLOW + + nextTierString + ); tooltip.add(""); tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "Community Goals are"); - tooltip.add( - EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "collaborative - anyone with a"); - tooltip.add( - EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "Bingo profile can help to reach"); + tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "collaborative - anyone with a"); + tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "Bingo profile can help to reach"); tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "the goal!"); tooltip.add(""); tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "The more you contribute"); - tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + - "towards the goal, the more you"); + tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "towards the goal, the more you"); tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "will be rewarded"); if (finalTier == totalTiers) { @@ -266,14 +286,12 @@ public class BingoPage { return tooltip; } - private static void showMissingDataMessage(int guiLeft, int guiTop) { + private void showMissingDataMessage(int guiLeft, int guiTop) { String message = EnumChatFormatting.RED + "No Bingo data for current event!"; - Utils.drawStringCentered(message, Minecraft.getMinecraft().fontRendererObj, - guiLeft + 431 / 2f, guiTop + 101, true, 0 - ); + Utils.drawStringCentered(message, Minecraft.getMinecraft().fontRendererObj, guiLeft + 431 / 2f, guiTop + 101, true, 0); } - private static List<String> jsonArrayToStringList(JsonArray completedGoals) { + private List<String> jsonArrayToStringList(JsonArray completedGoals) { List<String> list = new ArrayList<>(); for (JsonElement completedGoal : completedGoals) { list.add(completedGoal.getAsString()); @@ -281,7 +299,7 @@ public class BingoPage { return list; } - private static List<JsonObject> jsonArrayToJsonObjectList(JsonArray goals) { + private List<JsonObject> jsonArrayToJsonObjectList(JsonArray goals) { List<JsonObject> list = new ArrayList<>(); for (JsonElement goal : goals) { list.add(goal.getAsJsonObject()); @@ -290,7 +308,7 @@ public class BingoPage { return list; } - private static void processBingoResources() { + private void processBingoResources() { long currentTime = System.currentTimeMillis(); //renew every 2 minutes diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java index c15190a1..4aff5cdb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java @@ -29,6 +29,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import java.awt.*; @@ -39,30 +40,51 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; -public class CollectionPage { +public class CollectionsPage extends GuiProfileViewerPage { - private static int guiLeft; - private static int guiTop; - private static int sizeX = 413; - private static int sizeY = 202; public static final ResourceLocation pv_cols = new ResourceLocation("notenoughupdates:pv_cols.png"); public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.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 String[] romans = new String[]{ - "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", - "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XIX", "XX" + private static final String[] romans = new String[] { + "I", + "II", + "III", + "IV", + "V", + "VI", + "VII", + "VIII", + "IX", + "X", + "XI", + "XII", + "XIII", + "XIV", + "XV", + "XVI", + "XVII", + "XIX", + "XX", }; - private static List<String> tooltipToDisplay = null; private static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US); + private static List<String> tooltipToDisplay = null; private static ItemStack selectedCollectionCategory = null; - public static void drawColsPage(int mouseX, int mouseY, int width, int height) { - guiLeft = GuiProfileViewer.getGuiLeft(); - guiTop = GuiProfileViewer.getGuiTop(); + private int page = 0; + private int maxPage = 0; + + public CollectionsPage(GuiProfileViewer instance) { + super(instance); + } + + public void drawPage(int mouseX, int mouseY, float partialTicks) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_cols); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); + Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST); JsonObject collectionInfo = GuiProfileViewer.getProfile().getCollectionInfo(GuiProfileViewer.getProfileId()); if (collectionInfo == null) { @@ -76,6 +98,7 @@ public class CollectionPage { ); return; } + JsonObject resourceCollectionInfo = ProfileViewer.getResourceCollectionInformation(); if (resourceCollectionInfo == null) return; @@ -87,18 +110,29 @@ public class CollectionPage { if (selectedCollectionCategory == null) selectedCollectionCategory = stack; Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); if (stack == selectedCollectionCategory) { - Utils.drawTexturedRect(guiLeft + 7, guiTop + 10 + collectionCatYSize * yIndex, 20, 20, - 20 / 256f, 0, 20 / 256f, 0, GL11.GL_NEAREST - ); - Utils.drawItemStackWithText( - stack, - guiLeft + 10, - guiTop + 13 + collectionCatYSize * yIndex, - "" + (yIndex + 1) + Utils.drawTexturedRect( + guiLeft + 7, + guiTop + 10 + collectionCatYSize * yIndex, + 20, + 20, + 20 / 256f, + 0, + 20 / 256f, + 0, + GL11.GL_NEAREST ); + Utils.drawItemStackWithText(stack, guiLeft + 10, guiTop + 13 + collectionCatYSize * yIndex, "" + (yIndex + 1)); } else { - Utils.drawTexturedRect(guiLeft + 7, guiTop + 10 + collectionCatYSize * yIndex, 20, 20, - 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft + 7, + guiTop + 10 + collectionCatYSize * yIndex, + 20, + 20, + 0, + 20 / 256f, + 0, + 20 / 256f, + GL11.GL_NEAREST ); Utils.drawItemStackWithText(stack, guiLeft + 9, guiTop + 12 + collectionCatYSize * yIndex, "" + (yIndex + 1)); } @@ -106,6 +140,53 @@ public class CollectionPage { } } + List<String> collections = ProfileViewer.getCollectionCatToCollectionMap().get(selectedCollectionCategory); + List<String> minions = ProfileViewer.getCollectionCatToMinionMap().get(selectedCollectionCategory); + + maxPage = Math.max((collections != null ? collections.size() : 0) / 20, (minions != null ? minions.size() : 0) / 20); + + if (maxPage != 0) { + 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 + 250 && mouseX < guiLeft + 100 + 20 + 12 + 250) { + rightHovered = true; + } + } + } + Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.resource_packs); + + if (page > 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 (page < 1) { + Utils.drawTexturedRect( + guiLeft + 100 + 15 + 250, + guiTop + 6, + 12, + 16, + 5 / 256f, + 29 / 256f, + !rightHovered ? 0 : 32 / 256f, + !rightHovered ? 32 / 256f : 64 / 256f, + GL11.GL_NEAREST + ); + } + } + Utils.drawStringCentered( selectedCollectionCategory.getDisplayName() + " Collections", Minecraft.getMinecraft().fontRendererObj, @@ -121,15 +202,14 @@ public class CollectionPage { JsonObject totalAmounts = collectionInfo.get("total_amounts").getAsJsonObject(); JsonObject personalAmounts = collectionInfo.get("personal_amounts").getAsJsonObject(); - List<String> collections = ProfileViewer.getCollectionCatToCollectionMap().get(selectedCollectionCategory); if (collections != null) { - for (int i = 0; i < collections.size(); i++) { + for (int i = page * 20, j = 0; i < Math.min((page + 1) * 20, collections.size()); i++, j++) { String collection = collections.get(i); if (collection != null) { ItemStack collectionItem = ProfileViewer.getCollectionToCollectionDisplayMap().get(collection); if (collectionItem != null) { - int xIndex = i % COLLS_XCOUNT; - int yIndex = i / COLLS_XCOUNT; + int xIndex = j % COLLS_XCOUNT; + int yIndex = j / COLLS_XCOUNT; float x = 39 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex; float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex; @@ -156,37 +236,66 @@ public class CollectionPage { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20 * (1 - completedness), - 0, 20 / 256f, 0, 20 * (1 - completedness) / 256f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y, + 20, + 20 * (1 - completedness), + 0, + 20 / 256f, + 0, + 20 * (1 - completedness) / 256f, + GL11.GL_NEAREST ); GlStateManager.color(1, 185 / 255f, 0, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(guiLeft + x, guiTop + y + 20 * (1 - completedness), 20, 20 * (completedness), - 0, 20 / 256f, 20 * (1 - completedness) / 256f, 20 / 256f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y + 20 * (1 - completedness), + 20, + 20 * (completedness), + 0, + 20 / 256f, + 20 * (1 - completedness) / 256f, + 20 / 256f, + GL11.GL_NEAREST ); Utils.drawItemStack(collectionItem, guiLeft + (int) x + 2, guiTop + (int) y + 2); if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) { if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) { tooltipToDisplay = new ArrayList<>(); - tooltipToDisplay.add(collectionItem.getDisplayName() + " " + - (completedness >= 1 ? EnumChatFormatting.GOLD : EnumChatFormatting.GRAY) + tierString); tooltipToDisplay.add( - "Collected: " + numberFormat.format(Utils.getElementAsFloat(personalAmounts.get(collection), 0))); + collectionItem.getDisplayName() + + " " + + (completedness >= 1 ? EnumChatFormatting.GOLD : EnumChatFormatting.GRAY) + + tierString + ); + tooltipToDisplay.add( + "Collected: " + numberFormat.format(Utils.getElementAsFloat(personalAmounts.get(collection), 0)) + ); tooltipToDisplay.add("Total Collected: " + numberFormat.format(amount)); } } GlStateManager.color(1, 1, 1, 1); if (tier >= 0) { - Utils.drawStringCentered(tierString, Minecraft.getMinecraft().fontRendererObj, - guiLeft + x + 10, guiTop + y - 4, true, + Utils.drawStringCentered( + tierString, + Minecraft.getMinecraft().fontRendererObj, + guiLeft + x + 10, + guiTop + y - 4, + true, tierStringColour ); } - Utils.drawStringCentered(GuiProfileViewer.shortNumberFormat(amount, 0) + "", Minecraft.getMinecraft().fontRendererObj, - guiLeft + x + 10, guiTop + y + 26, true, + Utils.drawStringCentered( + GuiProfileViewer.shortNumberFormat(amount, 0) + "", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + x + 10, + guiTop + y + 26, + true, color.getRGB() ); } @@ -203,14 +312,12 @@ public class CollectionPage { 4210752 ); - List<String> minions = ProfileViewer.getCollectionCatToMinionMap().get(selectedCollectionCategory); if (minions != null) { - for (int i = 0; i < minions.size(); i++) { + for (int i = page * 20, j = 0; i < Math.min((page + 1) * 20, minions.size()); i++, j++) { String minion = minions.get(i); if (minion != null) { JsonObject misc = Constants.MISC; - float MAX_MINION_TIER = - Utils.getElementAsFloat(Utils.getElement(misc, "minions." + minion + "_GENERATOR"), 11); + float MAX_MINION_TIER = Utils.getElementAsFloat(Utils.getElement(misc, "minions." + minion + "_GENERATOR"), 11); int tier = (int) Utils.getElementAsFloat(minionTiers.get(minion), 0); JsonObject minionJson; @@ -221,8 +328,8 @@ public class CollectionPage { } if (minionJson != null) { - int xIndex = i % COLLS_XCOUNT; - int yIndex = i / COLLS_XCOUNT; + int xIndex = j % COLLS_XCOUNT; + int yIndex = j / COLLS_XCOUNT; float x = 231 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex; float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex; @@ -246,13 +353,29 @@ public class CollectionPage { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20 * (1 - completedness), - 0, 20 / 256f, 0, 20 * (1 - completedness) / 256f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y, + 20, + 20 * (1 - completedness), + 0, + 20 / 256f, + 0, + 20 * (1 - completedness) / 256f, + GL11.GL_NEAREST ); GlStateManager.color(1, 185 / 255f, 0, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(guiLeft + x, guiTop + y + 20 * (1 - completedness), 20, 20 * (completedness), - 0, 20 / 256f, 20 * (1 - completedness) / 256f, 20 / 256f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y + 20 * (1 - completedness), + 20, + 20 * (completedness), + 0, + 20 / 256f, + 20 * (1 - completedness) / 256f, + 20 / 256f, + GL11.GL_NEAREST ); Utils.drawItemStack( @@ -263,18 +386,21 @@ public class CollectionPage { if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) { if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) { - tooltipToDisplay = NotEnoughUpdates.INSTANCE.manager.jsonToStack(minionJson) - .getTooltip( - Minecraft.getMinecraft().thePlayer, - false - ); + tooltipToDisplay = + NotEnoughUpdates.INSTANCE.manager + .jsonToStack(minionJson) + .getTooltip(Minecraft.getMinecraft().thePlayer, false); } } GlStateManager.color(1, 1, 1, 1); if (tier >= 0) { - Utils.drawStringCentered(tierString, Minecraft.getMinecraft().fontRendererObj, - guiLeft + x + 10, guiTop + y - 4, true, + Utils.drawStringCentered( + tierString, + Minecraft.getMinecraft().fontRendererObj, + guiLeft + x + 10, + guiTop + y - 4, + true, tierStringColour ); } @@ -288,12 +414,21 @@ public class CollectionPage { for (String line : tooltipToDisplay) { grayTooltip.add(EnumChatFormatting.GRAY + line); } - Utils.drawHoveringText(grayTooltip, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj); + Utils.drawHoveringText( + grayTooltip, + mouseX, + mouseY, + getInstance().width, + getInstance().height, + -1, + Minecraft.getMinecraft().fontRendererObj + ); tooltipToDisplay = null; } } - protected static void keyTypedCols(char typedChar, int keyCode) throws IOException { + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { ItemStack stack = null; Iterator<ItemStack> items = ProfileViewer.getCollectionCatToCollectionMap().keySet().iterator(); switch (keyCode) { @@ -315,19 +450,40 @@ public class CollectionPage { } if (stack != null) { selectedCollectionCategory = stack; + page = 0; } Utils.playPressSound(); } - public static void mouseReleasedCols(int mouseX, int mouseY, int mouseButton) { + @Override + public void mouseReleased(int mouseX, int mouseY, int mouseButton) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + if (maxPage != 0) { + if (mouseY > guiTop + 6 && mouseY < guiTop + 22) { + if (mouseX > guiLeft + 100 - 15 - 12 && mouseX < guiLeft + 100 - 20) { + if (page > 0) { + page--; + return; + } + } else if (mouseX > guiLeft + 100 + 15 + 250 && mouseX < guiLeft + 100 + 20 + 12 + 250) { + if (page < 1) { + page++; + return; + } + } + } + } + int collectionCatSize = ProfileViewer.getCollectionCatToCollectionMap().size(); int collectionCatYSize = (int) (162f / (collectionCatSize - 1 + 0.0000001f)); int yIndex = 0; for (ItemStack stack : ProfileViewer.getCollectionCatToCollectionMap().keySet()) { if (mouseX > guiLeft + 7 && mouseX < guiLeft + 7 + 20) { - if (mouseY > guiTop + 10 + collectionCatYSize * yIndex && - mouseY < guiTop + 10 + collectionCatYSize * yIndex + 20) { + if (mouseY > guiTop + 10 + collectionCatYSize * yIndex && mouseY < guiTop + 10 + collectionCatYSize * yIndex + 20) { selectedCollectionCategory = stack; + page = 0; Utils.playPressSound(); return; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java new file mode 100644 index 00000000..c4608299 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java @@ -0,0 +1,817 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer; + +import com.google.common.collect.Lists; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.io.IOException; +import java.util.Base64; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.UUID; + +public class DungeonPage extends GuiProfileViewerPage { + + private static final ResourceLocation pv_dung = new ResourceLocation("notenoughupdates:pv_dung.png"); + private static final ItemStack DEADBUSH = new ItemStack(Item.getItemFromBlock(Blocks.deadbush)); + private static final String[] dungSkillsName = { "Healer", "Mage", "Berserk", "Archer", "Tank" }; + private static final ItemStack[] BOSS_HEADS = new ItemStack[7]; + private static final ItemStack[] dungSkillsStack = { + new ItemStack(Items.potionitem, 1, 16389), + new ItemStack(Items.blaze_rod), + new ItemStack(Items.iron_sword), + new ItemStack(Items.bow), + new ItemStack(Items.leather_chestplate), + }; + private static final String[] bossFloorArr = { "Bonzo", "Scarf", "Professor", "Thorn", "Livid", "Sadan", "Necron" }; + private static final String[] bossFloorHeads = { + "12716ecbf5b8da00b05f316ec6af61e8bd02805b21eb8e440151468dc656549c", + "7de7bbbdf22bfe17980d4e20687e386f11d59ee1db6f8b4762391b79a5ac532d", + "9971cee8b833a62fc2a612f3503437fdf93cad692d216b8cf90bbb0538c47dd8", + "8b6a72138d69fbbd2fea3fa251cabd87152e4f1c97e5f986bf685571db3cc0", + "c1007c5b7114abec734206d4fc613da4f3a0e99f71ff949cedadc99079135a0b", + "fa06cb0c471c1c9bc169af270cd466ea701946776056e472ecdaeb49f0f4a4dc", + "a435164c05cea299a3f016bbbed05706ebb720dac912ce4351c2296626aecd9a", + }; + + private static final LinkedHashMap<String, ItemStack> dungeonsModeIcons = new LinkedHashMap<String, ItemStack>() { + { + put( + "catacombs", + Utils.editItemStackInfo( + NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("DUNGEON_STONE") + ), + EnumChatFormatting.GRAY + "Normal Mode", + true + ) + ); + put( + "master_catacombs", + Utils.editItemStackInfo( + NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("MASTER_SKULL_TIER_7") + ), + EnumChatFormatting.GRAY + "Master Mode", + true + ) + ); + } + }; + + private static int floorTime = 7; + private final HashMap<String, HashMap<String, ProfileViewer.Level>> levelObjClasseses = new HashMap<>(); + + private final HashMap<String, ProfileViewer.Level> levelObjCatas = new HashMap<>(); + private final GuiElementTextField dungeonLevelTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT); + private int floorLevelTo = -1; + private long floorLevelToXP = -1; + private boolean onMasterMode = false; + + public DungeonPage(GuiProfileViewer instance) { + super(instance); + } + + @Override + public void drawPage(int mouseX, int mouseY, float partialTicks) { + FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj; + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dung); + Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST); + + ProfileViewer.Profile profile = GuiProfileViewer.getProfile(); + String profileId = GuiProfileViewer.getProfileId(); + JsonObject hypixelInfo = profile.getHypixelProfile(); + if (hypixelInfo == null) return; + JsonObject profileInfo = profile.getProfileInformation(profileId); + if (profileInfo == null) return; + + JsonObject leveling = Constants.LEVELING; + if (leveling == null) return; + + int sectionWidth = 110; + + String dungeonString = onMasterMode ? "master_catacombs" : "catacombs"; + + Utils.renderShadowedString( + EnumChatFormatting.RED + (onMasterMode ? "Master Mode" : "Catacombs"), + (guiLeft + getInstance().sizeX / 2), + guiTop + 5, + sectionWidth + ); + + ProfileViewer.Level levelObjCata = levelObjCatas.get(profileId); + //Catacombs level thingy + { + if (levelObjCata == null) { + float cataXp = Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.experience"), 0); + levelObjCata = + ProfileViewer.getLevel( + Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(), + cataXp, + 99, + false + ); + levelObjCata.totalXp = cataXp; + levelObjCatas.put(profileId, levelObjCata); + } + + String skillName = EnumChatFormatting.RED + "Catacombs"; + float level = levelObjCata.level; + int levelFloored = (int) Math.floor(level); + + if (floorLevelTo == -1 && levelFloored >= 0) { + dungeonLevelTextField.setText("" + (levelFloored + 1)); + calculateFloorLevelXP(); + } + + int x = guiLeft + 23; + int y = guiTop + 25; + + getInstance().renderXpBar(skillName, DEADBUSH, x, y, sectionWidth, levelObjCata, mouseX, mouseY); + + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Until Cata " + floorLevelTo + ": ", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(floorLevelToXP, 0), + x, + y + 16, + sectionWidth + ); + + if (mouseX > x && mouseX < x + sectionWidth && mouseY > y + 16 && mouseY < y + 24 && !onMasterMode) { + float F5 = + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + 5), 0)); //this can prob be done better + float F6 = + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + 6), 0)); + float F7 = + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + 7), 0)); + if (F5 > 150) { + F5 = 150; + } + if (F6 > 100) { + F6 = 100; + } + if (F7 > 50) { + F7 = 50; + } + float xpF5 = 2000 * (F5 / 100 + 1); + float xpF6 = 4000 * (F6 / 100 + 1); + float xpF7 = 20000 * (F7 / 100 + 1); + if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { + xpF5 *= 1.1; + xpF6 *= 1.1; + xpF7 *= 1.1; + } + + long runsF5 = (int) Math.ceil(floorLevelToXP / xpF5); + long runsF6 = (int) Math.ceil(floorLevelToXP / xpF6); + long runsF7 = (int) Math.ceil(floorLevelToXP / xpF7); + + float timeF5 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.5"), + 0 + ); + float timeF6 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.6"), + 0 + ); + float timeF7 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.7"), + 0 + ); + + getInstance().tooltipToDisplay = + Lists.newArrayList( + String.format("# F5 Runs (%s xp) : %d", GuiProfileViewer.shortNumberFormat(xpF5, 0), runsF5), + String.format("# F6 Runs (%s xp) : %d", GuiProfileViewer.shortNumberFormat(xpF6, 0), runsF6), + String.format("# F7 Runs (%s xp) : %d", GuiProfileViewer.shortNumberFormat(xpF7, 0), runsF7), + "" + ); + boolean hasTime = false; + if (timeF5 > 1000) { + getInstance() + .tooltipToDisplay.add(String.format("Expected Time (F5) : %s", Utils.prettyTime(runsF5 * (long) (timeF5 * 1.2)))); + hasTime = true; + } + if (timeF6 > 1000) { + getInstance() + .tooltipToDisplay.add(String.format("Expected Time (F6) : %s", Utils.prettyTime(runsF6 * (long) (timeF6 * 1.2)))); + hasTime = true; + } + if (timeF7 > 1000) { + getInstance() + .tooltipToDisplay.add(String.format("Expected Time (F7) : %s", Utils.prettyTime(runsF7 * (long) (timeF7 * 1.2)))); + hasTime = true; + } + if (hasTime) { + getInstance().tooltipToDisplay.add(""); + } + if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { + getInstance() + .tooltipToDisplay.add( + "[Hold " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + " to show without Expert Ring]" + ); + } + if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { + if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) getInstance().tooltipToDisplay.add(""); + getInstance().tooltipToDisplay.add("Number of runs is calculated as [Remaining XP]/[XP per Run]."); + getInstance().tooltipToDisplay.add("The [XP per Run] is the average xp gained from an S+ run"); + getInstance() + .tooltipToDisplay.add( + "The " + + EnumChatFormatting.DARK_PURPLE + + "Catacombs Expert Ring" + + EnumChatFormatting.GRAY + + " is assumed to be used, unless " + + EnumChatFormatting.YELLOW + + "SHIFT" + + EnumChatFormatting.GRAY + + " is held." + ); + getInstance().tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%"); + } else { + getInstance() + .tooltipToDisplay.add("[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]"); + } + } + + if (mouseX > x && mouseX < x + sectionWidth && mouseY > y + 16 && mouseY < y + 24 && onMasterMode) { + float M3 = + ( + Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + 3), + 0 + ) + ); + float M4 = + ( + Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + 4), + 0 + ) + ); + float M5 = + ( + Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + 5), + 0 + ) + ); //this can prob be done better + float M6 = + ( + Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + 6), + 0 + ) + ); + if (M3 > 50) { + M3 = 50; + } + if (M4 > 50) { + M4 = 50; + } + if (M5 > 50) { + M5 = 50; + } + if (M6 > 50) { + M6 = 50; + } + float xpM3 = 36500 * (M3 / 100 + 1); + float xpM4 = 48500 * (M4 / 100 + 1); + float xpM5 = 70000 * (M5 / 100 + 1); + float xpM6 = 100000 * (M6 / 100 + 1); + //No clue if M3 or M4 xp values are right + if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { + xpM3 *= 1.1; + xpM4 *= 1.1; + xpM5 *= 1.1; + xpM6 *= 1.1; + } + + long runsM3 = (int) Math.ceil(floorLevelToXP / xpM3); + long runsM4 = (int) Math.ceil(floorLevelToXP / xpM4); + long runsM5 = (int) Math.ceil(floorLevelToXP / xpM5); + long runsM6 = (int) Math.ceil(floorLevelToXP / xpM6); + + float timeM3 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.3"), + 0 + ); + float timeM4 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.4"), + 0 + ); + float timeM5 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.5"), + 0 + ); + float timeM6 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.6"), + 0 + ); + + getInstance().tooltipToDisplay = + Lists.newArrayList( + String.format("# M3 Runs (%s xp) : %d", GuiProfileViewer.shortNumberFormat(xpM3, 0), runsM3), + String.format("# M4 Runs (%s xp) : %d", GuiProfileViewer.shortNumberFormat(xpM4, 0), runsM4), + String.format("# M5 Runs (%s xp) : %d", GuiProfileViewer.shortNumberFormat(xpM5, 0), runsM5), + String.format("# M6 Runs (%s xp) : %d", GuiProfileViewer.shortNumberFormat(xpM6, 0), runsM6), + "" + ); + boolean hasTime = false; + if (timeM3 > 1000) { + getInstance() + .tooltipToDisplay.add(String.format("Expected Time (M3) : %s", Utils.prettyTime(runsM3 * (long) (timeM3 * 1.2)))); + hasTime = true; + } + if (timeM4 > 1000) { + getInstance() + .tooltipToDisplay.add(String.format("Expected Time (M4) : %s", Utils.prettyTime(runsM4 * (long) (timeM4 * 1.2)))); + hasTime = true; + } + if (timeM5 > 1000) { + getInstance() + .tooltipToDisplay.add(String.format("Expected Time (M5) : %s", Utils.prettyTime(runsM5 * (long) (timeM5 * 1.2)))); + hasTime = true; + } + if (timeM6 > 1000) { + getInstance() + .tooltipToDisplay.add(String.format("Expected Time (M6) : %s", Utils.prettyTime(runsM6 * (long) (timeM6 * 1.2)))); + hasTime = true; + } + if (hasTime) { + getInstance().tooltipToDisplay.add(""); + } + if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { + getInstance() + .tooltipToDisplay.add( + "[Hold " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + " to show without Expert Ring]" + ); + } + if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { + if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) getInstance().tooltipToDisplay.add(""); + getInstance().tooltipToDisplay.add("Number of runs is calculated as [Remaining XP]/[XP per Run]."); + getInstance().tooltipToDisplay.add("The [XP per Run] is the average xp gained from an S+ run"); + getInstance() + .tooltipToDisplay.add( + "The " + + EnumChatFormatting.DARK_PURPLE + + "Catacombs Expert Ring" + + EnumChatFormatting.GRAY + + " is assumed to be used, unless " + + EnumChatFormatting.YELLOW + + "SHIFT" + + EnumChatFormatting.GRAY + + " is held." + ); + getInstance().tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%"); + } else { + getInstance() + .tooltipToDisplay.add("[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]"); + } + } + + dungeonLevelTextField.setSize(20, 10); + dungeonLevelTextField.render(x + 22, y + 29); + int calcLen = fontRendererObj.getStringWidth("Calculate"); + Utils.renderShadowedString(EnumChatFormatting.WHITE + "Calculate", x + sectionWidth - 17 - calcLen / 2f, y + 30, 100); + + //Random stats + + float secrets = Utils.getElementAsFloat(Utils.getElement(hypixelInfo, "achievements.skyblock_treasure_hunter"), 0); + float totalRunsF = 0; + float totalRunsF5 = 0; + for (int i = 1; i <= 7; i++) { + float runs = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + i), + 0 + ); + totalRunsF += runs; + if (i >= 5) { + totalRunsF5 += runs; + } + } + float totalRunsM = 0; + float totalRunsM5 = 0; + for (int i = 1; i <= 7; i++) { + float runs = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + i), + 0 + ); + totalRunsM += runs; + if (i >= 5) { + totalRunsM5 += runs; + } + } + float totalRuns = totalRunsF + totalRunsM; + + float mobKills; + float mobKillsF = 0; + for (int i = 1; i <= 7; i++) { + float kills = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.mobs_killed." + i), + 0 + ); + mobKillsF += kills; + } + float mobKillsM = 0; + for (int i = 1; i <= 7; i++) { + float kills = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.mobs_killed." + i), + 0 + ); + mobKillsM += kills; + } + mobKills = mobKillsF + mobKillsM; + + int miscTopY = y + 55; + + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Total Runs " + (onMasterMode ? "M" : "F"), + EnumChatFormatting.WHITE.toString() + ((int) (onMasterMode ? totalRunsM : totalRunsF)), + x, + miscTopY, + sectionWidth + ); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Total Runs (" + (onMasterMode ? "M" : "F") + "5-7) ", + EnumChatFormatting.WHITE.toString() + ((int) (onMasterMode ? totalRunsM5 : totalRunsF5)), + x, + miscTopY + 10, + sectionWidth + ); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Secrets (Total) ", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(secrets, 0), + x, + miscTopY + 20, + sectionWidth + ); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Secrets (/Run) ", + EnumChatFormatting.WHITE.toString() + (Math.round(secrets / Math.max(1, totalRuns) * 100) / 100f), + x, + miscTopY + 30, + sectionWidth + ); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Mob Kills (Total) ", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(mobKills, 0), + x, + miscTopY + 40, + sectionWidth + ); + + int y3 = y + 117; + + for (int i = 1; i <= 7; i++) { + int w = fontRendererObj.getStringWidth("" + i); + + int bx = x + sectionWidth * i / 8 - w / 2; + + boolean invert = i == floorTime; + float uMin = 20 / 256f; + float uMax = 29 / 256f; + float vMin = 0 / 256f; + float vMax = 11 / 256f; + + GlStateManager.color(1, 1, 1, 1); + Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements); + Utils.drawTexturedRect( + bx - 2, + y3 - 2, + 9, + 11, + invert ? uMax : uMin, + invert ? uMin : uMax, + invert ? vMax : vMin, + invert ? vMin : vMax, + GL11.GL_NEAREST + ); + + Utils.renderShadowedString(EnumChatFormatting.WHITE.toString() + i, bx + w / 2, y3, 10); + } + + float timeNorm = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time." + floorTime), + 0 + ); + float timeS = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time_s." + floorTime), + 0 + ); + float timeSPLUS = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time_s_plus." + floorTime), + 0 + ); + String timeNormStr = timeNorm <= 0 ? "N/A" : Utils.prettyTime((long) timeNorm); + String timeSStr = timeS <= 0 ? "N/A" : Utils.prettyTime((long) timeS); + String timeSPlusStr = timeSPLUS <= 0 ? "N/A" : Utils.prettyTime((long) timeSPLUS); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Floor " + floorTime + " ", + EnumChatFormatting.WHITE + timeNormStr, + x, + y3 + 10, + sectionWidth + ); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Floor " + floorTime + " S", + EnumChatFormatting.WHITE + timeSStr, + x, + y3 + 20, + sectionWidth + ); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Floor " + floorTime + " S+", + EnumChatFormatting.WHITE + timeSPlusStr, + x, + y3 + 30, + sectionWidth + ); + } + + //Completions + { + int x = guiLeft + 161; + int y = guiTop + 27; + + Utils.renderShadowedString(EnumChatFormatting.RED + "Boss Collections", x + sectionWidth / 2, y, sectionWidth); + for (int i = 1; i <= 7; i++) { + float compl = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".tier_completions." + i), + 0 + ); + + if (BOSS_HEADS[i - 1] == null) { + String textureLink = bossFloorHeads[i - 1]; + + 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); + + BOSS_HEADS[i - 1] = stack; + } + + GlStateManager.pushMatrix(); + GlStateManager.translate(x - 4, y + 10 + 20 * (i - 1), 0); + GlStateManager.scale(1.3f, 1.3f, 1); + Utils.drawItemStack(BOSS_HEADS[i - 1], 0, 0); + GlStateManager.popMatrix(); + + Utils.renderAlignedString( + String.format(EnumChatFormatting.YELLOW + "%s (" + (onMasterMode ? "M" : "F") + "%d) ", bossFloorArr[i - 1], i), + EnumChatFormatting.WHITE.toString() + (int) compl, + x + 16, + y + 18 + 20 * (i - 1), + sectionWidth - 15 + ); + } + } + + //Skills + { + int x = guiLeft + 298; + int y = guiTop + 27; + + //Gui.drawRect(x, y, x+120, y+147, 0xffffffff); + + Utils.renderShadowedString(EnumChatFormatting.DARK_PURPLE + "Class Levels", x + sectionWidth / 2, y, sectionWidth); + + JsonElement activeClassElement = Utils.getElement(profileInfo, "dungeons.selected_dungeon_class"); + String activeClass = null; + if (activeClassElement instanceof JsonPrimitive && ((JsonPrimitive) activeClassElement).isString()) { + activeClass = activeClassElement.getAsString(); + } + + for (int i = 0; i < dungSkillsName.length; i++) { + String skillName = dungSkillsName[i]; + + HashMap<String, ProfileViewer.Level> levelObjClasses = levelObjClasseses.computeIfAbsent(profileId, k -> new HashMap<>()); + if (!levelObjClasses.containsKey(skillName)) { + float cataXp = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.player_classes." + skillName.toLowerCase() + ".experience"), + 0 + ); + ProfileViewer.Level levelObj = ProfileViewer.getLevel( + Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(), + cataXp, + 50, + false + ); + levelObjClasses.put(skillName, levelObj); + } + + String colour = EnumChatFormatting.WHITE.toString(); + if (skillName.toLowerCase().equals(activeClass)) { + colour = EnumChatFormatting.GREEN.toString(); + } + + ProfileViewer.Level levelObj = levelObjClasses.get(skillName); + + getInstance() + .renderXpBar(colour + skillName, dungSkillsStack[i], x, y + 20 + 29 * i, sectionWidth, levelObj, mouseX, mouseY); + } + } + + drawSideButtons(); + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj; + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + if (mouseX >= guiLeft + 50 && mouseX <= guiLeft + 70 && mouseY >= guiTop + 54 && mouseY <= guiTop + 64) { + dungeonLevelTextField.mouseClicked(mouseX, mouseY, mouseButton); + } else { + dungeonLevelTextField.otherComponentClick(); + } + + int cW = fontRendererObj.getStringWidth("Calculate"); + if (mouseX >= guiLeft + 23 + 110 - 17 - cW && mouseX <= guiLeft + 23 + 110 - 17 && mouseY >= guiTop + 55 && mouseY <= guiTop + 65) { + calculateFloorLevelXP(); + } + + int y = guiTop + 142; + + if (mouseY >= y - 2 && mouseY <= y + 9) { + for (int i = 1; i <= 7; i++) { + int w = fontRendererObj.getStringWidth("" + i); + + int x = guiLeft + 23 + 110 * i / 8 - w / 2; + + if (mouseX >= x - 2 && mouseX <= x + 7) { + floorTime = i; + return false; + } + } + } + if (mouseX >= guiLeft - 29 && mouseX <= guiLeft) { + if (mouseY >= guiTop && mouseY <= guiTop + 28) { + onMasterMode = false; + } else if (mouseY + 28 >= guiTop && mouseY <= guiTop + 28 * 2) { + onMasterMode = true; + } + } + return false; + } + + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { + dungeonLevelTextField.keyTyped(typedChar, keyCode); + } + + private void drawSideButtons() { + GlStateManager.enableDepth(); + GlStateManager.translate(0, 0, 5); + if (onMasterMode) { + drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), true); + } else { + drawSideButton(0, dungeonsModeIcons.get("catacombs"), true); + } + GlStateManager.translate(0, 0, -3); + + GlStateManager.translate(0, 0, -2); + if (!onMasterMode) { + drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), false); + } else { + drawSideButton(0, dungeonsModeIcons.get("catacombs"), false); + } + GlStateManager.disableDepth(); + } + + private void drawSideButton(int yIndex, ItemStack itemStack, boolean pressed) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + + int x = guiLeft - 28; + int y = guiTop + yIndex * 28; + + float uMin = 193 / 256f; + float uMax = 223 / 256f; + float vMin = 200 / 256f; + float vMax = 228 / 256f; + if (pressed) { + uMin = 224 / 256f; + uMax = 1f; + + if (yIndex != 0) { + vMin = 228 / 256f; + vMax = 1f; + } + + getInstance().renderBlurredBackground(getInstance().width, getInstance().height, x + 2, y + 2, 30, 28 - 4); + } else { + getInstance().renderBlurredBackground(getInstance().width, getInstance().height, x + 2, y + 2, 28 - 2, 28 - 4); + } + + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(516, 0.1F); + + Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements); + + Utils.drawTexturedRect(x, y, pressed ? 32 : 28, 28, uMin, uMax, vMin, vMax, GL11.GL_NEAREST); + + GlStateManager.enableDepth(); + Utils.drawItemStack(itemStack, x + 8, y + 7); + } + + private void calculateFloorLevelXP() { + JsonObject leveling = Constants.LEVELING; + if (leveling == null) return; + ProfileViewer.Level levelObjCata = levelObjCatas.get(GuiProfileViewer.getProfileId()); + if (levelObjCata == null) return; + + try { + dungeonLevelTextField.setCustomBorderColour(0xffffffff); + floorLevelTo = Integer.parseInt(dungeonLevelTextField.getText()); + + JsonArray levelingArray = Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(); + + float remaining = -((levelObjCata.level % 1) * levelObjCata.maxXpForLevel); + + for (int level = 0; level < Math.min(floorLevelTo, levelingArray.size()); level++) { + if (level < Math.floor(levelObjCata.level)) { + continue; + } + remaining += levelingArray.get(level).getAsFloat(); + } + + if (remaining < 0) { + remaining = 0; + } + floorLevelToXP = (long) remaining; + } catch (Exception e) { + dungeonLevelTextField.setCustomBorderColour(0xffff0000); + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java new file mode 100644 index 00000000..3a071d47 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java @@ -0,0 +1,516 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.lang3.text.WordUtils; +import org.lwjgl.opengl.GL11; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeMap; + +public class ExtraPage extends GuiProfileViewerPage { + + private static final ResourceLocation pv_extra = new ResourceLocation("notenoughupdates:pv_extra.png"); + private TreeMap<Integer, Set<String>> topKills = null; + private TreeMap<Integer, Set<String>> topDeaths = null; + + public ExtraPage(GuiProfileViewer instance) { + super(instance); + } + + @Override + public void drawPage(int mouseX, int mouseY, float partialTicks) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_extra); + Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST); + + ProfileViewer.Profile profile = GuiProfileViewer.getProfile(); + String profileId = GuiProfileViewer.getProfileId(); + JsonObject profileInfo = profile.getProfileInformation(profileId); + if (profileInfo == null) return; + Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(profileId); + + float xStart = 22; + float xOffset = 103; + float yStartTop = 27; + float yStartBottom = 105; + float yOffset = 10; + + float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), 0); + float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0); + + Utils.renderAlignedString( + EnumChatFormatting.GOLD + "Bank Balance", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(bankBalance, 0), + guiLeft + xStart, + guiTop + yStartTop, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.GOLD + "Purse", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(purseBalance, 0), + guiLeft + xStart, + guiTop + yStartTop + yOffset, + 76 + ); + + { + String lastSaveText = getTimeSinceString(profileInfo, "last_save"); + if (lastSaveText != null) { + Utils.renderAlignedString( + EnumChatFormatting.AQUA + "Last Seen", + EnumChatFormatting.WHITE + lastSaveText, + guiLeft + xStart, + guiTop + yStartTop + yOffset * 2, + 76 + ); + } + } + { + String first_join = getTimeSinceString(profileInfo, "first_join"); + if (first_join != null) { + Utils.renderAlignedString( + EnumChatFormatting.AQUA + "Joined", + EnumChatFormatting.WHITE + first_join, + guiLeft + xStart, + guiTop + yStartTop + yOffset * 3, + 76 + ); + } + } + JsonObject guildInfo = profile.getGuildInformation(null); + boolean shouldRenderGuild = guildInfo != null && guildInfo.has("name"); + { + if (shouldRenderGuild) { + Utils.renderAlignedString( + EnumChatFormatting.AQUA + "Guild", + EnumChatFormatting.WHITE + guildInfo.get("name").getAsString(), + guiLeft + xStart, + guiTop + yStartTop + yOffset * 4, + 76 + ); + } + } + { + GuiProfileViewer.pronouns.peekValue().flatMap(it -> it).ifPresent(choice -> Utils.renderAlignedString( + EnumChatFormatting.GREEN + "Pronouns", + EnumChatFormatting.WHITE + String.join(" / ", choice.render()), + guiLeft + xStart, + guiTop + yStartTop + yOffset * (shouldRenderGuild ? 5 : 4), + 76 + )); + } + + float fairySouls = Utils.getElementAsFloat(Utils.getElement(profileInfo, "fairy_souls_collected"), 0); + + int fairySoulMax = 227; + if (Constants.FAIRYSOULS != null && Constants.FAIRYSOULS.has("Max Souls")) { + fairySoulMax = Constants.FAIRYSOULS.get("Max Souls").getAsInt(); + } + Utils.renderAlignedString( + EnumChatFormatting.LIGHT_PURPLE + "Fairy Souls", + EnumChatFormatting.WHITE.toString() + (int) fairySouls + "/" + fairySoulMax, + guiLeft + xStart, + guiTop + yStartBottom, + 76 + ); + + if (skyblockInfo != null) { + float totalSkillLVL = 0; + float totalTrueSkillLVL = 0; + float totalSlayerLVL = 0; + float totalSkillCount = 0; + float totalSlayerCount = 0; + float totalSlayerXP = 0; + + List<String> skills = Arrays.asList("taming", "mining", "foraging", "enchanting", "farming", "combat", "fishing", "alchemy"); + List<String> slayers = Arrays.asList("zombie", "spider", "wolf", "enderman", "blaze"); + + for (Map.Entry<String, ProfileViewer.Level> entry : skyblockInfo.entrySet()) { + if (skills.contains(entry.getKey())) { + totalSkillLVL += entry.getValue().level; + totalTrueSkillLVL += Math.floor(entry.getValue().level); + totalSkillCount++; + } else if (slayers.contains(entry.getKey())) { + totalSlayerLVL += entry.getValue().level; + totalSlayerCount++; + totalSlayerXP += entry.getValue().totalXp; + } + } + + float avgSkillLVL = totalSkillLVL / totalSkillCount; + float avgTrueSkillLVL = totalTrueSkillLVL / totalSkillCount; + float avgSlayerLVL = totalSlayerLVL / totalSlayerCount; + + Utils.renderAlignedString( + EnumChatFormatting.RED + "AVG Skill Level", + EnumChatFormatting.WHITE.toString() + Math.floor(avgSkillLVL * 10) / 10, + guiLeft + xStart, + guiTop + yStartBottom + yOffset, + 76 + ); + + Utils.renderAlignedString( + EnumChatFormatting.RED + "True AVG Skill Level", + EnumChatFormatting.WHITE.toString() + Math.floor(avgTrueSkillLVL * 10) / 10, + guiLeft + xStart, + guiTop + yStartBottom + yOffset * 2, + 76 + ); + + Utils.renderAlignedString( + EnumChatFormatting.RED + "AVG Slayer Level", + EnumChatFormatting.WHITE.toString() + Math.floor(avgSlayerLVL * 10) / 10, + guiLeft + xStart, + guiTop + yStartBottom + yOffset * 3, + 76 + ); + + Utils.renderAlignedString( + EnumChatFormatting.RED + "Total Slayer XP", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(totalSlayerXP, 0), + guiLeft + xStart, + guiTop + yStartBottom + yOffset * 4, + 76 + ); + } + + float auctions_bids = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_bids"), 0); + float auctions_highest_bid = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_highest_bid"), 0); + float auctions_won = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_won"), 0); + float auctions_created = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_created"), 0); + float auctions_gold_spent = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_gold_spent"), 0); + float auctions_gold_earned = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_gold_earned"), 0); + + Utils.renderAlignedString( + EnumChatFormatting.DARK_PURPLE + "Auction Bids", + EnumChatFormatting.WHITE.toString() + (int) auctions_bids, + guiLeft + xStart + xOffset, + guiTop + yStartTop, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_PURPLE + "Highest Bid", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(auctions_highest_bid, 0), + guiLeft + xStart + xOffset, + guiTop + yStartTop + yOffset, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_PURPLE + "Auctions Won", + EnumChatFormatting.WHITE.toString() + (int) auctions_won, + guiLeft + xStart + xOffset, + guiTop + yStartTop + yOffset * 2, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_PURPLE + "Auctions Created", + EnumChatFormatting.WHITE.toString() + (int) auctions_created, + guiLeft + xStart + xOffset, + guiTop + yStartTop + yOffset * 3, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_PURPLE + "Gold Spent", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(auctions_gold_spent, 0), + guiLeft + xStart + xOffset, + guiTop + yStartTop + yOffset * 4, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_PURPLE + "Gold Earned", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(auctions_gold_earned, 0), + guiLeft + xStart + xOffset, + guiTop + yStartTop + yOffset * 5, + 76 + ); + + //Slayer values + float zombie_boss_kills_tier_2 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_2"), + 0 + ); + float zombie_boss_kills_tier_3 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_3"), + 0 + ); + float zombie_boss_kills_tier_4 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_4"), + 0 + ); + float wolf_boss_kills_tier_2 = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.wolf.boss_kills_tier_2"), 0); + float wolf_boss_kills_tier_3 = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.wolf.boss_kills_tier_3"), 0); + float spider_boss_kills_tier_2 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "slayer_bosses.spider.boss_kills_tier_2"), + 0 + ); + float spider_boss_kills_tier_3 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "slayer_bosses.spider.boss_kills_tier_3"), + 0 + ); + float enderman_boss_kills_tier_2 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "slayer_bosses.enderman.boss_kills_tier_2"), + 0 + ); + float enderman_boss_kills_tier_3 = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "slayer_bosses.enderman.boss_kills_tier_3"), + 0 + ); + float blaze_boss_kills_tier_2 = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.blaze.boss_kills_tier_2"), 0); + float blaze_boss_kills_tier_3 = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.blaze.boss_kills_tier_3"), 0); + + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Revenant T3", + EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_2, + guiLeft + xStart + xOffset, + guiTop + yStartBottom, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Revenant T4", + EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_3, + guiLeft + xStart + xOffset, + guiTop + yStartBottom + yOffset, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Revenant T5", + EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_4, + guiLeft + xStart + xOffset, + guiTop + yStartBottom + yOffset * 2, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Tarantula T3", + EnumChatFormatting.WHITE.toString() + (int) spider_boss_kills_tier_2, + guiLeft + xStart + xOffset, + guiTop + yStartBottom + yOffset * 3, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Tarantula T4", + EnumChatFormatting.WHITE.toString() + (int) spider_boss_kills_tier_3, + guiLeft + xStart + xOffset, + guiTop + yStartBottom + yOffset * 4, + 76 + ); + + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Sven T3", + EnumChatFormatting.WHITE.toString() + (int) wolf_boss_kills_tier_2, + guiLeft + xStart + xOffset * 2, + guiTop + yStartBottom + yOffset * 0, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Sven T4", + EnumChatFormatting.WHITE.toString() + (int) wolf_boss_kills_tier_3, + guiLeft + xStart + xOffset * 2, + guiTop + yStartBottom + yOffset * 1, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Voidgloom T3", + EnumChatFormatting.WHITE.toString() + (int) enderman_boss_kills_tier_2, + guiLeft + xStart + xOffset * 2, + guiTop + yStartBottom + yOffset * 2, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Voidgloom T4", + EnumChatFormatting.WHITE.toString() + (int) enderman_boss_kills_tier_3, + guiLeft + xStart + xOffset * 2, + guiTop + yStartBottom + yOffset * 3, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Inferno T3", + EnumChatFormatting.WHITE.toString() + (int) blaze_boss_kills_tier_2, + guiLeft + xStart + xOffset * 2, + guiTop + yStartBottom + yOffset * 4, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_AQUA + "Inferno T4", + EnumChatFormatting.WHITE.toString() + (int) blaze_boss_kills_tier_3, + guiLeft + xStart + xOffset * 2, + guiTop + yStartBottom + yOffset * 5, + 76 + ); + + float pet_milestone_ores_mined = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.pet_milestone_ores_mined"), 0); + float pet_milestone_sea_creatures_killed = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "stats.pet_milestone_sea_creatures_killed"), + 0 + ); + + float items_fished = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished"), 0); + float items_fished_treasure = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished_treasure"), 0); + float items_fished_large_treasure = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished_large_treasure"), 0); + + Utils.renderAlignedString( + EnumChatFormatting.GREEN + "Ores Mined", + EnumChatFormatting.WHITE.toString() + (int) pet_milestone_ores_mined, + guiLeft + xStart + xOffset * 2, + guiTop + yStartTop, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.GREEN + "Sea Creatures Killed", + EnumChatFormatting.WHITE.toString() + (int) pet_milestone_sea_creatures_killed, + guiLeft + xStart + xOffset * 2, + guiTop + yStartTop + yOffset, + 76 + ); + + Utils.renderAlignedString( + EnumChatFormatting.GREEN + "Items Fished", + EnumChatFormatting.WHITE.toString() + (int) items_fished, + guiLeft + xStart + xOffset * 2, + guiTop + yStartTop + yOffset * 3, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.GREEN + "Treasures Fished", + EnumChatFormatting.WHITE.toString() + (int) items_fished_treasure, + guiLeft + xStart + xOffset * 2, + guiTop + yStartTop + yOffset * 4, + 76 + ); + Utils.renderAlignedString( + EnumChatFormatting.GREEN + "Large Treasures", + EnumChatFormatting.WHITE.toString() + (int) items_fished_large_treasure, + guiLeft + xStart + xOffset * 2, + guiTop + yStartTop + yOffset * 5, + 76 + ); + + if (topKills == null) { + topKills = new TreeMap<>(); + JsonObject stats = profileInfo.get("stats").getAsJsonObject(); + for (Map.Entry<String, JsonElement> entry : stats.entrySet()) { + if (entry.getKey().startsWith("kills_")) { + if (entry.getValue().isJsonPrimitive()) { + JsonPrimitive prim = (JsonPrimitive) entry.getValue(); + if (prim.isNumber()) { + String name = WordUtils.capitalizeFully(entry.getKey().substring("kills_".length()).replace("_", " ")); + Set<String> kills = topKills.computeIfAbsent(prim.getAsInt(), k -> new HashSet<>()); + kills.add(name); + } + } + } + } + } + if (topDeaths == null) { + topDeaths = new TreeMap<>(); + JsonObject stats = profileInfo.get("stats").getAsJsonObject(); + for (Map.Entry<String, JsonElement> entry : stats.entrySet()) { + if (entry.getKey().startsWith("deaths_")) { + if (entry.getValue().isJsonPrimitive()) { + JsonPrimitive prim = (JsonPrimitive) entry.getValue(); + if (prim.isNumber()) { + String name = WordUtils.capitalizeFully(entry.getKey().substring("deaths_".length()).replace("_", " ")); + Set<String> deaths = topDeaths.computeIfAbsent(prim.getAsInt(), k -> new HashSet<>()); + deaths.add(name); + } + } + } + } + } + + int index = 0; + for (int killCount : topKills.descendingKeySet()) { + if (index >= 6) break; + Set<String> kills = topKills.get(killCount); + for (String killType : kills) { + if (index >= 6) break; + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + killType + " Kills", + EnumChatFormatting.WHITE.toString() + killCount, + guiLeft + xStart + xOffset * 3, + guiTop + yStartTop + yOffset * index, + 76 + ); + index++; + } + } + index = 0; + for (int deathCount : topDeaths.descendingKeySet()) { + if (index >= 6) break; + Set<String> deaths = topDeaths.get(deathCount); + for (String deathType : deaths) { + if (index >= 6) break; + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Deaths: " + deathType, + EnumChatFormatting.WHITE.toString() + deathCount, + guiLeft + xStart + xOffset * 3, + guiTop + yStartBottom + yOffset * index, + 76 + ); + index++; + } + } + } + + private String getTimeSinceString(JsonObject profileInfo, String path) { + JsonElement lastSaveElement = Utils.getElement(profileInfo, path); + + if (lastSaveElement != null && lastSaveElement.isJsonPrimitive()) { + Instant lastSave = Instant.ofEpochMilli(lastSaveElement.getAsLong()); + LocalDateTime lastSaveTime = LocalDateTime.ofInstant(lastSave, TimeZone.getDefault().toZoneId()); + long timeDiff = System.currentTimeMillis() - lastSave.toEpochMilli(); + LocalDateTime sinceOnline = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeDiff), ZoneId.of("UTC")); + String renderText; + + if (timeDiff < 60000L) { + renderText = sinceOnline.getSecond() + " seconds ago."; + } else if (timeDiff < 3600000L) { + renderText = sinceOnline.getMinute() + " minutes ago."; + } else if (timeDiff < 86400000L) { + renderText = sinceOnline.getHour() + " hours ago."; + } else if (timeDiff < 31556952000L) { + renderText = sinceOnline.getDayOfYear() + " days ago."; + } else { + renderText = lastSaveTime.format(DateTimeFormatter.ofPattern("dd-MM-yyyy")); + } + return renderText; + } + return null; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java index a21145d1..41396832 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java @@ -19,54 +19,36 @@ package io.github.moulberry.notenoughupdates.profileviewer; -import com.google.common.base.Splitter; -import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import com.mojang.authlib.GameProfile; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.cosmetics.ShaderManager; import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField; +import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay; import io.github.moulberry.notenoughupdates.profileviewer.bestiary.BestiaryPage; -import io.github.moulberry.notenoughupdates.profileviewer.trophy.TrophyFishingPage; -import io.github.moulberry.notenoughupdates.profileviewer.weight.lily.LilyWeight; -import io.github.moulberry.notenoughupdates.profileviewer.weight.senither.SenitherWeight; +import io.github.moulberry.notenoughupdates.profileviewer.trophy.TrophyFishPage; +import io.github.moulberry.notenoughupdates.util.AsyncDependencyLoader; import io.github.moulberry.notenoughupdates.util.Constants; -import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.PronounDB; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityOtherPlayerMP; -import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.client.renderer.entity.RenderManager; -import net.minecraft.client.resources.DefaultPlayerSkin; import net.minecraft.client.shader.Framebuffer; import net.minecraft.client.shader.Shader; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EnumPlayerModelParts; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.JsonToNBT; -import net.minecraft.nbt.NBTException; -import net.minecraft.nbt.NBTTagByteArray; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTTagString; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.Matrix4f; import net.minecraft.util.ResourceLocation; -import org.apache.commons.lang3.text.WordUtils; import org.lwjgl.input.Keyboard; -import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL14; import org.lwjgl.opengl.GL20; @@ -76,42 +58,17 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.text.NumberFormat; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Base64; import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Objects; import java.util.Optional; -import java.util.Set; -import java.util.TimeZone; -import java.util.TreeMap; import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.function.Supplier; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static io.github.moulberry.notenoughupdates.util.Utils.roundToNearestInt; +import java.util.concurrent.CompletableFuture; public class GuiProfileViewer extends GuiScreen { - public static final ResourceLocation pv_basic = new ResourceLocation("notenoughupdates:pv_basic.png"); - public static final ResourceLocation pv_dung = new ResourceLocation("notenoughupdates:pv_dung.png"); - public static final ResourceLocation pv_extra = new ResourceLocation("notenoughupdates:pv_extra.png"); - public static final ResourceLocation pv_mining = new ResourceLocation("notenoughupdates:pv_mining.png"); - public static final ResourceLocation pv_invs = new ResourceLocation("notenoughupdates:pv_invs.png"); - public static final ResourceLocation pv_pets = new ResourceLocation("notenoughupdates:pv_pets.png"); public static final ResourceLocation pv_dropdown = new ResourceLocation("notenoughupdates:pv_dropdown.png"); public static final ResourceLocation pv_bg = new ResourceLocation("notenoughupdates:pv_bg.png"); public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png"); @@ -123,164 +80,107 @@ public class GuiProfileViewer extends GuiScreen { new ResourceLocation("minecraft:textures/gui/resource_packs.png"); public static final ResourceLocation icons = new ResourceLocation("textures/gui/icons.png"); public static final HashMap<String, HashMap<String, Float>> PET_STAT_BOOSTS = - new HashMap<String, HashMap<String, Float>>() {{ - put("PET_ITEM_BIG_TEETH_COMMON", new HashMap<String, Float>() {{ - put("CRIT_CHANCE", 5f); - }}); - put("PET_ITEM_HARDENED_SCALES_UNCOMMON", new HashMap<String, Float>() {{ - put("DEFENCE", 25f); - }}); - put("PET_ITEM_LUCKY_CLOVER", new HashMap<String, Float>() {{ - put("MAGIC_FIND", 7f); - }}); - put("PET_ITEM_SHARPENED_CLAWS_UNCOMMON", new HashMap<String, Float>() {{ - put("CRIT_DAMAGE", 15f); - }}); - }}; + new HashMap<String, HashMap<String, Float>>() { + { + put( + "PET_ITEM_BIG_TEETH_COMMON", + new HashMap<String, Float>() { + { + put("CRIT_CHANCE", 5f); + } + } + ); + put( + "PET_ITEM_HARDENED_SCALES_UNCOMMON", + new HashMap<String, Float>() { + { + put("DEFENCE", 25f); + } + } + ); + put( + "PET_ITEM_LUCKY_CLOVER", + new HashMap<String, Float>() { + { + put("MAGIC_FIND", 7f); + } + } + ); + put( + "PET_ITEM_SHARPENED_CLAWS_UNCOMMON", + new HashMap<String, Float>() { + { + put("CRIT_DAMAGE", 15f); + } + } + ); + } + }; public static final HashMap<String, HashMap<String, Float>> PET_STAT_BOOSTS_MULT = - new HashMap<String, HashMap<String, Float>>() {{ - put("PET_ITEM_IRON_CLAWS_COMMON", new HashMap<String, Float>() {{ - put("CRIT_DAMAGE", 1.4f); - put("CRIT_CHANCE", 1.4f); - }}); - put("PET_ITEM_TEXTBOOK", new HashMap<String, Float>() {{ - put("INTELLIGENCE", 2f); - }}); - }}; - private static final ResourceLocation CHEST_GUI_TEXTURE = - new ResourceLocation("textures/gui/container/generic_54.png"); - private static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US); - private static final ItemStack DEADBUSH = new ItemStack(Item.getItemFromBlock(Blocks.deadbush)); - private static final ItemStack iron_pick = new ItemStack(Items.iron_pickaxe); - private static final ItemStack[] BOSS_HEADS = new ItemStack[7]; - private static final String[] dungSkillsName = {"Healer", "Mage", "Berserk", "Archer", "Tank"}; - private static final ItemStack[] dungSkillsStack = { - new ItemStack(Items.potionitem, 1, 16389), - new ItemStack(Items.blaze_rod), - new ItemStack(Items.iron_sword), - new ItemStack(Items.bow), - new ItemStack(Items.leather_chestplate) - }; - private static final String[] bossFloorArr = {"Bonzo", "Scarf", "Professor", "Thorn", "Livid", "Sadan", "Necron"}; - private static final String[] bossFloorHeads = { - "12716ecbf5b8da00b05f316ec6af61e8bd02805b21eb8e440151468dc656549c", - "7de7bbbdf22bfe17980d4e20687e386f11d59ee1db6f8b4762391b79a5ac532d", - "9971cee8b833a62fc2a612f3503437fdf93cad692d216b8cf90bbb0538c47dd8", - "8b6a72138d69fbbd2fea3fa251cabd87152e4f1c97e5f986bf685571db3cc0", - "c1007c5b7114abec734206d4fc613da4f3a0e99f71ff949cedadc99079135a0b", - "fa06cb0c471c1c9bc169af270cd466ea701946776056e472ecdaeb49f0f4a4dc", - "a435164c05cea299a3f016bbbed05706ebb720dac912ce4351c2296626aecd9a" - }; - private static final LinkedHashMap<String, ItemStack> dungeonsModeIcons = new LinkedHashMap<String, ItemStack>() {{ - put( - "catacombs", - Utils.editItemStackInfo(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("DUNGEON_STONE")), EnumChatFormatting.GRAY + "Normal Mode", true) - ); - put( - "master_catacombs", - Utils.editItemStackInfo(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("MASTER_SKULL_TIER_7")), EnumChatFormatting.GRAY + "Master Mode", true) - ); - }}; - private static final LinkedHashMap<String, ItemStack> invNameToDisplayMap = new LinkedHashMap<String, ItemStack>() {{ - put( - "inv_contents", - Utils.createItemStack(Item.getItemFromBlock(Blocks.chest), EnumChatFormatting.GRAY + "Inventory") - ); - put( - "ender_chest_contents", - Utils.createItemStack(Item.getItemFromBlock(Blocks.ender_chest), EnumChatFormatting.GRAY + "Ender Chest") - ); - // put("backpack_contents", Utils.createItemStack(Item.getItemFromBlock(Blocks.dropper), EnumChatFormatting.GRAY+"Backpacks")); - put( - "backpack_contents", - Utils.editItemStackInfo(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("JUMBO_BACKPACK")), EnumChatFormatting.GRAY + "Backpacks", true) - ); - put( - "personal_vault_contents", - Utils.editItemStackInfo(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("IRON_CHEST")), EnumChatFormatting.GRAY + "Personal Vault", true) - ); - put("talisman_bag", Utils.createItemStack(Items.golden_apple, EnumChatFormatting.GRAY + "Accessory Bag")); - put("wardrobe_contents", Utils.createItemStack(Items.leather_chestplate, EnumChatFormatting.GRAY + "Wardrobe")); - put("fishing_bag", Utils.createItemStack(Items.fish, EnumChatFormatting.GRAY + "Fishing Bag")); - put("potion_bag", Utils.createItemStack(Items.potionitem, EnumChatFormatting.GRAY + "Potion Bag")); - }}; - private static final Pattern DAMAGE_PATTERN = Pattern.compile("^Damage: \\+([0-9]+)"); - private static final Pattern STRENGTH_PATTERN = Pattern.compile("^Strength: \\+([0-9]+)"); - private static final Pattern FISHSPEED_PATTERN = Pattern.compile("^Increases fishing speed by \\+([0-9]+)"); + new HashMap<String, HashMap<String, Float>>() { + { + put( + "PET_ITEM_IRON_CLAWS_COMMON", + new HashMap<String, Float>() { + { + put("CRIT_DAMAGE", 1.4f); + put("CRIT_CHANCE", 1.4f); + } + } + ); + put( + "PET_ITEM_TEXTBOOK", + new HashMap<String, Float>() { + { + put("INTELLIGENCE", 2f); + } + } + ); + } + }; + + public static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US); + private static final char[] c = new char[]{'k', 'm', 'b', 't'}; - private static final ExecutorService profileLoader = Executors.newFixedThreadPool(1); public static ProfileViewerPage currentPage = ProfileViewerPage.BASIC; - public static HashMap<String, String> MINION_RARITY_TO_NUM = new HashMap<String, String>() {{ - put("COMMON", "0"); - put("UNCOMMON", "1"); - put("RARE", "2"); - put("EPIC", "3"); - put("LEGENDARY", "4"); - put("MYTHIC", "5"); - }}; - private static int floorTime = 7; + public static HashMap<String, String> MINION_RARITY_TO_NUM = new HashMap<String, String>() { + { + put("COMMON", "0"); + put("UNCOMMON", "1"); + put("RARE", "2"); + put("EPIC", "3"); + put("LEGENDARY", "4"); + put("MYTHIC", "5"); + } + }; private static int guiLeft; private static int guiTop; private static ProfileViewer.Profile profile; - private final GuiElementTextField playerNameTextField; - private final HashMap<String, ProfileViewer.Level> levelObjCatas = new HashMap<>(); - private final HashMap<String, ProfileViewer.Level> levelObjhotms = new HashMap<>(); - private final HashMap<String, HashMap<String, ProfileViewer.Level>> levelObjClasseses = new HashMap<>(); - private final GuiElementTextField dungeonLevelTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT); - - private final int COLLS_XCOUNT = 5; - private final int COLLS_YCOUNT = 4; - private final float COLLS_XPADDING = (190 - COLLS_XCOUNT * 20) / (float) (COLLS_XCOUNT + 1); - private final float COLLS_YPADDING = (202 - COLLS_YCOUNT * 20) / (float) (COLLS_YCOUNT + 1); - private final ItemStack fillerStack = new ItemStack(Item.getItemFromBlock(Blocks.stained_glass_pane), 1, 15); - private final GuiElementTextField inventoryTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT); - private final HashMap<String, ResourceLocation[]> panoramasMap = new HashMap<>(); + private static String profileId = null; + public static AsyncDependencyLoader<Optional<PronounDB.PronounChoice>> pronouns = + AsyncDependencyLoader.withEqualsInvocation( + () -> + NotEnoughUpdates.INSTANCE.config.profileViewer.showPronounsInPv + ? Optional.ofNullable(profile).map(it -> Utils.parseDashlessUUID(it.getUuid())) + : Optional.<UUID>empty(), + uuid -> CompletableFuture.supplyAsync(() -> uuid.flatMap(PronounDB::getPronounsFor)) + ); + public final GuiElementTextField playerNameTextField; + public final GuiElementTextField inventoryTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT); + private final Map<ProfileViewerPage, GuiProfileViewerPage> pages = new HashMap<>(); + public int sizeX; + public int sizeY; + public float backgroundRotation = 0; + public long currentTime = 0; + public long lastTime = 0; + public long startTime = 0; + public List<String> tooltipToDisplay = null; Shader blurShaderHorz = null; Framebuffer blurOutputHorz = null; Shader blurShaderVert = null; Framebuffer blurOutputVert = null; - private int sizeX; - private int sizeY; - private float backgroundRotation = 0; - private long currentTime = 0; - private long lastTime = 0; - private long startTime = 0; - private List<String> tooltipToDisplay = null; - private static String profileId = null; private boolean profileDropdownSelected = false; - private int floorLevelTo = -1; - private long floorLevelToXP = -1; - private boolean onMasterMode = false; - private int selectedPet = -1; - private int petsPage = 0; - private List<JsonObject> sortedPets = null; - private List<ItemStack> sortedPetsStack = null; - private ItemStack[] bestWeapons = null; - private ItemStack[] bestRods = null; - private ItemStack[] armorItems = null; - private ItemStack[] equipmentItems = null; - private HashMap<String, ItemStack[][][]> inventoryItems = new HashMap<>(); - private String selectedInventory = "inv_contents"; - private int currentInventoryIndex = 0; - private int arrowCount = -1; - private int greenCandyCount = -1; - private int purpleCandyCount = -1; - private EntityOtherPlayerMP entityPlayer = null; - private ResourceLocation playerLocationSkin = null; - private ResourceLocation playerLocationCape = null; - private String skinType = null; - private TreeMap<Integer, Set<String>> topKills = null; - private TreeMap<Integer, Set<String>> topDeaths = null; - private int backgroundClickedX = -1; - private boolean loadingProfile = false; + private double lastBgBlurFactor = -1; private boolean showBingoPage; @@ -291,114 +191,93 @@ public class GuiProfileViewer extends GuiScreen { if (profile.getHypixelProfile() != null) { name = profile.getHypixelProfile().get("displayname").getAsString(); } - playerNameTextField = new GuiElementTextField( - name, - GuiElementTextField.SCALE_TEXT - ); + playerNameTextField = new GuiElementTextField(name, GuiElementTextField.SCALE_TEXT); playerNameTextField.setSize(100, 20); if (currentPage == ProfileViewerPage.LOADING) { currentPage = ProfileViewerPage.BASIC; } + + pages.put(ProfileViewerPage.BASIC, new BasicPage(this)); + pages.put(ProfileViewerPage.DUNGEON, new DungeonPage(this)); + pages.put(ProfileViewerPage.EXTRA, new ExtraPage(this)); + pages.put(ProfileViewerPage.INVENTORIES, new InventoriesPage(this)); + pages.put(ProfileViewerPage.COLLECTIONS, new CollectionsPage(this)); + pages.put(ProfileViewerPage.PETS, new PetsPage(this)); + pages.put(ProfileViewerPage.MINING, new MiningPage(this)); + pages.put(ProfileViewerPage.BINGO, new BingoPage(this)); + pages.put(ProfileViewerPage.TROPHY_FISH, new TrophyFishPage(this)); + pages.put(ProfileViewerPage.BESTIARY, new BestiaryPage(this)); } - private static JsonObject getPetInfo(String pet_name, String rarity) { - JsonObject petInfo = new JsonObject(); + private static float getMaxLevelXp(JsonArray levels, int offset, int maxLevel) { + float xpTotal = 0; - if (Constants.PETS == null) { - Utils.showOutdatedRepoNotification(); - return null; + for (int i = offset; i < offset + maxLevel - 1; i++) { + xpTotal += levels.get(i).getAsFloat(); } - if (Constants.PETS.has("custom_pet_leveling") && - Constants.PETS.getAsJsonObject("custom_pet_leveling").has(pet_name)) { - JsonObject pet = Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(pet_name); - if (pet.has("type") && pet.has("pet_levels")) { - int type = pet.get("type").getAsInt(); - switch (type) { - case 1: - JsonArray defaultLevels = Constants.PETS.getAsJsonArray("pet_levels"); - defaultLevels.addAll(pet.getAsJsonArray("pet_levels")); - petInfo.add("pet_levels", Constants.PETS.getAsJsonArray("pet_levels")); - break; - case 2: - petInfo.add("pet_levels", pet.getAsJsonArray("pet_levels")); - break; - default: - petInfo.add("pet_levels", Constants.PETS.getAsJsonArray("pet_levels")); - break; - } - } else { - petInfo.add("pet_levels", Constants.PETS.getAsJsonArray("pet_levels")); - } - if (pet.has("max_level")) { - petInfo.add("max_level", pet.get("max_level")); - } else { - petInfo.add("max_level", new JsonPrimitive(100)); - } + return xpTotal; + } - if (pet.has("pet_rarity_offset")) { - petInfo.add("offset", pet.get("pet_rarity_offset")); - } else { - petInfo.add("offset", Constants.PETS.getAsJsonObject("pet_rarity_offset").get(rarity)); + public static PetLevel getPetLevel( + String petType, + String rarity, + float exp + ) { + int offset = PetInfoOverlay.Rarity.valueOf(rarity).petOffset; + int maxLevel = 100; + + JsonArray levels = new JsonArray(); + levels.addAll(Constants.PETS.get("pet_levels").getAsJsonArray()); + JsonElement customLevelingJson = Constants.PETS.get("custom_pet_leveling").getAsJsonObject().get(petType); + if (customLevelingJson != null) { + switch (Utils.getElementAsInt(Utils.getElement(customLevelingJson, "type"), 0)) { + case 1: + levels.addAll(customLevelingJson.getAsJsonObject().get("pet_levels").getAsJsonArray()); + break; + case 2: + levels = customLevelingJson.getAsJsonObject().get("pet_levels").getAsJsonArray(); + break; } - - } else { - //System.out.println("Default Path"); - petInfo.add("offset", Constants.PETS.getAsJsonObject("pet_rarity_offset").get(rarity)); - petInfo.add("max_level", new JsonPrimitive(100)); - petInfo.add("pet_levels", Constants.PETS.getAsJsonArray("pet_levels")); + maxLevel = Utils.getElementAsInt(Utils.getElement(customLevelingJson, "max_level"), 100); } - return petInfo; + float maxXP = getMaxLevelXp(levels, offset, maxLevel); + boolean isMaxed = exp >= maxXP; - } - - public static PetLevel getPetLevel(String pet_name, String rarity, float exp) { - JsonObject petInfo = getPetInfo(pet_name, rarity); - if (petInfo == null) { - return null; - } - int offset = petInfo.get("offset").getAsInt(); - int maxPetLevel = petInfo.get("max_level").getAsInt(); - JsonArray levels = petInfo.getAsJsonArray("pet_levels"); - - float xpTotal = 0; - float level = 1; + int level = 1; float currentLevelRequirement = 0; - float currentLevelProgress = 0; - - boolean addLevel = true; - - for (int i = offset; i < offset + maxPetLevel - 1; i++) { - if (addLevel) { - currentLevelRequirement = levels.get(i).getAsFloat(); - xpTotal += currentLevelRequirement; - if (xpTotal > exp) { - currentLevelProgress = (exp - (xpTotal - currentLevelRequirement)); - addLevel = false; - } else { - level += 1; + float xpThisLevel = 0; + float pct = 0; + + if (isMaxed) { + level = maxLevel; + currentLevelRequirement = levels.get(offset + level - 2).getAsFloat(); + xpThisLevel = currentLevelRequirement; + pct = 1; + } else { + long totalExp = 0; + for (int i = offset; i < levels.size(); i++) { + currentLevelRequirement = levels.get(i).getAsLong(); + totalExp += currentLevelRequirement; + if (totalExp >= exp) { + xpThisLevel = currentLevelRequirement - (totalExp - exp); + level = Math.min(i - offset + 1, maxLevel); + break; } - } else { - - xpTotal += levels.get(i).getAsFloat(); - } + pct = currentLevelRequirement != 0 ? xpThisLevel / currentLevelRequirement : 0; + level += pct; } - level += currentLevelProgress / currentLevelRequirement; - if (level <= 0) { - level = 1; - } else if (level > maxPetLevel) { - level = maxPetLevel; - } - PetLevel levelObj = new PetLevel(); + GuiProfileViewer.PetLevel levelObj = new GuiProfileViewer.PetLevel(); levelObj.level = level; + levelObj.maxLevel = maxLevel; levelObj.currentLevelRequirement = currentLevelRequirement; - levelObj.maxXP = xpTotal; - levelObj.levelPercentage = currentLevelProgress / currentLevelRequirement; - levelObj.levelXp = currentLevelProgress; + levelObj.maxXP = maxXP; + levelObj.levelPercentage = pct; + levelObj.levelXp = xpThisLevel; levelObj.totalXp = exp; return levelObj; } @@ -414,56 +293,10 @@ public class GuiProfileViewer extends GuiScreen { double d = ((long) n / 100) / 10.0; boolean isRound = (d * 10) % 10 == 0; - return (d < 1000 ? - ((d > 99.9 || isRound || (!isRound && d > 9.99) ? - (int) d * 10 / 10 : d + "" - ) + "" + c[iteration]) - : shortNumberFormat(d, iteration + 1)); - } - - public static void drawEntityOnScreen( - int posX, - int posY, - int scale, - float mouseX, - float mouseY, - EntityLivingBase ent - ) { - GlStateManager.enableColorMaterial(); - GlStateManager.pushMatrix(); - GlStateManager.translate((float) posX, (float) posY, 50.0F); - GlStateManager.scale((float) (-scale), (float) scale, (float) scale); - GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F); - float renderYawOffset = ent.renderYawOffset; - float f1 = ent.rotationYaw; - float f2 = ent.rotationPitch; - float f3 = ent.prevRotationYawHead; - float f4 = ent.rotationYawHead; - GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F); - RenderHelper.enableStandardItemLighting(); - GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F); - GlStateManager.rotate(25, 1.0F, 0.0F, 0.0F); - ent.renderYawOffset = (float) Math.atan(mouseX / 40.0F) * 20.0F; - ent.rotationYaw = (float) Math.atan(mouseX / 40.0F) * 40.0F; - ent.rotationPitch = -((float) Math.atan(mouseY / 40.0F)) * 20.0F; - ent.rotationYawHead = ent.rotationYaw; - ent.prevRotationYawHead = ent.rotationYaw; - RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager(); - rendermanager.setPlayerViewY(180.0F); - rendermanager.setRenderShadow(false); - rendermanager.renderEntityWithPosYaw(ent, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F); - - ent.renderYawOffset = renderYawOffset; - ent.rotationYaw = f1; - ent.rotationPitch = f2; - ent.prevRotationYawHead = f3; - ent.rotationYawHead = f4; - GlStateManager.popMatrix(); - RenderHelper.disableStandardItemLighting(); - GlStateManager.disableRescaleNormal(); - GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); - GlStateManager.disableTexture2D(); - GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); + return d < 1000 ? (isRound || d > 9.99 ? (int) d * 10 / 10 : d + "") + "" + c[iteration] : shortNumberFormat( + d, + iteration + 1 + ); } public static int getGuiLeft() { @@ -490,7 +323,7 @@ public class GuiProfileViewer extends GuiScreen { ProfileViewerPage page = currentPage; if (profile == null) { page = ProfileViewerPage.INVALID_NAME; - } else if (profile.getPlayerInformation(null) == null) { + } else if (profile.getSkyblockProfiles(null) == null) { page = ProfileViewerPage.LOADING; } else if (profile.getLatestProfile() == null) { page = ProfileViewerPage.NO_SKYBLOCK; @@ -502,30 +335,26 @@ public class GuiProfileViewer extends GuiScreen { { //this is just to cache the guild info if (profile != null) { - profile.getGuildInfo(null); + profile.getGuildInformation(null); } } this.sizeX = 431; this.sizeY = 202; - this.guiLeft = (this.width - this.sizeX) / 2; - this.guiTop = (this.height - this.sizeY) / 2; + guiLeft = (this.width - this.sizeX) / 2; + guiTop = (this.height - this.sizeY) / 2; - boolean bingo = false; JsonObject currProfileInfo = profile != null ? profile.getProfileInformation(profileId) : null; if (NotEnoughUpdates.INSTANCE.config.profileViewer.alwaysShowBingoTab) { showBingoPage = true; } else { - if (currProfileInfo != null && currProfileInfo.has("game_mode") && - currProfileInfo.get("game_mode").getAsString().equals("bingo")) { - showBingoPage = true; - } else { - showBingoPage = false; - } + showBingoPage = + currProfileInfo != null && + currProfileInfo.has("game_mode") && + currProfileInfo.get("game_mode").getAsString().equals("bingo"); } - if (!showBingoPage && currentPage == ProfileViewerPage.BINGO) - currentPage = ProfileViewerPage.BASIC; + if (!showBingoPage && currentPage == ProfileViewerPage.BINGO) currentPage = ProfileViewerPage.BASIC; super.drawScreen(mouseX, mouseY, partialTicks); drawDefaultBackground(); @@ -561,38 +390,54 @@ public class GuiProfileViewer extends GuiScreen { //Render Profile chooser button renderBlurredBackground(width, height, guiLeft + 2, guiTop + sizeY + 3 + 2, 100 - 4, 20 - 4); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown); - Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 3, 100, 20, - 0, 100 / 200f, 0, 20 / 185f, GL11.GL_NEAREST - ); - Utils.drawStringCenteredScaledMaxWidth(profileId, Minecraft.getMinecraft().fontRendererObj, guiLeft + 50, - guiTop + sizeY + 3 + 10, true, 90, new Color(63, 224, 208, 255).getRGB() + Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 3, 100, 20, 0, 100 / 200f, 0, 20 / 185f, GL11.GL_NEAREST); + Utils.drawStringCenteredScaledMaxWidth( + profileId, + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 50, + guiTop + sizeY + 3 + 10, + true, + 90, + new Color(63, 224, 208, 255).getRGB() ); //ironman icon - if (currProfileInfo != null && currProfileInfo.has("game_mode") && - currProfileInfo.get("game_mode").getAsString().equals("ironman")) { + if ( + currProfileInfo != null && + currProfileInfo.has("game_mode") && + currProfileInfo.get("game_mode").getAsString().equals("ironman") + ) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_ironman); Utils.drawTexturedRect(guiLeft - 16 - 5, guiTop + sizeY + 5, 16, 16, GL11.GL_NEAREST); } //bingo! icon - if (currProfileInfo != null && currProfileInfo.has("game_mode") && - currProfileInfo.get("game_mode").getAsString().equals("bingo")) { + if ( + currProfileInfo != null && + currProfileInfo.has("game_mode") && + currProfileInfo.get("game_mode").getAsString().equals("bingo") + ) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_bingo); Utils.drawTexturedRect(guiLeft - 16 - 5, guiTop + sizeY + 5, 16, 16, GL11.GL_NEAREST); } //stranded icon - if (currProfileInfo != null && currProfileInfo.has("game_mode") && - currProfileInfo.get("game_mode").getAsString().equals("island")) { + if ( + currProfileInfo != null && + currProfileInfo.has("game_mode") && + currProfileInfo.get("game_mode").getAsString().equals("island") + ) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_stranded); Utils.drawTexturedRect(guiLeft - 16 - 5, guiTop + sizeY + 5, 16, 16, GL11.GL_NEAREST); } //icon if game mode is unknown - if (currProfileInfo != null && currProfileInfo.has("game_mode") && - !currProfileInfo.get("game_mode").getAsString().equals("island") && - !currProfileInfo.get("game_mode").getAsString().equals("bingo") && - !currProfileInfo.get("game_mode").getAsString().equals("ironman")) { + if ( + currProfileInfo != null && + currProfileInfo.has("game_mode") && + !currProfileInfo.get("game_mode").getAsString().equals("island") && + !currProfileInfo.get("game_mode").getAsString().equals("bingo") && + !currProfileInfo.get("game_mode").getAsString().equals("ironman") + ) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_unknown); Utils.drawTexturedRect(guiLeft - 16 - 5, guiTop + sizeY + 5, 16, 16, GL11.GL_NEAREST); @@ -600,8 +445,16 @@ public class GuiProfileViewer extends GuiScreen { //Render Open In Skycrypt button renderBlurredBackground(width, height, guiLeft + 100 + 6 + 2, guiTop + sizeY + 3 + 2, 100 - 4, 20 - 4); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown); - Utils.drawTexturedRect(guiLeft + 100 + 6, guiTop + sizeY + 3, 100, 20, - 0, 100 / 200f, 0, 20 / 185f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft + 100 + 6, + guiTop + sizeY + 3, + 100, + 20, + 0, + 100 / 200f, + 0, + 20 / 185f, + GL11.GL_NEAREST ); Utils.drawStringCenteredScaledMaxWidth( "Open in Skycrypt", @@ -613,25 +466,39 @@ public class GuiProfileViewer extends GuiScreen { new Color(63, 224, 208, 255).getRGB() ); - if (profileDropdownSelected && !profile.getProfileIds().isEmpty() && scaledResolution.getScaleFactor() != 4) { + if (profileDropdownSelected && !profile.getProfileNames().isEmpty() && scaledResolution.getScaleFactor() != 4) { int dropdownOptionSize = scaledResolution.getScaleFactor() == 3 ? 10 : 20; - int numProfiles = profile.getProfileIds().size(); + int numProfiles = profile.getProfileNames().size(); int sizeYDropdown = numProfiles * dropdownOptionSize; renderBlurredBackground(width, height, guiLeft + 2, guiTop + sizeY + 23, 100 - 4, sizeYDropdown - 2); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown); - Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 23 - 3, 100, 3, - 100 / 200f, 1, 0, 3 / 185f, GL11.GL_NEAREST - ); - Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 23 + sizeYDropdown - 4, 100, 4, - 100 / 200f, 1, 181 / 185f, 1, GL11.GL_NEAREST + Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 23 - 3, 100, 3, 100 / 200f, 1, 0, 3 / 185f, GL11.GL_NEAREST); + Utils.drawTexturedRect( + guiLeft, + guiTop + sizeY + 23 + sizeYDropdown - 4, + 100, + 4, + 100 / 200f, + 1, + 181 / 185f, + 1, + GL11.GL_NEAREST ); - Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 23, 100, sizeYDropdown - 4, - 100 / 200f, 1, (181 - sizeYDropdown) / 185f, 181 / 185f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft, + guiTop + sizeY + 23, + 100, + sizeYDropdown - 4, + 100 / 200f, + 1, + (181 - sizeYDropdown) / 185f, + 181 / 185f, + GL11.GL_NEAREST ); - for (int yIndex = 0; yIndex < profile.getProfileIds().size(); yIndex++) { - String otherProfileId = profile.getProfileIds().get(yIndex); + for (int yIndex = 0; yIndex < profile.getProfileNames().size(); yIndex++) { + String otherProfileId = profile.getProfileNames().get(yIndex); Utils.drawStringCenteredScaledMaxWidth( otherProfileId, Minecraft.getMinecraft().fontRendererObj, @@ -642,8 +509,11 @@ public class GuiProfileViewer extends GuiScreen { new Color(33, 112, 104, 255).getRGB() ); currProfileInfo = profile.getProfileInformation(otherProfileId); - if (currProfileInfo != null && currProfileInfo.has("game_mode") && - currProfileInfo.get("game_mode").getAsString().equals("ironman")) { + if ( + currProfileInfo != null && + currProfileInfo.has("game_mode") && + currProfileInfo.get("game_mode").getAsString().equals("ironman") + ) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_ironman); Utils.drawTexturedRect( @@ -654,8 +524,11 @@ public class GuiProfileViewer extends GuiScreen { GL11.GL_NEAREST ); } - if (currProfileInfo != null && currProfileInfo.has("game_mode") && - currProfileInfo.get("game_mode").getAsString().equals("bingo")) { + if ( + currProfileInfo != null && + currProfileInfo.has("game_mode") && + currProfileInfo.get("game_mode").getAsString().equals("bingo") + ) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_bingo); Utils.drawTexturedRect( @@ -666,8 +539,11 @@ public class GuiProfileViewer extends GuiScreen { GL11.GL_NEAREST ); } - if (currProfileInfo != null && currProfileInfo.has("game_mode") && - currProfileInfo.get("game_mode").getAsString().equals("island")) { + if ( + currProfileInfo != null && + currProfileInfo.has("game_mode") && + currProfileInfo.get("game_mode").getAsString().equals("island") + ) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_stranded); Utils.drawTexturedRect( @@ -678,10 +554,13 @@ public class GuiProfileViewer extends GuiScreen { GL11.GL_NEAREST ); } - if (currProfileInfo != null && currProfileInfo.has("game_mode") && - !currProfileInfo.get("game_mode").getAsString().equals("island") && - !currProfileInfo.get("game_mode").getAsString().equals("bingo") && - !currProfileInfo.get("game_mode").getAsString().equals("ironman")) { + if ( + currProfileInfo != null && + currProfileInfo.has("game_mode") && + !currProfileInfo.get("game_mode").getAsString().equals("island") && + !currProfileInfo.get("game_mode").getAsString().equals("bingo") && + !currProfileInfo.get("game_mode").getAsString().equals("ironman") + ) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_unknown); Utils.drawTexturedRect( @@ -693,172 +572,156 @@ public class GuiProfileViewer extends GuiScreen { ); } } - } } } GlStateManager.color(1, 1, 1, 1); - switch (page) { - case BASIC: - drawBasicPage(mouseX, mouseY, partialTicks); - break; - case DUNGEON: - drawDungPage(mouseX, mouseY, partialTicks); - break; - case EXTRA: - drawExtraPage(mouseX, mouseY, partialTicks); - break; - case INVENTORIES: - drawInvsPage(mouseX, mouseY); - break; - case COLLECTIONS: - CollectionPage.drawColsPage(mouseX, mouseY, width, height); - break; - case PETS: - drawPetsPage(mouseX, mouseY, partialTicks); - break; - case MINING: - drawMiningPage(mouseX, mouseY, partialTicks); - break; - case BINGO: - BingoPage.renderPage(mouseX, mouseY); - break; - case TROPHY_FISH: - TrophyFishingPage.renderPage(mouseX, mouseY); - break; - case BESTIARY: - BestiaryPage.renderPage(mouseX, mouseY); - break; - case LOADING: - String str = EnumChatFormatting.YELLOW + "Loading player profiles."; - long currentTimeMod = System.currentTimeMillis() % 1000; - if (currentTimeMod > 333) { - if (currentTimeMod < 666) { - str += "."; - } else { - str += ".."; - } - } - Utils.drawStringCentered(str, Minecraft.getMinecraft().fontRendererObj, - guiLeft + sizeX / 2f, guiTop + 101, true, 0 - ); - - //This is just here to inform the player what to do - //like typing /api new or telling them to go find a psychotherapist - long timeDiff = System.currentTimeMillis() - startTime; + if (pages.containsKey(page)) { + pages.get(page).drawPage(mouseX, mouseY, partialTicks); + } else { + switch (page) { + case LOADING: + String str = EnumChatFormatting.YELLOW + "Loading player profiles."; + long currentTimeMod = System.currentTimeMillis() % 1000; + if (currentTimeMod > 333) { + if (currentTimeMod < 666) { + str += "."; + } else { + str += ".."; + } + } - if (timeDiff > 20000) { - Utils.drawStringCentered( - EnumChatFormatting.YELLOW + "Its taking a while...", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + sizeX / 2f, - guiTop + 111, - true, - 0 - ); Utils.drawStringCentered( - EnumChatFormatting.YELLOW + "Try \"/api new\".", + str, Minecraft.getMinecraft().fontRendererObj, guiLeft + sizeX / 2f, - guiTop + 121, + guiTop + 101, true, 0 ); - if (timeDiff > 60000) { + + //This is just here to inform the player what to do + //like typing /api new or telling them to go find a psychotherapist + long timeDiff = System.currentTimeMillis() - startTime; + + if (timeDiff > 20000) { Utils.drawStringCentered( - EnumChatFormatting.YELLOW + "Might be hypixel's fault.", + EnumChatFormatting.YELLOW + "Its taking a while...", Minecraft.getMinecraft().fontRendererObj, guiLeft + sizeX / 2f, - guiTop + 131, + guiTop + 111, true, 0 ); - if (timeDiff > 180000) { + Utils.drawStringCentered( + EnumChatFormatting.YELLOW + "Try \"/api new\".", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + sizeX / 2f, + guiTop + 121, + true, + 0 + ); + if (timeDiff > 60000) { Utils.drawStringCentered( - EnumChatFormatting.YELLOW + "Wow you're still here?", + EnumChatFormatting.YELLOW + "Might be hypixel's fault.", Minecraft.getMinecraft().fontRendererObj, guiLeft + sizeX / 2f, - guiTop + 141, + guiTop + 131, true, 0 ); - if (timeDiff > 360000) { - long second = (timeDiff / 1000) % 60; - long minute = (timeDiff / (1000 * 60)) % 60; - long hour = (timeDiff / (1000 * 60 * 60)) % 24; - - String time = String.format("%02d:%02d:%02d", hour, minute, second); - Utils.drawStringCentered( - EnumChatFormatting.YELLOW + "You've wasted your time here for: " + time, - Minecraft.getMinecraft().fontRendererObj, - guiLeft + sizeX / 2f, - guiTop + 151, - true, - 0 - ); + if (timeDiff > 180000) { Utils.drawStringCentered( - EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "What are you doing with your life?", + EnumChatFormatting.YELLOW + "Wow you're still here?", Minecraft.getMinecraft().fontRendererObj, guiLeft + sizeX / 2f, - guiTop + 161, + guiTop + 141, true, 0 ); - if (timeDiff > 600000) { + if (timeDiff > 360000) { + long second = (timeDiff / 1000) % 60; + long minute = (timeDiff / (1000 * 60)) % 60; + long hour = (timeDiff / (1000 * 60 * 60)) % 24; + + String time = String.format("%02d:%02d:%02d", hour, minute, second); Utils.drawStringCentered( - EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "Maniac", + EnumChatFormatting.YELLOW + "You've wasted your time here for: " + time, Minecraft.getMinecraft().fontRendererObj, guiLeft + sizeX / 2f, - guiTop + 171, + guiTop + 151, true, 0 ); - if (timeDiff > 1200000) { + Utils.drawStringCentered( + EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "What are you doing with your life?", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + sizeX / 2f, + guiTop + 161, + true, + 0 + ); + if (timeDiff > 600000) { Utils.drawStringCentered( - EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "You're a menace to society", + EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "Maniac", Minecraft.getMinecraft().fontRendererObj, guiLeft + sizeX / 2f, - guiTop + 181, + guiTop + 171, true, 0 ); - if (timeDiff > 1800000) { + if (timeDiff > 1200000) { Utils.drawStringCentered( - EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + - "You don't know what's gonna happen to you", + EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "You're a menace to society", Minecraft.getMinecraft().fontRendererObj, guiLeft + sizeX / 2f, - guiTop + 191, + guiTop + 181, true, 0 ); - if (timeDiff > 3000000) { + if (timeDiff > 1800000) { Utils.drawStringCentered( - EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "You really want this?", + EnumChatFormatting.RED + + "" + + EnumChatFormatting.BOLD + + "You don't know what's gonna happen to you", Minecraft.getMinecraft().fontRendererObj, guiLeft + sizeX / 2f, - guiTop + 91, + guiTop + 191, true, 0 ); - if (timeDiff > 3300000) { + if (timeDiff > 3000000) { Utils.drawStringCentered( - EnumChatFormatting.DARK_RED + "" + EnumChatFormatting.BOLD + "OW LORD FORGIVE ME FOR THIS", + EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "You really want this?", Minecraft.getMinecraft().fontRendererObj, guiLeft + sizeX / 2f, - guiTop + 71, + guiTop + 91, true, 0 ); - if (timeDiff > 3600000) { - throw new Error("Go do something productive") { - @Override - public void printStackTrace() { - throw new Error("Go do something productive"); - } - }; + if (timeDiff > 3300000) { + Utils.drawStringCentered( + EnumChatFormatting.DARK_RED + + "" + + EnumChatFormatting.BOLD + + "OW LORD FORGIVE ME FOR THIS", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + sizeX / 2f, + guiTop + 71, + true, + 0 + ); + if (timeDiff > 3600000) { + throw new Error("Go do something productive") { + @Override + public void printStackTrace() { + throw new Error("Go do something productive"); + } + }; + } } } } @@ -868,29 +731,29 @@ public class GuiProfileViewer extends GuiScreen { } } } - } - break; - case INVALID_NAME: - Utils.drawStringCentered( - EnumChatFormatting.RED + "Invalid name or API is down!", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + sizeX / 2f, - guiTop + 101, - true, - 0 - ); - break; - case NO_SKYBLOCK: - Utils.drawStringCentered( - EnumChatFormatting.RED + "No skyblock data found!", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + sizeX / 2f, - guiTop + 101, - true, - 0 - ); - break; + break; + case INVALID_NAME: + Utils.drawStringCentered( + EnumChatFormatting.RED + "Invalid name or API is down!", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + sizeX / 2f, + guiTop + 101, + true, + 0 + ); + break; + case NO_SKYBLOCK: + Utils.drawStringCentered( + EnumChatFormatting.RED + "No skyblock data found!", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + sizeX / 2f, + guiTop + 101, + true, + 0 + ); + break; + } } lastTime = currentTime; @@ -990,38 +853,13 @@ public class GuiProfileViewer extends GuiScreen { } } } - switch (currentPage) { - case DUNGEON: - mouseClickedDung(mouseX, mouseY, mouseButton); - break; - case INVENTORIES: - inventoryTextField.setSize(88, 20); - if (mouseX > guiLeft + 19 && mouseX < guiLeft + 19 + 88) { - if (mouseY > guiTop + sizeY - 26 - 20 && mouseY < guiTop + sizeY - 26) { - inventoryTextField.mouseClicked(mouseX, mouseY, mouseButton); - playerNameTextField.otherComponentClick(); - return; - } - } - break; - case PETS: - if (sortedPets == null) break; - 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; - if (mouseX > guiLeft + x && mouseX < guiLeft + x + 20) { - if (mouseY > guiTop + y && mouseY < guiTop + y + 20) { - selectedPet = i; - return; - } - } - } - break; + if (pages.containsKey(currentPage)) { + if (pages.get(currentPage).mouseClicked(mouseX, mouseY, mouseButton)) { + return; + } } + if (mouseX > guiLeft + sizeX - 100 && mouseX < guiLeft + sizeX) { if (mouseY > guiTop + sizeY + 5 && mouseY < guiTop + sizeY + 25) { playerNameTextField.mouseClicked(mouseX, mouseY, mouseButton); @@ -1029,14 +867,22 @@ public class GuiProfileViewer extends GuiScreen { return; } } - if (mouseX > guiLeft + 106 && mouseX < guiLeft + 106 + 100 && profile != null && - !profile.getProfileIds().isEmpty() && profileId != null) { + if ( + mouseX > guiLeft + 106 && + mouseX < guiLeft + 106 + 100 && + profile != null && + !profile.getProfileNames().isEmpty() && + profileId != null + ) { if (mouseY > guiTop + sizeY + 3 && mouseY < guiTop + sizeY + 23) { try { Desktop desk = Desktop.getDesktop(); - desk.browse(new URI( - "https://sky.shiiyu.moe/stats/" + profile.getHypixelProfile().get("displayname").getAsString() + "/" + - profileId)); + desk.browse( + new URI( + "https://sky.shiiyu.moe/stats/" + profile.getHypixelProfile().get("displayname").getAsString() + "/" + + profileId + ) + ); Utils.playPressSound(); return; } catch (UnsupportedOperationException | IOException | URISyntaxException ignored) { @@ -1047,14 +893,14 @@ public class GuiProfileViewer extends GuiScreen { } } - if (mouseX > guiLeft && mouseX < guiLeft + 100 && profile != null && !profile.getProfileIds().isEmpty()) { + if (mouseX > guiLeft && mouseX < guiLeft + 100 && profile != null && !profile.getProfileNames().isEmpty()) { ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); if (mouseY > guiTop + sizeY + 3 && mouseY < guiTop + sizeY + 23) { if (scaledResolution.getScaleFactor() == 4) { profileDropdownSelected = false; int profileNum = 0; - for (int index = 0; index < profile.getProfileIds().size(); index++) { - if (profile.getProfileIds().get(index).equals(profileId)) { + for (int index = 0; index < profile.getProfileNames().size(); index++) { + if (profile.getProfileNames().get(index).equals(profileId)) { profileNum = index; break; } @@ -1064,10 +910,10 @@ public class GuiProfileViewer extends GuiScreen { } else { profileNum--; } - if (profileNum >= profile.getProfileIds().size()) profileNum = 0; - if (profileNum < 0) profileNum = profile.getProfileIds().size() - 1; + if (profileNum >= profile.getProfileNames().size()) profileNum = 0; + if (profileNum < 0) profileNum = profile.getProfileNames().size() - 1; - String newProfileId = profile.getProfileIds().get(profileNum); + String newProfileId = profile.getProfileNames().get(profileNum); if (profileId != null && !profileId.equals(newProfileId)) { resetCache(); } @@ -1079,8 +925,8 @@ public class GuiProfileViewer extends GuiScreen { int dropdownOptionSize = scaledResolution.getScaleFactor() == 3 ? 10 : 20; int extraY = mouseY - (guiTop + sizeY + 23); int index = extraY / dropdownOptionSize; - if (index >= 0 && index < profile.getProfileIds().size()) { - String newProfileId = profile.getProfileIds().get(index); + if (index >= 0 && index < profile.getProfileNames().size()) { + String newProfileId = profile.getProfileNames().get(index); if (profileId != null && !profileId.equals(newProfileId)) { resetCache(); } @@ -1099,25 +945,21 @@ public class GuiProfileViewer extends GuiScreen { @Override protected void keyTyped(char typedChar, int keyCode) throws IOException { super.keyTyped(typedChar, keyCode); - switch (currentPage) { - case INVENTORIES: - keyTypedInvs(typedChar, keyCode); - inventoryTextField.keyTyped(typedChar, keyCode); - break; - case COLLECTIONS: - CollectionPage.keyTypedCols(typedChar, keyCode); - break; - case DUNGEON: - keyTypedDung(typedChar, keyCode); - break; + + if (pages.containsKey(currentPage)) { + pages.get(currentPage).keyTyped(typedChar, keyCode); } + if (playerNameTextField.getFocus()) { if (keyCode == Keyboard.KEY_RETURN) { currentPage = ProfileViewerPage.LOADING; - NotEnoughUpdates.profileViewer.getProfileByName(playerNameTextField.getText(), profile -> { //todo: invalid name - if (profile != null) profile.resetCache(); - Minecraft.getMinecraft().displayGuiScreen(new GuiProfileViewer(profile)); - }); + NotEnoughUpdates.profileViewer.getProfileByName( + playerNameTextField.getText(), + profile -> { //todo: invalid name + if (profile != null) profile.resetCache(); + Minecraft.getMinecraft().displayGuiScreen(new GuiProfileViewer(profile)); + } + ); } playerNameTextField.keyTyped(typedChar, keyCode); } @@ -1127,799 +969,12 @@ public class GuiProfileViewer extends GuiScreen { protected void mouseReleased(int mouseX, int mouseY, int mouseButton) { super.mouseReleased(mouseX, mouseY, mouseButton); - switch (currentPage) { - case INVENTORIES: - mouseReleasedInvs(mouseX, mouseY, mouseButton); - break; - case COLLECTIONS: - CollectionPage.mouseReleasedCols(mouseX, mouseY, mouseButton); - break; - case PETS: - mouseReleasedPets(mouseX, mouseY, mouseButton); - break; - case BESTIARY: - BestiaryPage.mouseReleased(mouseX, mouseY, mouseButton); - } - } - - protected void mouseClickedDung(int mouseX, int mouseY, int mouseButton) { - if (mouseX >= guiLeft + 50 && mouseX <= guiLeft + 70 && - mouseY >= guiTop + 54 && mouseY <= guiTop + 64) { - dungeonLevelTextField.mouseClicked(mouseX, mouseY, mouseButton); - } else { - dungeonLevelTextField.otherComponentClick(); - } - - int cW = fontRendererObj.getStringWidth("Calculate"); - if (mouseX >= guiLeft + 23 + 110 - 17 - cW && mouseX <= guiLeft + 23 + 110 - 17 && - mouseY >= guiTop + 55 && mouseY <= guiTop + 65) { - calculateFloorLevelXP(); - } - - int y = guiTop + 142; - - if (mouseY >= y - 2 && mouseY <= y + 9) { - for (int i = 1; i <= 7; i++) { - int w = fontRendererObj.getStringWidth("" + i); - - int x = guiLeft + 23 + 110 * i / 8 - w / 2; - - if (mouseX >= x - 2 && mouseX <= x + 7) { - floorTime = i; - return; - } - } - } - if (mouseX >= guiLeft - 29 && mouseX <= guiLeft) { - if (mouseY >= guiTop && mouseY <= guiTop + 28) { - onMasterMode = false; - } else if (mouseY + 28 >= guiTop && mouseY <= guiTop + 28 * 2) { - onMasterMode = true; - } - } - } - - protected void keyTypedDung(char typedChar, int keyCode) { - dungeonLevelTextField.keyTyped(typedChar, keyCode); - } - - protected void keyTypedInvs(char typedChar, int keyCode) throws IOException { - switch (keyCode) { - case Keyboard.KEY_1: - case Keyboard.KEY_NUMPAD1: - selectedInventory = "inv_contents"; - break; - case Keyboard.KEY_2: - case Keyboard.KEY_NUMPAD2: - selectedInventory = "ender_chest_contents"; - break; - case Keyboard.KEY_3: - case Keyboard.KEY_NUMPAD3: - selectedInventory = "backpack_contents"; - break; - case Keyboard.KEY_4: - case Keyboard.KEY_NUMPAD4: - selectedInventory = "personal_vault_contents"; - break; - case Keyboard.KEY_5: - case Keyboard.KEY_NUMPAD5: - selectedInventory = "talisman_bag"; - break; - case Keyboard.KEY_6: - case Keyboard.KEY_NUMPAD6: - selectedInventory = "wardrobe_contents"; - break; - case Keyboard.KEY_7: - case Keyboard.KEY_NUMPAD7: - selectedInventory = "fishing_bag"; - break; - case Keyboard.KEY_8: - case Keyboard.KEY_NUMPAD8: - selectedInventory = "potion_bag"; - break; - default: - return; - - } - Utils.playPressSound(); - } - - - - private void mouseReleasedPets(int mouseX, int mouseY, int mouseButton) { - if (mouseY > guiTop + 6 && mouseY < guiTop + 22) { - if (mouseX > guiLeft + 100 - 15 - 12 && mouseX < guiLeft + 100 - 20) { - if (petsPage > 0) { - petsPage--; - } - return; - } else if (mouseX > guiLeft + 100 + 15 && mouseX < guiLeft + 100 + 20 + 12) { - if (sortedPets != null && petsPage < Math.ceil(sortedPets.size() / 20f) - 1) { - petsPage++; - } - return; - } - } - } - - private void mouseReleasedInvs(int mouseX, int mouseY, int mouseButton) { - if (mouseButton == 0) { - int i = 0; - for (Map.Entry<String, ItemStack> entry : invNameToDisplayMap.entrySet()) { - int xIndex = i % 3; - int yIndex = i / 3; - - int x = guiLeft + 19 + 34 * xIndex; - int y = guiTop + 26 + 34 * yIndex; - - if (mouseX >= x && mouseX <= x + 16) { - if (mouseY >= y && mouseY <= y + 16) { - if (selectedInventory != entry.getKey()) Utils.playPressSound(); - selectedInventory = entry.getKey(); - return; - } - } - - i++; - } - - JsonObject inventoryInfo = profile.getInventoryInfo(profileId); - if (inventoryInfo == null) return; - - ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, selectedInventory); - if (currentInventoryIndex >= inventories.length) currentInventoryIndex = inventories.length - 1; - if (currentInventoryIndex < 0) currentInventoryIndex = 0; - - ItemStack[][] inventory = inventories[currentInventoryIndex]; - if (inventory == null) return; - - int inventoryRows = inventory.length; - int invSizeY = inventoryRows * 18 + 17 + 7; - - int y = guiTop + 101 - invSizeY / 2; - int staticSelectorHeight = guiTop + 177; - - if (mouseY > staticSelectorHeight && mouseY < staticSelectorHeight + 16) { - if (mouseX > guiLeft + 320 - 12 && mouseX < guiLeft + 320 + 12) { - if (mouseX < guiLeft + 320) { - currentInventoryIndex--; - } else { - currentInventoryIndex++; - } - } - } - } - } - - - private void calculateFloorLevelXP() { - JsonObject leveling = Constants.LEVELING; - if (leveling == null) return; - ProfileViewer.Level levelObjCata = levelObjCatas.get(profileId); - if (levelObjCata == null) return; - - try { - dungeonLevelTextField.setCustomBorderColour(0xffffffff); - floorLevelTo = Integer.parseInt(dungeonLevelTextField.getText()); - - JsonArray levelingArray = Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(); - - float remaining = -((levelObjCata.level % 1) * levelObjCata.maxXpForLevel); - - for (int level = 0; level < Math.min(floorLevelTo, levelingArray.size()); level++) { - if (level < Math.floor(levelObjCata.level)) { - continue; - } - remaining += levelingArray.get(level).getAsFloat(); - } - - if (remaining < 0) { - remaining = 0; - } - floorLevelToXP = (long) remaining; - } catch (Exception e) { - dungeonLevelTextField.setCustomBorderColour(0xffff0000); - } - } - - private void drawDungPage(int mouseX, int mouseY, float partialTicks) { - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dung); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); - - JsonObject hypixelInfo = profile.getHypixelProfile(); - if (hypixelInfo == null) return; - JsonObject profileInfo = profile.getProfileInformation(profileId); - if (profileInfo == null) return; - - JsonObject leveling = Constants.LEVELING; - if (leveling == null) return; - - int sectionWidth = 110; - - String dungeonString = onMasterMode ? "master_catacombs" : "catacombs"; - - //Utils.drawStringCentered((onMasterMode?"Master Mode":"Catacombs"),fontRendererObj,(guiLeft+sizeX/2), guiTop+10, true, 0xffff0000); - Utils.renderShadowedString(EnumChatFormatting.RED + (onMasterMode ? "Master Mode" : "Catacombs"), - (guiLeft + sizeX / 2), guiTop + 5, sectionWidth - ); - - ProfileViewer.Level levelObjCata = levelObjCatas.get(profileId); - //Catacombs level thingy - { - if (levelObjCata == null) { - float cataXp = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.catacombs.experience" - ), 0); - levelObjCata = ProfileViewer.getLevel(Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(), - cataXp, 99, false - ); - levelObjCata.totalXp = cataXp; - levelObjCatas.put(profileId, levelObjCata); - } - - String skillName = EnumChatFormatting.RED + "Catacombs"; - float level = levelObjCata.level; - int levelFloored = (int) Math.floor(level); - - if (floorLevelTo == -1 && levelFloored >= 0) { - dungeonLevelTextField.setText("" + (levelFloored + 1)); - calculateFloorLevelXP(); - } - - int x = guiLeft + 23; - int y = guiTop + 25; - - renderXpBar(skillName, DEADBUSH, x, y, sectionWidth, levelObjCata, mouseX, mouseY); - - Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Until Cata " + floorLevelTo + ": ", - EnumChatFormatting.WHITE + shortNumberFormat(floorLevelToXP, 0), x, y + 16, sectionWidth - ); - - if (mouseX > x && mouseX < x + sectionWidth && mouseY > y + 16 && mouseY < y + 24 && !onMasterMode) { - float F5 = (Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.catacombs.tier_completions." + 5 - ), 0)); //this can prob be done better - float F6 = (Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.catacombs.tier_completions." + 6 - ), 0)); - float F7 = (Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.catacombs.tier_completions." + 7 - ), 0)); - if (F5 > 150) { - F5 = 150; - } - if (F6 > 100) { - F6 = 100; - } - if (F7 > 50) { - F7 = 50; - } - float xpF5 = 2000 * (F5 / 100 + 1); - float xpF6 = 4000 * (F6 / 100 + 1); - float xpF7 = 20000 * (F7 / 100 + 1); - if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { - xpF5 *= 1.1; - xpF6 *= 1.1; - xpF7 *= 1.1; - } - - long runsF5 = (int) Math.ceil(floorLevelToXP / xpF5); - long runsF6 = (int) Math.ceil(floorLevelToXP / xpF6); - long runsF7 = (int) Math.ceil(floorLevelToXP / xpF7); - - float timeF5 = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.catacombs.fastest_time_s_plus.5" - ), 0); - float timeF6 = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.catacombs.fastest_time_s_plus.6" - ), 0); - float timeF7 = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.catacombs.fastest_time_s_plus.7" - ), 0); - - tooltipToDisplay = Lists.newArrayList( - String.format("# F5 Runs (%s xp) : %d", shortNumberFormat(xpF5, 0), runsF5), - String.format("# F6 Runs (%s xp) : %d", shortNumberFormat(xpF6, 0), runsF6), - String.format("# F7 Runs (%s xp) : %d", shortNumberFormat(xpF7, 0), runsF7), - "" - ); - boolean hasTime = false; - if (timeF5 > 1000) { - tooltipToDisplay.add(String.format( - "Expected Time (F5) : %s", - Utils.prettyTime(runsF5 * (long) (timeF5 * 1.2)) - )); - hasTime = true; - } - if (timeF6 > 1000) { - tooltipToDisplay.add(String.format( - "Expected Time (F6) : %s", - Utils.prettyTime(runsF6 * (long) (timeF6 * 1.2)) - )); - hasTime = true; - } - if (timeF7 > 1000) { - tooltipToDisplay.add(String.format( - "Expected Time (F7) : %s", - Utils.prettyTime(runsF7 * (long) (timeF7 * 1.2)) - )); - hasTime = true; - } - if (hasTime) { - tooltipToDisplay.add(""); - } - if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { - tooltipToDisplay.add( - "[Hold " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + " to show without Expert Ring]"); - } - if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { - if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) tooltipToDisplay.add(""); - tooltipToDisplay.add("Number of runs is calculated as [Remaining XP]/[XP per Run]."); - tooltipToDisplay.add("The [XP per Run] is the average xp gained from an S+ run"); - tooltipToDisplay.add( - "The " + EnumChatFormatting.DARK_PURPLE + "Catacombs Expert Ring" + EnumChatFormatting.GRAY + - " is assumed to be used, unless " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + - " is held."); - tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%"); - } else { - tooltipToDisplay.add( - "[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]"); - } - } - - if (mouseX > x && mouseX < x + sectionWidth && mouseY > y + 16 && mouseY < y + 24 && onMasterMode) { - float M3 = (Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.tier_completions." + 3 - ), 0)); - float M4 = (Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.tier_completions." + 4 - ), 0)); - float M5 = (Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.tier_completions." + 5 - ), 0)); //this can prob be done better - float M6 = (Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.tier_completions." + 6 - ), 0)); - if (M3 > 50) { - M3 = 50; - } - if (M4 > 50) { - M4 = 50; - } - if (M5 > 50) { - M5 = 50; - } - if (M6 > 50) { - M6 = 50; - } - float xpM3 = 36500 * (M3 / 100 + 1); - float xpM4 = 48500 * (M4 / 100 + 1); - float xpM5 = 70000 * (M5 / 100 + 1); - float xpM6 = 100000 * (M6 / 100 + 1); - //No clue if M3 or M4 xp values are right - if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { - xpM3 *= 1.1; - xpM4 *= 1.1; - xpM5 *= 1.1; - xpM6 *= 1.1; - } - - long runsM3 = (int) Math.ceil(floorLevelToXP / xpM3); - long runsM4 = (int) Math.ceil(floorLevelToXP / xpM4); - long runsM5 = (int) Math.ceil(floorLevelToXP / xpM5); - long runsM6 = (int) Math.ceil(floorLevelToXP / xpM6); - - float timeM3 = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.3" - ), 0); - float timeM4 = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.4" - ), 0); - float timeM5 = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.5" - ), 0); - float timeM6 = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.6" - ), 0); - - tooltipToDisplay = Lists.newArrayList( - String.format("# M3 Runs (%s xp) : %d", shortNumberFormat(xpM3, 0), runsM3), - String.format("# M4 Runs (%s xp) : %d", shortNumberFormat(xpM4, 0), runsM4), - String.format("# M5 Runs (%s xp) : %d", shortNumberFormat(xpM5, 0), runsM5), - String.format("# M6 Runs (%s xp) : %d", shortNumberFormat(xpM6, 0), runsM6), - "" - ); - boolean hasTime = false; - if (timeM3 > 1000) { - tooltipToDisplay.add(String.format( - "Expected Time (M3) : %s", - Utils.prettyTime(runsM3 * (long) (timeM3 * 1.2)) - )); - hasTime = true; - } - if (timeM4 > 1000) { - tooltipToDisplay.add(String.format( - "Expected Time (M4) : %s", - Utils.prettyTime(runsM4 * (long) (timeM4 * 1.2)) - )); - hasTime = true; - } - if (timeM5 > 1000) { - tooltipToDisplay.add(String.format( - "Expected Time (M5) : %s", - Utils.prettyTime(runsM5 * (long) (timeM5 * 1.2)) - )); - hasTime = true; - } - if (timeM6 > 1000) { - tooltipToDisplay.add(String.format( - "Expected Time (M6) : %s", - Utils.prettyTime(runsM6 * (long) (timeM6 * 1.2)) - )); - hasTime = true; - } - if (hasTime) { - tooltipToDisplay.add(""); - } - if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { - tooltipToDisplay.add( - "[Hold " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + " to show without Expert Ring]"); - } - if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { - if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) tooltipToDisplay.add(""); - tooltipToDisplay.add("Number of runs is calculated as [Remaining XP]/[XP per Run]."); - tooltipToDisplay.add("The [XP per Run] is the average xp gained from an S+ run"); - tooltipToDisplay.add( - "The " + EnumChatFormatting.DARK_PURPLE + "Catacombs Expert Ring" + EnumChatFormatting.GRAY + - " is assumed to be used, unless " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + - " is held."); - tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%"); - } else { - tooltipToDisplay.add( - "[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]"); - } - } - - dungeonLevelTextField.setSize(20, 10); - dungeonLevelTextField.render(x + 22, y + 29); - int calcLen = fontRendererObj.getStringWidth("Calculate"); - Utils.renderShadowedString(EnumChatFormatting.WHITE + "Calculate", x + sectionWidth - 17 - calcLen / 2f, - y + 30, 100 - ); - - //Random stats - - float secrets = Utils.getElementAsFloat(Utils.getElement( - hypixelInfo, - "achievements.skyblock_treasure_hunter" - ), 0); - float totalRuns = 0; - float totalRunsF = 0; - float totalRunsF5 = 0; - for (int i = 1; i <= 7; i++) { - float runs = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.catacombs.tier_completions." + i - ), 0); - totalRunsF += runs; - if (i >= 5) { - totalRunsF5 += runs; - } - } - float totalRunsM = 0; - float totalRunsM5 = 0; - for (int i = 1; i <= 7; i++) { - float runs = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.tier_completions." + i - ), 0); - totalRunsM += runs; - if (i >= 5) { - totalRunsM5 += runs; - } - } - totalRuns = totalRunsF + totalRunsM; - - float mobKills = 0; - float mobKillsF = 0; - float mobKillsF5 = 0; - for (int i = 1; i <= 7; i++) { - float kills = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.catacombs.mobs_killed." + i - ), 0); - mobKillsF += kills; - if (i >= 5) { - mobKillsF5 += kills; - } - } - float mobKillsM = 0; - float mobKillsM5 = 0; - for (int i = 1; i <= 7; i++) { - float kills = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types.master_catacombs.mobs_killed." + i - ), 0); - mobKillsM += kills; - if (i >= 5) { - mobKillsM5 += kills; - } - } - mobKills = mobKillsF + mobKillsM; - - int miscTopY = y + 55; - - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Total Runs " + (onMasterMode ? "M" : "F"), - EnumChatFormatting.WHITE.toString() + ((int) (onMasterMode ? totalRunsM : totalRunsF)), - x, - miscTopY, - sectionWidth - ); - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Total Runs (" + (onMasterMode ? "M" : "F") + "5-7) ", - EnumChatFormatting.WHITE.toString() + ((int) (onMasterMode ? totalRunsM5 : totalRunsF5)), - x, - miscTopY + 10, - sectionWidth - ); - Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Secrets (Total) ", - EnumChatFormatting.WHITE + shortNumberFormat(secrets, 0), x, miscTopY + 20, sectionWidth - ); - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Secrets (/Run) ", - EnumChatFormatting.WHITE.toString() + (Math.round(secrets / Math.max(1, totalRuns) * 100) / 100f), - x, - miscTopY + 30, - sectionWidth - ); - Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Mob Kills (Total) ", - EnumChatFormatting.WHITE + shortNumberFormat(mobKills, 0), x, miscTopY + 40, sectionWidth - ); - - int y3 = y + 117; - - for (int i = 1; i <= 7; i++) { - int w = fontRendererObj.getStringWidth("" + i); - - int bx = x + sectionWidth * i / 8 - w / 2; - - boolean invert = i == floorTime; - float uMin = 20 / 256f; - float uMax = 29 / 256f; - float vMin = 0 / 256f; - float vMax = 11 / 256f; - - GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(bx - 2, y3 - 2, 9, 11, - invert ? uMax : uMin, invert ? uMin : uMax, - invert ? vMax : vMin, invert ? vMin : vMax, GL11.GL_NEAREST - ); - - Utils.renderShadowedString(EnumChatFormatting.WHITE.toString() + i, bx + w / 2, y3, 10); - } - - float timeNorm = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types." + dungeonString + ".fastest_time." + floorTime - ), 0); - float timeS = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types." + dungeonString + ".fastest_time_s." + floorTime - ), 0); - float timeSPLUS = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types." + dungeonString + ".fastest_time_s_plus." + floorTime - ), 0); - String timeNormStr = timeNorm <= 0 ? "N/A" : Utils.prettyTime((long) timeNorm); - String timeSStr = timeS <= 0 ? "N/A" : Utils.prettyTime((long) timeS); - String timeSPlusStr = timeSPLUS <= 0 ? "N/A" : Utils.prettyTime((long) timeSPLUS); - Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Floor " + floorTime + " ", - EnumChatFormatting.WHITE + timeNormStr, x, y3 + 10, sectionWidth - ); - Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Floor " + floorTime + " S", - EnumChatFormatting.WHITE + timeSStr, x, y3 + 20, sectionWidth - ); - Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Floor " + floorTime + " S+", - EnumChatFormatting.WHITE + timeSPlusStr, x, y3 + 30, sectionWidth - ); - } - - //Completions - { - int x = guiLeft + 161; - int y = guiTop + 27; - - Utils.renderShadowedString(EnumChatFormatting.RED + "Boss Collections", - x + sectionWidth / 2, y, sectionWidth - ); - for (int i = 1; i <= 7; i++) { - float compl = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.dungeon_types." + dungeonString + ".tier_completions." + i - ), 0); - - if (BOSS_HEADS[i - 1] == null) { - String textureLink = bossFloorHeads[i - 1]; - - 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); - - BOSS_HEADS[i - 1] = stack; - } - - GlStateManager.pushMatrix(); - GlStateManager.translate(x - 4, y + 10 + 20 * (i - 1), 0); - GlStateManager.scale(1.3f, 1.3f, 1); - Utils.drawItemStack(BOSS_HEADS[i - 1], 0, 0); - GlStateManager.popMatrix(); - - Utils.renderAlignedString(String.format( - EnumChatFormatting.YELLOW + "%s (" + (onMasterMode ? "M" : "F") + "%d) ", - bossFloorArr[i - 1], - i - ), - EnumChatFormatting.WHITE.toString() + (int) compl, - x + 16, y + 18 + 20 * (i - 1), sectionWidth - 15 - ); - - } - } - - //Skills - { - int x = guiLeft + 298; - int y = guiTop + 27; - - //Gui.drawRect(x, y, x+120, y+147, 0xffffffff); - - Utils.renderShadowedString(EnumChatFormatting.DARK_PURPLE + "Class Levels", - x + sectionWidth / 2, y, sectionWidth - ); - - JsonElement activeClassElement = Utils.getElement(profileInfo, "dungeons.selected_dungeon_class"); - String activeClass = null; - if (activeClassElement instanceof JsonPrimitive && ((JsonPrimitive) activeClassElement).isString()) { - activeClass = activeClassElement.getAsString(); - } - - for (int i = 0; i < dungSkillsName.length; i++) { - String skillName = dungSkillsName[i]; - - HashMap<String, ProfileViewer.Level> levelObjClasses = - levelObjClasseses.computeIfAbsent(profileId, k -> new HashMap<>()); - if (!levelObjClasses.containsKey(skillName)) { - float cataXp = Utils.getElementAsFloat(Utils.getElement( - profileInfo, - "dungeons.player_classes." + skillName.toLowerCase() + ".experience" - ), 0); - ProfileViewer.Level levelObj = - ProfileViewer.getLevel(Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(), - cataXp, 50, false - ); - levelObjClasses.put(skillName, levelObj); - } - - String colour = EnumChatFormatting.WHITE.toString(); - if (skillName.toLowerCase().equals(activeClass)) { - colour = EnumChatFormatting.GREEN.toString(); - } - - ProfileViewer.Level levelObj = levelObjClasses.get(skillName); - - renderXpBar(colour + skillName, dungSkillsStack[i], x, y + 20 + 29 * i, sectionWidth, levelObj, mouseX, mouseY); - } - } - - drawSideButtons(); - - //drawSideButton(0, dungeonsModeIcons.get("catacombs"), true); - //drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), true); - //drawSideButton(1, dungeonsModeIcons.get("catacombs"), true); - //drawSideButton(2, dungeonsModeIcons.get("catacombs"), false); - } - - //TODO: improve this shit - private void drawSideButtons() { - // GlStateManager.pushMatrix(); - GlStateManager.enableDepth(); - GlStateManager.translate(0, 0, 5); - if (onMasterMode) { - drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), true); - } else { - drawSideButton(0, dungeonsModeIcons.get("catacombs"), true); - } - GlStateManager.translate(0, 0, -3); - - GlStateManager.translate(0, 0, -2); - if (!onMasterMode) { - drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), false); - } else { - drawSideButton(0, dungeonsModeIcons.get("catacombs"), false); + if (pages.containsKey(currentPage)) { + pages.get(currentPage).mouseReleased(mouseX, mouseY, mouseButton); } - GlStateManager.disableDepth(); - //GlStateManager.popMatrix(); } - private void drawSideButton(int yIndex, ItemStack itemStack, boolean pressed) { - GlStateManager.disableLighting(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.enableAlpha(); - GlStateManager.alphaFunc(516, 0.1F); - - int x = guiLeft - 28; - int y = guiTop + yIndex * 28; - - float uMin = 193 / 256f; - float uMax = 223 / 256f; - float vMin = 200 / 256f; - float vMax = 228 / 256f; - if (pressed) { - uMin = 224 / 256f; - uMax = 1f; - - if (yIndex != 0) { - vMin = 228 / 256f; - vMax = 1f; - } - - renderBlurredBackground(width, height, x + 2, y + 2, 30, 28 - 4); - } else { - renderBlurredBackground(width, height, x + 2, y + 2, 28 - 2, 28 - 4); - } - - GlStateManager.disableLighting(); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.enableAlpha(); - GlStateManager.alphaFunc(516, 0.1F); - - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - - Utils.drawTexturedRect(x, y, pressed ? 32 : 28, 28, uMin, uMax, vMin, vMax, GL11.GL_NEAREST); - - GlStateManager.enableDepth(); - Utils.drawItemStack(itemStack, x + 8, y + 7); - } - - private void renderXpBar( + public void renderXpBar( String skillName, ItemStack stack, int x, @@ -1948,17 +1003,18 @@ public class GuiProfileViewer extends GuiScreen { if (mouseY > y - 4 && mouseY < y + 13) { String levelStr; String totalXpStr = null; - if (skillName.contains("Catacombs")) - totalXpStr = EnumChatFormatting.GRAY + "Total XP: " + EnumChatFormatting.DARK_PURPLE + + if (skillName.contains("Catacombs")) totalXpStr = + EnumChatFormatting.GRAY + "Total XP: " + EnumChatFormatting.DARK_PURPLE + numberFormat.format(levelObj.totalXp); if (levelObj.maxed) { levelStr = EnumChatFormatting.GOLD + "MAXED!"; } else { int maxXp = (int) levelObj.maxXpForLevel; - levelStr = EnumChatFormatting.DARK_PURPLE + shortNumberFormat( - Math.round((level % 1) * maxXp), - 0 - ) + "/" + shortNumberFormat(maxXp, 0); + levelStr = + EnumChatFormatting.DARK_PURPLE + + shortNumberFormat(Math.round((level % 1) * maxXp), 0) + + "/" + + shortNumberFormat(maxXp, 0); } if (totalXpStr != null) { tooltipToDisplay = Utils.createList(levelStr, totalXpStr); @@ -1981,3034 +1037,11 @@ public class GuiProfileViewer extends GuiScreen { GL11.glTranslatef(-(x), -(y - 6f), 0); } - 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; - } - - private void drawPetsPage(int mouseX, int mouseY, float partialTicks) { - JsonObject petsInfo = profile.getPetsInfo(profileId); - if (petsInfo == null) return; - JsonObject petsJson = Constants.PETS; - if (petsJson == null) return; - - String location = null; - JsonObject status = profile.getPlayerStatus(); - if (status != null && status.has("mode")) { - location = status.get("mode").getAsString(); - } - - backgroundRotation += (currentTime - lastTime) / 400f; - 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) { - 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 tier1 = pet1.get("tier").getAsString(); - String tierNum1 = MINION_RARITY_TO_NUM.get(tier1); - if (tierNum1 == null) return 1; - int tierNum1I = Integer.parseInt(tierNum1); - float exp1 = pet1.get("exp").getAsFloat(); - - String tier2 = pet2.get("tier").getAsString(); - String tierNum2 = MINION_RARITY_TO_NUM.get(tier2); - if (tierNum2 == null) return -1; - int tierNum2I = Integer.parseInt(tierNum2); - float exp2 = pet2.get("exp").getAsFloat(); - - if (tierNum1I != tierNum2I) { - return tierNum2I - tierNum1I; - } else { - return (int) (exp2 - exp1); - } - }); - 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 = 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); - } - - 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(); - HashMap<String, String> replacements = new HashMap<>(); - 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<String, String> replacements = - NotEnoughUpdates.INSTANCE.manager.getLoreReplacements(petname, tier, (int) Math.floor(level)); - - if (heldItem != null) { - HashMap<String, Float> petStatBoots = PET_STAT_BOOSTS.get(heldItem); - HashMap<String, Float> petStatBootsMult = PET_STAT_BOOSTS_MULT.get(heldItem); - if (petStatBoots != null) { - for (Map.Entry<String, Float> 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<String, Float> 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<Integer, Integer> 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<String, String> 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<String, String> replacement : replacements.entrySet()) { - displayName = displayName.replace("{" + replacement.getKey() + "}", replacement.getValue()); - } - display.setTag("Name", new NBTTagString(displayName)); - } - tag.setTag("display", display); - } - stack.setTagCompound(tag); - - } - sortedPetsStack.add(stack); - } - } - - Panorama.drawPanorama(-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, sizeX, sizeY, GL11.GL_NEAREST); - - Utils.drawStringCentered(EnumChatFormatting.DARK_PURPLE + "Pets", Minecraft.getMinecraft().fontRendererObj, - 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(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(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); - - if (mouseX > guiLeft + x && mouseX < guiLeft + x + 20) { - if (mouseY > guiTop + y && mouseY < guiTop + y + 20) { - tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } - } - } - } - - if (selectedPet >= 0) { - ItemStack petStack; - if (sortedPetsStack.size() <= selectedPet) { - petStack = getQuestionmarkSkull(); - } 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(((currentTime - startTime) / 800f) % (2 * Math.PI)); - - int displayLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(display); - int halfDisplayLen = displayLen / 2; - - GlStateManager.pushMatrix(); - GlStateManager.translate(x, y, 0); - - 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 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); - renderBar(guiLeft + 319, guiTop + 38, 98, (float) Math.floor(level) / 100f); - - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "To Next LVL", - EnumChatFormatting.WHITE.toString() + (int) (level % 1 * 100) + "%", - guiLeft + 319, - guiTop + 46, - 98 - ); - renderBar(guiLeft + 319, guiTop + 56, 98, level % 1); - - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "To Max LVL", - EnumChatFormatting.WHITE.toString() + Math.min(100, (int) (exp / maxXP * 100)) + "%", - guiLeft + 319, - guiTop + 64, - 98 - ); - renderBar(guiLeft + 319, guiTop + 74, 98, exp / maxXP); - - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Total XP", - EnumChatFormatting.WHITE + shortNumberFormat(exp, 0), - guiLeft + 319, - guiTop + 125, - 98 - ); - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Current LVL XP", - EnumChatFormatting.WHITE + shortNumberFormat((level % 1) * currentLevelRequirement, 0), - guiLeft + 319, - guiTop + 143, - 98 - ); - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Required LVL XP", - EnumChatFormatting.WHITE + shortNumberFormat(currentLevelRequirement, 0), - guiLeft + 319, - guiTop + 161, - 98 - ); - } - } - - - - public int countItemsInInventory( - String internalname, - JsonObject inventoryInfo, - boolean specific, - String... invsToSearch - ) { - int count = 0; - for (String inv : invsToSearch) { - JsonArray invItems = inventoryInfo.get(inv).getAsJsonArray(); - for (int i = 0; i < invItems.size(); i++) { - if (invItems.get(i) == null || !invItems.get(i).isJsonObject()) continue; - JsonObject item = invItems.get(i).getAsJsonObject(); - if ((specific && item.get("internalname").getAsString().equals(internalname)) || - (!specific && item.get("internalname").getAsString().contains(internalname))) { - if (item.has("count")) { - count += item.get("count").getAsInt(); - } else { - count += 1; - } - } - } - } - return count; - } - - private ItemStack[] findBestItems( - JsonObject inventoryInfo, - int numItems, - String[] invsToSearch, - String[] typeMatches, - Pattern... importantPatterns - ) { - ItemStack[] bestItems = new ItemStack[numItems]; - TreeMap<Integer, Set<ItemStack>> map = new TreeMap<>(); - for (String inv : invsToSearch) { - JsonArray invItems = inventoryInfo.get(inv).getAsJsonArray(); - for (int i = 0; i < invItems.size(); i++) { - if (invItems.get(i) == null || !invItems.get(i).isJsonObject()) continue; - JsonObject item = invItems.get(i).getAsJsonObject(); - JsonArray lore = item.get("lore").getAsJsonArray(); - if (Utils.checkItemType(lore, true, typeMatches) >= 0) { - int importance = 0; - for (int j = 0; j < lore.size(); j++) { - String line = lore.get(j).getAsString(); - for (Pattern pattern : importantPatterns) { - Matcher matcher = pattern.matcher(Utils.cleanColour(line)); - if (matcher.find()) { - importance += Integer.parseInt(matcher.group(1)); - } - } - } - map.computeIfAbsent(importance, k -> new HashSet<>()).add( - NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false)); - } - } - } - int i = 0; - outer: - for (int key : map.descendingKeySet()) { - Set<ItemStack> items = map.get(key); - for (ItemStack item : items) { - bestItems[i] = item; - if (++i >= bestItems.length) break outer; - } - } - - return bestItems; - } - - private int getRowsForInventory(String invName) { - switch (invName) { - case "wardrobe_contents": - return 4; - case "backpack_contents": - return 5; - case "ender_chest_contents": - return 5; - } - return 6; - } - - private boolean useActualMax(String invName) { - switch (invName) { - case "talisman_bag": - case "fishing_bag": - case "potion_bag": - case "personal_vault_contents": - return true; - } - return false; - } - - private int getIgnoredRowsForInventory(String invName) { - switch (invName) { - case "talisman_bag": - case "fishing_bag": - case "potion_bag": - return 1; - } - return 0; - } - - public ItemStack[][][] getItemsForInventory(JsonObject inventoryInfo, String invName) { - if (inventoryItems.containsKey(invName)) return inventoryItems.get(invName); - - JsonArray jsonInv = Utils.getElement(inventoryInfo, invName).getAsJsonArray(); - - if (jsonInv.size() == 0) return new ItemStack[1][][]; - - int jsonInvSize; - if (useActualMax(invName)) { - jsonInvSize = (int) Math.ceil(jsonInv.size() / 9f) * 9; - } else { - jsonInvSize = 9 * 4; - float divideBy = 9f; - if (invName.equals("wardrobe_contents")) { - divideBy = 36f; - } - for (int i = 9 * 4; i < jsonInv.size(); i++) { - JsonElement item = jsonInv.get(i); - if (item != null && item.isJsonObject()) { - jsonInvSize = (int) (Math.ceil((i + 1) / divideBy) * (int) divideBy); - } - } - } - - int rowSize = 9; - int rows = jsonInvSize / rowSize; - int maxRowsPerPage = getRowsForInventory(invName); - int maxInvSize = rowSize * maxRowsPerPage; - - int numInventories = (jsonInvSize - 1) / maxInvSize + 1; - JsonArray backPackSizes = (JsonArray) inventoryInfo.get("backpack_sizes"); - if (invName.equals("backpack_contents")) { - numInventories = backPackSizes.size(); - } - - ItemStack[][][] inventories = new ItemStack[numInventories][][]; - - //int availableSlots = getAvailableSlotsForInventory(inventoryInfo, collectionInfo, invName); - int startNumberJ = 0; - - for (int i = 0; i < numInventories; i++) { - int thisRows = Math.min(maxRowsPerPage, rows - maxRowsPerPage * i); - int invSize = 0; - - if (invName.equals("backpack_contents")) { - thisRows = backPackSizes.get(i).getAsInt() / 9; - invSize = startNumberJ + (thisRows * 9); - maxInvSize = thisRows * 9; - } else { - startNumberJ = maxInvSize * i; - invSize = Math.min(jsonInvSize, maxInvSize + maxInvSize * i); - } - if (thisRows <= 0) break; - - ItemStack[][] items = new ItemStack[thisRows][rowSize]; - - for (int j = startNumberJ; j < invSize; j++) { - - int xIndex = (j % maxInvSize) % rowSize; - int yIndex = (j % maxInvSize) / rowSize; - if (invName.equals("inv_contents")) { - yIndex--; - if (yIndex < 0) yIndex = rows - 1; - } - if (yIndex >= thisRows) { - break; - } - - if (j >= jsonInv.size()) { - items[yIndex][xIndex] = fillerStack; - continue; - } - if (jsonInv.get(j) == null || !jsonInv.get(j).isJsonObject()) { - continue; - } - - JsonObject item = jsonInv.get(j).getAsJsonObject(); - ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false); - if (item.has("item_contents")) { - JsonArray bytesArr = item.get("item_contents").getAsJsonArray(); - byte[] bytes = new byte[bytesArr.size()]; - for (int bytesArrI = 0; bytesArrI < bytesArr.size(); bytesArrI++) { - bytes[bytesArrI] = bytesArr.get(bytesArrI).getAsByte(); - } - //byte[] bytes2 = null; - NBTTagCompound tag = stack.getTagCompound(); - if (tag != null && tag.hasKey("ExtraAttributes", 10)) { - NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); - for (String key : ea.getKeySet()) { - if (key.endsWith("backpack_data") || key.equals("new_year_cake_bag_data")) { - ea.setTag(key, new NBTTagByteArray(bytes)); - break; - } - } - tag.setTag("ExtraAttributes", ea); - stack.setTagCompound(tag); - } - } - - items[yIndex][xIndex] = stack; - } - inventories[i] = items; - if (invName.equals("backpack_contents")) { - startNumberJ = startNumberJ + backPackSizes.get(i).getAsInt(); - } - } - - inventoryItems.put(invName, inventories); - return inventories; - } - - private void drawInvsPage(int mouseX, int mouseY) { - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_invs); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); - inventoryTextField.setSize(88, 20); - - JsonObject inventoryInfo = profile.getInventoryInfo(profileId); - if (inventoryInfo == null) return; - - int invNameIndex = 0; - for (Map.Entry<String, ItemStack> entry : invNameToDisplayMap.entrySet()) { - int xIndex = invNameIndex % 3; - int yIndex = invNameIndex / 3; - - int x = 19 + 34 * xIndex; - int y = 26 + 34 * yIndex; - - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - if (entry.getKey().equals(selectedInventory)) { - Utils.drawTexturedRect(guiLeft + x - 2, guiTop + y - 2, 20, 20, 20 / 256f, 0, - 20 / 256f, 0, GL11.GL_NEAREST - ); - x++; - y++; - } else { - Utils.drawTexturedRect(guiLeft + x - 2, guiTop + y - 2, 20, 20, 0, 20 / 256f, - 0, 20 / 256f, GL11.GL_NEAREST - ); - } - - Utils.drawItemStackWithText(entry.getValue(), guiLeft + x, guiTop + y, "" + (invNameIndex + 1)); - - if (mouseX >= guiLeft + x && mouseX <= guiLeft + x + 16) { - if (mouseY >= guiTop + y && mouseY <= guiTop + y + 16) { - tooltipToDisplay = entry.getValue().getTooltip(Minecraft.getMinecraft().thePlayer, false); - if (Objects.equals(entry.getKey(), "talisman_bag")) { - StringBuilder magicalPowerString = new StringBuilder(EnumChatFormatting.DARK_GRAY + "Magical Power: "); - int magicalPower = PlayerStats.getMagicalPower(inventoryInfo); - tooltipToDisplay.add(magicalPower == -1 - ? magicalPowerString.append(EnumChatFormatting.RED).append("Error while calculating!").toString() - : magicalPowerString.append(EnumChatFormatting.GOLD).append(numberFormat.format(magicalPower)).toString()); - - StringBuilder selectedPowerString = new StringBuilder(EnumChatFormatting.DARK_GRAY + "Selected Power: "); - String selectedPower = PlayerStats.getSelectedMagicalPower(profile.getProfileInformation(profileId)); - tooltipToDisplay.add(selectedPower == null - ? selectedPowerString.append(EnumChatFormatting.RED).append("None!").toString() - : selectedPowerString.append(EnumChatFormatting.GREEN).append(selectedPower).toString()); - } - } - } - - invNameIndex++; - } - - inventoryTextField.render(guiLeft + 19, guiTop + sizeY - 26 - 20); - - if (armorItems == null) { - armorItems = new ItemStack[4]; - JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray(); - for (int i = 0; i < armor.size(); i++) { - if (armor.get(i) == null || !armor.get(i).isJsonObject()) continue; - armorItems[i] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(armor.get(i).getAsJsonObject(), false); - } - } - - for (int i = 0; i < armorItems.length; i++) { - ItemStack stack = armorItems[i]; - if (stack != null) { - Utils.drawItemStack(stack, guiLeft + 173, guiTop + 67 - 18 * i); - if (stack != fillerStack) { - if (mouseX >= guiLeft + 173 - 1 && mouseX <= guiLeft + 173 + 16 + 1) { - if (mouseY >= guiTop + 67 - 18 * i - 1 && mouseY <= guiTop + 67 - 18 * i + 16 + 1) { - tooltipToDisplay = stack.getTooltip( - Minecraft.getMinecraft().thePlayer, - Minecraft.getMinecraft().gameSettings.advancedItemTooltips - ); - } - } - } - } - } - - if (equipmentItems == null) { - equipmentItems = new ItemStack[4]; - JsonArray equippment = Utils.getElement(inventoryInfo, "equippment_contents").getAsJsonArray(); - for (int i = 0; i < equippment.size(); i++) { - if (equippment.get(i) == null || !equippment.get(i).isJsonObject()) continue; - equipmentItems[i] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(equippment.get(i).getAsJsonObject(), false); - } - } - - for (int i = 0; i < equipmentItems.length; i++) { - ItemStack stack = equipmentItems[i]; - if (stack != null) { - Utils.drawItemStack(stack, guiLeft + 192, guiTop + 13 + 18 * i); - if (stack != fillerStack) { - if (mouseX >= guiLeft + 192 - 1 && mouseX <= guiLeft + 192 + 16 + 1) { - if (mouseY >= guiTop + 13 + 18 * i - 1 && mouseY <= guiTop + 13 + 18 * i + 16 + 1) { - tooltipToDisplay = stack.getTooltip( - Minecraft.getMinecraft().thePlayer, - Minecraft.getMinecraft().gameSettings.advancedItemTooltips - ); - } - } - } - } - } - - ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, selectedInventory); - if (currentInventoryIndex >= inventories.length) currentInventoryIndex = inventories.length - 1; - if (currentInventoryIndex < 0) currentInventoryIndex = 0; - - ItemStack[][] inventory = inventories[currentInventoryIndex]; - if (inventory == null) { - if (selectedInventory.equalsIgnoreCase("personal_vault_contents")) { - Utils.drawStringCentered( - EnumChatFormatting.RED + "Personal Vault API not enabled!", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + 317, - guiTop + 101, - true, - 0 - ); - } else { - Utils.drawStringCentered( - EnumChatFormatting.RED + "Inventory API not enabled!", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + 317, - guiTop + 101, - true, - 0 - ); - } - return; - } - - if (bestWeapons == null) { - bestWeapons = findBestItems(inventoryInfo, 6, new String[]{"inv_contents", "ender_chest_contents"}, - new String[]{"SWORD", "BOW"}, DAMAGE_PATTERN, STRENGTH_PATTERN - ); - } - if (bestRods == null) { - bestRods = findBestItems(inventoryInfo, 3, new String[]{"inv_contents", "ender_chest_contents"}, - new String[]{"FISHING ROD"}, FISHSPEED_PATTERN - ); - } - - for (int i = 0; i < bestWeapons.length; i++) { - if (bestWeapons[i] == null) continue; - ItemStack stack = bestWeapons[i]; - Utils.drawItemStack(stack, guiLeft + 143, guiTop + 13 + 18 * i); - if (mouseX >= guiLeft + 143 - 1 && mouseX <= guiLeft + 143 + 16 + 1) { - if (mouseY >= guiTop + 13 + 18 * i - 1 && mouseY <= guiTop + 13 + 18 * i + 16 + 1) { - tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } - } - } - - for (int i = 0; i < bestRods.length; i++) { - if (bestRods[i] == null) continue; - ItemStack stack = bestRods[i]; - Utils.drawItemStack(stack, guiLeft + 143, guiTop + 137 + 18 * i); - if (mouseX >= guiLeft + 143 - 1 && mouseX <= guiLeft + 143 + 16 + 1) { - if (mouseY >= guiTop + 137 + 18 * i - 1 && mouseY <= guiTop + 137 + 18 * i + 16 + 1) { - tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } - } - } - - if (arrowCount == -1) { - arrowCount = countItemsInInventory("ARROW", inventoryInfo, false, "quiver"); - } - if (greenCandyCount == -1) { - greenCandyCount = countItemsInInventory("GREEN_CANDY", inventoryInfo, true, "candy_inventory_contents"); - } - if (purpleCandyCount == -1) { - purpleCandyCount = countItemsInInventory("PURPLE_CANDY", inventoryInfo, true, "candy_inventory_contents"); - } - - Utils.drawItemStackWithText(NotEnoughUpdates.INSTANCE.manager.jsonToStack( - NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("ARROW")), guiLeft + 173, guiTop + 101, - "" + (arrowCount > 999 ? shortNumberFormat(arrowCount, 0) : arrowCount) - ); - Utils.drawItemStackWithText( - NotEnoughUpdates.INSTANCE.manager.jsonToStack( - NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("GREEN_CANDY")), - guiLeft + 173, - guiTop + 119, - "" + greenCandyCount - ); - Utils.drawItemStackWithText( - NotEnoughUpdates.INSTANCE.manager.jsonToStack( - NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("PURPLE_CANDY")), - guiLeft + 173, - guiTop + 137, - "" + purpleCandyCount - ); - if (mouseX > guiLeft + 173 && mouseX < guiLeft + 173 + 16) { - if (mouseY > guiTop + 101 && mouseY < guiTop + 137 + 16) { - if (mouseY < guiTop + 101 + 17) { - tooltipToDisplay = - Utils.createList(EnumChatFormatting.WHITE + "Arrow " + EnumChatFormatting.GRAY + "x" + arrowCount); - } else if (mouseY < guiTop + 119 + 17) { - tooltipToDisplay = Utils.createList( - EnumChatFormatting.GREEN + "Green Candy " + EnumChatFormatting.GRAY + "x" + greenCandyCount); - } else { - tooltipToDisplay = Utils.createList( - EnumChatFormatting.DARK_PURPLE + "Purple Candy " + EnumChatFormatting.GRAY + "x" + purpleCandyCount); - } - } - } - - int inventoryRows = inventory.length; - - GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); - Minecraft.getMinecraft().getTextureManager().bindTexture(CHEST_GUI_TEXTURE); - - int invSizeY = inventoryRows * 18 + 17 + 7; - - int x = guiLeft + 320 - 176 / 2; - int y = guiTop + 101 - invSizeY / 2; - int staticSelectorHeight = guiTop + 177; - - this.drawTexturedModalRect(x, y, 0, 0, 176, inventoryRows * 18 + 17); - this.drawTexturedModalRect(x, y + inventoryRows * 18 + 17, 0, 215, 176, 7); - - boolean leftHovered = false; - boolean rightHovered = false; - if (Mouse.isButtonDown(0)) { - if (mouseY > staticSelectorHeight && mouseY < staticSelectorHeight + 16) { - if (mouseX > guiLeft + 320 - 12 && mouseX < guiLeft + 320 + 12) { - if (mouseX < guiLeft + 320) { - leftHovered = true; - } else { - rightHovered = true; - } - } - } - } - Minecraft.getMinecraft().getTextureManager().bindTexture(resource_packs); - - if (currentInventoryIndex > 0) { - Utils.drawTexturedRect(guiLeft + 320 - 12, staticSelectorHeight, 12, 16, - 29 / 256f, 53 / 256f, !leftHovered ? 0 : 32 / 256f, !leftHovered ? 32 / 256f : 64 / 256f, GL11.GL_NEAREST - ); - } - if (currentInventoryIndex < inventories.length - 1) { - Utils.drawTexturedRect(guiLeft + 320, staticSelectorHeight, 12, 16, - 5 / 256f, 29 / 256f, !rightHovered ? 0 : 32 / 256f, !rightHovered ? 32 / 256f : 64 / 256f, GL11.GL_NEAREST - ); - } - - fontRendererObj.drawString( - Utils.cleanColour(invNameToDisplayMap.get(selectedInventory).getDisplayName()), - x + 8, - y + 6, - 4210752 - ); - - ItemStack stackToRender = null; - int overlay = new Color(0, 0, 0, 100).getRGB(); - for (int yIndex = 0; yIndex < inventory.length; yIndex++) { - if (inventory[yIndex] == null) continue; - - for (int xIndex = 0; xIndex < inventory[yIndex].length; xIndex++) { - ItemStack stack = inventory[yIndex][xIndex]; - - if (stack != null) Utils.drawItemStack(stack, x + 8 + xIndex * 18, y + 18 + yIndex * 18); - - if (inventoryTextField.getText() != null && !inventoryTextField.getText().isEmpty() && - (stack == null || - !NotEnoughUpdates.INSTANCE.manager.doesStackMatchSearch(stack, inventoryTextField.getText()))) { - GlStateManager.translate(0, 0, 50); - drawRect( - x + 8 + xIndex * 18, - y + 18 + yIndex * 18, - x + 8 + xIndex * 18 + 16, - y + 18 + yIndex * 18 + 16, - overlay - ); - GlStateManager.translate(0, 0, -50); - } - - if (stack == null || stack == fillerStack) continue; - - if (mouseX >= x + 8 + xIndex * 18 && mouseX <= x + 8 + xIndex * 18 + 16) { - if (mouseY >= y + 18 + yIndex * 18 && mouseY <= y + 18 + yIndex * 18 + 16) { - stackToRender = stack; - } - } - } - } - if (stackToRender != null) { - tooltipToDisplay = stackToRender.getTooltip(Minecraft.getMinecraft().thePlayer, false); - } - - } - - private String niceUuid(String uuidStr) { - if (uuidStr.length() != 32) return uuidStr; - - StringBuilder niceAucId = new StringBuilder(); - niceAucId.append(uuidStr, 0, 8); - niceAucId.append("-"); - niceAucId.append(uuidStr, 8, 12); - niceAucId.append("-"); - niceAucId.append(uuidStr, 12, 16); - niceAucId.append("-"); - niceAucId.append(uuidStr, 16, 20); - niceAucId.append("-"); - niceAucId.append(uuidStr, 20, 32); - return niceAucId.toString(); - } - public EntityOtherPlayerMP getEntityPlayer() { - return entityPlayer; + return ((BasicPage) pages.get(ProfileViewerPage.BASIC)).entityPlayer; } - private void drawExtraPage(int mouseX, int mouseY, float partialTicks) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_extra); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); - - JsonObject profileInfo = profile.getProfileInformation(profileId); - if (profileInfo == null) return; - JsonObject skillInfo = profile.getSkillInfo(profileId); - - float xStart = 22; - float xOffset = 103; - float yStartTop = 27; - float yStartBottom = 105; - float yOffset = 10; - - float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), 0); - float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0); - - Utils.renderAlignedString( - EnumChatFormatting.GOLD + "Bank Balance", - EnumChatFormatting.WHITE + shortNumberFormat(bankBalance, 0), - guiLeft + xStart, - guiTop + yStartTop, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.GOLD + "Purse", - EnumChatFormatting.WHITE + shortNumberFormat(purseBalance, 0), - guiLeft + xStart, - guiTop + yStartTop + yOffset, - 76 - ); - - { - String lastSaveText = this.getTimeSinceString(profileInfo, "last_save"); - if (lastSaveText != null) { - Utils.renderAlignedString(EnumChatFormatting.AQUA + "Last Seen", EnumChatFormatting.WHITE + lastSaveText, - guiLeft + xStart, guiTop + yStartTop + yOffset * 2, 76 - ); - } - - } - { - String first_join = this.getTimeSinceString(profileInfo, "first_join"); - if (first_join != null) { - Utils.renderAlignedString(EnumChatFormatting.AQUA + "Joined", EnumChatFormatting.WHITE + first_join, - guiLeft + xStart, guiTop + yStartTop + yOffset * 3, 76 - ); - } - - } - { - JsonObject guildInfo = profile.getGuildInfo(null); - if (guildInfo != null && guildInfo.has("name")) { - Utils.renderAlignedString( - EnumChatFormatting.AQUA + "Guild", - EnumChatFormatting.WHITE + guildInfo.get("name").getAsString(), - guiLeft + xStart, - guiTop + yStartTop + yOffset * 4, - 76 - ); - } - } - - float fairySouls = Utils.getElementAsFloat(Utils.getElement(profileInfo, "fairy_souls_collected"), 0); - - int fairySoulMax = 227; - if (Constants.FAIRYSOULS != null && Constants.FAIRYSOULS.has("Max Souls")) { - fairySoulMax = Constants.FAIRYSOULS.get("Max Souls").getAsInt(); - } - Utils.renderAlignedString( - EnumChatFormatting.LIGHT_PURPLE + "Fairy Souls", - EnumChatFormatting.WHITE.toString() + (int) fairySouls + "/" + fairySoulMax, - guiLeft + xStart, - guiTop + yStartBottom, - 76 - ); - if (skillInfo != null) { - float totalSkillLVL = 0; - float totalTrueSkillLVL = 0; - float totalSlayerLVL = 0; - float totalSkillCount = 0; - float totalSlayerCount = 0; - float totalSlayerXP = 0; - - for (Map.Entry<String, JsonElement> entry : skillInfo.entrySet()) { - if (entry.getKey().startsWith("level_skill")) { - if (entry.getKey().contains("runecrafting")) continue; - if (entry.getKey().contains("carpentry")) continue; - if (entry.getKey().contains("catacombs")) continue; - if (entry.getKey().contains("social")) continue; - - totalSkillLVL += entry.getValue().getAsFloat(); - totalTrueSkillLVL += Math.floor(entry.getValue().getAsFloat()); - totalSkillCount++; - } else if (entry.getKey().startsWith("level_slayer")) { - totalSlayerLVL += entry.getValue().getAsFloat(); - totalSlayerCount++; - } else if (entry.getKey().startsWith("experience_slayer")) { - totalSlayerXP += entry.getValue().getAsFloat(); - } - } - - float avgSkillLVL = totalSkillLVL / totalSkillCount; - float avgTrueSkillLVL = totalTrueSkillLVL / totalSkillCount; - float avgSlayerLVL = totalSlayerLVL / totalSlayerCount; - - Utils.renderAlignedString( - EnumChatFormatting.RED + "AVG Skill Level", - EnumChatFormatting.WHITE.toString() + Math.floor(avgSkillLVL * 10) / 10, - guiLeft + xStart, - guiTop + yStartBottom + yOffset, - 76 - ); - - Utils.renderAlignedString( - EnumChatFormatting.RED + "True AVG Skill Level", - EnumChatFormatting.WHITE.toString() + Math.floor(avgTrueSkillLVL * 10) / 10, - guiLeft + xStart, - guiTop + yStartBottom + yOffset * 2, - 76 - ); - - Utils.renderAlignedString( - EnumChatFormatting.RED + "AVG Slayer Level", - EnumChatFormatting.WHITE.toString() + Math.floor(avgSlayerLVL * 10) / 10, - guiLeft + xStart, - guiTop + yStartBottom + yOffset * 3, - 76 - ); - - Utils.renderAlignedString( - EnumChatFormatting.RED + "Total Slayer XP", - EnumChatFormatting.WHITE + shortNumberFormat(totalSlayerXP, 0), - guiLeft + xStart, - guiTop + yStartBottom + yOffset * 4, - 76 - ); - } - - float auctions_bids = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_bids"), 0); - float auctions_highest_bid = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_highest_bid"), 0); - float auctions_won = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_won"), 0); - float auctions_created = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_created"), 0); - float auctions_gold_spent = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_gold_spent"), 0); - float auctions_gold_earned = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_gold_earned"), 0); - - Utils.renderAlignedString( - EnumChatFormatting.DARK_PURPLE + "Auction Bids", - EnumChatFormatting.WHITE.toString() + (int) auctions_bids, - guiLeft + xStart + xOffset, - guiTop + yStartTop, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_PURPLE + "Highest Bid", - EnumChatFormatting.WHITE + shortNumberFormat(auctions_highest_bid, 0), - guiLeft + xStart + xOffset, - guiTop + yStartTop + yOffset, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_PURPLE + "Auctions Won", - EnumChatFormatting.WHITE.toString() + (int) auctions_won, - guiLeft + xStart + xOffset, - guiTop + yStartTop + yOffset * 2, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_PURPLE + "Auctions Created", - EnumChatFormatting.WHITE.toString() + (int) auctions_created, - guiLeft + xStart + xOffset, - guiTop + yStartTop + yOffset * 3, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_PURPLE + "Gold Spent", - EnumChatFormatting.WHITE + shortNumberFormat(auctions_gold_spent, 0), - guiLeft + xStart + xOffset, - guiTop + yStartTop + yOffset * 4, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_PURPLE + "Gold Earned", - EnumChatFormatting.WHITE + shortNumberFormat(auctions_gold_earned, 0), - guiLeft + xStart + xOffset, - guiTop + yStartTop + yOffset * 5, - 76 - ); - - //Slayer values - float zombie_boss_kills_tier_2 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_2"), 0); - float zombie_boss_kills_tier_3 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_3"), 0); - float zombie_boss_kills_tier_4 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_4"), 0); - float wolf_boss_kills_tier_2 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.wolf.boss_kills_tier_2"), 0); - float wolf_boss_kills_tier_3 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.wolf.boss_kills_tier_3"), 0); - float spider_boss_kills_tier_2 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.spider.boss_kills_tier_2"), 0); - float spider_boss_kills_tier_3 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.spider.boss_kills_tier_3"), 0); - float enderman_boss_kills_tier_2 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.enderman.boss_kills_tier_2"), 0); - float enderman_boss_kills_tier_3 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.enderman.boss_kills_tier_3"), 0); - float blaze_boss_kills_tier_2 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.blaze.boss_kills_tier_2"), 0); - float blaze_boss_kills_tier_3 = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.blaze.boss_kills_tier_3"), 0); - - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Revenant T3", - EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_2, - guiLeft + xStart + xOffset, - guiTop + yStartBottom, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Revenant T4", - EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_3, - guiLeft + xStart + xOffset, - guiTop + yStartBottom + yOffset, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Revenant T5", - EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_4, - guiLeft + xStart + xOffset, - guiTop + yStartBottom + yOffset * 2, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Tarantula T3", - EnumChatFormatting.WHITE.toString() + (int) spider_boss_kills_tier_2, - guiLeft + xStart + xOffset, - guiTop + yStartBottom + yOffset * 3, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Tarantula T4", - EnumChatFormatting.WHITE.toString() + (int) spider_boss_kills_tier_3, - guiLeft + xStart + xOffset, - guiTop + yStartBottom + yOffset * 4, - 76 - ); - - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Sven T3", - EnumChatFormatting.WHITE.toString() + (int) wolf_boss_kills_tier_2, - guiLeft + xStart + xOffset * 2, - guiTop + yStartBottom + yOffset * 0, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Sven T4", - EnumChatFormatting.WHITE.toString() + (int) wolf_boss_kills_tier_3, - guiLeft + xStart + xOffset * 2, - guiTop + yStartBottom + yOffset * 1, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Voidgloom T3", - EnumChatFormatting.WHITE.toString() + (int) enderman_boss_kills_tier_2, - guiLeft + xStart + xOffset * 2, - guiTop + yStartBottom + yOffset * 2, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Voidgloom T4", - EnumChatFormatting.WHITE.toString() + (int) enderman_boss_kills_tier_3, - guiLeft + xStart + xOffset * 2, - guiTop + yStartBottom + yOffset * 3, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Inferno T3", - EnumChatFormatting.WHITE.toString() + (int) blaze_boss_kills_tier_2, - guiLeft + xStart + xOffset * 2, - guiTop + yStartBottom + yOffset * 4, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_AQUA + "Inferno T4", - EnumChatFormatting.WHITE.toString() + (int) blaze_boss_kills_tier_3, - guiLeft + xStart + xOffset * 2, - guiTop + yStartBottom + yOffset * 5, - 76 - ); - - float pet_milestone_ores_mined = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.pet_milestone_ores_mined"), 0); - float pet_milestone_sea_creatures_killed = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.pet_milestone_sea_creatures_killed"), 0); - - float items_fished = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished"), 0); - float items_fished_treasure = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished_treasure"), 0); - float items_fished_large_treasure = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished_large_treasure"), 0); - - Utils.renderAlignedString( - EnumChatFormatting.GREEN + "Ores Mined", - EnumChatFormatting.WHITE.toString() + (int) pet_milestone_ores_mined, - guiLeft + xStart + xOffset * 2, - guiTop + yStartTop, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.GREEN + "Sea Creatures Killed", - EnumChatFormatting.WHITE.toString() + (int) pet_milestone_sea_creatures_killed, - guiLeft + xStart + xOffset * 2, - guiTop + yStartTop + yOffset, - 76 - ); - - Utils.renderAlignedString( - EnumChatFormatting.GREEN + "Items Fished", - EnumChatFormatting.WHITE.toString() + (int) items_fished, - guiLeft + xStart + xOffset * 2, - guiTop + yStartTop + yOffset * 3, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.GREEN + "Treasures Fished", - EnumChatFormatting.WHITE.toString() + (int) items_fished_treasure, - guiLeft + xStart + xOffset * 2, - guiTop + yStartTop + yOffset * 4, - 76 - ); - Utils.renderAlignedString( - EnumChatFormatting.GREEN + "Large Treasures", - EnumChatFormatting.WHITE.toString() + (int) items_fished_large_treasure, - guiLeft + xStart + xOffset * 2, - guiTop + yStartTop + yOffset * 5, - 76 - ); - - if (topKills == null) { - topKills = new TreeMap<>(); - JsonObject stats = profileInfo.get("stats").getAsJsonObject(); - for (Map.Entry<String, JsonElement> entry : stats.entrySet()) { - if (entry.getKey().startsWith("kills_")) { - if (entry.getValue().isJsonPrimitive()) { - JsonPrimitive prim = (JsonPrimitive) entry.getValue(); - if (prim.isNumber()) { - String name = WordUtils.capitalizeFully(entry.getKey().substring("kills_".length()).replace("_", " ")); - Set<String> kills = topKills.computeIfAbsent(prim.getAsInt(), k -> new HashSet<>()); - kills.add(name); - } - } - } - } - } - if (topDeaths == null) { - topDeaths = new TreeMap<>(); - JsonObject stats = profileInfo.get("stats").getAsJsonObject(); - for (Map.Entry<String, JsonElement> entry : stats.entrySet()) { - if (entry.getKey().startsWith("deaths_")) { - if (entry.getValue().isJsonPrimitive()) { - JsonPrimitive prim = (JsonPrimitive) entry.getValue(); - if (prim.isNumber()) { - String name = WordUtils.capitalizeFully(entry.getKey().substring("deaths_".length()).replace("_", " ")); - Set<String> deaths = topDeaths.computeIfAbsent(prim.getAsInt(), k -> new HashSet<>()); - deaths.add(name); - } - } - } - } - } - - int index = 0; - for (int killCount : topKills.descendingKeySet()) { - if (index >= 6) break; - Set<String> kills = topKills.get(killCount); - for (String killType : kills) { - if (index >= 6) break; - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + killType + " Kills", - EnumChatFormatting.WHITE.toString() + killCount, - guiLeft + xStart + xOffset * 3, - guiTop + yStartTop + yOffset * index, - 76 - ); - index++; - } - } - index = 0; - for (int deathCount : topDeaths.descendingKeySet()) { - if (index >= 6) break; - Set<String> deaths = topDeaths.get(deathCount); - for (String deathType : deaths) { - if (index >= 6) break; - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Deaths: " + deathType, - EnumChatFormatting.WHITE.toString() + deathCount, - guiLeft + xStart + xOffset * 3, - guiTop + yStartBottom + yOffset * index, - 76 - ); - index++; - } - } - } - - private void drawMiningPage(int mouseX, int mouseY, float partialTicks) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_mining); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); - - JsonObject profileInfo = profile.getProfileInformation(profileId); - if (profileInfo == null) return; - JsonObject skillInfo = profile.getSkillInfo(profileId); - - float xStart = 22; - float xOffset = 103; - float yStartTop = 27; - float yStartBottom = 105; - float yOffset = 10; - - int x = guiLeft + 23; - int y = guiTop + 25; - int sectionWidth = 110; - JsonObject leveling = Constants.LEVELING; - ProfileViewer.Level levelObjhotm = levelObjhotms.get(profileId); - if (levelObjhotm == null) { - float hotmXp = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.experience"), 0); - levelObjhotm = ProfileViewer.getLevel(Utils.getElementOrDefault(leveling, "HOTM", new JsonArray()).getAsJsonArray(), - hotmXp, 7, false - ); - levelObjhotms.put(profileId, levelObjhotm); - } - - String skillName = EnumChatFormatting.RED + "HOTM"; - //The stats that show - float mithrilPowder = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_mithril"), 0); - float gemstonePowder = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_gemstone"), 0); - float mithrilPowderTotal = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_spent_mithril"), 0); - float gemstonePowderTotal = - (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_spent_gemstone"), 0)); - String jadeCrystal = - (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.jade_crystal.state"), "Not Found")); - float crystalPlacedAmount = - (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.crystals.jade_crystal.total_placed"), 0)); - String jadeCrystalString = "§c✖"; - String amethystCrystal = (Utils.getElementAsString( - Utils.getElement(profileInfo, "mining_core.crystals.amethyst_crystal.state"), - "Not Found" - )); - String amethystCrystalString = "§c✖"; - String amberCrystal = (Utils.getElementAsString( - Utils.getElement(profileInfo, "mining_core.crystals.amber_crystal.state"), - "Not Found" - )); - String amberCrystalString = "§c✖"; - String sapphireCrystal = (Utils.getElementAsString( - Utils.getElement(profileInfo, "mining_core.crystals.sapphire_crystal.state"), - "Not Found" - )); - String sapphireCrystalString = "§c✖"; - String topazCrystal = (Utils.getElementAsString( - Utils.getElement(profileInfo, "mining_core.crystals.topaz_crystal.state"), - "Not Found" - )); - String topazCrystalString = "§c✖"; - String jasperCrystal = (Utils.getElementAsString( - Utils.getElement(profileInfo, "mining_core.crystals.jasper_crystal.state"), - "Not Found" - )); - String jasperCrystalString = "§c✖"; - String rubyCrystal = - (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.ruby_crystal.state"), "Not Found")); - String rubyCrystalString = "§c✖"; - int miningFortune = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune"), 0))); - int miningFortuneStat = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune"), 0)) * 5); - int miningSpeed = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed"), 0))); - int miningSpeedStat = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed"), 0)) * 20); - int dailyPowder = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_powder"), 0))); - int dailyPowderStat = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_powder"), 0)) * 36 + 364); - int effMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0))); - float effMinerStat = - (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)) * 0.4 + - 10.4); - float effMinerStat2 = - (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)) * .06 + - 0.31); - int tittyInsane = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.titanium_insanium"), 0))); - float tittyInsaneStat = - (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.titanium_insanium"), 0)) * .1 + - 2); - int luckofcave = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.random_event"), 0))); - int luckofcaveStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.random_event"), 0))); - int madMining = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_madness"), 0))); - int skyMall = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_effect"), 0))); - int goblinKiller = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.goblin_killer"), 0))); - int seasonMine = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_experience"), 0))); - float seasonMineStat = (float) ( - (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.mining_experience"), 0)) * 0.1 + 5); - int quickForge = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.forge_time"), 0))); - float quickForgeStat = - (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.forge_time"), 0)) * .5 + 10); - int frontLoad = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.front_loaded"), 0))); - int orbit = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.experience_orbs"), 0))); - float orbitStat = - (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.experience_orbs"), 0)) * .01 + - 0.2); - int crystallized = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fallen_star_bonus"), 0))); - int crystallizedStat = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fallen_star_bonus"), 0)) * 6 + 14); - int professional = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.professional"), 0))); - int professionalStat = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.professional"), 0)) * 5 + 50); - int greatExplorer = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.great_explorer"), 0))); - int greatExplorerStat = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.great_explorer"), 0)) * 4 + 16); - int fortunate = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fortunate"), 0))); - int fortunateStat = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fortunate"), 0)) * 4 + 20); - int lonesomeMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.lonesome_miner"), 0))); - float lonesomeMinerStat = - (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.lonesome_miner"), 0)) * .5 + - 5); - int miningFortune2 = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune_2"), 0))); - int miningFortune2Stat = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune_2"), 0)) * 5); - int miningSpeed2 = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_2"), 0))); - int miningSpeed2Stat = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_2"), 0)) * 40); - int miningSpeedBoost = - ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_boost"), 0))); - int veinSeeker = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.vein_seeker"), 0))); - int powderBuff = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.powder_buff"), 0))); - int potm = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.special_0"), 0))); - int fortnite = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.precision_mining"), 0))); - int starPowder = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.star_powder"), 0))); - int pickoblus = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.pickaxe_toss"), 0))); - int maniacMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.maniac_miner"), 0))); - - if (effMinerStat2 < 1) { - effMinerStat2 = 1; - } - int mole = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mole"), 0))); - float moleStat = - (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.mole"), 0)) * 0.051); - double moleperkstat = (double) mole / 20 - 0.55 + 50; - double moleperkstat2 = (double) Math.round(moleperkstat * 100) / 100; - - float output = Math.round((float) (moleperkstat2 % 1) * 100); - if (output == 0) { - output = 100; - } - - //The logic for some of the stats - if (Objects.equals(jadeCrystal, "NOT_FOUND")) { - jadeCrystalString = "§c✖"; - } else if (Objects.equals(jadeCrystal, "FOUND")) { - jadeCrystalString = "§a✔"; - } - if (Objects.equals(amethystCrystal, "NOT_FOUND")) { - amethystCrystalString = "§c✖"; - } else if (Objects.equals(amethystCrystal, "FOUND")) { - amethystCrystalString = "§a✔"; - } - if (Objects.equals(amberCrystal, "NOT_FOUND")) { - amberCrystalString = "§c✖"; - } else if (Objects.equals(amberCrystal, "FOUND")) { - amberCrystalString = "§a✔"; - } - if (Objects.equals(sapphireCrystal, "NOT_FOUND")) { - sapphireCrystalString = "§c✖"; - } else if (Objects.equals(sapphireCrystal, "FOUND")) { - sapphireCrystalString = "§a✔"; - } - if (Objects.equals(topazCrystal, "NOT_FOUND")) { - topazCrystalString = "§c✖"; - } else if (Objects.equals(topazCrystal, "FOUND")) { - topazCrystalString = "§a✔"; - } - if (Objects.equals(jasperCrystal, "NOT_FOUND")) { - jasperCrystalString = "§c✖"; - } else if (Objects.equals(jasperCrystal, "FOUND")) { - jasperCrystalString = "§a✔"; - } - if (Objects.equals(rubyCrystal, "NOT_FOUND")) { - rubyCrystalString = "§c✖"; - } else if (Objects.equals(rubyCrystal, "FOUND")) { - rubyCrystalString = "§a✔"; - } - - //The rendering of the stats - //hotm level - renderXpBar(skillName, iron_pick, x, y, sectionWidth, levelObjhotm, mouseX, mouseY); - //Powder - Utils.renderAlignedString( - EnumChatFormatting.DARK_GREEN + "Mithril Powder", - EnumChatFormatting.WHITE + shortNumberFormat(mithrilPowder, 0), - guiLeft + xStart, - guiTop + yStartTop + 24, - 115 - ); - Utils.renderAlignedString( - EnumChatFormatting.LIGHT_PURPLE + "Gemstone Powder", - EnumChatFormatting.WHITE + shortNumberFormat(gemstonePowder, 0), - guiLeft + xStart, - guiTop + yStartTop + 44, - 115 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_GREEN + "Total Mithril Powder", - EnumChatFormatting.WHITE + shortNumberFormat(mithrilPowderTotal + mithrilPowder, 0), - guiLeft + xStart, - guiTop + yStartTop + 34, - 115 - ); - Utils.renderAlignedString( - EnumChatFormatting.LIGHT_PURPLE + "Total Gemstone Powder", - EnumChatFormatting.WHITE + shortNumberFormat(gemstonePowderTotal + gemstonePowder, 0), - guiLeft + xStart, - guiTop + yStartTop + 54, - 115 - ); - //Crystals - Utils.renderAlignedString(EnumChatFormatting.GREEN + "Jade Crystal:", EnumChatFormatting.WHITE + jadeCrystalString, - guiLeft + xStart, guiTop + yStartTop + 74, 110 - ); - Utils.renderAlignedString(EnumChatFormatting.GOLD + "Amber Crystal:", EnumChatFormatting.WHITE + amberCrystalString, - guiLeft + xStart, guiTop + yStartTop + 84, 110 - ); - Utils.renderAlignedString( - EnumChatFormatting.DARK_PURPLE + "Amethyst Crystal:", - EnumChatFormatting.WHITE + amethystCrystalString, - guiLeft + xStart, - guiTop + yStartTop + 94, - 110 - ); - Utils.renderAlignedString( - EnumChatFormatting.AQUA + "Sapphire Crystal:", - EnumChatFormatting.WHITE + sapphireCrystalString, - guiLeft + xStart, - guiTop + yStartTop + 104, - 110 - ); - Utils.renderAlignedString( - EnumChatFormatting.YELLOW + "Topaz Crystal:", - EnumChatFormatting.WHITE + topazCrystalString, - guiLeft + xStart, - guiTop + yStartTop + 114, - 110 - ); - Utils.renderAlignedString( - EnumChatFormatting.LIGHT_PURPLE + "Jasper Crystal:", - EnumChatFormatting.WHITE + jasperCrystalString, - guiLeft + xStart, - guiTop + yStartTop + 124, - 110 - ); - Utils.renderAlignedString(EnumChatFormatting.RED + "Ruby Crystal:", EnumChatFormatting.WHITE + rubyCrystalString, - guiLeft + xStart, guiTop + yStartTop + 134, 110 - ); - Utils.renderAlignedString( - EnumChatFormatting.BLUE + "Total Placed Crystals:", - EnumChatFormatting.WHITE + shortNumberFormat(crystalPlacedAmount, 0), - guiLeft + xStart, - guiTop + yStartTop + 149, - 110 - ); - - //hotm render - //Pain - - renderHotmPerk( - miningSpeed, - (int) (guiLeft + xStart + 255), - (int) (guiTop + yStartTop + 138), - mouseX, - mouseY, - () -> miningSpeed != 50 && miningSpeed != 0 ? Lists.newArrayList( - "Mining Speed", - EnumChatFormatting.GRAY + "Level " + miningSpeed + EnumChatFormatting.DARK_GRAY + "/50", - "", - EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "+" + miningSpeedStat + - EnumChatFormatting.GOLD + " ⸕ Mining", - EnumChatFormatting.GOLD + "Speed" + EnumChatFormatting.GRAY + ".", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + numberFormat.format(Math.pow(miningSpeed + 2, 3)) + " Mithril Powder" - ) : Lists.newArrayList( - "Mining Speed", - EnumChatFormatting.GRAY + "Level " + miningSpeed + EnumChatFormatting.DARK_GRAY + "/50", - "", - EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "+" + miningSpeedStat + - EnumChatFormatting.GOLD + " ⸕ Mining", - EnumChatFormatting.GOLD + "Speed" + EnumChatFormatting.GRAY + "." - ), - 50 - ); - - renderHotmPerk( - miningFortune, - (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 114), - mouseX, mouseY, - () -> miningFortune != 0 && miningFortune != 50 ? Lists.newArrayList( - "Mining Fortune", - EnumChatFormatting.GRAY + "Level " + miningFortune + EnumChatFormatting.DARK_GRAY + "/50", - "", - EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "+" + miningFortuneStat + - EnumChatFormatting.GOLD + " ☘ Mining", - EnumChatFormatting.GOLD + "Fortune" + EnumChatFormatting.GRAY + ".", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + numberFormat.format(Math.pow(miningFortune + 2, 3)) + " Mithril Powder" - ) : Lists.newArrayList( - "Mining Fortune", - EnumChatFormatting.GRAY + "Level " + miningFortune + EnumChatFormatting.DARK_GRAY + "/50", - "", - EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "+" + miningFortuneStat + - EnumChatFormatting.GOLD + " ☘ Mining", - EnumChatFormatting.GOLD + "Fortune" + EnumChatFormatting.GRAY + "." - ), - 50 - ); - - renderHotmPerk( - tittyInsane, - (int) (guiLeft + xStart + 231), (int) (guiTop + yStartTop + 114), - mouseX, mouseY, - () -> tittyInsane != 0 && tittyInsane != 50 ? Lists.newArrayList( - "Titanium Insanium", - EnumChatFormatting.GRAY + "Level " + tittyInsane + EnumChatFormatting.DARK_GRAY + "/50", - "", - EnumChatFormatting.GRAY + "When mining Mithril Ore, you", - EnumChatFormatting.GRAY + "have a " + EnumChatFormatting.GREEN + tittyInsaneStat + "% " + - EnumChatFormatting.GRAY + "chance to", - EnumChatFormatting.GRAY + "convert the block into Titanium", - EnumChatFormatting.GRAY + "Ore.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + numberFormat.format((int) Math.pow(tittyInsane + 2, 3)) + " Mithril Powder" - ) : Lists.newArrayList( - "Titanium Insanium", - EnumChatFormatting.GRAY + "Level " + tittyInsane + EnumChatFormatting.DARK_GRAY + "/50", - "", - EnumChatFormatting.GRAY + "When mining Mithril Ore, you", - EnumChatFormatting.GRAY + "have a " + EnumChatFormatting.GREEN + tittyInsaneStat + "% " + - EnumChatFormatting.GRAY + "chance to", - EnumChatFormatting.GRAY + "convert the block into Titanium", - EnumChatFormatting.GRAY + "Ore." - ), - 50 - ); - - renderPickaxeAbility( - miningSpeedBoost, - (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 114), - mouseX, mouseY, - () -> potm == 0 ? Lists.newArrayList( // Peak of the mountain == 0 - "Mining Speed Boost", - "", - EnumChatFormatting.GRAY + "Pickaxe Ability: Mining Speed Boost", - EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "200% " + EnumChatFormatting.GOLD + "⸕ Mining", - EnumChatFormatting.GOLD + "Speed " + EnumChatFormatting.GRAY + "for " + EnumChatFormatting.GREEN + "15s" + - EnumChatFormatting.GRAY, - EnumChatFormatting.DARK_GRAY + "Cooldown: " + EnumChatFormatting.GREEN + "120s" - ) : Lists.newArrayList( // Peak of the mountain > 0 - "Mining Speed Boost", - "", - EnumChatFormatting.GRAY + "Pickaxe Ability: Mining Speed Boost", - EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "300% " + EnumChatFormatting.GOLD + "⸕ Mining", - EnumChatFormatting.GOLD + "Speed " + EnumChatFormatting.GRAY + "for " + EnumChatFormatting.GREEN + "20s" + - EnumChatFormatting.GRAY, - EnumChatFormatting.DARK_GRAY + "Cooldown: " + EnumChatFormatting.GREEN + "120s" - ) - ); - - renderPickaxeAbility( - veinSeeker, - (int) (guiLeft + xStart + 183), (int) (guiTop + yStartTop + 18), - mouseX, mouseY, - () -> Lists.newArrayList( - "Vein Seeker", - "", - "§6Pickaxe Ability: Vein Seeker", - "§7Points in the direction of the", - "§7nearest vein and grants §a+§a3§7", - "§7§6Mining Spread §7for §a14s§7§7.", - "§8Cooldown: §a60s" - ) - ); - - renderHotmPerk( - luckofcave, - (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 90), - mouseX, mouseY, - () -> luckofcave != 0 && luckofcave != 45 ? Lists.newArrayList( - "Luck of the Cave", - "§7Level " + luckofcave + EnumChatFormatting.DARK_GRAY + "/45", - "", - "§7Increases the chance for you to", - "§7trigger rare occurrences im", - "§2Dwarven Mines " + EnumChatFormatting.GRAY + "by " + EnumChatFormatting.GREEN + luckofcaveStat + "%§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + numberFormat.format((int) Math.pow(luckofcave + 2, 3.07)) + " Mithril Powder" - ) : Lists.newArrayList( - "Luck of the Cave", - "§7Level " + luckofcave + EnumChatFormatting.DARK_GRAY + "/45", - "", - "§7Increases the chance for you to", - "§7trigger rare occurrences im", - "§2Dwarven Mines " + EnumChatFormatting.GRAY + "by " + EnumChatFormatting.GREEN + luckofcaveStat + "%§7." - ), - 45 - ); - - renderHotmPerk( - dailyPowder, - (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 90), - mouseX, mouseY, - () -> dailyPowder != 0 && dailyPowder != 100 ? Lists.newArrayList( - "Daily Powder", - EnumChatFormatting.GRAY + "Level " + dailyPowder + EnumChatFormatting.DARK_GRAY + "/100", - "", - EnumChatFormatting.GRAY + "Gains " + EnumChatFormatting.GREEN + dailyPowderStat + " Powder" + - EnumChatFormatting.GRAY + " from the", - EnumChatFormatting.GRAY + "first ore you mine every day.", - EnumChatFormatting.GRAY + "Works for all Powder types.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + (200 + ((dailyPowder) * 18)) + " Mithril Powder" - ) : Lists.newArrayList( - "Daily Powder", - EnumChatFormatting.GRAY + "Level " + dailyPowder + EnumChatFormatting.DARK_GRAY + "/100", - "", - EnumChatFormatting.GRAY + "Gains " + EnumChatFormatting.GREEN + dailyPowderStat + " Powder" + - EnumChatFormatting.GRAY + " from the", - EnumChatFormatting.GRAY + "first ore you mine every day.", - EnumChatFormatting.GRAY + "Works for all Powder types." - ), - 100 - ); - - float finalEffMinerStat2 = effMinerStat2; - renderHotmPerk( - effMiner, - (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 66), - mouseX, mouseY, - () -> effMiner != 0 && effMiner != 100 ? Lists.newArrayList( - "Efficient Miner", - EnumChatFormatting.GRAY + "Level " + effMiner + EnumChatFormatting.DARK_GRAY + "/100", - "", - EnumChatFormatting.GRAY + "When mining ores, you have a", - EnumChatFormatting.GREEN + "" + effMinerStat + "%" + EnumChatFormatting.GRAY + " chance to mine " + - EnumChatFormatting.GREEN + Math.round(finalEffMinerStat2), - EnumChatFormatting.GRAY + "adjacent ores.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + numberFormat.format((int) Math.pow(effMiner + 2, 2.6)) + " Mithril Powder" - ) : Lists.newArrayList( - "Efficient Miner", - EnumChatFormatting.GRAY + "Level " + effMiner + EnumChatFormatting.DARK_GRAY + "/100", - "", - EnumChatFormatting.GRAY + "When mining ores, you have a", - EnumChatFormatting.GREEN + "" + effMinerStat + "%" + EnumChatFormatting.GRAY + " chance to mine " + - EnumChatFormatting.GREEN + Math.round(finalEffMinerStat2), - EnumChatFormatting.GRAY + "adjacent ores." - ), - 100 - ); - - renderHotmPerk( - potm, - (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 42), - mouseX, mouseY, - () -> { - switch (potm) { - case 0: - return Lists.newArrayList( - EnumChatFormatting.RED + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "50000 Mithril Powder" - ); - case 1: - return Lists.newArrayList( - EnumChatFormatting.YELLOW + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", - "", - "§7§8+§c1 Pickaxe Ability Level", - "§7§8+§51 Token of the Mountain", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "50000 Mithril Powder" - ); - case 2: - return Lists.newArrayList( - EnumChatFormatting.YELLOW + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", - "", - "§7§8+§c1 Pickaxe Ability Level", - "§7§8+§51 Token of the Mountain", - "§7§8+§a1 Forge Slot", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "75000 Mithril Powder" - ); - case 3: - return Lists.newArrayList( - EnumChatFormatting.YELLOW + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", - "", - "§7§8+§c1 Pickaxe Ability Level", - "§7§8+§51 Token of the Mountain", - "§7§8+§a1 Forge Slot", - "§7§8+§a1 Commission Slot", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "100000 Mithril Powder" - ); - case 4: - return Lists.newArrayList( - EnumChatFormatting.YELLOW + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", - "", - "§7§8+§c1 Pickaxe Ability Level", - "§7§8+§51 Token of the Mountain", - "§7§8+§a1 Forge Slot", - "§7§8+§a1 Commission Slot", - "§7§8+§21 Mithril Powder §7when", - "§7mining §fMithril", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "125000 Mithril Powder" - ); - case 5: - return Lists.newArrayList( - EnumChatFormatting.GREEN + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", - "", - "§7§8+§c1 Pickaxe Ability Level", - "§7§8+§51 Token of the Mountain", - "§7§8+§a1 Forge Slot", - "§7§8+§a1 Commission Slot", - "§7§8+§21 Mithril Powder §7when", - "§7mining §fMithril", - "§7§8+§51 Token of the Mountain" - ); - } - return null; - }, - potm > 0 ? new ItemStack(Blocks.redstone_block) : new ItemStack(Blocks.bedrock), - true // A redstone block or bedrock is being rendered, so standard GUI item lighting needs to be enabled. - ); - - float finalOutput = output; - renderHotmPerk( - mole, - (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 18), - mouseX, mouseY, - () -> mole != 0 && mole != 190 ? Lists.newArrayList( - "Mole", - EnumChatFormatting.GRAY + "Level " + mole + EnumChatFormatting.DARK_GRAY + "/190", - "", - EnumChatFormatting.GRAY + "When mining hard stone, you have", - EnumChatFormatting.GRAY + "a " + EnumChatFormatting.GREEN + finalOutput + "% " + EnumChatFormatting.GRAY + - "chance to mine " + EnumChatFormatting.GREEN, - EnumChatFormatting.GREEN + "" + Math.round(moleStat) + EnumChatFormatting.GRAY + " adjacent hard stone block" + - (moleStat == 1.0 ? "." : "s."), - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.LIGHT_PURPLE + "" + numberFormat.format((int) Math.pow(mole + 2, 2.2)) + " Gemstone Powder" - ) : Lists.newArrayList( - "Mole", - EnumChatFormatting.GRAY + "Level " + mole + EnumChatFormatting.DARK_GRAY + "/190", - "", - EnumChatFormatting.GRAY + "When mining hard stone, you have", - EnumChatFormatting.GRAY + "a " + EnumChatFormatting.GREEN + finalOutput + "% " + EnumChatFormatting.GRAY + - "chance to mine " + EnumChatFormatting.GREEN, - EnumChatFormatting.GREEN + "" + Math.round(moleStat) + EnumChatFormatting.GRAY + " adjacent hard stone block" + - (moleStat == 1.0 ? "." : "s.") - ), - 190 - ); - - renderHotmPerk( - powderBuff, - (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop - 6), - mouseX, mouseY, - () -> powderBuff != 0 && powderBuff != 50 ? Lists.newArrayList( - "Powder Buff", - EnumChatFormatting.GRAY + "Level " + powderBuff + EnumChatFormatting.DARK_GRAY + "/50", - "", - EnumChatFormatting.GRAY + "Gain " + EnumChatFormatting.GREEN + powderBuff + "% " + EnumChatFormatting.GRAY + - "more Mithril", - EnumChatFormatting.GRAY + "Powder and Gemstone Powder§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.LIGHT_PURPLE + "" + numberFormat.format((int) Math.pow(powderBuff + 2, 3.2)) + " Gemstone Powder" - ) : Lists.newArrayList( - "Powder Buff", - EnumChatFormatting.GRAY + "Level " + powderBuff + EnumChatFormatting.DARK_GRAY + "/50", - "", - EnumChatFormatting.GRAY + "Gain " + EnumChatFormatting.GREEN + powderBuff + "% " + EnumChatFormatting.GRAY + - "more Mithril", - EnumChatFormatting.GRAY + "Powder and Gemstone Powder§7." - ), - 50 - ); - - renderHotmPerk( - skyMall, - (int) (guiLeft + xStart + 183), (int) (guiTop + yStartTop + 66), - mouseX, mouseY, - () -> Lists.newArrayList( - "Sky Mall", - "§7Every SkyBlock day, you receive", - "§7a random buff in the §2Dwarven", - "§2Mines§7.", - "", - "§7Possible Buffs", - "§8 ■ §7Gain §a+100 §6⸕ Mining Speed.", - "§8 ■ §7Gain §a+50 §6☘ Mining Fortune.", - "§8 ■ §7Gain §a+15% §7chance to gain", - " §7extra Powder while mining.", - "§8 ■ §7Reduce Pickaxe Ability cooldown", - " §7by §a20%", "§8 ■ §7§a10x §7chance to find Goblins", - " §7while mining.", - "§8 ■ §7Gain §a5x §9Titanium §7drops." - ), - new ItemStack(skyMall > 0 ? Items.diamond : Items.coal) - ); - - renderHotmPerk( - goblinKiller, - (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 42), - mouseX, mouseY, - () -> Lists.newArrayList( - "Goblin Killer", - "§7Killing a §6Golden Goblin", - "§6§7gives §2200 §7extra §2Mithril", - "§2Powder§7, while killing other", - "§7Goblins gives some based on", - "§7their wits." - ), - new ItemStack(goblinKiller > 0 ? Items.diamond : Items.coal) - ); - - renderHotmPerk( - seasonMine, - (int) (guiLeft + xStart + 231), (int) (guiTop + yStartTop + 66), - mouseX, mouseY, - () -> seasonMine != 0 && seasonMine != 100 ? Lists.newArrayList( - "Seasoned Mineman", - "§7Level " + seasonMine + "§8/100", - "", - "§7Increases your Mining", - "§7experience gain by " + EnumChatFormatting.GREEN + seasonMineStat + "%§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + numberFormat.format((int) Math.pow(seasonMine + 2, 2.3)) + " Mithril Powder" - ) : Lists.newArrayList( - "Seasoned Mineman", - "§7Level " + seasonMine + "§8/100", - "", - "§7Increases your Mining", - "§7experience gain by " + EnumChatFormatting.GREEN + seasonMineStat + "%§7." - ), - 100 - ); - - renderHotmPerk( - madMining, - (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 66), - mouseX, mouseY, - () -> Lists.newArrayList( - "Mining Madness", - "§7Grants §a+50 §6⸕ Mining Speed", - "§7and §6☘ Mining Fortune§7." - ), - new ItemStack(madMining > 0 ? Items.diamond : Items.coal) - ); - - renderHotmPerk( - lonesomeMiner, - (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 18), - mouseX, mouseY, - () -> lonesomeMiner != 0 && lonesomeMiner != 45 ? Lists.newArrayList( - "Lonesome Miner", - "§7Level " + lonesomeMiner + EnumChatFormatting.DARK_GRAY + "/45", - "", - "§7Increases §c❁ Strength, §9☣ Crit", - "§9Chance, §9☠ Crit Damage, §a❈", - "§aDefense, and §c❤ Health", - "§c§7statistics gain by " + EnumChatFormatting.GREEN + lonesomeMinerStat + "%§7", - "§7while in the Crystal Hollows.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.LIGHT_PURPLE + "" + numberFormat.format((int) Math.pow(lonesomeMiner + 2, 3.07)) + " Gemstone Powder" - ) : Lists.newArrayList( - "Lonesome Miner", - "§7Level " + lonesomeMiner + EnumChatFormatting.DARK_GRAY + "/45", - "", - "§7Increases §c❁ Strength, §9☣ Crit", - "§9Chance, §9☠ Crit Damage, §a❈", - "§aDefense, and §c❤ Health", - "§c§7statistics gain by " + EnumChatFormatting.GREEN + lonesomeMinerStat + "%§7" - ), - 45 - ); - - renderHotmPerk( - professional, - (int) (guiLeft + xStart + 231), (int) (guiTop + yStartTop + 18), - mouseX, mouseY, - () -> professional != 0 && professional != 140 ? Lists.newArrayList( - "Professional", - "§7Level " + professional + EnumChatFormatting.DARK_GRAY + "/140", - "", - "§7Gain §a+" + professionalStat + "§6 ⸕ Mining", - "§6Speed§7 when mining Gemstones.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.LIGHT_PURPLE + "" + numberFormat.format((int) Math.pow(professional + 2, 2.3)) + " Gemstone Powder" - ) : Lists.newArrayList( - "Professional", - "§7Level " + professional + EnumChatFormatting.DARK_GRAY + "/140", - "", - "§7Gain §a+" + professionalStat + "§6 ⸕ Mining", - "§6Speed§7 when mining Gemstones." - ), - 140 - ); - - renderHotmPerk( - miningSpeed2, - (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop - 6), - mouseX, mouseY, - () -> miningSpeed2 != 0 && miningSpeed2 != 50 ? Lists.newArrayList( - "Mining Speed 2", - "§7Level " + miningSpeed2 + EnumChatFormatting.DARK_GRAY + "/50", - "", - "§7Grants " + EnumChatFormatting.GREEN + "+" + miningSpeed2Stat + EnumChatFormatting.GOLD + " ⸕ Mining", - "§6Speed§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.LIGHT_PURPLE + "" + numberFormat.format(Math.pow(miningSpeed2 + 2, 3))+ " Gemstone Powder" - ) : Lists.newArrayList( - "Mining Speed 2", - "§7Level " + miningSpeed2 + EnumChatFormatting.DARK_GRAY + "/50", - "", - "§7Grants " + EnumChatFormatting.GREEN + "+" + miningSpeed2Stat + EnumChatFormatting.GOLD + " ⸕ Mining", - "§6Speed§7." - ), - 50 - ); - - renderHotmPerk( - quickForge, - (int) (guiLeft + xStart + 279), (int) (guiTop + yStartTop + 114), - mouseX, mouseY, - () -> quickForge != 0 && quickForge != 20 ? Lists.newArrayList( - "Quick Forge", - "§7Level " + quickForge + EnumChatFormatting.DARK_GRAY + "/20", - "", - "§7Decreases the time it takes to", - "§7forge by §a" + (quickForgeStat < 20 ? quickForgeStat : 30) + "%§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + numberFormat.format((int) Math.pow(quickForge + 2, 4)) + " Mithril Powder" - ) : Lists.newArrayList( - "Quick Forge", - "§7Level " + quickForge + EnumChatFormatting.DARK_GRAY + "/20", - "", - "§7Decreases the time it takes to", - "§7forge by §a" + (quickForgeStat < 20 ? quickForgeStat : 30) + "%§7." - ), - 20 - ); - - renderHotmPerk( - fortunate, - (int) (guiLeft + xStart + 279), (int) (guiTop + yStartTop + 18), - mouseX, mouseY, - () -> fortunate != 0 && fortunate != 20 ? Lists.newArrayList( - "Fortunate", - "§7Level " + fortunate + EnumChatFormatting.DARK_GRAY + "/20", - "", - "§7Gain " + EnumChatFormatting.GREEN + "+" + fortunateStat + " §6☘ Mining", - "§6Fortune§7 when mining Gemstone.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + numberFormat.format((int) Math.pow(fortunate + 2, 3.05)) + " Mithril Powder" - ) : Lists.newArrayList( - "Fortunate", - "§7Level " + fortunate + EnumChatFormatting.DARK_GRAY + "/20", - "", - "§7Gain " + EnumChatFormatting.GREEN + "+" + fortunateStat + " §6☘ Mining", - "§6Fortune§7 when mining Gemstone." - ), - 20 - ); - - renderHotmPerk( - greatExplorer, - (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 18), - mouseX, mouseY, - () -> greatExplorer != 0 && greatExplorer != 20 ? Lists.newArrayList( - "Great Explorer", - "§7Level " + greatExplorer + EnumChatFormatting.DARK_GRAY + "/20", - "", - "§7Grants " + EnumChatFormatting.GREEN + "+" + greatExplorerStat + "% " + EnumChatFormatting.GRAY + "chance to", - "§7find treasure.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.LIGHT_PURPLE + "" + numberFormat.format((int) Math.pow(greatExplorer + 2, 4)) + " Gemstone Powder" - ) : Lists.newArrayList( - "Great Explorer", - "§7Level " + greatExplorer + EnumChatFormatting.DARK_GRAY + "/20", - "", - "§7Grants " + EnumChatFormatting.GREEN + "+" + greatExplorerStat + "% " + EnumChatFormatting.GRAY + "chance to", - "§7find treasure." - ), - 20 - ); - - renderHotmPerk( - miningFortune2, - (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop - 6), - mouseX, mouseY, - () -> miningFortune2 != 0 && miningFortune2 != 50 ? Lists.newArrayList( - "Mining Fortune 2", - "§7Level " + miningFortune2 + EnumChatFormatting.DARK_GRAY + "/50", - "", - "§7Grants §a+§a" + miningFortune2Stat + "§7 §6☘ Mining", "§6Fortune§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.LIGHT_PURPLE + "" + numberFormat.format((int) Math.pow(miningFortune2 + 2, 3.2)) + " Gemstone Powder" - ) : Lists.newArrayList( - "Mining Fortune 2", - "§7Level " + miningFortune2 + EnumChatFormatting.DARK_GRAY + "/50", - "", - "§7Grants §a+§a" + miningFortune2Stat + "§7 §6☘ Mining", "§6Fortune§7." - ), - 50 - ); - - renderHotmPerk( - orbit, - (int) (guiLeft + xStart + 279), (int) (guiTop + yStartTop + 66), - mouseX, mouseY, - () -> orbit != 0 && orbit != 80 ? Lists.newArrayList( - "Orbiter", - "§7Level " + orbit + EnumChatFormatting.DARK_GRAY + "/80", - "", - "§7When mining ores, you have a", - EnumChatFormatting.GREEN + "" + orbitStat + "%" + EnumChatFormatting.GRAY + " chance to get a random", - "§7amount of experience orbs.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + (int) ((orbit + 1) * 70) + " Mithril Powder" - ) : Lists.newArrayList( - "Orbiter", - "§7Level " + orbit + EnumChatFormatting.DARK_GRAY + "/80", - "", - "§7When mining ores, you have a", - EnumChatFormatting.GREEN + "" + orbitStat + "%" + EnumChatFormatting.GRAY + " chance to get a random", - "§7amount of experience orbs." - ), - 80 - ); - - renderHotmPerk( - frontLoad, - (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 66), - mouseX, mouseY, - () -> Lists.newArrayList( - "Front Loaded", - "§7Grants §a+100 §6⸕ Mining Speed", - "§7and §6☘ Mining Fortune §7for", - "§7the first §e2,500 §7ores you", - "§7mine in a day." - ), - new ItemStack(frontLoad > 0 ? Items.diamond : Items.coal) - ); - - renderHotmPerk( - starPowder, - (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 42), - mouseX, mouseY, - () -> Lists.newArrayList( - "Star Powder", - "§7Mining Mithril Ore near §5Fallen", - "§5Crystals §7gives §a+3 §7extra", - "§7Mithril Powder§7." - ), - new ItemStack(starPowder > 0 ? Items.diamond : Items.coal) - ); - - renderHotmPerk( - fortnite, - (int) (guiLeft + xStart + 327), (int) (guiTop + yStartTop + 66), - mouseX, mouseY, - () -> Lists.newArrayList( - "Precision Mining", - "§7When mining ore, a particle", - "§7target appears on the block that", - "§7increases your §6⸕ Mining Speed", - "§7by §a30% §7when aiming at it." - ), - new ItemStack(fortnite > 0 ? Items.diamond : Items.coal) - ); - - renderHotmPerk( - crystallized, - (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 90), - mouseX, mouseY, - () -> crystallized != 0 && crystallized != 30 ? Lists.newArrayList( - "Crystallized", - "§7Level " + crystallized + EnumChatFormatting.DARK_GRAY + "/30", - "", - "§7Grants §a+§a" + crystallizedStat + "§7 §6⸕ Mining", - "§6Speed §7and a §a" + crystallizedStat + "%§7 §7chance", - "§7to deal §a+1 §7extra damage near", - "§7§5Fallen Stars§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "" + numberFormat.format((int) Math.pow(crystallized + 2, 2.4)) + " Mithril Powder" - ) : Lists.newArrayList( - "Crystallized", - "§7Level " + crystallized + EnumChatFormatting.DARK_GRAY + "/30", - "", - "§7Grants §a+§a" + crystallizedStat + "§7 §6⸕ Mining", - "§6Speed §7and a §a" + crystallizedStat + "%§7 §7chance", - "§7to deal §a+1 §7extra damage near", - "§7§5Fallen Stars§7." - ), - 30 - ); - - renderPickaxeAbility( - pickoblus, - (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 114), - mouseX, mouseY, - () -> Lists.newArrayList( - "Pickobulus", - "", - "§6Pickaxe Ability: Pickobulus", - "§7Throw your pickaxe to create an", - "§7explosion on impact, mining all", - "§7ores within a §a2§7 block", - "§7radius.", - "§8Cooldown: §a" + (potm == 0 ? "120s" : "110s") - ) - ); - - renderPickaxeAbility( - maniacMiner, - (int) (guiLeft + xStart + 327), (int) (guiTop + yStartTop + 18), - mouseX, mouseY, - () -> Lists.newArrayList( - EnumChatFormatting.RED + "Maniac Miner", - "", - "§6Pickaxe Ability: Maniac Miner", - "§7Spends all your Mana and grants", - "§7§a+1 §6⸕ Mining Speed §7for", - "§7every 10 Mana spent, for", - "§7§a§a15s§7§7.", - "§8Cooldown: §a59s" - ) - ); - } - - /** - * Renders a standard HOTM perk that can be levelled. - */ - private void renderHotmPerk( - int perkLevel, - int xPosition, - int yPosition, - int mouseX, - int mouseY, - Supplier<ArrayList<String>> tooltipSupplier, - int maxLevel - ) { - renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, false, maxLevel); - } - - /** - * Renders a pickaxe ability that can be unlocked once and not levelled. - */ - private void renderPickaxeAbility( - int perkLevel, - int xPosition, - int yPosition, - int mouseX, - int mouseY, - Supplier<ArrayList<String>> tooltipSupplier - ) { - renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, true, -1); - } - - /** - * Renders a HOTM perk. This method is only called from its overloads above. - */ - private void renderHotmPerk( - int perkLevel, - int xPosition, - int yPosition, - int mouseX, - int mouseY, - Supplier<ArrayList<String>> tooltipSupplier, - boolean isPickaxeAbility, - int maxLevel - ) { - boolean unlocked = perkLevel > 0; - GlStateManager.color(1, 1, 1, 1); - GlStateManager.disableLighting(); - - ItemStack itemStack; - if (isPickaxeAbility) { - RenderHelper.enableGUIStandardItemLighting(); // GUI standard item lighting must be enabled for items that are rendered as blocks, like emerald blocks. - itemStack = - new ItemStack(unlocked ? Blocks.emerald_block : Blocks.coal_block); // Pickaxe abilities are rendered as blocks - } else { // Non-pickaxe abilities are rendered as items - itemStack = new ItemStack(unlocked ? (perkLevel >= maxLevel ? Items.diamond : Items.emerald) : Items.coal); - } - - ArrayList<String> tooltip = tooltipSupplier.get(); - // Prepend the green, yellow, or red color on the first line of each tooltip depending on if the perk is unlocked - tooltip.set( - 0, - (unlocked - ? (perkLevel >= maxLevel ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) - : EnumChatFormatting.RED) + tooltip.get(0) - ); - - NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Custom Resource Packs - NBTTagCompound display = new NBTTagCompound(); - display.setString("Name", tooltip.get(0)); - nbt.setTag("display", display); - itemStack.setTagCompound(nbt); - - Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, xPosition, yPosition); - GlStateManager.enableLighting(); - if (mouseX >= xPosition && mouseX < xPosition + 16) { - if (mouseY >= yPosition && mouseY <= yPosition + 16) { - Utils.drawHoveringText(tooltip, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj); - } - } - } - - /** - * A separate method similar to the one above, but allowing the caller to specify an ItemStack to render. - * Used for rendering Peak of the Mountain and perks that are unlocked once and not upgraded. - */ - private void renderHotmPerk( - int perkLevel, - int xPosition, - int yPosition, - int mouseX, - int mouseY, - Supplier<ArrayList<String>> tooltipSupplier, - ItemStack itemStack - ) { - renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, itemStack, false); - } - - /** - * This method renders a HOTM perk using the provided ItemStack. - * It is overloaded by the method above, and is only called directly to render Peak of the Mountain. - */ - private void renderHotmPerk( - int perkLevel, - int xPosition, - int yPosition, - int mouseX, - int mouseY, - Supplier<ArrayList<String>> tooltipSupplier, - ItemStack itemStack, - boolean isRenderingBlock - ) { - boolean unlocked = perkLevel > 0; - GlStateManager.color(1, 1, 1, 1); - GlStateManager.disableLighting(); - if (isRenderingBlock) RenderHelper.enableGUIStandardItemLighting(); - - ArrayList<String> tooltip = tooltipSupplier.get(); - // Prepend the green or red color on the first line of each tooltip depending on if the perk is unlocked - if (!tooltip.get(0).contains("Peak of the Mountain")) tooltip.set( - 0, - (unlocked ? EnumChatFormatting.GREEN : EnumChatFormatting.RED) + tooltip.get(0) - ); //Peak of the Moutain has three color options, and is set already - - NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Resource Packs - NBTTagCompound display = new NBTTagCompound(); - display.setString("Name", tooltip.get(0)); - if (tooltip.get(0).contains("Peak of the Mountain")) display.setString("Lore", tooltip.get(1)); //Set Lore to Level - nbt.setTag("display", display); - itemStack.setTagCompound(nbt); - - Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, xPosition, yPosition); - GlStateManager.enableLighting(); - if (mouseX >= xPosition && mouseX < xPosition + 16) { - if (mouseY >= yPosition && mouseY <= yPosition + 16) { - Utils.drawHoveringText(tooltip, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj); - } - } - } - - private String getTimeSinceString(JsonObject profileInfo, String path) { - JsonElement lastSaveElement = Utils.getElement(profileInfo, path); - - if (lastSaveElement != null && lastSaveElement.isJsonPrimitive()) { - - Instant lastSave = Instant.ofEpochMilli(lastSaveElement.getAsLong()); - LocalDateTime lastSaveTime = LocalDateTime.ofInstant(lastSave, TimeZone.getDefault().toZoneId()); - long timeDiff = System.currentTimeMillis() - lastSave.toEpochMilli(); - LocalDateTime sinceOnline = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeDiff), ZoneId.of("UTC")); - String renderText; - - if (timeDiff < 60000L) { - renderText = sinceOnline.getSecond() + " seconds ago."; - } else if (timeDiff < 3600000L) { - renderText = sinceOnline.getMinute() + " minutes ago."; - } else if (timeDiff < 86400000L) { - renderText = sinceOnline.getHour() + " hours ago."; - } else if (timeDiff < 31556952000L) { - renderText = sinceOnline.getDayOfYear() + " days ago."; - } else { - renderText = lastSaveTime.format(DateTimeFormatter.ofPattern("dd-MM-yyyy")); - } - return renderText; - } - return null; - } - - private void drawBasicPage(int mouseX, int mouseY, float partialTicks) { - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - - String location = null; - JsonObject status = profile.getPlayerStatus(); - if (status != null && status.has("mode")) { - location = status.get("mode").getAsString(); - } - - int extraRotation = 0; - if (Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) { - if (backgroundClickedX == -1) { - if (mouseX > guiLeft + 23 && mouseX < guiLeft + 23 + 81) { - if (mouseY > guiTop + 44 && mouseY < guiTop + 44 + 108) { - backgroundClickedX = mouseX; - } - } - } - } else { - if (backgroundClickedX != -1) { - backgroundRotation += mouseX - backgroundClickedX; - backgroundClickedX = -1; - } - } - if (backgroundClickedX == -1) { - backgroundRotation += (currentTime - lastTime) / 400f; - } else { - extraRotation = mouseX - backgroundClickedX; - } - backgroundRotation %= 360; - - String panoramaIdentifier = "day"; - if (SBInfo.getInstance().currentTimeDate != null) { - if (SBInfo.getInstance().currentTimeDate.getHours() <= 6 || - SBInfo.getInstance().currentTimeDate.getHours() >= 20) { - panoramaIdentifier = "night"; - } - } - - Panorama.drawPanorama(-backgroundRotation - extraRotation, guiLeft + 23, guiTop + 44, 81, 108, 0.37f, 0.8f, - Panorama.getPanoramasForLocation(location == null ? "unknown" : location, panoramaIdentifier) - ); - - Minecraft.getMinecraft().getTextureManager().bindTexture(pv_basic); - Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST); - - if (entityPlayer != null && profile.getHypixelProfile() != null) { - String playerName = null; - if (profile.getHypixelProfile().has("prefix")) { - playerName = - Utils.getElementAsString(profile.getHypixelProfile().get("prefix"), "") + " " + entityPlayer.getName(); - } else { - String rank = Utils.getElementAsString( - profile.getHypixelProfile().get("rank"), - Utils.getElementAsString(profile.getHypixelProfile().get("newPackageRank"), "NONE") - ); - String monthlyPackageRank = - Utils.getElementAsString(profile.getHypixelProfile().get("monthlyPackageRank"), "NONE"); - if (!rank.equals("YOUTUBER") && !monthlyPackageRank.equals("NONE")) { - rank = monthlyPackageRank; - } - EnumChatFormatting rankPlusColorECF = EnumChatFormatting.getValueByName(Utils.getElementAsString( - profile.getHypixelProfile().get("rankPlusColor"), - "GOLD" - )); - String rankPlusColor = EnumChatFormatting.GOLD.toString(); - if (rankPlusColorECF != null) { - rankPlusColor = rankPlusColorECF.toString(); - } - - JsonObject misc = Constants.MISC; - if (misc != null) { - if (misc.has("ranks")) { - String rankName = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".tag"), null); - String rankColor = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".color"), "7"); - String rankPlus = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".plus"), ""); - - String name = entityPlayer.getName(); - - if (misc.has("special_bois")) { - JsonArray special_bois = misc.get("special_bois").getAsJsonArray(); - for (int i = 0; i < special_bois.size(); i++) { - if (special_bois.get(i).getAsString().equals(profile.getUuid())) { - name = Utils.chromaString(name); - break; - } - } - } - - playerName = EnumChatFormatting.GRAY + name; - if (rankName != null) { - StringBuilder sb = new StringBuilder(); - sb.append("\u00A7" + rankColor); - sb.append("["); - sb.append(rankName); - sb.append(rankPlusColor); - sb.append(rankPlus); - sb.append("\u00A7" + rankColor); - sb.append("] "); - sb.append(name); - playerName = sb.toString(); - } - } - } - - } - if (playerName != null) { - int rankPrefixLen = fr.getStringWidth(playerName); - int halfRankPrefixLen = rankPrefixLen / 2; - - int x = guiLeft + 63; - int y = guiTop + 54; - - drawRect(x - halfRankPrefixLen - 1, y - 1, x + halfRankPrefixLen + 1, y + 8, new Color(0, 0, 0, 64).getRGB()); - - fr.drawString(playerName, x - halfRankPrefixLen, y, 0, true); - } - } - - long networth = profile.getNetWorth(profileId); - if (networth > 0) { - Utils.drawStringCentered( - EnumChatFormatting.GREEN + "Net Worth: " + EnumChatFormatting.GOLD + numberFormat.format(networth), - fr, - guiLeft + 63, - guiTop + 38, - true, - 0 - ); - try { - double networthInCookies = (networth / NotEnoughUpdates.INSTANCE.manager.auctionManager - .getBazaarInfo("BOOSTER_COOKIE") - .get("avg_buy") - .getAsDouble()); - String networthIRLMoney = Long.toString(Math.round(((networthInCookies * 325) / 675) * 4.99)); - if (mouseX > guiLeft + 8 && - mouseX < guiLeft + 8 + fontRendererObj.getStringWidth("Net Worth: " + numberFormat.format(networth))) { - if (mouseY > guiTop + 32 && mouseY < guiTop + 32 + fontRendererObj.FONT_HEIGHT) { - tooltipToDisplay = new ArrayList<>(); - tooltipToDisplay.add( - EnumChatFormatting.GREEN + "Net worth in IRL money: " + EnumChatFormatting.DARK_GREEN + "$" + - EnumChatFormatting.GOLD + networthIRLMoney); - tooltipToDisplay.add(""); - if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) { - tooltipToDisplay.add(EnumChatFormatting.RED + "This is calculated using the current"); - tooltipToDisplay.add(EnumChatFormatting.RED + "price of booster cookies on bazaar and the price"); - tooltipToDisplay.add(EnumChatFormatting.RED + "for cookies using gems, then the price of gems"); - tooltipToDisplay.add(EnumChatFormatting.RED + "is where we get the amount of IRL money you"); - tooltipToDisplay.add(EnumChatFormatting.RED + "theoretically have on skyblock in net worth."); - } else { - tooltipToDisplay.add(EnumChatFormatting.GRAY + "[SHIFT for Info]"); - } - if (!NotEnoughUpdates.INSTANCE.config.hidden.dev) { - tooltipToDisplay.add(""); - tooltipToDisplay.add(EnumChatFormatting.RED + "THIS IS IN NO WAY ENDORSING IRL TRADING!"); - } - } - } - } catch (Exception ignored) { - } - } - - if (status != null) { - JsonElement onlineElement = Utils.getElement(status, "online"); - boolean online = onlineElement != null && onlineElement.isJsonPrimitive() && onlineElement.getAsBoolean(); - String statusStr = online ? EnumChatFormatting.GREEN + "ONLINE" : EnumChatFormatting.RED + "OFFLINE"; - String locationStr = null; - if (profile.getUuid().equals("20934ef9488c465180a78f861586b4cf")) { - locationStr = "Ignoring DMs"; - } else if (profile.getUuid().equals("b876ec32e396476ba1158438d83c67d4")) { - statusStr = EnumChatFormatting.LIGHT_PURPLE + "Long live Potato King"; - ItemStack potato_crown = NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("POTATO_CROWN")); - potato_crown.addEnchantment(Enchantment.unbreaking, 1656638942); // this number may be useful - Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI( - new ItemStack(Items.potato), - guiLeft + 35, - guiTop + 160 - ); - Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(potato_crown, guiLeft + 50, guiTop + 162); - Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI( - new ItemStack(Items.potato), - guiLeft + 63, - guiTop + 160 - ); - } else if (online) { - locationStr = NotEnoughUpdates.INSTANCE.navigation.getNameForAreaModeOrUnknown(location); - } - if (locationStr != null) { - statusStr += EnumChatFormatting.GRAY + " - " + EnumChatFormatting.GREEN + locationStr; - } - - Utils.drawStringCentered(statusStr, fr, guiLeft + 63, guiTop + 160, true, 0); - } - - if (entityPlayer == null) { - if (!loadingProfile || ((ThreadPoolExecutor) profileLoader).getActiveCount() == 0) { - loadingProfile = true; - UUID playerUUID = UUID.fromString(niceUuid(profile.getUuid())); - - profileLoader.submit(() -> { - GameProfile fakeProfile = Minecraft - .getMinecraft() - .getSessionService() - .fillProfileProperties(new GameProfile(playerUUID, "CoolGuy123"), false); - entityPlayer = new EntityOtherPlayerMP(Minecraft.getMinecraft().theWorld, fakeProfile) { - public ResourceLocation getLocationSkin() { - return playerLocationSkin == null - ? DefaultPlayerSkin.getDefaultSkin(this.getUniqueID()) - : playerLocationSkin; - } - - public ResourceLocation getLocationCape() { - return playerLocationCape; - } - - public String getSkinType() { - return skinType == null ? DefaultPlayerSkin.getSkinType(this.getUniqueID()) : skinType; - } - }; - entityPlayer.setAlwaysRenderNameTag(false); - entityPlayer.setCustomNameTag(""); - }); - } - } else { - entityPlayer.refreshDisplayName(); - byte b = 0; - for (EnumPlayerModelParts part : EnumPlayerModelParts.values()) { - b |= part.getPartMask(); - } - entityPlayer.getDataWatcher().updateObject(10, b); - } - - JsonObject profileInfo = profile.getProfileInformation(profileId); - if (profileInfo == null) return; - - JsonObject skillInfo = profile.getSkillInfo(profileId); - JsonObject inventoryInfo = profile.getInventoryInfo(profileId); - - if (entityPlayer != null) { - if (backgroundClickedX != -1 && Mouse.isButtonDown(1)) { - Arrays.fill(entityPlayer.inventory.armorInventory, null); - } else { - if (inventoryInfo != null && inventoryInfo.has("inv_armor")) { - JsonArray items = inventoryInfo.get("inv_armor").getAsJsonArray(); - if (items != null && items.size() == 4) { - for (int i = 0; i < entityPlayer.inventory.armorInventory.length; i++) { - JsonElement itemElement = items.get(i); - if (itemElement != null && itemElement.isJsonObject()) { - entityPlayer.inventory.armorInventory[i] = - NotEnoughUpdates.INSTANCE.manager.jsonToStack(itemElement.getAsJsonObject(), false); - } - } - } - } else { - Arrays.fill(entityPlayer.inventory.armorInventory, null); - } - } - if (entityPlayer.getUniqueID().toString().equals("ae6193ab-494a-4719-b6e7-d50392c8f012")) { - entityPlayer.inventory.armorInventory[3] = NotEnoughUpdates.INSTANCE.manager.jsonToStack( - NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("SMALL_BACKPACK")); - } - } - - if (entityPlayer != null && playerLocationSkin == null) { - try { - Minecraft - .getMinecraft() - .getSkinManager() - .loadProfileTextures(entityPlayer.getGameProfile(), (type, location1, profileTexture) -> { - switch (type) { - case SKIN: - playerLocationSkin = location1; - skinType = profileTexture.getMetadata("model"); - - if (skinType == null) { - skinType = "default"; - } - - break; - case CAPE: - playerLocationCape = location1; - } - }, false); - } catch (Exception ignored) { - } - } - - GlStateManager.color(1, 1, 1, 1); - JsonObject petsInfo = profile.getPetsInfo(profileId); - if (petsInfo != null) { - JsonElement activePetElement = petsInfo.get("active_pet"); - if (activePetElement != null && activePetElement.isJsonObject()) { - JsonObject activePet = activePetElement.getAsJsonObject(); - - String type = activePet.get("type").getAsString(); - - for (int i = 0; i < 4; i++) { - JsonObject item = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(type + ";" + i); - if (item != null) { - int x = guiLeft + 20; - float y = guiTop + 82 + 15 * (float) Math.sin(((currentTime - startTime) / 800f) % (2 * Math.PI)); - GlStateManager.translate(x, y, 0); - ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false); - - //Remove extra attributes so no CIT - NBTTagCompound stackTag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound(); - stackTag.removeTag("ExtraAttributes"); - stack.setTagCompound(stackTag); - - GlStateManager.scale(1.5f, 1.5f, 1); - GlStateManager.enableDepth(); - Utils.drawItemStack(stack, 0, 0); - GlStateManager.scale(1 / 1.5f, 1 / 1.5f, 1); - GlStateManager.translate(-x, -y, 0); - break; - } - } - } - } - if (entityPlayer != null) { - drawEntityOnScreen( - guiLeft + 63, - guiTop + 128 + 7, - 36, - guiLeft + 63 - mouseX, - guiTop + 129 - mouseY, - entityPlayer - ); - } - - PlayerStats.Stats stats = profile.getStats(profileId); - - if (stats != null) { - Splitter splitter = Splitter.on(" ").omitEmptyStrings().limit(2); - for (int i = 0; i < PlayerStats.defaultStatNames.length; i++) { - String statName = PlayerStats.defaultStatNames[i]; - //if (statName.equals("mining_fortune") || statName.equals("mining_speed")) continue; - String statNamePretty = PlayerStats.defaultStatNamesPretty[i]; - - int val = Math.round(stats.get(statName)); - - GlStateManager.color(1, 1, 1, 1); - GlStateManager.enableBlend(); - GL14.glBlendFuncSeparate( - GL11.GL_SRC_ALPHA, - GL11.GL_ONE_MINUS_SRC_ALPHA, - GL11.GL_ONE, - GL11.GL_ONE_MINUS_SRC_ALPHA - ); - Utils.renderAlignedString( - statNamePretty, - EnumChatFormatting.WHITE.toString() + val, - guiLeft + 132, - guiTop + 21 + 11f * i, - 80 - ); - - if (mouseX > guiLeft + 132 && mouseX < guiLeft + 212) { - if (mouseY > guiTop + 21 + 11f * i && mouseY < guiTop + 37 + 11f * i) { - List<String> split = splitter.splitToList(statNamePretty); - PlayerStats.Stats baseStats = PlayerStats.getBaseStats(); - tooltipToDisplay = new ArrayList<>(); - tooltipToDisplay.add(statNamePretty); - int base = Math.round(baseStats.get(statName)); - tooltipToDisplay.add( - EnumChatFormatting.GRAY + "Base " + split.get(1) + ": " + EnumChatFormatting.GREEN + base + " " + - split.get(0)); - int passive = Math.round(profile.getPassiveStats(profileId).get(statName) - baseStats.get(statName)); - tooltipToDisplay.add( - EnumChatFormatting.GRAY + "Passive " + split.get(1) + " Bonus: +" + EnumChatFormatting.YELLOW + passive + - " " + split.get(0)); - int itemBonus = Math.round(stats.get(statName) - profile.getPassiveStats(profileId).get(statName)); - tooltipToDisplay.add( - EnumChatFormatting.GRAY + "Item " + split.get(1) + " Bonus: +" + EnumChatFormatting.DARK_PURPLE + - itemBonus + " " + split.get(0)); - int finalStat = Math.round(stats.get(statName)); - tooltipToDisplay.add( - EnumChatFormatting.GRAY + "Final " + split.get(1) + ": +" + EnumChatFormatting.RED + finalStat + " " + - split.get(0)); - } - } - } - } else { - Utils.drawStringCentered(EnumChatFormatting.RED + "Skill/Inv/Coll", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 172, guiTop + 101 - 10, true, 0 - ); - Utils.drawStringCentered(EnumChatFormatting.RED + "APIs not", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 172, guiTop + 101, true, 0 - ); - Utils.drawStringCentered(EnumChatFormatting.RED + "enabled!", Minecraft.getMinecraft().fontRendererObj, - guiLeft + 172, guiTop + 101 + 10, true, 0 - ); - } - - if (skillInfo != null) { - int position = 0; - for (Map.Entry<String, ItemStack> entry : ProfileViewer.getSkillToSkillDisplayMap().entrySet()) { - if (entry.getValue() == null || entry.getKey() == null) { - position++; - continue; - } - - int yPosition = position % 8; - int xPosition = position / 8; - - String skillName = entry.getValue().getDisplayName(); - - float level = Utils.getElementAsFloat(skillInfo.get("level_" + entry.getKey()), 0); - int levelFloored = (int) Math.floor(level); - - int x = guiLeft + 237 + 86 * xPosition; - int y = guiTop + 24 + 21 * yPosition; - - Utils.renderAlignedString(skillName, EnumChatFormatting.WHITE.toString() + levelFloored, x + 14, y - 4, 60); - - if (skillInfo.get("maxed_" + entry.getKey()).getAsBoolean()) { - renderGoldBar(x, y + 6, 80); - } else { - renderBar(x, y + 6, 80, level % 1); - } - - if (mouseX > x && mouseX < x + 80) { - if (mouseY > y - 4 && mouseY < y + 13) { - tooltipToDisplay = new ArrayList<>(); - tooltipToDisplay.add(skillName); - if (skillInfo.get("maxed_" + entry.getKey()).getAsBoolean()) { - tooltipToDisplay.add(EnumChatFormatting.GRAY + "Progress: " + EnumChatFormatting.GOLD + "MAXED!"); - } else { - int maxXp = (int) skillInfo.get("maxxp_" + entry.getKey()).getAsFloat(); - tooltipToDisplay.add(EnumChatFormatting.GRAY + "Progress: " + EnumChatFormatting.DARK_PURPLE + - shortNumberFormat(Math.round((level % 1) * maxXp), 0) + "/" + shortNumberFormat(maxXp, 0)); - } - String totalXpS = numberFormat.format((int) skillInfo.get("experience_" + entry.getKey()).getAsFloat()); - tooltipToDisplay.add(EnumChatFormatting.GRAY + "Total XP: " + - EnumChatFormatting.DARK_PURPLE + totalXpS); - } - } - - GL11.glTranslatef((x), (y - 6f), 0); - GL11.glScalef(0.7f, 0.7f, 1); - Utils.drawItemStackLinear(entry.getValue(), 0, 0); - GL11.glScalef(1 / 0.7f, 1 / 0.7f, 1); - GL11.glTranslatef(-(x), -(y - 6f), 0); - - position++; - } - } else { - Utils.drawStringCentered( - EnumChatFormatting.RED + "Skills API not enabled!", - Minecraft.getMinecraft().fontRendererObj, - guiLeft + 322, - guiTop + 101, - true, - 0 - ); - } - - renderWeight(mouseX, mouseY, skillInfo, profileInfo); - } - - private void renderWeight(int mouseX, int mouseY, JsonObject skillInfo, JsonObject profileInfo) { - if (skillInfo == null) { - return; - } - - if(Constants.WEIGHT == null) { - Utils.showOutdatedRepoNotification(); - return; - } - - FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; - - SenitherWeight senitherWeight = new SenitherWeight(skillInfo); - LilyWeight lilyWeight = new LilyWeight(skillInfo, profileInfo); - - Utils.drawStringCentered( - EnumChatFormatting.GREEN + "Senither Weight: " + EnumChatFormatting.GOLD + numberFormat.format(roundToNearestInt(senitherWeight.getTotalWeight().getRaw())), - fr, - guiLeft + 63, - guiTop + 18, - true, - 0 - ); - - int textWidth = fontRendererObj.getStringWidth("Senither Weight: " + numberFormat.format(roundToNearestInt(senitherWeight.getTotalWeight().getRaw()))); - if (mouseX > guiLeft + 63 - textWidth / 2 && - mouseX < guiLeft + 63 + textWidth / 2) { - if (mouseY > guiTop + 12 && mouseY < guiTop + 12 + fontRendererObj.FONT_HEIGHT) { - tooltipToDisplay = new ArrayList<>(); - tooltipToDisplay.add(EnumChatFormatting.GREEN + "Skills: " + EnumChatFormatting.GOLD + numberFormat.format(roundToNearestInt(senitherWeight.getSkillsWeight().getWeightStruct().getRaw()))); - tooltipToDisplay.add(EnumChatFormatting.GREEN + "Slayer: " + EnumChatFormatting.GOLD + numberFormat.format(roundToNearestInt(senitherWeight.getSlayerWeight().getWeightStruct().getRaw()))); - tooltipToDisplay.add(EnumChatFormatting.GREEN + "Dungeons: " + EnumChatFormatting.GOLD + numberFormat.format(roundToNearestInt(senitherWeight.getDungeonsWeight().getWeightStruct().getRaw()))); - } - } - - Utils.drawStringCentered( - EnumChatFormatting.GREEN + "Lily Weight: " + EnumChatFormatting.GOLD + numberFormat.format(roundToNearestInt(lilyWeight.getTotalWeight().getRaw())), - fr, - guiLeft + 63, - guiTop + 28, - true, - 0 - ); - - int fontWidth = fontRendererObj.getStringWidth("Lily Weight: " + numberFormat.format(roundToNearestInt(lilyWeight.getTotalWeight().getRaw()))); - if (mouseX > guiLeft + 63 - fontWidth / 2 && - mouseX < guiLeft + 63 + fontWidth / 2) { - if (mouseY > guiTop + 22 && mouseY < guiTop + 22 + fontRendererObj.FONT_HEIGHT) { - tooltipToDisplay = new ArrayList<>(); - tooltipToDisplay.add(EnumChatFormatting.GREEN + "Skills: " + EnumChatFormatting.GOLD + numberFormat.format(roundToNearestInt(lilyWeight.getSkillsWeight().getWeightStruct().getRaw()))); - tooltipToDisplay.add(EnumChatFormatting.GREEN + "Slayer: " + EnumChatFormatting.GOLD + numberFormat.format(roundToNearestInt(lilyWeight.getSlayerWeight().getWeightStruct().getRaw()))); - tooltipToDisplay.add(EnumChatFormatting.GREEN + "Dungeons: " + EnumChatFormatting.GOLD + numberFormat.format(roundToNearestInt(lilyWeight.getDungeonsWeight().getWeightStruct().getRaw()))); - } - } - } - - private void renderGoldBar(float x, float y, float xSize) { + public void renderGoldBar(float x, float y, float xSize) { if (!OpenGlHelper.areShadersSupported()) { renderBar(x, y, xSize, 1); return; @@ -5035,19 +1068,15 @@ public class GuiProfileViewer extends GuiScreen { GL20.glUseProgram(0); } - private void renderBar(float x, float y, float xSize, float completed) { + public void renderBar(float x, float y, float xSize, float completed) { Minecraft.getMinecraft().getTextureManager().bindTexture(icons); completed = Math.round(completed / 0.05f) * 0.05f; - - float notcompleted = 1 - completed; - - int displayNum = 0;//tl.x%5; - + float notCompleted = 1 - completed; GlStateManager.color(1, 1, 1, 1); - float width = 0; + float width; - if (completed < 0.5f && (displayNum == 1 || displayNum == 0)) { + if (completed < 0.5f) { width = (0.5f - completed) * xSize; Utils.drawTexturedRect( x + xSize * completed, @@ -5061,8 +1090,8 @@ public class GuiProfileViewer extends GuiScreen { GL11.GL_NEAREST ); } - if (completed < 1f && (displayNum == 2 || displayNum == 0)) { - width = Math.min(xSize * notcompleted, xSize / 2f); + if (completed < 1f) { + width = Math.min(xSize * notCompleted, xSize / 2f); Utils.drawTexturedRect( x + (xSize / 2f) + Math.max(xSize * (completed - 0.5f), 0), y, @@ -5076,38 +1105,28 @@ public class GuiProfileViewer extends GuiScreen { ); } - if (completed > 0f && (displayNum == 3 || displayNum == 0)) { + if (completed > 0f) { width = Math.min(xSize * completed, xSize / 2f); - Utils.drawTexturedRect(x, y, width, 5, - 0 / 256f, width / 256f, 79 / 256f, 84 / 256f, GL11.GL_NEAREST - ); + Utils.drawTexturedRect(x, y, width, 5, 0 / 256f, width / 256f, 79 / 256f, 84 / 256f, GL11.GL_NEAREST); } - if (completed > 0.5f && (displayNum == 4 || displayNum == 0)) { + if (completed > 0.5f) { width = Math.min(xSize * (completed - 0.5f), xSize / 2f); - Utils.drawTexturedRect(x + (xSize / 2f), y, width, 5, - (182 - (xSize / 2f)) / 256f, (182 - (xSize / 2f) + width) / 256f, 79 / 256f, 84 / 256f, GL11.GL_NEAREST + Utils.drawTexturedRect( + x + (xSize / 2f), + y, + width, + 5, + (182 - (xSize / 2f)) / 256f, + (182 - (xSize / 2f) + width) / 256f, + 79 / 256f, + 84 / 256f, + GL11.GL_NEAREST ); } } public void resetCache() { - bestWeapons = null; - bestRods = null; - armorItems = null; - equipmentItems = null; - inventoryItems = new HashMap<>(); - currentInventoryIndex = 0; - arrowCount = -1; - greenCandyCount = -1; - purpleCandyCount = -1; - entityPlayer = null; - playerLocationSkin = null; - playerLocationCape = null; - skinType = null; - petsPage = 0; - sortedPets = null; - sortedPetsStack = null; - selectedPet = -1; + pages.values().forEach(GuiProfileViewerPage::resetCache); } /** @@ -5157,9 +1176,13 @@ public class GuiProfileViewer extends GuiScreen { if (blurShaderHorz == null) { try { - blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", - Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz - ); + blurShaderHorz = + new Shader( + Minecraft.getMinecraft().getResourceManager(), + "blur", + Minecraft.getMinecraft().getFramebuffer(), + blurOutputHorz + ); blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0); blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); } catch (Exception ignored) { @@ -5167,8 +1190,11 @@ public class GuiProfileViewer extends GuiScreen { } if (blurShaderVert == null) { try { - blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", - blurOutputHorz, blurOutputVert + blurShaderVert = new Shader( + Minecraft.getMinecraft().getResourceManager(), + "blur", + blurOutputHorz, + blurOutputVert ); blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1); blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height)); @@ -5259,11 +1285,12 @@ public class GuiProfileViewer extends GuiScreen { public Optional<ItemStack> getItem() { return Optional.ofNullable(stack); } - } public static class PetLevel { + public float level; + public float maxLevel; public float currentLevelRequirement; public float maxXP; public float levelPercentage; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewerPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewerPage.java new file mode 100644 index 00000000..2c7fd9f4 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewerPage.java @@ -0,0 +1,53 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer; + +import java.io.IOException; + +public abstract class GuiProfileViewerPage { + + private final GuiProfileViewer instance; + + public GuiProfileViewerPage(GuiProfileViewer instance) { + this.instance = instance; + } + + /** + * @return Instance of the current {@link GuiProfileViewer} + */ + public GuiProfileViewer getInstance() { + return instance; + } + + public abstract void drawPage(int mouseX, int mouseY, float partialTicks); + + /** + * @return Whether to return in calling method + */ + public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + return false; + } + + public void mouseReleased(int mouseX, int mouseY, int mouseButton) {} + + public void keyTyped(char typedChar, int keyCode) throws IOException {} + + public void resetCache() {} +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java new file mode 100644 index 00000000..8bba9c76 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java @@ -0,0 +1,784 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +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.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.profileviewer.info.QuiverInfo; +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.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagByteArray; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer.pv_elements; + +public class InventoriesPage extends GuiProfileViewerPage { + + public static final ResourceLocation pv_invs = new ResourceLocation("notenoughupdates:pv_invs.png"); + private static final Pattern DAMAGE_PATTERN = Pattern.compile("^Damage: \\+(\\d+)"); + private static final ResourceLocation CHEST_GUI_TEXTURE = new ResourceLocation("textures/gui/container/generic_54.png"); + private static final Pattern STRENGTH_PATTERN = Pattern.compile("^Strength: \\+(\\d+)"); + private static final Pattern FISHSPEED_PATTERN = Pattern.compile("^Increases fishing speed by \\+(\\d+)"); + private static final LinkedHashMap<String, ItemStack> invNameToDisplayMap = new LinkedHashMap<String, ItemStack>() { + { + put("inv_contents", Utils.createItemStack(Item.getItemFromBlock(Blocks.chest), EnumChatFormatting.GRAY + "Inventory")); + put( + "ender_chest_contents", + Utils.createItemStack(Item.getItemFromBlock(Blocks.ender_chest), EnumChatFormatting.GRAY + "Ender Chest") + ); + // put("backpack_contents", Utils.createItemStack(Item.getItemFromBlock(Blocks.dropper), EnumChatFormatting.GRAY+"Backpacks")); + put( + "backpack_contents", + Utils.editItemStackInfo( + NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("JUMBO_BACKPACK") + ), + EnumChatFormatting.GRAY + "Backpacks", + true + ) + ); + put( + "personal_vault_contents", + Utils.editItemStackInfo( + NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("IRON_CHEST")), + EnumChatFormatting.GRAY + "Personal Vault", + true + ) + ); + put("talisman_bag", Utils.createItemStack(Items.golden_apple, EnumChatFormatting.GRAY + "Accessory Bag")); + put("wardrobe_contents", Utils.createItemStack(Items.leather_chestplate, EnumChatFormatting.GRAY + "Wardrobe")); + put("fishing_bag", Utils.createItemStack(Items.fish, EnumChatFormatting.GRAY + "Fishing Bag")); + put("potion_bag", Utils.createItemStack(Items.potionitem, EnumChatFormatting.GRAY + "Potion Bag")); + } + }; + private final ItemStack fillerStack = new ItemStack(Item.getItemFromBlock(Blocks.stained_glass_pane), 1, 15); + private HashMap<String, ItemStack[][][]> inventoryItems = new HashMap<>(); + + private ItemStack[] bestWeapons = null; + private ItemStack[] bestRods = null; + private ItemStack[] armorItems = null; + private ItemStack[] equipmentItems = null; + private String selectedInventory = "inv_contents"; + private int currentInventoryIndex = 0; + private int arrowCount = -1; + private int greenCandyCount = -1; + private int purpleCandyCount = -1; + + public InventoriesPage(GuiProfileViewer instance) { + super(instance); + } + + @Override + public void drawPage(int mouseX, int mouseY, float partialTicks) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_invs); + Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST); + getInstance().inventoryTextField.setSize(88, 20); + + ProfileViewer.Profile profile = GuiProfileViewer.getProfile(); + String profileId = GuiProfileViewer.getProfileId(); + JsonObject inventoryInfo = profile.getInventoryInfo(profileId); + if (inventoryInfo == null) return; + + int invNameIndex = 0; + for (Map.Entry<String, ItemStack> entry : invNameToDisplayMap.entrySet()) { + int xIndex = invNameIndex % 3; + int yIndex = invNameIndex / 3; + + int x = 19 + 34 * xIndex; + int y = 26 + 34 * yIndex; + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); + if (entry.getKey().equals(selectedInventory)) { + Utils.drawTexturedRect(guiLeft + x - 2, guiTop + y - 2, 20, 20, 20 / 256f, 0, 20 / 256f, 0, GL11.GL_NEAREST); + x++; + y++; + } else { + Utils.drawTexturedRect(guiLeft + x - 2, guiTop + y - 2, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST); + } + + Utils.drawItemStackWithText(entry.getValue(), guiLeft + x, guiTop + y, "" + (invNameIndex + 1), true); + + if (mouseX >= guiLeft + x && mouseX <= guiLeft + x + 16) { + if (mouseY >= guiTop + y && mouseY <= guiTop + y + 16) { + getInstance().tooltipToDisplay = entry.getValue().getTooltip(Minecraft.getMinecraft().thePlayer, false); + if (Objects.equals(entry.getKey(), "talisman_bag")) { + StringBuilder magicalPowerString = new StringBuilder(EnumChatFormatting.DARK_GRAY + "Magical Power: "); + int magicalPower = PlayerStats.getMagicalPower(inventoryInfo); + getInstance() + .tooltipToDisplay.add( + magicalPower == -1 + ? magicalPowerString.append(EnumChatFormatting.RED).append("Error while calculating!").toString() + : magicalPowerString + .append(EnumChatFormatting.GOLD) + .append(GuiProfileViewer.numberFormat.format(magicalPower)) + .toString() + ); + + StringBuilder selectedPowerString = new StringBuilder(EnumChatFormatting.DARK_GRAY + "Selected Power: "); + String selectedPower = PlayerStats.getSelectedMagicalPower(profile.getProfileInformation(profileId)); + getInstance() + .tooltipToDisplay.add( + selectedPower == null + ? selectedPowerString.append(EnumChatFormatting.RED).append("None!").toString() + : selectedPowerString.append(EnumChatFormatting.GREEN).append(selectedPower).toString() + ); + } + } + } + + invNameIndex++; + } + + getInstance().inventoryTextField.render(guiLeft + 19, guiTop + getInstance().sizeY - 26 - 20); + + if (armorItems == null) { + armorItems = new ItemStack[4]; + JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray(); + for (int i = 0; i < armor.size(); i++) { + if (armor.get(i) == null || !armor.get(i).isJsonObject()) continue; + armorItems[i] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(armor.get(i).getAsJsonObject(), false); + } + } + + for (int i = 0; i < armorItems.length; i++) { + ItemStack stack = armorItems[i]; + if (stack != null) { + Utils.drawItemStack(stack, guiLeft + 173, guiTop + 67 - 18 * i, true); + if (stack != fillerStack) { + if (mouseX >= guiLeft + 173 - 1 && mouseX <= guiLeft + 173 + 16 + 1) { + if (mouseY >= guiTop + 67 - 18 * i - 1 && mouseY <= guiTop + 67 - 18 * i + 16 + 1) { + getInstance().tooltipToDisplay = + stack.getTooltip( + Minecraft.getMinecraft().thePlayer, + Minecraft.getMinecraft().gameSettings.advancedItemTooltips + ); + } + } + } + } + } + + if (equipmentItems == null) { + equipmentItems = new ItemStack[4]; + JsonArray equippment = Utils.getElement(inventoryInfo, "equippment_contents").getAsJsonArray(); + for (int i = 0; i < equippment.size(); i++) { + if (equippment.get(i) == null || !equippment.get(i).isJsonObject()) continue; + equipmentItems[i] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(equippment.get(i).getAsJsonObject(), false); + } + } + + for (int i = 0; i < equipmentItems.length; i++) { + ItemStack stack = equipmentItems[i]; + if (stack != null) { + Utils.drawItemStack(stack, guiLeft + 192, guiTop + 13 + 18 * i, true); + if (stack != fillerStack) { + if (mouseX >= guiLeft + 192 - 1 && mouseX <= guiLeft + 192 + 16 + 1) { + if (mouseY >= guiTop + 13 + 18 * i - 1 && mouseY <= guiTop + 13 + 18 * i + 16 + 1) { + getInstance().tooltipToDisplay = + stack.getTooltip( + Minecraft.getMinecraft().thePlayer, + Minecraft.getMinecraft().gameSettings.advancedItemTooltips + ); + } + } + } + } + } + + ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, selectedInventory); + if (currentInventoryIndex >= inventories.length) currentInventoryIndex = inventories.length - 1; + if (currentInventoryIndex < 0) currentInventoryIndex = 0; + + ItemStack[][] inventory = inventories[currentInventoryIndex]; + if (inventory == null) { + if (selectedInventory.equalsIgnoreCase("personal_vault_contents")) { + Utils.drawStringCentered( + EnumChatFormatting.RED + "Personal Vault API not enabled!", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 317, + guiTop + 101, + true, + 0 + ); + } else { + Utils.drawStringCentered( + EnumChatFormatting.RED + "Inventory API not enabled!", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + 317, + guiTop + 101, + true, + 0 + ); + } + return; + } + + if (bestWeapons == null) { + bestWeapons = + findBestItems( + inventoryInfo, + 6, + new String[] { "inv_contents", "ender_chest_contents" }, + new String[] { "SWORD", "BOW" }, + DAMAGE_PATTERN, + STRENGTH_PATTERN + ); + } + if (bestRods == null) { + bestRods = + findBestItems( + inventoryInfo, + 3, + new String[] { "inv_contents", "ender_chest_contents" }, + new String[] { "FISHING ROD" }, + FISHSPEED_PATTERN + ); + } + + for (int i = 0; i < bestWeapons.length; i++) { + if (bestWeapons[i] == null) continue; + ItemStack stack = bestWeapons[i]; + Utils.drawItemStack(stack, guiLeft + 143, guiTop + 13 + 18 * i, true); + if (mouseX >= guiLeft + 143 - 1 && mouseX <= guiLeft + 143 + 16 + 1) { + if (mouseY >= guiTop + 13 + 18 * i - 1 && mouseY <= guiTop + 13 + 18 * i + 16 + 1) { + getInstance().tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + } + } + + for (int i = 0; i < bestRods.length; i++) { + if (bestRods[i] == null) continue; + ItemStack stack = bestRods[i]; + Utils.drawItemStack(stack, guiLeft + 143, guiTop + 137 + 18 * i, true); + if (mouseX >= guiLeft + 143 - 1 && mouseX <= guiLeft + 143 + 16 + 1) { + if (mouseY >= guiTop + 137 + 18 * i - 1 && mouseY <= guiTop + 137 + 18 * i + 16 + 1) { + getInstance().tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + } + } + + if (arrowCount == -1) { + arrowCount = countItemsInInventory("ARROW", inventoryInfo, false, "quiver"); + } + if (greenCandyCount == -1) { + greenCandyCount = countItemsInInventory("GREEN_CANDY", inventoryInfo, true, "candy_inventory_contents"); + } + if (purpleCandyCount == -1) { + purpleCandyCount = countItemsInInventory("PURPLE_CANDY", inventoryInfo, true, "candy_inventory_contents"); + } + + Utils.drawItemStackWithText( + NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("ARROW")), + guiLeft + 173, + guiTop + 101, + "" + (arrowCount > 999 ? GuiProfileViewer.shortNumberFormat(arrowCount, 0) : arrowCount), + true + ); + Utils.drawItemStackWithText( + NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("GREEN_CANDY")), + guiLeft + 173, + guiTop + 119, + "" + greenCandyCount, + true + ); + Utils.drawItemStackWithText( + NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("PURPLE_CANDY")), + guiLeft + 173, + guiTop + 137, + "" + purpleCandyCount, + true + ); + if (mouseX > guiLeft + 173 && mouseX < guiLeft + 173 + 16) { + if (mouseY > guiTop + 101 && mouseY < guiTop + 137 + 16) { + if (mouseY < guiTop + 101 + 17) { + QuiverInfo quiverInfo = PlayerStats.getQuiverInfo(inventoryInfo, profile.getProfileInformation(profileId)); + if (quiverInfo == null) { + getInstance().tooltipToDisplay = Utils.createList(EnumChatFormatting.RED + "Error checking Quiver"); + } else { + getInstance().tooltipToDisplay = quiverInfo.generateProfileViewerTooltip(); + } + } else if (mouseY < guiTop + 119 + 17) { + getInstance().tooltipToDisplay = + Utils.createList(EnumChatFormatting.GREEN + "Green Candy " + EnumChatFormatting.GRAY + "x" + greenCandyCount); + } else { + getInstance().tooltipToDisplay = + Utils.createList( + EnumChatFormatting.DARK_PURPLE + "Purple Candy " + EnumChatFormatting.GRAY + "x" + purpleCandyCount + ); + } + } + } + + int inventoryRows = inventory.length; + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + Minecraft.getMinecraft().getTextureManager().bindTexture(CHEST_GUI_TEXTURE); + + int invSizeY = inventoryRows * 18 + 17 + 7; + + int x = guiLeft + 320 - 176 / 2; + int y = guiTop + 101 - invSizeY / 2; + int staticSelectorHeight = guiTop + 177; + + getInstance().drawTexturedModalRect(x, y, 0, 0, 176, inventoryRows * 18 + 17); + getInstance().drawTexturedModalRect(x, y + inventoryRows * 18 + 17, 0, 215, 176, 7); + + boolean leftHovered = false; + boolean rightHovered = false; + if (Mouse.isButtonDown(0)) { + if (mouseY > staticSelectorHeight && mouseY < staticSelectorHeight + 16) { + if (mouseX > guiLeft + 320 - 12 && mouseX < guiLeft + 320 + 12) { + if (mouseX < guiLeft + 320) { + leftHovered = true; + } else { + rightHovered = true; + } + } + } + } + Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.resource_packs); + + if (currentInventoryIndex > 0) { + Utils.drawTexturedRect( + guiLeft + 320 - 12, + staticSelectorHeight, + 12, + 16, + 29 / 256f, + 53 / 256f, + !leftHovered ? 0 : 32 / 256f, + !leftHovered ? 32 / 256f : 64 / 256f, + GL11.GL_NEAREST + ); + } + if (currentInventoryIndex < inventories.length - 1) { + Utils.drawTexturedRect( + guiLeft + 320, + staticSelectorHeight, + 12, + 16, + 5 / 256f, + 29 / 256f, + !rightHovered ? 0 : 32 / 256f, + !rightHovered ? 32 / 256f : 64 / 256f, + GL11.GL_NEAREST + ); + } + + Minecraft + .getMinecraft() + .fontRendererObj.drawString( + Utils.cleanColour(invNameToDisplayMap.get(selectedInventory).getDisplayName()), + x + 8, + y + 6, + 4210752 + ); + + ItemStack stackToRender = null; + int overlay = new Color(0, 0, 0, 100).getRGB(); + for (int yIndex = 0; yIndex < inventory.length; yIndex++) { + if (inventory[yIndex] == null) continue; + + for (int xIndex = 0; xIndex < inventory[yIndex].length; xIndex++) { + ItemStack stack = inventory[yIndex][xIndex]; + + if (stack != null) Utils.drawItemStack(stack, x + 8 + xIndex * 18, y + 18 + yIndex * 18, true); + + if ( + getInstance().inventoryTextField.getText() != null && + !getInstance().inventoryTextField.getText().isEmpty() && + ( + stack == null || + !NotEnoughUpdates.INSTANCE.manager.doesStackMatchSearch(stack, getInstance().inventoryTextField.getText()) + ) + ) { + GlStateManager.translate(0, 0, 50); + GuiScreen.drawRect( + x + 8 + xIndex * 18, + y + 18 + yIndex * 18, + x + 8 + xIndex * 18 + 16, + y + 18 + yIndex * 18 + 16, + overlay + ); + GlStateManager.translate(0, 0, -50); + } + + if (stack == null || stack == fillerStack) continue; + + if (mouseX >= x + 8 + xIndex * 18 && mouseX <= x + 8 + xIndex * 18 + 16) { + if (mouseY >= y + 18 + yIndex * 18 && mouseY <= y + 18 + yIndex * 18 + 16) { + stackToRender = stack; + } + } + } + } + if (stackToRender != null) { + getInstance().tooltipToDisplay = stackToRender.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + } + + @Override + public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + 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; + } + } + return false; + } + + @Override + public void mouseReleased(int mouseX, int mouseY, int mouseButton) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + if (mouseButton == 0) { + int i = 0; + for (Map.Entry<String, ItemStack> entry : invNameToDisplayMap.entrySet()) { + int xIndex = i % 3; + int yIndex = i / 3; + + int x = guiLeft + 19 + 34 * xIndex; + int y = guiTop + 26 + 34 * yIndex; + + if (mouseX >= x && mouseX <= x + 16) { + if (mouseY >= y && mouseY <= y + 16) { + if (!selectedInventory.equals(entry.getKey())) Utils.playPressSound(); + selectedInventory = entry.getKey(); + return; + } + } + + i++; + } + + JsonObject inventoryInfo = GuiProfileViewer.getProfile().getInventoryInfo(GuiProfileViewer.getProfileId()); + if (inventoryInfo == null) return; + + ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, selectedInventory); + if (currentInventoryIndex >= inventories.length) currentInventoryIndex = inventories.length - 1; + if (currentInventoryIndex < 0) currentInventoryIndex = 0; + + ItemStack[][] inventory = inventories[currentInventoryIndex]; + if (inventory == null) return; + + int inventoryRows = inventory.length; + + int staticSelectorHeight = guiTop + 177; + + if (mouseY > staticSelectorHeight && mouseY < staticSelectorHeight + 16) { + if (mouseX > guiLeft + 320 - 12 && mouseX < guiLeft + 320 + 12) { + if (mouseX < guiLeft + 320) { + currentInventoryIndex--; + } else { + currentInventoryIndex++; + } + } + } + } + } + + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { + switch (keyCode) { + case Keyboard.KEY_1: + case Keyboard.KEY_NUMPAD1: + selectedInventory = "inv_contents"; + break; + case Keyboard.KEY_2: + case Keyboard.KEY_NUMPAD2: + selectedInventory = "ender_chest_contents"; + break; + case Keyboard.KEY_3: + case Keyboard.KEY_NUMPAD3: + selectedInventory = "backpack_contents"; + break; + case Keyboard.KEY_4: + case Keyboard.KEY_NUMPAD4: + selectedInventory = "personal_vault_contents"; + break; + case Keyboard.KEY_5: + case Keyboard.KEY_NUMPAD5: + selectedInventory = "talisman_bag"; + break; + case Keyboard.KEY_6: + case Keyboard.KEY_NUMPAD6: + selectedInventory = "wardrobe_contents"; + break; + case Keyboard.KEY_7: + case Keyboard.KEY_NUMPAD7: + selectedInventory = "fishing_bag"; + break; + case Keyboard.KEY_8: + case Keyboard.KEY_NUMPAD8: + selectedInventory = "potion_bag"; + break; + default: + getInstance().inventoryTextField.keyTyped(typedChar, keyCode); + return; + } + Utils.playPressSound(); + getInstance().inventoryTextField.keyTyped(typedChar, keyCode); + } + + @Override + public void resetCache() { + inventoryItems = new HashMap<>(); + bestWeapons = null; + bestRods = null; + armorItems = null; + equipmentItems = null; + currentInventoryIndex = 0; + arrowCount = -1; + greenCandyCount = -1; + purpleCandyCount = -1; + } + + private int countItemsInInventory(String internalname, JsonObject inventoryInfo, boolean specific, String... invsToSearch) { + int count = 0; + for (String inv : invsToSearch) { + JsonArray invItems = inventoryInfo.get(inv).getAsJsonArray(); + for (int i = 0; i < invItems.size(); i++) { + if (invItems.get(i) == null || !invItems.get(i).isJsonObject()) continue; + JsonObject item = invItems.get(i).getAsJsonObject(); + if ( + (specific && item.get("internalname").getAsString().equals(internalname)) || + (!specific && item.get("internalname").getAsString().contains(internalname)) + ) { + if (item.has("count")) { + count += item.get("count").getAsInt(); + } else { + count += 1; + } + } + } + } + return count; + } + + private ItemStack[] findBestItems( + JsonObject inventoryInfo, + int numItems, + String[] invsToSearch, + String[] typeMatches, + Pattern... importantPatterns + ) { + ItemStack[] bestItems = new ItemStack[numItems]; + TreeMap<Integer, Set<ItemStack>> map = new TreeMap<>(); + for (String inv : invsToSearch) { + JsonArray invItems = inventoryInfo.get(inv).getAsJsonArray(); + for (int i = 0; i < invItems.size(); i++) { + if (invItems.get(i) == null || !invItems.get(i).isJsonObject()) continue; + JsonObject item = invItems.get(i).getAsJsonObject(); + JsonArray lore = item.get("lore").getAsJsonArray(); + if (Utils.checkItemType(lore, true, typeMatches) >= 0) { + int importance = 0; + for (int j = 0; j < lore.size(); j++) { + String line = lore.get(j).getAsString(); + for (Pattern pattern : importantPatterns) { + Matcher matcher = pattern.matcher(Utils.cleanColour(line)); + if (matcher.find()) { + importance += Integer.parseInt(matcher.group(1)); + } + } + } + map.computeIfAbsent(importance, k -> new HashSet<>()).add(NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false)); + } + } + } + int i = 0; + outer:for (int key : map.descendingKeySet()) { + Set<ItemStack> items = map.get(key); + for (ItemStack item : items) { + bestItems[i] = item; + if (++i >= bestItems.length) break outer; + } + } + + return bestItems; + } + + private ItemStack[][][] getItemsForInventory(JsonObject inventoryInfo, String invName) { + if (inventoryItems.containsKey(invName)) return inventoryItems.get(invName); + + JsonArray jsonInv = Utils.getElement(inventoryInfo, invName).getAsJsonArray(); + + if (jsonInv.size() == 0) return new ItemStack[1][][]; + + int jsonInvSize; + if (useActualMax(invName)) { + jsonInvSize = (int) Math.ceil(jsonInv.size() / 9f) * 9; + } else { + jsonInvSize = 9 * 4; + float divideBy = 9f; + if (invName.equals("wardrobe_contents")) { + divideBy = 36f; + } + for (int i = 9 * 4; i < jsonInv.size(); i++) { + JsonElement item = jsonInv.get(i); + if (item != null && item.isJsonObject()) { + jsonInvSize = (int) (Math.ceil((i + 1) / divideBy) * (int) divideBy); + } + } + } + + int rowSize = 9; + int rows = jsonInvSize / rowSize; + int maxRowsPerPage = getRowsForInventory(invName); + int maxInvSize = rowSize * maxRowsPerPage; + + int numInventories = (jsonInvSize - 1) / maxInvSize + 1; + JsonArray backPackSizes = (JsonArray) inventoryInfo.get("backpack_sizes"); + if (invName.equals("backpack_contents")) { + numInventories = backPackSizes.size(); + } + + ItemStack[][][] inventories = new ItemStack[numInventories][][]; + + //int availableSlots = getAvailableSlotsForInventory(inventoryInfo, collectionInfo, invName); + int startNumberJ = 0; + + for (int i = 0; i < numInventories; i++) { + int thisRows = Math.min(maxRowsPerPage, rows - maxRowsPerPage * i); + int invSize; + + if (invName.equals("backpack_contents")) { + thisRows = backPackSizes.get(i).getAsInt() / 9; + invSize = startNumberJ + (thisRows * 9); + maxInvSize = thisRows * 9; + } else { + startNumberJ = maxInvSize * i; + invSize = Math.min(jsonInvSize, maxInvSize + maxInvSize * i); + } + if (thisRows <= 0) break; + + ItemStack[][] items = new ItemStack[thisRows][rowSize]; + + for (int j = startNumberJ; j < invSize; j++) { + int xIndex = (j % maxInvSize) % rowSize; + int yIndex = (j % maxInvSize) / rowSize; + if (invName.equals("inv_contents")) { + yIndex--; + if (yIndex < 0) yIndex = rows - 1; + } + if (yIndex >= thisRows) { + break; + } + + if (j >= jsonInv.size()) { + items[yIndex][xIndex] = fillerStack; + continue; + } + if (jsonInv.get(j) == null || !jsonInv.get(j).isJsonObject()) { + continue; + } + + JsonObject item = jsonInv.get(j).getAsJsonObject(); + ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false); + if (item.has("item_contents")) { + JsonArray bytesArr = item.get("item_contents").getAsJsonArray(); + byte[] bytes = new byte[bytesArr.size()]; + for (int bytesArrI = 0; bytesArrI < bytesArr.size(); bytesArrI++) { + bytes[bytesArrI] = bytesArr.get(bytesArrI).getAsByte(); + } + //byte[] bytes2 = null; + NBTTagCompound tag = stack.getTagCompound(); + if (tag != null && tag.hasKey("ExtraAttributes", 10)) { + NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes"); + for (String key : ea.getKeySet()) { + if (key.endsWith("backpack_data") || key.equals("new_year_cake_bag_data")) { + ea.setTag(key, new NBTTagByteArray(bytes)); + break; + } + } + tag.setTag("ExtraAttributes", ea); + stack.setTagCompound(tag); + } + } + + items[yIndex][xIndex] = stack; + } + inventories[i] = items; + if (invName.equals("backpack_contents")) { + startNumberJ = startNumberJ + backPackSizes.get(i).getAsInt(); + } + } + + inventoryItems.put(invName, inventories); + return inventories; + } + + private boolean useActualMax(String invName) { + switch (invName) { + case "talisman_bag": + case "fishing_bag": + case "potion_bag": + case "personal_vault_contents": + return true; + } + return false; + } + + private int getRowsForInventory(String invName) { + switch (invName) { + case "wardrobe_contents": + return 4; + case "backpack_contents": + case "ender_chest_contents": + return 5; + default: + return 6; + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java new file mode 100644 index 00000000..fc305e94 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java @@ -0,0 +1,1425 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer; + +import com.google.common.collect.Lists; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Objects; +import java.util.function.Supplier; + +public class MiningPage extends GuiProfileViewerPage { + + public static final ResourceLocation pv_mining = new ResourceLocation("notenoughupdates:pv_mining.png"); + private static final ItemStack iron_pick = new ItemStack(Items.iron_pickaxe); + private final HashMap<String, ProfileViewer.Level> levelObjhotms = new HashMap<>(); + + public MiningPage(GuiProfileViewer instance) { + super(instance); + } + + @Override + public void drawPage(int mouseX, int mouseY, float partialTicks) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + + Minecraft.getMinecraft().getTextureManager().bindTexture(pv_mining); + Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST); + + ProfileViewer.Profile profile = GuiProfileViewer.getProfile(); + String profileId = GuiProfileViewer.getProfileId(); + JsonObject profileInfo = profile.getProfileInformation(profileId); + if (profileInfo == null) return; + + float xStart = 22; + float yStartTop = 27; + + int x = guiLeft + 23; + int y = guiTop + 25; + int sectionWidth = 110; + JsonObject leveling = Constants.LEVELING; + ProfileViewer.Level levelObjhotm = levelObjhotms.get(profileId); + if (levelObjhotm == null) { + float hotmXp = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.experience"), 0); + levelObjhotm = + ProfileViewer.getLevel(Utils.getElementOrDefault(leveling, "HOTM", new JsonArray()).getAsJsonArray(), hotmXp, 7, false); + levelObjhotms.put(profileId, levelObjhotm); + } + + String skillName = EnumChatFormatting.RED + "HOTM"; + //The stats that show + float mithrilPowder = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_mithril"), 0); + float gemstonePowder = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_gemstone"), 0); + float mithrilPowderTotal = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_spent_mithril"), 0); + float gemstonePowderTotal = (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_spent_gemstone"), 0)); + String jadeCrystal = + (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.jade_crystal.state"), "Not Found")); + float crystalPlacedAmount = + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.crystals.jade_crystal.total_placed"), 0)); + String jadeCrystalString = "§c✖"; + String amethystCrystal = + (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.amethyst_crystal.state"), "Not Found")); + String amethystCrystalString = "§c✖"; + String amberCrystal = + (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.amber_crystal.state"), "Not Found")); + String amberCrystalString = "§c✖"; + String sapphireCrystal = + (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.sapphire_crystal.state"), "Not Found")); + String sapphireCrystalString = "§c✖"; + String topazCrystal = + (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.topaz_crystal.state"), "Not Found")); + String topazCrystalString = "§c✖"; + String jasperCrystal = + (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.jasper_crystal.state"), "Not Found")); + String jasperCrystalString = "§c✖"; + String rubyCrystal = + (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.ruby_crystal.state"), "Not Found")); + String rubyCrystalString = "§c✖"; + int miningFortune = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune"), 0))); + int miningFortuneStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune"), 0)) * 5); + int miningSpeed = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed"), 0))); + int miningSpeedStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed"), 0)) * 20); + int dailyPowder = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_powder"), 0))); + int dailyPowderStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_powder"), 0)) * 36 + 364); + int effMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0))); + float effMinerStat = (float) ( + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)) * 0.4 + 10.4 + ); + float effMinerStat2 = (float) ( + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)) * .06 + 0.31 + ); + int tittyInsane = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.titanium_insanium"), 0))); + float tittyInsaneStat = (float) ( + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.titanium_insanium"), 0)) * .1 + 2 + ); + int luckofcave = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.random_event"), 0))); + int luckofcaveStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.random_event"), 0))); + int madMining = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_madness"), 0))); + int skyMall = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_effect"), 0))); + int goblinKiller = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.goblin_killer"), 0))); + int seasonMine = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_experience"), 0))); + float seasonMineStat = (float) ( + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.mining_experience"), 0)) * 0.1 + 5 + ); + int quickForge = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.forge_time"), 0))); + float quickForgeStat = (float) ( + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.forge_time"), 0)) * .5 + 10 + ); + int frontLoad = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.front_loaded"), 0))); + int orbit = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.experience_orbs"), 0))); + float orbitStat = (float) ( + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.experience_orbs"), 0)) * .01 + 0.2 + ); + int crystallized = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fallen_star_bonus"), 0))); + int crystallizedStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fallen_star_bonus"), 0)) * 6 + 14); + int professional = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.professional"), 0))); + int professionalStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.professional"), 0)) * 5 + 50); + int greatExplorer = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.great_explorer"), 0))); + int greatExplorerStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.great_explorer"), 0)) * 4 + 16); + int fortunate = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fortunate"), 0))); + int fortunateStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fortunate"), 0)) * 4 + 20); + int lonesomeMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.lonesome_miner"), 0))); + float lonesomeMinerStat = (float) ( + (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.lonesome_miner"), 0)) * .5 + 5 + ); + int miningFortune2 = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune_2"), 0))); + int miningFortune2Stat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune_2"), 0)) * 5); + int miningSpeed2 = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_2"), 0))); + int miningSpeed2Stat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_2"), 0)) * 40); + int miningSpeedBoost = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_boost"), 0))); + int veinSeeker = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.vein_seeker"), 0))); + int powderBuff = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.powder_buff"), 0))); + int potm = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.special_0"), 0))); + int fortnite = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.precision_mining"), 0))); + int starPowder = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.star_powder"), 0))); + int pickoblus = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.pickaxe_toss"), 0))); + int maniacMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.maniac_miner"), 0))); + + if (effMinerStat2 < 1) { + effMinerStat2 = 1; + } + int mole = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mole"), 0))); + float moleStat = (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.mole"), 0)) * 0.051); + double moleperkstat = (double) mole / 20 - 0.55 + 50; + double moleperkstat2 = (double) Math.round(moleperkstat * 100) / 100; + + float output = Math.round((float) (moleperkstat2 % 1) * 100); + if (output == 0) { + output = 100; + } + + //The logic for some of the stats + if (Objects.equals(jadeCrystal, "NOT_FOUND")) { + jadeCrystalString = "§c✖"; + } else if (Objects.equals(jadeCrystal, "FOUND")) { + jadeCrystalString = "§a✔"; + } + if (Objects.equals(amethystCrystal, "NOT_FOUND")) { + amethystCrystalString = "§c✖"; + } else if (Objects.equals(amethystCrystal, "FOUND")) { + amethystCrystalString = "§a✔"; + } + if (Objects.equals(amberCrystal, "NOT_FOUND")) { + amberCrystalString = "§c✖"; + } else if (Objects.equals(amberCrystal, "FOUND")) { + amberCrystalString = "§a✔"; + } + if (Objects.equals(sapphireCrystal, "NOT_FOUND")) { + sapphireCrystalString = "§c✖"; + } else if (Objects.equals(sapphireCrystal, "FOUND")) { + sapphireCrystalString = "§a✔"; + } + if (Objects.equals(topazCrystal, "NOT_FOUND")) { + topazCrystalString = "§c✖"; + } else if (Objects.equals(topazCrystal, "FOUND")) { + topazCrystalString = "§a✔"; + } + if (Objects.equals(jasperCrystal, "NOT_FOUND")) { + jasperCrystalString = "§c✖"; + } else if (Objects.equals(jasperCrystal, "FOUND")) { + jasperCrystalString = "§a✔"; + } + if (Objects.equals(rubyCrystal, "NOT_FOUND")) { + rubyCrystalString = "§c✖"; + } else if (Objects.equals(rubyCrystal, "FOUND")) { + rubyCrystalString = "§a✔"; + } + + //The rendering of the stats + //hotm level + getInstance().renderXpBar(skillName, iron_pick, x, y, sectionWidth, levelObjhotm, mouseX, mouseY); + //Powder + Utils.renderAlignedString( + EnumChatFormatting.DARK_GREEN + "Mithril Powder", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(mithrilPowder, 0), + guiLeft + xStart, + guiTop + yStartTop + 24, + 115 + ); + Utils.renderAlignedString( + EnumChatFormatting.LIGHT_PURPLE + "Gemstone Powder", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(gemstonePowder, 0), + guiLeft + xStart, + guiTop + yStartTop + 44, + 115 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_GREEN + "Total Mithril Powder", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(mithrilPowderTotal + mithrilPowder, 0), + guiLeft + xStart, + guiTop + yStartTop + 34, + 115 + ); + Utils.renderAlignedString( + EnumChatFormatting.LIGHT_PURPLE + "Total Gemstone Powder", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(gemstonePowderTotal + gemstonePowder, 0), + guiLeft + xStart, + guiTop + yStartTop + 54, + 115 + ); + //Crystals + Utils.renderAlignedString( + EnumChatFormatting.GREEN + "Jade Crystal:", + EnumChatFormatting.WHITE + jadeCrystalString, + guiLeft + xStart, + guiTop + yStartTop + 74, + 110 + ); + Utils.renderAlignedString( + EnumChatFormatting.GOLD + "Amber Crystal:", + EnumChatFormatting.WHITE + amberCrystalString, + guiLeft + xStart, + guiTop + yStartTop + 84, + 110 + ); + Utils.renderAlignedString( + EnumChatFormatting.DARK_PURPLE + "Amethyst Crystal:", + EnumChatFormatting.WHITE + amethystCrystalString, + guiLeft + xStart, + guiTop + yStartTop + 94, + 110 + ); + Utils.renderAlignedString( + EnumChatFormatting.AQUA + "Sapphire Crystal:", + EnumChatFormatting.WHITE + sapphireCrystalString, + guiLeft + xStart, + guiTop + yStartTop + 104, + 110 + ); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Topaz Crystal:", + EnumChatFormatting.WHITE + topazCrystalString, + guiLeft + xStart, + guiTop + yStartTop + 114, + 110 + ); + Utils.renderAlignedString( + EnumChatFormatting.LIGHT_PURPLE + "Jasper Crystal:", + EnumChatFormatting.WHITE + jasperCrystalString, + guiLeft + xStart, + guiTop + yStartTop + 124, + 110 + ); + Utils.renderAlignedString( + EnumChatFormatting.RED + "Ruby Crystal:", + EnumChatFormatting.WHITE + rubyCrystalString, + guiLeft + xStart, + guiTop + yStartTop + 134, + 110 + ); + Utils.renderAlignedString( + EnumChatFormatting.BLUE + "Total Placed Crystals:", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(crystalPlacedAmount, 0), + guiLeft + xStart, + guiTop + yStartTop + 149, + 110 + ); + + //hotm render + //Pain + + renderHotmPerk( + miningSpeed, + (int) (guiLeft + xStart + 255), + (int) (guiTop + yStartTop + 138), + mouseX, + mouseY, + () -> + miningSpeed != 50 && miningSpeed != 0 + ? Lists.newArrayList( + "Mining Speed", + EnumChatFormatting.GRAY + "Level " + miningSpeed + EnumChatFormatting.DARK_GRAY + "/50", + "", + EnumChatFormatting.GRAY + + "Grants " + + EnumChatFormatting.GREEN + + "+" + + miningSpeedStat + + EnumChatFormatting.GOLD + + " ⸕ Mining", + EnumChatFormatting.GOLD + "Speed" + EnumChatFormatting.GRAY + ".", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + + "" + + GuiProfileViewer.numberFormat.format(Math.pow(miningSpeed + 2, 3)) + + " Mithril Powder" + ) + : Lists.newArrayList( + "Mining Speed", + EnumChatFormatting.GRAY + "Level " + miningSpeed + EnumChatFormatting.DARK_GRAY + "/50", + "", + EnumChatFormatting.GRAY + + "Grants " + + EnumChatFormatting.GREEN + + "+" + + miningSpeedStat + + EnumChatFormatting.GOLD + + " ⸕ Mining", + EnumChatFormatting.GOLD + "Speed" + EnumChatFormatting.GRAY + "." + ), + 50 + ); + + renderHotmPerk( + miningFortune, + (int) (guiLeft + xStart + 255), + (int) (guiTop + yStartTop + 114), + mouseX, + mouseY, + () -> + miningFortune != 0 && miningFortune != 50 + ? Lists.newArrayList( + "Mining Fortune", + EnumChatFormatting.GRAY + "Level " + miningFortune + EnumChatFormatting.DARK_GRAY + "/50", + "", + EnumChatFormatting.GRAY + + "Grants " + + EnumChatFormatting.GREEN + + "+" + + miningFortuneStat + + EnumChatFormatting.GOLD + + " ☘ Mining", + EnumChatFormatting.GOLD + "Fortune" + EnumChatFormatting.GRAY + ".", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + + "" + + GuiProfileViewer.numberFormat.format(Math.pow(miningFortune + 2, 3)) + + " Mithril Powder" + ) + : Lists.newArrayList( + "Mining Fortune", + EnumChatFormatting.GRAY + "Level " + miningFortune + EnumChatFormatting.DARK_GRAY + "/50", + "", + EnumChatFormatting.GRAY + + "Grants " + + EnumChatFormatting.GREEN + + "+" + + miningFortuneStat + + EnumChatFormatting.GOLD + + " ☘ Mining", + EnumChatFormatting.GOLD + "Fortune" + EnumChatFormatting.GRAY + "." + ), + 50 + ); + + renderHotmPerk( + tittyInsane, + (int) (guiLeft + xStart + 231), + (int) (guiTop + yStartTop + 114), + mouseX, + mouseY, + () -> + tittyInsane != 0 && tittyInsane != 50 + ? Lists.newArrayList( + "Titanium Insanium", + EnumChatFormatting.GRAY + "Level " + tittyInsane + EnumChatFormatting.DARK_GRAY + "/50", + "", + EnumChatFormatting.GRAY + "When mining Mithril Ore, you", + EnumChatFormatting.GRAY + + "have a " + + EnumChatFormatting.GREEN + + tittyInsaneStat + + "% " + + EnumChatFormatting.GRAY + + "chance to", + EnumChatFormatting.GRAY + "convert the block into Titanium", + EnumChatFormatting.GRAY + "Ore.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(tittyInsane + 2, 3)) + + " Mithril Powder" + ) + : Lists.newArrayList( + "Titanium Insanium", + EnumChatFormatting.GRAY + "Level " + tittyInsane + EnumChatFormatting.DARK_GRAY + "/50", + "", + EnumChatFormatting.GRAY + "When mining Mithril Ore, you", + EnumChatFormatting.GRAY + + "have a " + + EnumChatFormatting.GREEN + + tittyInsaneStat + + "% " + + EnumChatFormatting.GRAY + + "chance to", + EnumChatFormatting.GRAY + "convert the block into Titanium", + EnumChatFormatting.GRAY + "Ore." + ), + 50 + ); + + renderPickaxeAbility( + miningSpeedBoost, + (int) (guiLeft + xStart + 207), + (int) (guiTop + yStartTop + 114), + mouseX, + mouseY, + () -> + potm == 0 + ? Lists.newArrayList( // Peak of the mountain == 0 + "Mining Speed Boost", + "", + EnumChatFormatting.GRAY + "Pickaxe Ability: Mining Speed Boost", + EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "200% " + EnumChatFormatting.GOLD + "⸕ Mining", + EnumChatFormatting.GOLD + + "Speed " + + EnumChatFormatting.GRAY + + "for " + + EnumChatFormatting.GREEN + + "15s" + + EnumChatFormatting.GRAY, + EnumChatFormatting.DARK_GRAY + "Cooldown: " + EnumChatFormatting.GREEN + "120s" + ) + : Lists.newArrayList( // Peak of the mountain > 0 + "Mining Speed Boost", + "", + EnumChatFormatting.GRAY + "Pickaxe Ability: Mining Speed Boost", + EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "300% " + EnumChatFormatting.GOLD + "⸕ Mining", + EnumChatFormatting.GOLD + + "Speed " + + EnumChatFormatting.GRAY + + "for " + + EnumChatFormatting.GREEN + + "20s" + + EnumChatFormatting.GRAY, + EnumChatFormatting.DARK_GRAY + "Cooldown: " + EnumChatFormatting.GREEN + "120s" + ) + ); + + renderPickaxeAbility( + veinSeeker, + (int) (guiLeft + xStart + 183), + (int) (guiTop + yStartTop + 18), + mouseX, + mouseY, + () -> + Lists.newArrayList( + "Vein Seeker", + "", + "§6Pickaxe Ability: Vein Seeker", + "§7Points in the direction of the", + "§7nearest vein and grants §a+§a3§7", + "§7§6Mining Spread §7for §a14s§7§7.", + "§8Cooldown: §a60s" + ) + ); + + renderHotmPerk( + luckofcave, + (int) (guiLeft + xStart + 207), + (int) (guiTop + yStartTop + 90), + mouseX, + mouseY, + () -> + luckofcave != 0 && luckofcave != 45 + ? Lists.newArrayList( + "Luck of the Cave", + "§7Level " + luckofcave + EnumChatFormatting.DARK_GRAY + "/45", + "", + "§7Increases the chance for you to", + "§7trigger rare occurrences im", + "§2Dwarven Mines " + EnumChatFormatting.GRAY + "by " + EnumChatFormatting.GREEN + luckofcaveStat + "%§7.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(luckofcave + 2, 3.07)) + + " Mithril Powder" + ) + : Lists.newArrayList( + "Luck of the Cave", + "§7Level " + luckofcave + EnumChatFormatting.DARK_GRAY + "/45", + "", + "§7Increases the chance for you to", + "§7trigger rare occurrences im", + "§2Dwarven Mines " + EnumChatFormatting.GRAY + "by " + EnumChatFormatting.GREEN + luckofcaveStat + "%§7." + ), + 45 + ); + + renderHotmPerk( + dailyPowder, + (int) (guiLeft + xStart + 255), + (int) (guiTop + yStartTop + 90), + mouseX, + mouseY, + () -> + dailyPowder != 0 && dailyPowder != 100 + ? Lists.newArrayList( + "Daily Powder", + EnumChatFormatting.GRAY + "Level " + dailyPowder + EnumChatFormatting.DARK_GRAY + "/100", + "", + EnumChatFormatting.GRAY + + "Gains " + + EnumChatFormatting.GREEN + + dailyPowderStat + + " Powder" + + EnumChatFormatting.GRAY + + " from the", + EnumChatFormatting.GRAY + "first ore you mine every day.", + EnumChatFormatting.GRAY + "Works for all Powder types.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + "" + (200 + ((dailyPowder) * 18)) + " Mithril Powder" + ) + : Lists.newArrayList( + "Daily Powder", + EnumChatFormatting.GRAY + "Level " + dailyPowder + EnumChatFormatting.DARK_GRAY + "/100", + "", + EnumChatFormatting.GRAY + + "Gains " + + EnumChatFormatting.GREEN + + dailyPowderStat + + " Powder" + + EnumChatFormatting.GRAY + + " from the", + EnumChatFormatting.GRAY + "first ore you mine every day.", + EnumChatFormatting.GRAY + "Works for all Powder types." + ), + 100 + ); + + float finalEffMinerStat2 = effMinerStat2; + renderHotmPerk( + effMiner, + (int) (guiLeft + xStart + 255), + (int) (guiTop + yStartTop + 66), + mouseX, + mouseY, + () -> + effMiner != 0 && effMiner != 100 + ? Lists.newArrayList( + "Efficient Miner", + EnumChatFormatting.GRAY + "Level " + effMiner + EnumChatFormatting.DARK_GRAY + "/100", + "", + EnumChatFormatting.GRAY + "When mining ores, you have a", + EnumChatFormatting.GREEN + + "" + + effMinerStat + + "%" + + EnumChatFormatting.GRAY + + " chance to mine " + + EnumChatFormatting.GREEN + + Math.round(finalEffMinerStat2), + EnumChatFormatting.GRAY + "adjacent ores.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(effMiner + 2, 2.6)) + + " Mithril Powder" + ) + : Lists.newArrayList( + "Efficient Miner", + EnumChatFormatting.GRAY + "Level " + effMiner + EnumChatFormatting.DARK_GRAY + "/100", + "", + EnumChatFormatting.GRAY + "When mining ores, you have a", + EnumChatFormatting.GREEN + + "" + + effMinerStat + + "%" + + EnumChatFormatting.GRAY + + " chance to mine " + + EnumChatFormatting.GREEN + + Math.round(finalEffMinerStat2), + EnumChatFormatting.GRAY + "adjacent ores." + ), + 100 + ); + + renderHotmPerk( + potm, + (int) (guiLeft + xStart + 255), + (int) (guiTop + yStartTop + 42), + mouseX, + mouseY, + () -> { + switch (potm) { + case 0: + return Lists.newArrayList( + EnumChatFormatting.RED + "Peak of the Mountain", + EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + "50000 Mithril Powder" + ); + case 1: + return Lists.newArrayList( + EnumChatFormatting.YELLOW + "Peak of the Mountain", + EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", + "", + "§7§8+§c1 Pickaxe Ability Level", + "§7§8+§51 Token of the Mountain", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + "50000 Mithril Powder" + ); + case 2: + return Lists.newArrayList( + EnumChatFormatting.YELLOW + "Peak of the Mountain", + EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", + "", + "§7§8+§c1 Pickaxe Ability Level", + "§7§8+§51 Token of the Mountain", + "§7§8+§a1 Forge Slot", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + "75000 Mithril Powder" + ); + case 3: + return Lists.newArrayList( + EnumChatFormatting.YELLOW + "Peak of the Mountain", + EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", + "", + "§7§8+§c1 Pickaxe Ability Level", + "§7§8+§51 Token of the Mountain", + "§7§8+§a1 Forge Slot", + "§7§8+§a1 Commission Slot", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + "100000 Mithril Powder" + ); + case 4: + return Lists.newArrayList( + EnumChatFormatting.YELLOW + "Peak of the Mountain", + EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", + "", + "§7§8+§c1 Pickaxe Ability Level", + "§7§8+§51 Token of the Mountain", + "§7§8+§a1 Forge Slot", + "§7§8+§a1 Commission Slot", + "§7§8+§21 Mithril Powder §7when", + "§7mining §fMithril", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + "125000 Mithril Powder" + ); + case 5: + return Lists.newArrayList( + EnumChatFormatting.GREEN + "Peak of the Mountain", + EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5", + "", + "§7§8+§c1 Pickaxe Ability Level", + "§7§8+§51 Token of the Mountain", + "§7§8+§a1 Forge Slot", + "§7§8+§a1 Commission Slot", + "§7§8+§21 Mithril Powder §7when", + "§7mining §fMithril", + "§7§8+§51 Token of the Mountain" + ); + } + return null; + }, + potm > 0 ? new ItemStack(Blocks.redstone_block) : new ItemStack(Blocks.bedrock), + true // A redstone block or bedrock is being rendered, so standard GUI item lighting needs to be enabled. + ); + + float finalOutput = output; + renderHotmPerk( + mole, + (int) (guiLeft + xStart + 255), + (int) (guiTop + yStartTop + 18), + mouseX, + mouseY, + () -> + mole != 0 && mole != 190 + ? Lists.newArrayList( + "Mole", + EnumChatFormatting.GRAY + "Level " + mole + EnumChatFormatting.DARK_GRAY + "/190", + "", + EnumChatFormatting.GRAY + "When mining hard stone, you have", + EnumChatFormatting.GRAY + + "a " + + EnumChatFormatting.GREEN + + finalOutput + + "% " + + EnumChatFormatting.GRAY + + "chance to mine " + + EnumChatFormatting.GREEN, + EnumChatFormatting.GREEN + + "" + + Math.round(moleStat) + + EnumChatFormatting.GRAY + + " adjacent hard stone block" + + (moleStat == 1.0 ? "." : "s."), + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.LIGHT_PURPLE + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(mole + 2, 2.2)) + + " Gemstone Powder" + ) + : Lists.newArrayList( + "Mole", + EnumChatFormatting.GRAY + "Level " + mole + EnumChatFormatting.DARK_GRAY + "/190", + "", + EnumChatFormatting.GRAY + "When mining hard stone, you have", + EnumChatFormatting.GRAY + + "a " + + EnumChatFormatting.GREEN + + finalOutput + + "% " + + EnumChatFormatting.GRAY + + "chance to mine " + + EnumChatFormatting.GREEN, + EnumChatFormatting.GREEN + + "" + + Math.round(moleStat) + + EnumChatFormatting.GRAY + + " adjacent hard stone block" + + (moleStat == 1.0 ? "." : "s.") + ), + 190 + ); + + renderHotmPerk( + powderBuff, + (int) (guiLeft + xStart + 255), + (int) (guiTop + yStartTop - 6), + mouseX, + mouseY, + () -> + powderBuff != 0 && powderBuff != 50 + ? Lists.newArrayList( + "Powder Buff", + EnumChatFormatting.GRAY + "Level " + powderBuff + EnumChatFormatting.DARK_GRAY + "/50", + "", + EnumChatFormatting.GRAY + + "Gain " + + EnumChatFormatting.GREEN + + powderBuff + + "% " + + EnumChatFormatting.GRAY + + "more Mithril", + EnumChatFormatting.GRAY + "Powder and Gemstone Powder§7.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.LIGHT_PURPLE + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(powderBuff + 2, 3.2)) + + " Gemstone Powder" + ) + : Lists.newArrayList( + "Powder Buff", + EnumChatFormatting.GRAY + "Level " + powderBuff + EnumChatFormatting.DARK_GRAY + "/50", + "", + EnumChatFormatting.GRAY + + "Gain " + + EnumChatFormatting.GREEN + + powderBuff + + "% " + + EnumChatFormatting.GRAY + + "more Mithril", + EnumChatFormatting.GRAY + "Powder and Gemstone Powder§7." + ), + 50 + ); + + renderHotmPerk( + skyMall, + (int) (guiLeft + xStart + 183), + (int) (guiTop + yStartTop + 66), + mouseX, + mouseY, + () -> + Lists.newArrayList( + "Sky Mall", + "§7Every SkyBlock day, you receive", + "§7a random buff in the §2Dwarven", + "§2Mines§7.", + "", + "§7Possible Buffs", + "§8 ■ §7Gain §a+100 §6⸕ Mining Speed.", + "§8 ■ §7Gain §a+50 §6☘ Mining Fortune.", + "§8 ■ §7Gain §a+15% §7chance to gain", + " §7extra Powder while mining.", + "§8 ■ §7Reduce Pickaxe Ability cooldown", + " §7by §a20%", + "§8 ■ §7§a10x §7chance to find Goblins", + " §7while mining.", + "§8 ■ §7Gain §a5x §9Titanium §7drops." + ), + new ItemStack(skyMall > 0 ? Items.diamond : Items.coal) + ); + + renderHotmPerk( + goblinKiller, + (int) (guiLeft + xStart + 207), + (int) (guiTop + yStartTop + 42), + mouseX, + mouseY, + () -> + Lists.newArrayList( + "Goblin Killer", + "§7Killing a §6Golden Goblin", + "§6§7gives §2200 §7extra §2Mithril", + "§2Powder§7, while killing other", + "§7Goblins gives some based on", + "§7their wits." + ), + new ItemStack(goblinKiller > 0 ? Items.diamond : Items.coal) + ); + + renderHotmPerk( + seasonMine, + (int) (guiLeft + xStart + 231), + (int) (guiTop + yStartTop + 66), + mouseX, + mouseY, + () -> + seasonMine != 0 && seasonMine != 100 + ? Lists.newArrayList( + "Seasoned Mineman", + "§7Level " + seasonMine + "§8/100", + "", + "§7Increases your Mining", + "§7experience gain by " + EnumChatFormatting.GREEN + seasonMineStat + "%§7.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(seasonMine + 2, 2.3)) + + " Mithril Powder" + ) + : Lists.newArrayList( + "Seasoned Mineman", + "§7Level " + seasonMine + "§8/100", + "", + "§7Increases your Mining", + "§7experience gain by " + EnumChatFormatting.GREEN + seasonMineStat + "%§7." + ), + 100 + ); + + renderHotmPerk( + madMining, + (int) (guiLeft + xStart + 207), + (int) (guiTop + yStartTop + 66), + mouseX, + mouseY, + () -> Lists.newArrayList("Mining Madness", "§7Grants §a+50 §6⸕ Mining Speed", "§7and §6☘ Mining Fortune§7."), + new ItemStack(madMining > 0 ? Items.diamond : Items.coal) + ); + + renderHotmPerk( + lonesomeMiner, + (int) (guiLeft + xStart + 207), + (int) (guiTop + yStartTop + 18), + mouseX, + mouseY, + () -> + lonesomeMiner != 0 && lonesomeMiner != 45 + ? Lists.newArrayList( + "Lonesome Miner", + "§7Level " + lonesomeMiner + EnumChatFormatting.DARK_GRAY + "/45", + "", + "§7Increases §c❁ Strength, §9☣ Crit", + "§9Chance, §9☠ Crit Damage, §a❈", + "§aDefense, and §c❤ Health", + "§c§7statistics gain by " + EnumChatFormatting.GREEN + lonesomeMinerStat + "%§7", + "§7while in the Crystal Hollows.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.LIGHT_PURPLE + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(lonesomeMiner + 2, 3.07)) + + " Gemstone Powder" + ) + : Lists.newArrayList( + "Lonesome Miner", + "§7Level " + lonesomeMiner + EnumChatFormatting.DARK_GRAY + "/45", + "", + "§7Increases §c❁ Strength, §9☣ Crit", + "§9Chance, §9☠ Crit Damage, §a❈", + "§aDefense, and §c❤ Health", + "§c§7statistics gain by " + EnumChatFormatting.GREEN + lonesomeMinerStat + "%§7" + ), + 45 + ); + + renderHotmPerk( + professional, + (int) (guiLeft + xStart + 231), + (int) (guiTop + yStartTop + 18), + mouseX, + mouseY, + () -> + professional != 0 && professional != 140 + ? Lists.newArrayList( + "Professional", + "§7Level " + professional + EnumChatFormatting.DARK_GRAY + "/140", + "", + "§7Gain §a+" + professionalStat + "§6 ⸕ Mining", + "§6Speed§7 when mining Gemstones.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.LIGHT_PURPLE + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(professional + 2, 2.3)) + + " Gemstone Powder" + ) + : Lists.newArrayList( + "Professional", + "§7Level " + professional + EnumChatFormatting.DARK_GRAY + "/140", + "", + "§7Gain §a+" + professionalStat + "§6 ⸕ Mining", + "§6Speed§7 when mining Gemstones." + ), + 140 + ); + + renderHotmPerk( + miningSpeed2, + (int) (guiLeft + xStart + 207), + (int) (guiTop + yStartTop - 6), + mouseX, + mouseY, + () -> + miningSpeed2 != 0 && miningSpeed2 != 50 + ? Lists.newArrayList( + "Mining Speed 2", + "§7Level " + miningSpeed2 + EnumChatFormatting.DARK_GRAY + "/50", + "", + "§7Grants " + EnumChatFormatting.GREEN + "+" + miningSpeed2Stat + EnumChatFormatting.GOLD + " ⸕ Mining", + "§6Speed§7.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.LIGHT_PURPLE + + "" + + GuiProfileViewer.numberFormat.format(Math.pow(miningSpeed2 + 2, 3)) + + " Gemstone Powder" + ) + : Lists.newArrayList( + "Mining Speed 2", + "§7Level " + miningSpeed2 + EnumChatFormatting.DARK_GRAY + "/50", + "", + "§7Grants " + EnumChatFormatting.GREEN + "+" + miningSpeed2Stat + EnumChatFormatting.GOLD + " ⸕ Mining", + "§6Speed§7." + ), + 50 + ); + + renderHotmPerk( + quickForge, + (int) (guiLeft + xStart + 279), + (int) (guiTop + yStartTop + 114), + mouseX, + mouseY, + () -> + quickForge != 0 && quickForge != 20 + ? Lists.newArrayList( + "Quick Forge", + "§7Level " + quickForge + EnumChatFormatting.DARK_GRAY + "/20", + "", + "§7Decreases the time it takes to", + "§7forge by §a" + (quickForgeStat < 20 ? quickForgeStat : 30) + "%§7.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(quickForge + 2, 4)) + + " Mithril Powder" + ) + : Lists.newArrayList( + "Quick Forge", + "§7Level " + quickForge + EnumChatFormatting.DARK_GRAY + "/20", + "", + "§7Decreases the time it takes to", + "§7forge by §a" + (quickForgeStat < 20 ? quickForgeStat : 30) + "%§7." + ), + 20 + ); + + renderHotmPerk( + fortunate, + (int) (guiLeft + xStart + 279), + (int) (guiTop + yStartTop + 18), + mouseX, + mouseY, + () -> + fortunate != 0 && fortunate != 20 + ? Lists.newArrayList( + "Fortunate", + "§7Level " + fortunate + EnumChatFormatting.DARK_GRAY + "/20", + "", + "§7Gain " + EnumChatFormatting.GREEN + "+" + fortunateStat + " §6☘ Mining", + "§6Fortune§7 when mining Gemstone.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(fortunate + 2, 3.05)) + + " Mithril Powder" + ) + : Lists.newArrayList( + "Fortunate", + "§7Level " + fortunate + EnumChatFormatting.DARK_GRAY + "/20", + "", + "§7Gain " + EnumChatFormatting.GREEN + "+" + fortunateStat + " §6☘ Mining", + "§6Fortune§7 when mining Gemstone." + ), + 20 + ); + + renderHotmPerk( + greatExplorer, + (int) (guiLeft + xStart + 303), + (int) (guiTop + yStartTop + 18), + mouseX, + mouseY, + () -> + greatExplorer != 0 && greatExplorer != 20 + ? Lists.newArrayList( + "Great Explorer", + "§7Level " + greatExplorer + EnumChatFormatting.DARK_GRAY + "/20", + "", + "§7Grants " + EnumChatFormatting.GREEN + "+" + greatExplorerStat + "% " + EnumChatFormatting.GRAY + "chance to", + "§7find treasure.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.LIGHT_PURPLE + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(greatExplorer + 2, 4)) + + " Gemstone Powder" + ) + : Lists.newArrayList( + "Great Explorer", + "§7Level " + greatExplorer + EnumChatFormatting.DARK_GRAY + "/20", + "", + "§7Grants " + EnumChatFormatting.GREEN + "+" + greatExplorerStat + "% " + EnumChatFormatting.GRAY + "chance to", + "§7find treasure." + ), + 20 + ); + + renderHotmPerk( + miningFortune2, + (int) (guiLeft + xStart + 303), + (int) (guiTop + yStartTop - 6), + mouseX, + mouseY, + () -> + miningFortune2 != 0 && miningFortune2 != 50 + ? Lists.newArrayList( + "Mining Fortune 2", + "§7Level " + miningFortune2 + EnumChatFormatting.DARK_GRAY + "/50", + "", + "§7Grants §a+§a" + miningFortune2Stat + "§7 §6☘ Mining", + "§6Fortune§7.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.LIGHT_PURPLE + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(miningFortune2 + 2, 3.2)) + + " Gemstone Powder" + ) + : Lists.newArrayList( + "Mining Fortune 2", + "§7Level " + miningFortune2 + EnumChatFormatting.DARK_GRAY + "/50", + "", + "§7Grants §a+§a" + miningFortune2Stat + "§7 §6☘ Mining", + "§6Fortune§7." + ), + 50 + ); + + renderHotmPerk( + orbit, + (int) (guiLeft + xStart + 279), + (int) (guiTop + yStartTop + 66), + mouseX, + mouseY, + () -> + orbit != 0 && orbit != 80 + ? Lists.newArrayList( + "Orbiter", + "§7Level " + orbit + EnumChatFormatting.DARK_GRAY + "/80", + "", + "§7When mining ores, you have a", + EnumChatFormatting.GREEN + "" + orbitStat + "%" + EnumChatFormatting.GRAY + " chance to get a random", + "§7amount of experience orbs.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + "" + ((orbit + 1) * 70) + " Mithril Powder" + ) + : Lists.newArrayList( + "Orbiter", + "§7Level " + orbit + EnumChatFormatting.DARK_GRAY + "/80", + "", + "§7When mining ores, you have a", + EnumChatFormatting.GREEN + "" + orbitStat + "%" + EnumChatFormatting.GRAY + " chance to get a random", + "§7amount of experience orbs." + ), + 80 + ); + + renderHotmPerk( + frontLoad, + (int) (guiLeft + xStart + 303), + (int) (guiTop + yStartTop + 66), + mouseX, + mouseY, + () -> + Lists.newArrayList( + "Front Loaded", + "§7Grants §a+100 §6⸕ Mining Speed", + "§7and §6☘ Mining Fortune §7for", + "§7the first §e2,500 §7ores you", + "§7mine in a day." + ), + new ItemStack(frontLoad > 0 ? Items.diamond : Items.coal) + ); + + renderHotmPerk( + starPowder, + (int) (guiLeft + xStart + 303), + (int) (guiTop + yStartTop + 42), + mouseX, + mouseY, + () -> + Lists.newArrayList( + "Star Powder", + "§7Mining Mithril Ore near §5Fallen", + "§5Crystals §7gives §a+3 §7extra", + "§7Mithril Powder§7." + ), + new ItemStack(starPowder > 0 ? Items.diamond : Items.coal) + ); + + renderHotmPerk( + fortnite, + (int) (guiLeft + xStart + 327), + (int) (guiTop + yStartTop + 66), + mouseX, + mouseY, + () -> + Lists.newArrayList( + "Precision Mining", + "§7When mining ore, a particle", + "§7target appears on the block that", + "§7increases your §6⸕ Mining Speed", + "§7by §a30% §7when aiming at it." + ), + new ItemStack(fortnite > 0 ? Items.diamond : Items.coal) + ); + + renderHotmPerk( + crystallized, + (int) (guiLeft + xStart + 303), + (int) (guiTop + yStartTop + 90), + mouseX, + mouseY, + () -> + crystallized != 0 && crystallized != 30 + ? Lists.newArrayList( + "Crystallized", + "§7Level " + crystallized + EnumChatFormatting.DARK_GRAY + "/30", + "", + "§7Grants §a+§a" + crystallizedStat + "§7 §6⸕ Mining", + "§6Speed §7and a §a" + crystallizedStat + "%§7 §7chance", + "§7to deal §a+1 §7extra damage near", + "§7§5Fallen Stars§7.", + "", + EnumChatFormatting.GRAY + "Cost", + EnumChatFormatting.DARK_GREEN + + "" + + GuiProfileViewer.numberFormat.format((int) Math.pow(crystallized + 2, 2.4)) + + " Mithril Powder" + ) + : Lists.newArrayList( + "Crystallized", + "§7Level " + crystallized + EnumChatFormatting.DARK_GRAY + "/30", + "", + "§7Grants §a+§a" + crystallizedStat + "§7 §6⸕ Mining", + "§6Speed §7and a §a" + crystallizedStat + "%§7 §7chance", + "§7to deal §a+1 §7extra damage near", + "§7§5Fallen Stars§7." + ), + 30 + ); + + renderPickaxeAbility( + pickoblus, + (int) (guiLeft + xStart + 303), + (int) (guiTop + yStartTop + 114), + mouseX, + mouseY, + () -> + Lists.newArrayList( + "Pickobulus", + "", + "§6Pickaxe Ability: Pickobulus", + "§7Throw your pickaxe to create an", + "§7explosion on impact, mining all", + "§7ores within a §a2§7 block", + "§7radius.", + "§8Cooldown: §a" + (potm == 0 ? "120s" : "110s") + ) + ); + + renderPickaxeAbility( + maniacMiner, + (int) (guiLeft + xStart + 327), + (int) (guiTop + yStartTop + 18), + mouseX, + mouseY, + () -> + Lists.newArrayList( + EnumChatFormatting.RED + "Maniac Miner", + "", + "§6Pickaxe Ability: Maniac Miner", + "§7Spends all your Mana and grants", + "§7§a+1 §6⸕ Mining Speed §7for", + "§7every 10 Mana spent, for", + "§7§a§a15s§7§7.", + "§8Cooldown: §a59s" + ) + ); + } + + /** + * Renders a standard HOTM perk that can be levelled. + */ + private void renderHotmPerk( + int perkLevel, + int xPosition, + int yPosition, + int mouseX, + int mouseY, + Supplier<ArrayList<String>> tooltipSupplier, + int maxLevel + ) { + renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, false, maxLevel); + } + + /** + * Renders a pickaxe ability that can be unlocked once and not levelled. + */ + private void renderPickaxeAbility( + int perkLevel, + int xPosition, + int yPosition, + int mouseX, + int mouseY, + Supplier<ArrayList<String>> tooltipSupplier + ) { + renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, true, -1); + } + + /** + * Renders a HOTM perk. This method is only called from its overloads above. + */ + private void renderHotmPerk( + int perkLevel, + int xPosition, + int yPosition, + int mouseX, + int mouseY, + Supplier<ArrayList<String>> tooltipSupplier, + boolean isPickaxeAbility, + int maxLevel + ) { + boolean unlocked = perkLevel > 0; + GlStateManager.color(1, 1, 1, 1); + GlStateManager.disableLighting(); + + ItemStack itemStack; + if (isPickaxeAbility) { + RenderHelper.enableGUIStandardItemLighting(); // GUI standard item lighting must be enabled for items that are rendered as blocks, like emerald blocks. + itemStack = new ItemStack(unlocked ? Blocks.emerald_block : Blocks.coal_block); // Pickaxe abilities are rendered as blocks + } else { // Non-pickaxe abilities are rendered as items + itemStack = new ItemStack(unlocked ? (perkLevel >= maxLevel ? Items.diamond : Items.emerald) : Items.coal); + } + + ArrayList<String> tooltip = tooltipSupplier.get(); + // Prepend the green, yellow, or red color on the first line of each tooltip depending on if the perk is unlocked + tooltip.set( + 0, + (unlocked ? (perkLevel >= maxLevel ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW) : EnumChatFormatting.RED) + + tooltip.get(0) + ); + + NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Custom Resource Packs + NBTTagCompound display = new NBTTagCompound(); + display.setString("Name", tooltip.get(0)); + nbt.setTag("display", display); + itemStack.setTagCompound(nbt); + + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, xPosition, yPosition); + GlStateManager.enableLighting(); + if (mouseX >= xPosition && mouseX < xPosition + 16) { + if (mouseY >= yPosition && mouseY <= yPosition + 16) { + Utils.drawHoveringText( + tooltip, + mouseX, + mouseY, + getInstance().width, + getInstance().height, + -1, + Minecraft.getMinecraft().fontRendererObj + ); + } + } + } + + /** + * A separate method similar to the one above, but allowing the caller to specify an ItemStack to render. + * Used for rendering Peak of the Mountain and perks that are unlocked once and not upgraded. + */ + private void renderHotmPerk( + int perkLevel, + int xPosition, + int yPosition, + int mouseX, + int mouseY, + Supplier<ArrayList<String>> tooltipSupplier, + ItemStack itemStack + ) { + renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, itemStack, false); + } + + /** + * This method renders a HOTM perk using the provided ItemStack. + * It is overloaded by the method above, and is only called directly to render Peak of the Mountain. + */ + private void renderHotmPerk( + int perkLevel, + int xPosition, + int yPosition, + int mouseX, + int mouseY, + Supplier<ArrayList<String>> tooltipSupplier, + ItemStack itemStack, + boolean isRenderingBlock + ) { + boolean unlocked = perkLevel > 0; + GlStateManager.color(1, 1, 1, 1); + GlStateManager.disableLighting(); + if (isRenderingBlock) RenderHelper.enableGUIStandardItemLighting(); + + ArrayList<String> tooltip = tooltipSupplier.get(); + // Prepend the green or red color on the first line of each tooltip depending on if the perk is unlocked + if (!tooltip.get(0).contains("Peak of the Mountain")) tooltip.set( + 0, + (unlocked ? EnumChatFormatting.GREEN : EnumChatFormatting.RED) + tooltip.get(0) + ); //Peak of the Moutain has three color options, and is set already + + NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Resource Packs + NBTTagCompound display = new NBTTagCompound(); + display.setString("Name", tooltip.get(0)); + if (tooltip.get(0).contains("Peak of the Mountain")) display.setString("Lore", tooltip.get(1)); //Set Lore to Level + nbt.setTag("display", display); + itemStack.setTagCompound(nbt); + + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, xPosition, yPosition); + GlStateManager.enableLighting(); + if (mouseX >= xPosition && mouseX < xPosition + 16) { + if (mouseY >= yPosition && mouseY <= yPosition + 16) { + Utils.drawHoveringText( + tooltip, + mouseX, + mouseY, + getInstance().width, + getInstance().height, + -1, + Minecraft.getMinecraft().fontRendererObj + ); + } + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java index ed7eb55d..af904e1d 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java @@ -38,16 +38,14 @@ import java.io.IOException; import java.util.HashMap; public class Panorama { + private static final TexLoc tl = new TexLoc(97, 19, Keyboard.KEY_P); private static final TexLoc tl2 = new TexLoc(37, 80, Keyboard.KEY_L); - + private static final HashMap<String, ResourceLocation[]> panoramasMap = new HashMap<>(); private static ResourceLocation backgroundTexture = null; - private static int lastWidth = 0; private static int lastHeight = 0; - private static final HashMap<String, ResourceLocation[]> panoramasMap = new HashMap<>(); - public static synchronized ResourceLocation[] getPanoramasForLocation(String location, String identifier) { if (panoramasMap.containsKey(location + identifier)) return panoramasMap.get(location + identifier); try { @@ -63,8 +61,7 @@ public class Panorama { try { ResourceLocation[] panoramasArray = new ResourceLocation[6]; for (int i = 0; i < 6; i++) { - panoramasArray[i] = - new ResourceLocation("notenoughupdates:panoramas/" + location + "/panorama_" + i + ".jpg"); + panoramasArray[i] = new ResourceLocation("notenoughupdates:panoramas/" + location + "/panorama_" + i + ".jpg"); Minecraft.getMinecraft().getResourceManager().getResource(panoramasArray[i]); } panoramasMap.put(location + identifier, panoramasArray); @@ -172,7 +169,6 @@ public class Panorama { float scale = (float) Math.sqrt(3 / distSq); worldrenderer.pos(xr * scale, yr * scale, scale).tex(x2, y2).color(255, 255, 255, 255).endVertex(); - } tessellator.draw(); @@ -196,12 +192,16 @@ public class Panorama { GlStateManager.enableDepth(); } - if (backgroundTexture == null || lastWidth != width * scaledresolution.getScaleFactor() || - lastHeight != height * scaledresolution.getScaleFactor()) { - DynamicTexture viewportTexture = - new DynamicTexture(width * scaledresolution.getScaleFactor(), height * scaledresolution.getScaleFactor()); - backgroundTexture = - Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("background", viewportTexture); + if ( + backgroundTexture == null || + lastWidth != width * scaledresolution.getScaleFactor() || + lastHeight != height * scaledresolution.getScaleFactor() + ) { + DynamicTexture viewportTexture = new DynamicTexture( + width * scaledresolution.getScaleFactor(), + height * scaledresolution.getScaleFactor() + ); + backgroundTexture = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("background", viewportTexture); lastWidth = width * scaledresolution.getScaleFactor(); lastHeight = height * scaledresolution.getScaleFactor(); } @@ -224,14 +224,10 @@ public class Panorama { Tessellator tessellator = Tessellator.getInstance(); WorldRenderer worldrenderer = tessellator.getWorldRenderer(); worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); - worldrenderer.pos(x, y + height, 0) - .tex(0, 1).endVertex(); - worldrenderer.pos(x + width, y + height, 0) - .tex(0, 0).endVertex(); - worldrenderer.pos(x + width, y, 0) - .tex(1, 0).endVertex(); - worldrenderer.pos(x, y, 0) - .tex(1, 1).endVertex(); + worldrenderer.pos(x, y + height, 0).tex(0, 1).endVertex(); + worldrenderer.pos(x + width, y + height, 0).tex(0, 0).endVertex(); + worldrenderer.pos(x + width, y, 0).tex(1, 0).endVertex(); + worldrenderer.pos(x, y, 0).tex(1, 1).endVertex(); tessellator.draw(); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java new file mode 100644 index 00000000..22d86424 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java @@ -0,0 +1,598 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer; + +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.util.Constants; +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; +import org.lwjgl.opengl.GL11; + +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 { + + 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 List<JsonObject> sortedPets = null; + private List<ItemStack> 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(); + + ProfileViewer.Profile profile = GuiProfileViewer.getProfile(); + String profileId = GuiProfileViewer.getProfileId(); + JsonObject petsInfo = profile.getPetsInfo(profileId); + if (petsInfo == null) return; + JsonObject petsJson = Constants.PETS; + if (petsJson == null) return; + + String location = null; + JsonObject status = profile.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) { + 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 tier1 = pet1.get("tier").getAsString(); + String tierNum1 = GuiProfileViewer.MINION_RARITY_TO_NUM.get(tier1); + if (tierNum1 == null) return 1; + int tierNum1I = Integer.parseInt(tierNum1); + float exp1 = pet1.get("exp").getAsFloat(); + + String tier2 = pet2.get("tier").getAsString(); + String tierNum2 = GuiProfileViewer.MINION_RARITY_TO_NUM.get(tier2); + if (tierNum2 == null) return -1; + int tierNum2I = Integer.parseInt(tierNum2); + float exp2 = pet2.get("exp").getAsFloat(); + + if (tierNum1I != tierNum2I) { + return tierNum2I - tierNum1I; + } else { + return (int) (exp2 - exp1); + } + }); + 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<String, String> replacements = NotEnoughUpdates.INSTANCE.manager.getLoreReplacements( + petname, + tier, + (int) Math.floor(level) + ); + + if (heldItem != null) { + HashMap<String, Float> petStatBoots = GuiProfileViewer.PET_STAT_BOOSTS.get(heldItem); + HashMap<String, Float> petStatBootsMult = GuiProfileViewer.PET_STAT_BOOSTS_MULT.get(heldItem); + if (petStatBoots != null) { + for (Map.Entry<String, Float> 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<String, Float> 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<Integer, Integer> 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<String, String> 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<String, String> 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); + } + } + + 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", + Minecraft.getMinecraft().fontRendererObj, + 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 = getQuestionmarkSkull(); + } 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 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) (level % 1 * 100) + "%", + guiLeft + 319, + guiTop + 46, + 98 + ); + getInstance().renderBar(guiLeft + 319, guiTop + 56, 98, level % 1); + + 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 + GuiProfileViewer.shortNumberFormat(exp, 0), + guiLeft + 319, + guiTop + 125, + 98 + ); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Current LVL XP", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat((level % 1) * currentLevelRequirement, 0), + guiLeft + 319, + guiTop + 143, + 98 + ); + Utils.renderAlignedString( + EnumChatFormatting.YELLOW + "Required LVL XP", + EnumChatFormatting.WHITE + GuiProfileViewer.shortNumberFormat(currentLevelRequirement, 0), + guiLeft + 319, + guiTop + 161, + 98 + ); + } + } + + @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++; + } + } + } + } + + @Override + public void resetCache() { + petsPage = 0; + sortedPets = null; + 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/profileviewer/PlayerStats.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java index 4ee1f208..b0cc930a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java @@ -24,11 +24,12 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.profileviewer.info.QuiverInfo; import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.JsonUtils; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.JsonToNBT; -import net.minecraft.nbt.NBTException; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumChatFormatting; @@ -37,13 +38,20 @@ import org.jetbrains.annotations.Nullable; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.util.AbstractMap; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.Objects; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; public class PlayerStats { + public static final String HEALTH = "health"; public static final String DEFENCE = "defence"; public static final String STRENGTH = "strength"; @@ -58,7 +66,7 @@ public class PlayerStats { public static final String MINING_FORTUNE = "mining_fortune"; public static final String MINING_SPEED = "mining_speed"; - public static final String[] defaultStatNames = new String[]{ + public static final String[] defaultStatNames = new String[] { "health", "defence", "strength", @@ -73,9 +81,9 @@ public class PlayerStats { "ferocity", "ability_damage", "mining_fortune", - "mining_speed" + "mining_speed", }; - public static final String[] defaultStatNamesPretty = new String[]{ + public static final String[] defaultStatNamesPretty = new String[] { EnumChatFormatting.RED + "\u2764 Health", EnumChatFormatting.GREEN + "\u2748 Defence", EnumChatFormatting.RED + "\u2741 Strength", @@ -90,83 +98,23 @@ public class PlayerStats { EnumChatFormatting.RED + "\u2AFD Ferocity", EnumChatFormatting.RED + "\u2739 Ability Damage", EnumChatFormatting.GOLD + "\u2618 Mining Fortune", - EnumChatFormatting.GOLD + "\u2E15 Mining Speed" + EnumChatFormatting.GOLD + "\u2E15 Mining Speed", }; - - public static class Stats { - JsonObject statsJson = new JsonObject(); - - /*public float health; - public float defence; - public float strength; - public float speed; - public float crit_chance; - public float crit_damage; - public float bonus_attack_speed; - public float intelligence; - public float sea_creature_chance; - public float magic_find; - public float pet_luck;*/ - - public Stats(Stats... statses) { - for (Stats stats : statses) { - add(stats); - } - } - - /*@Override - public String toString() { - return String.format("{health=%s,defence=%s,strength=%s,speed=%s,crit_chance=%s,crit_damage=%s," + - "bonus_attack_speed=%s,intelligence=%s,sea_creature_chance=%s,magic_find=%s,pet_luck=%s}", - stats.get("health"), defence, strength, speed, crit_chance, crit_damage, bonus_attack_speed, intelligence, - sea_creature_chance, magic_find, pet_luck - ); - }*/ - - public float get(String statName) { - if (statsJson.has(statName)) { - return statsJson.get(statName).getAsFloat(); - } else { - return 0; - } - } - - public Stats add(Stats stats) { - for (Map.Entry<String, JsonElement> statEntry : stats.statsJson.entrySet()) { - if (statEntry.getValue().isJsonPrimitive() && ((JsonPrimitive) statEntry.getValue()).isNumber()) { - if (!statsJson.has(statEntry.getKey())) { - statsJson.add(statEntry.getKey(), statEntry.getValue()); - } else { - JsonPrimitive e = statsJson.get(statEntry.getKey()).getAsJsonPrimitive(); - float statNum = e.getAsFloat() + statEntry.getValue().getAsFloat(); - statsJson.add(statEntry.getKey(), new JsonPrimitive(statNum)); - } - } - } - return this; - } - - public void scale(String statName, float scale) { - if (statsJson.has(statName)) { - statsJson.add(statName, new JsonPrimitive(statsJson.get(statName).getAsFloat() * scale)); - } - } - - public void scaleAll(float scale) { - for (Map.Entry<String, JsonElement> statEntry : statsJson.entrySet()) { - statsJson.add(statEntry.getKey(), new JsonPrimitive(statEntry.getValue().getAsFloat() * scale)); - } - } - - public void addStat(String statName, float amount) { - if (!statsJson.has(statName)) { - statsJson.add(statName, new JsonPrimitive(amount)); - } else { - JsonPrimitive e = statsJson.get(statName).getAsJsonPrimitive(); - statsJson.add(statName, new JsonPrimitive(e.getAsFloat() + amount)); - } + private static final HashMap<String, Pattern> STAT_PATTERN_MAP = new HashMap<String, Pattern>() { + { + put(HEALTH, Pattern.compile("^Health: ((?:\\+|-)[0-9]+)")); + put(DEFENCE, Pattern.compile("^Defense: ((?:\\+|-)[0-9]+)")); + put(STRENGTH, Pattern.compile("^Strength: ((?:\\+|-)[0-9]+)")); + put(SPEED, Pattern.compile("^Speed: ((?:\\+|-)[0-9]+)")); + put(CRIT_CHANCE, Pattern.compile("^Crit Chance: ((?:\\+|-)[0-9]+)")); + put(CRIT_DAMAGE, Pattern.compile("^Crit Damage: ((?:\\+|-)[0-9]+)")); + put(BONUS_ATTACK_SPEED, Pattern.compile("^Bonus Attack Speed: ((?:\\+|-)[0-9]+)")); + put(INTELLIGENCE, Pattern.compile("^Intelligence: ((?:\\+|-)[0-9]+)")); + put(SEA_CREATURE_CHANCE, Pattern.compile("^Sea Creature Chance: ((?:\\+|-)[0-9]+)")); + put("ferocity", Pattern.compile("^Ferocity: ((?:\\+|-)[0-9]+)")); + put("ability_damage", Pattern.compile("^Ability Damage: ((?:\\+|-)[0-9]+)")); } - } + }; public static Stats getBaseStats() { JsonObject misc = Constants.MISC; @@ -193,29 +141,26 @@ public class PlayerStats { return bonus; } - private static Stats getSkillBonus(JsonObject skillInfo) { + private static Stats getSkillBonus(Map<String, ProfileViewer.Level> skyblockInfo) { JsonObject bonuses = Constants.BONUSES; if (bonuses == null) return null; Stats skillBonus = new Stats(); - for (Map.Entry<String, JsonElement> entry : skillInfo.entrySet()) { - if (entry.getKey().startsWith("level_")) { - String skill = entry.getKey().substring("level_".length()); - JsonElement element = Utils.getElement(bonuses, "bonus_stats." + skill); - if (element != null && element.isJsonObject()) { - JsonObject skillStatMap = element.getAsJsonObject(); - - Stats currentBonus = new Stats(); - for (int i = 1; i <= entry.getValue().getAsFloat(); i++) { - if (skillStatMap.has("" + i)) { - currentBonus = new Stats(); - for (Map.Entry<String, JsonElement> entry2 : skillStatMap.get("" + i).getAsJsonObject().entrySet()) { - currentBonus.addStat(entry2.getKey(), entry2.getValue().getAsFloat()); - } + for (Map.Entry<String, ProfileViewer.Level> entry : skyblockInfo.entrySet()) { + JsonElement element = Utils.getElement(bonuses, "bonus_stats." + entry.getKey()); + if (element != null && element.isJsonObject()) { + JsonObject skillStatMap = element.getAsJsonObject(); + + Stats currentBonus = new Stats(); + for (int i = 1; i <= entry.getValue().level; i++) { + if (skillStatMap.has("" + i)) { + currentBonus = new Stats(); + for (Map.Entry<String, JsonElement> entry2 : skillStatMap.get("" + i).getAsJsonObject().entrySet()) { + currentBonus.addStat(entry2.getKey(), entry2.getValue().getAsFloat()); } - skillBonus.add(currentBonus); } + skillBonus.add(currentBonus); } } } @@ -261,8 +206,7 @@ public class PlayerStats { } private static float harpBonus(JsonObject profile) { - String talk_to_melody = - Utils.getElementAsString(Utils.getElement(profile, "objectives.talk_to_melody.status"), "INCOMPLETE"); + String talk_to_melody = Utils.getElementAsString(Utils.getElement(profile, "objectives.talk_to_melody.status"), "INCOMPLETE"); if (talk_to_melody.equalsIgnoreCase("COMPLETE")) { return 26; } else { @@ -270,29 +214,24 @@ public class PlayerStats { } } - private static float hotmFortune(JsonObject profile, JsonObject skillInfo) { - int miningLevelFortune = - (int) (4 * (float) Math.floor(Utils.getElementAsFloat(Utils.getElement(skillInfo, "level_skill_mining"), 0))); - int miningFortuneStat = - ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_fortune"), 0)) * 5); - int miningFortune2Stat = - ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_fortune_2"), 0)) * 5); + private static float hotmFortune(JsonObject profile, Map<String, ProfileViewer.Level> skyblockInfo) { + int miningLevelFortune = (int) (4 * (float) Math.floor(skyblockInfo.get("mining").level)); + int miningFortuneStat = ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_fortune"), 0)) * 5); + int miningFortune2Stat = ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_fortune_2"), 0)) * 5); return miningFortuneStat + miningFortune2Stat + miningLevelFortune; } private static float hotmSpeed(JsonObject profile) { - int miningSpeedStat = - ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_speed"), 0)) * 20); - int miningSpeed2Stat = - ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_speed_2"), 0)) * 40); + int miningSpeedStat = ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_speed"), 0)) * 20); + int miningSpeed2Stat = ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_speed_2"), 0)) * 40); return miningSpeedStat + miningSpeed2Stat; } - public static Stats getPassiveBonuses(JsonObject skillInfo, JsonObject profile) { + public static Stats getPassiveBonuses(Map<String, ProfileViewer.Level> skyblockInfo, JsonObject profile) { Stats passiveBonuses = new Stats(); Stats fairyBonus = getFairyBonus((int) Utils.getElementAsFloat(Utils.getElement(profile, "fairy_exchanges"), 0)); - Stats skillBonus = getSkillBonus(skillInfo); + Stats skillBonus = getSkillBonus(skyblockInfo); Stats petBonus = getTamingBonus(profile); if (skillBonus == null || petBonus == null) { @@ -307,10 +246,10 @@ public class PlayerStats { return passiveBonuses; } - public static Stats getHOTMBonuses(JsonObject skillInfo, JsonObject profile) { + public static Stats getHOTMBonuses(Map<String, ProfileViewer.Level> skyblockInfo, JsonObject profile) { Stats hotmBonuses = new Stats(); - hotmBonuses.addStat(MINING_FORTUNE, hotmFortune(profile, skillInfo)); + hotmBonuses.addStat(MINING_FORTUNE, hotmFortune(profile, skyblockInfo)); hotmBonuses.addStat(MINING_SPEED, hotmSpeed(profile)); return hotmBonuses; @@ -347,7 +286,7 @@ public class PlayerStats { Stats stats, JsonObject inventoryInfo, JsonObject collectionInfo, - JsonObject skillInfo, + Map<String, ProfileViewer.Level> skyblockInfo, JsonObject profile ) { JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray(); @@ -361,7 +300,8 @@ public class PlayerStats { case "LAPIS_ARMOR_": bonuses.addStat(HEALTH, 60); break; - case "EMERALD_ARMOR_": { + case "EMERALD_ARMOR_": + { int bonus = (int) Math.floor(Utils.getElementAsFloat(Utils.getElement(collectionInfo, "EMERALD"), 0) / 3000); bonuses.addStat(HEALTH, bonus); bonuses.addStat(DEFENCE, bonus); @@ -380,10 +320,7 @@ public class PlayerStats { bonuses.addStat(HEALTH, 50 * Math.round(stats.get(CRIT_DAMAGE))); break; case "ANGLER_": - bonuses.addStat( - HEALTH, - 10 * (float) Math.floor(Utils.getElementAsFloat(Utils.getElement(skillInfo, "level_skill_fishing"), 0)) - ); + bonuses.addStat(HEALTH, 10 * (float) Math.floor(skyblockInfo.get("fishing").level)); bonuses.addStat(SEA_CREATURE_CHANCE, 4); break; case "ARMOR_OF_MAGMA_": @@ -424,20 +361,6 @@ public class PlayerStats { return bonuses; } - private static final HashMap<String, Pattern> STAT_PATTERN_MAP = new HashMap<String, Pattern>() {{ - put(HEALTH, Pattern.compile("^Health: ((?:\\+|-)[0-9]+)")); - put(DEFENCE, Pattern.compile("^Defense: ((?:\\+|-)[0-9]+)")); - put(STRENGTH, Pattern.compile("^Strength: ((?:\\+|-)[0-9]+)")); - put(SPEED, Pattern.compile("^Speed: ((?:\\+|-)[0-9]+)")); - put(CRIT_CHANCE, Pattern.compile("^Crit Chance: ((?:\\+|-)[0-9]+)")); - put(CRIT_DAMAGE, Pattern.compile("^Crit Damage: ((?:\\+|-)[0-9]+)")); - put(BONUS_ATTACK_SPEED, Pattern.compile("^Bonus Attack Speed: ((?:\\+|-)[0-9]+)")); - put(INTELLIGENCE, Pattern.compile("^Intelligence: ((?:\\+|-)[0-9]+)")); - put(SEA_CREATURE_CHANCE, Pattern.compile("^Sea Creature Chance: ((?:\\+|-)[0-9]+)")); - put("ferocity", Pattern.compile("^Ferocity: ((?:\\+|-)[0-9]+)")); - put("ability_damage", Pattern.compile("^Ability Damage: ((?:\\+|-)[0-9]+)")); - }}; - private static Stats getStatForItem(String internalname, JsonObject item, JsonArray lore) { Stats stats = new Stats(); for (int i = 0; i < lore.size(); i++) { @@ -501,8 +424,7 @@ public class PlayerStats { if (itemBonuses.containsKey(internalname)) { continue; } - if (!talismanOnly || - Utils.checkItemType(item.get("lore").getAsJsonArray(), true, "ACCESSORY", "HATCCESSORY") >= 0) { + if (!talismanOnly || Utils.checkItemType(item.get("lore").getAsJsonArray(), true, "ACCESSORY", "HATCCESSORY") >= 0) { Stats itemBonus = getStatForItem(internalname, item, item.get("lore").getAsJsonArray()); itemBonuses.put(internalname, itemBonus); @@ -534,13 +456,21 @@ public class PlayerStats { JsonObject petnums = Constants.PETNUMS; if (petsJson == null || petnums == null) return new Stats(); - if (petsInfo != null && petsInfo.has("active_pet") && petsInfo.get("active_pet") != null && - petsInfo.get("active_pet").isJsonObject()) { + if ( + petsInfo != null && + petsInfo.has("active_pet") && + petsInfo.get("active_pet") != null && + petsInfo.get("active_pet").isJsonObject() + ) { JsonObject pet = petsInfo.get("active_pet").getAsJsonObject(); - if (pet.has("type") && pet.get("type") != null && - pet.has("tier") && pet.get("tier") != null && - pet.has("exp") && pet.get("exp") != null) { - + if ( + pet.has("type") && + pet.get("type") != null && + pet.has("tier") && + pet.get("tier") != null && + pet.has("exp") && + pet.get("exp") != null + ) { String petname = pet.get("type").getAsString(); String tier = pet.get("tier").getAsString(); String heldItem = Utils.getElementAsString(pet.get("heldItem"), null); @@ -553,8 +483,11 @@ public class PlayerStats { float exp = pet.get("exp").getAsFloat(); if (tierNum == null) return new Stats(); - if (pet.has("heldItem") && !pet.get("heldItem").isJsonNull() && - pet.get("heldItem").getAsString().equals("PET_ITEM_TIER_BOOST")) { + if ( + pet.has("heldItem") && + !pet.get("heldItem").isJsonNull() && + pet.get("heldItem").getAsString().equals("PET_ITEM_TIER_BOOST") + ) { tierNum = "" + (Integer.parseInt(tierNum) + 1); } @@ -602,18 +535,15 @@ public class PlayerStats { String key = entryBoost.getKey().toLowerCase(); try { stats.addStat(key, entryBoost.getValue()); - } catch (Exception ignored) { - } + } catch (Exception ignored) {} } - } if (petStatBootsMult != null) { for (Map.Entry<String, Float> entryBoost : petStatBootsMult.entrySet()) { String key = entryBoost.getKey().toLowerCase(); try { stats.scale(key, entryBoost.getValue()); - } catch (Exception ignored) { - } + } catch (Exception ignored) {} } } } @@ -670,25 +600,30 @@ public class PlayerStats { } for (Map.Entry<String, JsonElement> statEntry : stats.statsJson.entrySet()) { - if (statEntry.getKey().equals(CRIT_DAMAGE) || - statEntry.getKey().equals(INTELLIGENCE) || - statEntry.getKey().equals(BONUS_ATTACK_SPEED)) continue; + if ( + statEntry.getKey().equals(CRIT_DAMAGE) || + statEntry.getKey().equals(INTELLIGENCE) || + statEntry.getKey().equals(BONUS_ATTACK_SPEED) + ) continue; stats.statsJson.add(statEntry.getKey(), new JsonPrimitive(Math.max(0, statEntry.getValue().getAsFloat()))); } } public static Stats getStats( - JsonObject skillInfo, JsonObject inventoryInfo, JsonObject collectionInfo, - JsonObject petsInfo, JsonObject profile + Map<String, ProfileViewer.Level> skyblockInfo, + JsonObject inventoryInfo, + JsonObject collectionInfo, + JsonObject petsInfo, + JsonObject profile ) { - if (skillInfo == null || inventoryInfo == null || collectionInfo == null || profile == null) return null; + if (skyblockInfo == null || inventoryInfo == null || collectionInfo == null || profile == null) return null; JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray(); JsonArray inventory = Utils.getElement(inventoryInfo, "inv_contents").getAsJsonArray(); JsonArray talisman_bag = Utils.getElement(inventoryInfo, "talisman_bag").getAsJsonArray(); - Stats passiveBonuses = getPassiveBonuses(skillInfo, profile); - Stats hotmBonuses = getHOTMBonuses(skillInfo, profile); + Stats passiveBonuses = getPassiveBonuses(skyblockInfo, profile); + Stats hotmBonuses = getHOTMBonuses(skyblockInfo, profile); Stats armorBonuses = getItemBonuses(false, armor); Stats talismanBonuses = getItemBonuses(true, inventory, talisman_bag); @@ -706,7 +641,7 @@ public class PlayerStats { stats = stats.add(passiveBonuses).add(armorBonuses).add(talismanBonuses).add(petBonus).add(hotmBonuses); - stats.add(getSetBonuses(stats, inventoryInfo, collectionInfo, skillInfo, profile)); + stats.add(getSetBonuses(stats, inventoryInfo, collectionInfo, skyblockInfo, profile)); stats.scaleAll(getStatMult(inventoryInfo)); @@ -723,37 +658,45 @@ public class PlayerStats { * @see io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer.Profile#getInventoryInfo(String) */ public static int getMagicalPower(JsonObject inventoryInfo) { - if (inventoryInfo == null || !inventoryInfo.has("talisman_bag") || - !inventoryInfo.get("talisman_bag").isJsonArray()) { + if (inventoryInfo == null || !inventoryInfo.has("talisman_bag") || !inventoryInfo.get("talisman_bag").isJsonArray()) { return -1; } - JsonArray accessories = inventoryInfo.get("talisman_bag").getAsJsonArray(); + + Map<String, Integer> accessories = JsonUtils.getJsonArrayAsStream(inventoryInfo.get("talisman_bag").getAsJsonArray()) + .map(o -> { + try { + return JsonToNBT.getTagFromJson(o.getAsJsonObject().get("nbttag").getAsString()); + } catch (Exception ignored) { + return null; + } + }).filter(Objects::nonNull).map(tag -> { + NBTTagList loreTagList = tag.getCompoundTag("display").getTagList("Lore", 8); + String lastElement = loreTagList.getStringTagAt(loreTagList.tagCount() - 1); + if (lastElement.contains(EnumChatFormatting.OBFUSCATED.toString())) { + lastElement = lastElement.substring(lastElement.indexOf(' ')).trim().substring(4); + } + JsonArray lastElementJsonArray = new JsonArray(); + lastElementJsonArray.add(new JsonPrimitive(lastElement)); + return new AbstractMap.SimpleEntry<>( + tag.getCompoundTag("ExtraAttributes").getString("id"), + Utils.getRarityFromLore(lastElementJsonArray) + ); + }).sorted(Comparator.comparingInt(e -> -e.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2)->v1, LinkedHashMap::new)); + + Set<String> ignoredTalismans = new HashSet<>(); int powderAmount = 0; - for (JsonElement element : accessories) { - if (element == null || !element.isJsonObject()) { - continue; - } - JsonObject accessory = element.getAsJsonObject(); - NBTTagCompound tag; - try { - tag = JsonToNBT.getTagFromJson(accessory.get("nbttag").getAsString()); - } catch (NBTException ignored) { + for (Map.Entry<String, Integer> entry : accessories.entrySet()) { + if (ignoredTalismans.contains(entry.getKey())) { continue; } - NBTTagList loreTagList = tag.getCompoundTag("display").getTagList("Lore", 8); - String id = tag.getCompoundTag("ExtraAttributes").getString("id"); - String lastElement = loreTagList.getStringTagAt(loreTagList.tagCount() - 1); - - //strip information that suggests the rarity has been upgraded (obfuscated char) - if (lastElement.contains("§k")) { - lastElement = lastElement.substring(lastElement.indexOf(' ')).trim().substring(4); + JsonArray children = Utils.getElementOrDefault(Constants.PARENTS, entry.getKey(), new JsonArray()).getAsJsonArray(); + for (JsonElement child : children) { + ignoredTalismans.add(child.getAsString()); } - JsonArray lastElementJsonArray = new JsonArray(); - lastElementJsonArray.add(new JsonPrimitive(lastElement)); - if (id.equals("HEGEMONY_ARTIFACT")) { - switch (Utils.getRarityFromLore(lastElementJsonArray)) { + if (entry.getKey().equals("HEGEMONY_ARTIFACT")) { + switch (entry.getValue()) { case 4: powderAmount += 16; break; @@ -762,7 +705,7 @@ public class PlayerStats { break; } } - switch (Utils.getRarityFromLore(lastElementJsonArray)) { + switch (entry.getValue()) { case 0: case 6: powderAmount += 3; @@ -784,7 +727,6 @@ public class PlayerStats { powderAmount += 22; break; } - } return powderAmount; } @@ -799,13 +741,123 @@ public class PlayerStats { public static @Nullable String getSelectedMagicalPower(JsonObject profileInfo) { String abs = "accessory_bag_storage"; - if (profileInfo == null - || !profileInfo.has(abs) - || !profileInfo.get(abs).isJsonObject() - || !profileInfo.get(abs).getAsJsonObject().has("selected_power")) { + if ( + profileInfo == null || + !profileInfo.has(abs) || + !profileInfo.get(abs).isJsonObject() || + !profileInfo.get(abs).getAsJsonObject().has("selected_power") + ) { return null; } String selectedPower = profileInfo.get(abs).getAsJsonObject().get("selected_power").getAsString(); return selectedPower.substring(0, 1).toUpperCase() + selectedPower.substring(1); } + + public static @Nullable QuiverInfo getQuiverInfo(JsonObject inventoryInfo, JsonObject profileInfo) { + if (inventoryInfo == null + || !inventoryInfo.has("quiver") + || !inventoryInfo.get("quiver").isJsonArray()) { + return null; + } + QuiverInfo quiverInfo = new QuiverInfo(); + quiverInfo.arrows = new HashMap<>(); + + JsonArray quiver = inventoryInfo.getAsJsonArray("quiver"); + for (JsonElement quiverEntry : quiver) { + if (quiverEntry == null || quiverEntry.isJsonNull() || !quiverEntry.isJsonObject()) { + continue; + } + JsonObject stack = quiverEntry.getAsJsonObject(); + if (!stack.has("internalname") || !stack.has("count")) { + continue; + } + String internalName = stack.get("internalname").getAsString(); + int count = stack.get("count").getAsInt(); + + quiverInfo.arrows.computeIfPresent(internalName, (key, existing) -> existing + count); + quiverInfo.arrows.putIfAbsent(internalName, count); + } + + if (profileInfo.has("favorite_arrow")) { + quiverInfo.selectedArrow = profileInfo.get("favorite_arrow").getAsString(); + } + + return quiverInfo; + } + + public static class Stats { + + JsonObject statsJson = new JsonObject(); + + /*public float health; + public float defence; + public float strength; + public float speed; + public float crit_chance; + public float crit_damage; + public float bonus_attack_speed; + public float intelligence; + public float sea_creature_chance; + public float magic_find; + public float pet_luck;*/ + + public Stats(Stats... statses) { + for (Stats stats : statses) { + add(stats); + } + } + + /*@Override + public String toString() { + return String.format("{health=%s,defence=%s,strength=%s,speed=%s,crit_chance=%s,crit_damage=%s," + + "bonus_attack_speed=%s,intelligence=%s,sea_creature_chance=%s,magic_find=%s,pet_luck=%s}", + stats.get("health"), defence, strength, speed, crit_chance, crit_damage, bonus_attack_speed, intelligence, + sea_creature_chance, magic_find, pet_luck + ); + }*/ + + public float get(String statName) { + if (statsJson.has(statName)) { + return statsJson.get(statName).getAsFloat(); + } else { + return 0; + } + } + + public Stats add(Stats stats) { + for (Map.Entry<String, JsonElement> statEntry : stats.statsJson.entrySet()) { + if (statEntry.getValue().isJsonPrimitive() && ((JsonPrimitive) statEntry.getValue()).isNumber()) { + if (!statsJson.has(statEntry.getKey())) { + statsJson.add(statEntry.getKey(), statEntry.getValue()); + } else { + JsonPrimitive e = statsJson.get(statEntry.getKey()).getAsJsonPrimitive(); + float statNum = e.getAsFloat() + statEntry.getValue().getAsFloat(); + statsJson.add(statEntry.getKey(), new JsonPrimitive(statNum)); + } + } + } + return this; + } + + public void scale(String statName, float scale) { + if (statsJson.has(statName)) { + statsJson.add(statName, new JsonPrimitive(statsJson.get(statName).getAsFloat() * scale)); + } + } + + public void scaleAll(float scale) { + for (Map.Entry<String, JsonElement> statEntry : statsJson.entrySet()) { + statsJson.add(statEntry.getKey(), new JsonPrimitive(statEntry.getValue().getAsFloat() * scale)); + } + } + + public void addStat(String statName, float amount) { + if (!statsJson.has(statName)) { + statsJson.add(statName, new JsonPrimitive(amount)); + } else { + JsonPrimitive e = statsJson.get(statName).getAsJsonPrimitive(); + statsJson.add(statName, new JsonPrimitive(e.getAsFloat() + amount)); + } + } + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java index 98bc1896..e89cbe8a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java @@ -40,6 +40,7 @@ import javax.annotation.Nullable; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Base64; import java.util.Collections; import java.util.HashMap; @@ -52,101 +53,225 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class ProfileViewer { - private static final HashMap<String, String> petRarityToNumMap = new HashMap<String, String>() {{ - put("COMMON", "0"); - put("UNCOMMON", "1"); - put("RARE", "2"); - put("EPIC", "3"); - put("LEGENDARY", "4"); - put("MYTHIC", "5"); - }}; - private static final LinkedHashMap<String, ItemStack> skillToSkillDisplayMap = - new LinkedHashMap<String, ItemStack>() {{ - put("skill_taming", Utils.createItemStack(Items.spawn_egg, EnumChatFormatting.LIGHT_PURPLE + "Taming")); - put("skill_mining", Utils.createItemStack(Items.stone_pickaxe, EnumChatFormatting.GRAY + "Mining")); - put( - "skill_foraging", - Utils.createItemStack(Item.getItemFromBlock(Blocks.sapling), EnumChatFormatting.DARK_GREEN + "Foraging") - ); + + private static final HashMap<String, String> petRarityToNumMap = new HashMap<String, String>() { + { + put("COMMON", "0"); + put("UNCOMMON", "1"); + put("RARE", "2"); + put("EPIC", "3"); + put("LEGENDARY", "4"); + put("MYTHIC", "5"); + } + }; + private static final LinkedHashMap<String, ItemStack> skillToSkillDisplayMap = new LinkedHashMap<String, ItemStack>() { + { + put("taming", Utils.createItemStack(Items.spawn_egg, EnumChatFormatting.LIGHT_PURPLE + "Taming")); + put("mining", Utils.createItemStack(Items.stone_pickaxe, EnumChatFormatting.GRAY + "Mining")); + put("foraging", Utils.createItemStack(Item.getItemFromBlock(Blocks.sapling), EnumChatFormatting.DARK_GREEN + "Foraging")); put( - "skill_enchanting", + "enchanting", Utils.createItemStack(Item.getItemFromBlock(Blocks.enchanting_table), EnumChatFormatting.GREEN + "Enchanting") ); put( - "skill_carpentry", + "carpentry", Utils.createItemStack(Item.getItemFromBlock(Blocks.crafting_table), EnumChatFormatting.DARK_RED + "Carpentry") ); - put("skill_farming", Utils.createItemStack(Items.golden_hoe, EnumChatFormatting.YELLOW + "Farming")); - put("skill_combat", Utils.createItemStack(Items.stone_sword, EnumChatFormatting.RED + "Combat")); - put("skill_fishing", Utils.createItemStack(Items.fishing_rod, EnumChatFormatting.AQUA + "Fishing")); - put("skill_alchemy", Utils.createItemStack(Items.brewing_stand, EnumChatFormatting.BLUE + "Alchemy")); + put("farming", Utils.createItemStack(Items.golden_hoe, EnumChatFormatting.YELLOW + "Farming")); + put("combat", Utils.createItemStack(Items.stone_sword, EnumChatFormatting.RED + "Combat")); + put("fishing", Utils.createItemStack(Items.fishing_rod, EnumChatFormatting.AQUA + "Fishing")); + put("alchemy", Utils.createItemStack(Items.brewing_stand, EnumChatFormatting.BLUE + "Alchemy")); + put("runecrafting", Utils.createItemStack(Items.magma_cream, EnumChatFormatting.DARK_PURPLE + "Runecrafting")); + put("social", Utils.createItemStack(Items.emerald, EnumChatFormatting.DARK_GREEN + "Social")); + // put("catacombs", Utils.createItemStack(Item.getItemFromBlock(Blocks.deadbush), EnumChatFormatting.GOLD+"Catacombs")); + put("zombie", Utils.createItemStack(Items.rotten_flesh, EnumChatFormatting.GOLD + "Rev Slayer")); + put("spider", Utils.createItemStack(Items.spider_eye, EnumChatFormatting.GOLD + "Tara Slayer")); + put("wolf", Utils.createItemStack(Items.bone, EnumChatFormatting.GOLD + "Sven Slayer")); + put("enderman", Utils.createItemStack(Items.ender_pearl, EnumChatFormatting.GOLD + "Ender Slayer")); + put("blaze", Utils.createItemStack(Items.blaze_rod, EnumChatFormatting.GOLD + "Blaze Slayer")); + } + }; + private static final ItemStack CAT_FARMING = Utils.createItemStack(Items.golden_hoe, EnumChatFormatting.YELLOW + "Farming"); + private static final ItemStack CAT_MINING = Utils.createItemStack(Items.stone_pickaxe, EnumChatFormatting.GRAY + "Mining"); + private static final ItemStack CAT_COMBAT = Utils.createItemStack(Items.stone_sword, EnumChatFormatting.RED + "Combat"); + private static final ItemStack CAT_FORAGING = Utils.createItemStack( + Item.getItemFromBlock(Blocks.sapling), + EnumChatFormatting.DARK_GREEN + "Foraging" + ); + private static final ItemStack CAT_FISHING = Utils.createItemStack(Items.fishing_rod, EnumChatFormatting.AQUA + "Fishing"); + private static final LinkedHashMap<ItemStack, List<String>> collectionCatToCollectionMap = new LinkedHashMap<ItemStack, List<String>>() { + { + put( + CAT_FARMING, + Utils.createList( + "WHEAT", + "CARROT_ITEM", + "POTATO_ITEM", + "PUMPKIN", + "MELON", + "SEEDS", + "MUSHROOM_COLLECTION", + "INK_SACK:3", + "CACTUS", + "SUGAR_CANE", + "FEATHER", + "LEATHER", + "PORK", + "RAW_CHICKEN", + "MUTTON", + "RABBIT", + "NETHER_STALK" + ) + ); put( - "skill_runecrafting", - Utils.createItemStack(Items.magma_cream, EnumChatFormatting.DARK_PURPLE + "Runecrafting") + CAT_MINING, + Utils.createList( + "COBBLESTONE", + "COAL", + "IRON_INGOT", + "GOLD_INGOT", + "DIAMOND", + "INK_SACK:4", + "EMERALD", + "REDSTONE", + "QUARTZ", + "OBSIDIAN", + "GLOWSTONE_DUST", + "GRAVEL", + "ICE", + "NETHERRACK", + "SAND", + "ENDER_STONE", + null, + "MITHRIL_ORE", + "HARD_STONE", + "GEMSTONE_COLLECTION", + "MYCEL", + "SAND:1", + "SULPHUR_ORE" + ) + ); + put( + CAT_COMBAT, + Utils.createList( + "ROTTEN_FLESH", + "BONE", + "STRING", + "SPIDER_EYE", + "SULPHUR", + "ENDER_PEARL", + "GHAST_TEAR", + "SLIME_BALL", + "BLAZE_ROD", + "MAGMA_CREAM", + null, + null, + null, + null, + "CHILI_PEPPER" + ) ); - put("skill_social2", Utils.createItemStack(Items.emerald, EnumChatFormatting.DARK_GREEN + "Social")); - // put("skill_catacombs", Utils.createItemStack(Item.getItemFromBlock(Blocks.deadbush), EnumChatFormatting.GOLD+"Catacombs")); - put("slayer_zombie", Utils.createItemStack(Items.rotten_flesh, EnumChatFormatting.GOLD + "Rev Slayer")); - put("slayer_spider", Utils.createItemStack(Items.spider_eye, EnumChatFormatting.GOLD + "Tara Slayer")); - put("slayer_wolf", Utils.createItemStack(Items.bone, EnumChatFormatting.GOLD + "Sven Slayer")); - put("slayer_enderman", Utils.createItemStack(Items.ender_pearl, EnumChatFormatting.GOLD + "Ender Slayer")); - put("slayer_blaze", Utils.createItemStack(Items.blaze_rod, EnumChatFormatting.GOLD + "Blaze Slayer")); - }}; - private static final ItemStack CAT_FARMING = - Utils.createItemStack(Items.golden_hoe, EnumChatFormatting.YELLOW + "Farming"); - private static final ItemStack CAT_MINING = - Utils.createItemStack(Items.stone_pickaxe, EnumChatFormatting.GRAY + "Mining"); - private static final ItemStack CAT_COMBAT = - Utils.createItemStack(Items.stone_sword, EnumChatFormatting.RED + "Combat"); - private static final ItemStack CAT_FORAGING = - Utils.createItemStack(Item.getItemFromBlock(Blocks.sapling), EnumChatFormatting.DARK_GREEN + "Foraging"); - private static final ItemStack CAT_FISHING = - Utils.createItemStack(Items.fishing_rod, EnumChatFormatting.AQUA + "Fishing"); - private static final LinkedHashMap<ItemStack, List<String>> collectionCatToCollectionMap = - new LinkedHashMap<ItemStack, List<String>>() {{ - put(CAT_FARMING, Utils.createList("WHEAT", "CARROT_ITEM", "POTATO_ITEM", "PUMPKIN", "MELON", "SEEDS", - "MUSHROOM_COLLECTION", "INK_SACK:3", "CACTUS", "SUGAR_CANE", "FEATHER", "LEATHER", "PORK", "RAW_CHICKEN", - "MUTTON", "RABBIT", "NETHER_STALK" - )); - put(CAT_MINING, Utils.createList("COBBLESTONE", "COAL", "IRON_INGOT", "GOLD_INGOT", "DIAMOND", "INK_SACK:4", - "EMERALD", "REDSTONE", "QUARTZ", "OBSIDIAN", "GLOWSTONE_DUST", "GRAVEL", "ICE", "NETHERRACK", "SAND", - "ENDER_STONE", null, "MITHRIL_ORE", "HARD_STONE", "GEMSTONE_COLLECTION" - )); - put(CAT_COMBAT, Utils.createList("ROTTEN_FLESH", "BONE", "STRING", "SPIDER_EYE", "SULPHUR", "ENDER_PEARL", - "GHAST_TEAR", "SLIME_BALL", "BLAZE_ROD", "MAGMA_CREAM", null, null, null, null, "CHILI_PEPPER" - )); put(CAT_FORAGING, Utils.createList("LOG", "LOG:1", "LOG:2", "LOG_2:1", "LOG_2", "LOG:3", null)); - put(CAT_FISHING, Utils.createList("RAW_FISH", "RAW_FISH:1", "RAW_FISH:2", "RAW_FISH:3", "PRISMARINE_SHARD", - "PRISMARINE_CRYSTALS", "CLAY_BALL", "WATER_LILY", "INK_SACK", "SPONGE", "MAGMA_FISH" - )); - - }}; - private static final LinkedHashMap<ItemStack, List<String>> collectionCatToMinionMap = - new LinkedHashMap<ItemStack, List<String>>() {{ - put(CAT_FARMING, Utils.createList("WHEAT", "CARROT", "POTATO", "PUMPKIN", "MELON", null, "MUSHROOM", - "COCOA", "CACTUS", "SUGAR_CANE", "CHICKEN", "COW", "PIG", null, "SHEEP", "RABBIT", "NETHER_WARTS" - )); - put(CAT_MINING, Utils.createList("COBBLESTONE", "COAL", "IRON", "GOLD", "DIAMOND", "LAPIS", "EMERALD", - "REDSTONE", "QUARTZ", "OBSIDIAN", "GLOWSTONE", "GRAVEL", "ICE", null, "SAND", "ENDER_STONE", "SNOW", - "MITHRIL", "HARD_STONE", null - )); - put(CAT_COMBAT, Utils.createList("ZOMBIE", "SKELETON", "SPIDER", "CAVESPIDER", "CREEPER", "ENDERMAN", - "GHAST", "SLIME", "BLAZE", "MAGMA_CUBE", "REVENANT", "TARANTULA", "VOIDLING", "INFERNO" - )); + put( + CAT_FISHING, + Utils.createList( + "RAW_FISH", + "RAW_FISH:1", + "RAW_FISH:2", + "RAW_FISH:3", + "PRISMARINE_SHARD", + "PRISMARINE_CRYSTALS", + "CLAY_BALL", + "WATER_LILY", + "INK_SACK", + "SPONGE", + "MAGMA_FISH" + ) + ); + } + }; + private static final LinkedHashMap<ItemStack, List<String>> collectionCatToMinionMap = new LinkedHashMap<ItemStack, List<String>>() { + { + put( + CAT_FARMING, + Utils.createList( + "WHEAT", + "CARROT", + "POTATO", + "PUMPKIN", + "MELON", + null, + "MUSHROOM", + "COCOA", + "CACTUS", + "SUGAR_CANE", + "CHICKEN", + "COW", + "PIG", + null, + "SHEEP", + "RABBIT", + "NETHER_WARTS" + ) + ); + put( + CAT_MINING, + Utils.createList( + "COBBLESTONE", + "COAL", + "IRON", + "GOLD", + "DIAMOND", + "LAPIS", + "EMERALD", + "REDSTONE", + "QUARTZ", + "OBSIDIAN", + "GLOWSTONE", + "GRAVEL", + "ICE", + null, + "SAND", + "ENDER_STONE", + "SNOW", + "MITHRIL", + "HARD_STONE", + null, + "MYCELIUM", + "RED_SAND", + null + ) + ); + put( + CAT_COMBAT, + Utils.createList( + "ZOMBIE", + "SKELETON", + "SPIDER", + "CAVESPIDER", + "CREEPER", + "ENDERMAN", + "GHAST", + "SLIME", + "BLAZE", + "MAGMA_CUBE", + "REVENANT", + "TARANTULA", + "VOIDLING", + "INFERNO" + ) + ); put(CAT_FORAGING, Utils.createList("OAK", "SPRUCE", "BIRCH", "DARK_OAK", "ACACIA", "JUNGLE", "FLOWER")); put(CAT_FISHING, Utils.createList("FISHING", null, null, null, null, null, "CLAY", null, null, null)); - - }}; - private static final LinkedHashMap<String, ItemStack> collectionToCollectionDisplayMap = - new LinkedHashMap<String, ItemStack>() {{ + } + }; + private static final LinkedHashMap<String, ItemStack> collectionToCollectionDisplayMap = new LinkedHashMap<String, ItemStack>() { + { /* FARMING COLLECTIONS */ put("WHEAT", Utils.createItemStack(Items.wheat, EnumChatFormatting.YELLOW + "Wheat")); put("CARROT_ITEM", Utils.createItemStack(Items.carrot, EnumChatFormatting.YELLOW + "Carrot")); put("POTATO_ITEM", Utils.createItemStack(Items.potato, EnumChatFormatting.YELLOW + "Potato")); - put( - "PUMPKIN", - Utils.createItemStack(Item.getItemFromBlock(Blocks.pumpkin), EnumChatFormatting.YELLOW + "Pumpkin") - ); + put("PUMPKIN", Utils.createItemStack(Item.getItemFromBlock(Blocks.pumpkin), EnumChatFormatting.YELLOW + "Pumpkin")); put("MELON", Utils.createItemStack(Items.melon, EnumChatFormatting.YELLOW + "Melon")); put("SEEDS", Utils.createItemStack(Items.wheat_seeds, EnumChatFormatting.YELLOW + "Seeds")); put( @@ -165,10 +290,7 @@ public class ProfileViewer { put("NETHER_STALK", Utils.createItemStack(Items.nether_wart, EnumChatFormatting.YELLOW + "Nether Wart")); /* MINING COLLECTIONS */ - put( - "COBBLESTONE", - Utils.createItemStack(Item.getItemFromBlock(Blocks.cobblestone), EnumChatFormatting.GRAY + "Cobblestone") - ); + put("COBBLESTONE", Utils.createItemStack(Item.getItemFromBlock(Blocks.cobblestone), EnumChatFormatting.GRAY + "Cobblestone")); put("COAL", Utils.createItemStack(Items.coal, EnumChatFormatting.GRAY + "Coal")); put("IRON_INGOT", Utils.createItemStack(Items.iron_ingot, EnumChatFormatting.GRAY + "Iron Ingot")); put("GOLD_INGOT", Utils.createItemStack(Items.gold_ingot, EnumChatFormatting.GRAY + "Gold Ingot")); @@ -177,27 +299,15 @@ public class ProfileViewer { put("EMERALD", Utils.createItemStack(Items.emerald, EnumChatFormatting.GRAY + "Emerald")); put("REDSTONE", Utils.createItemStack(Items.redstone, EnumChatFormatting.GRAY + "Redstone")); put("QUARTZ", Utils.createItemStack(Items.quartz, EnumChatFormatting.GRAY + "Nether Quartz")); - put( - "OBSIDIAN", - Utils.createItemStack(Item.getItemFromBlock(Blocks.obsidian), EnumChatFormatting.GRAY + "Obsidian") - ); + put("OBSIDIAN", Utils.createItemStack(Item.getItemFromBlock(Blocks.obsidian), EnumChatFormatting.GRAY + "Obsidian")); put("GLOWSTONE_DUST", Utils.createItemStack(Items.glowstone_dust, EnumChatFormatting.GRAY + "Glowstone Dust")); put("GRAVEL", Utils.createItemStack(Item.getItemFromBlock(Blocks.gravel), EnumChatFormatting.GRAY + "Gravel")); put("ICE", Utils.createItemStack(Item.getItemFromBlock(Blocks.ice), EnumChatFormatting.GRAY + "Ice")); - put( - "NETHERRACK", - Utils.createItemStack(Item.getItemFromBlock(Blocks.netherrack), EnumChatFormatting.GRAY + "Netherrack") - ); + put("NETHERRACK", Utils.createItemStack(Item.getItemFromBlock(Blocks.netherrack), EnumChatFormatting.GRAY + "Netherrack")); put("SAND", Utils.createItemStack(Item.getItemFromBlock(Blocks.sand), EnumChatFormatting.GRAY + "Sand")); - put( - "ENDER_STONE", - Utils.createItemStack(Item.getItemFromBlock(Blocks.end_stone), EnumChatFormatting.GRAY + "End Stone") - ); + put("ENDER_STONE", Utils.createItemStack(Item.getItemFromBlock(Blocks.end_stone), EnumChatFormatting.GRAY + "End Stone")); put("MITHRIL_ORE", Utils.createItemStack(Items.prismarine_crystals, EnumChatFormatting.GRAY + "Mithril")); - put( - "HARD_STONE", - Utils.createItemStack(Item.getItemFromBlock(Blocks.stone), EnumChatFormatting.GRAY + "Hard Stone") - ); + put("HARD_STONE", Utils.createItemStack(Item.getItemFromBlock(Blocks.stone), EnumChatFormatting.GRAY + "Hard Stone")); put( "GEMSTONE_COLLECTION", Utils.createSkull( @@ -206,6 +316,9 @@ public class ProfileViewer { "ewogICJ0aW1lc3RhbXAiIDogMTYxODA4Mzg4ODc3MSwKICAicHJvZmlsZUlkIiA6ICJjNTBhZmE4YWJlYjk0ZTQ1OTRiZjFiNDI1YTk4MGYwMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUd29FQmFlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2FhYzE1ZjZmY2YyY2U5NjNlZjRjYTcxZjFhODY4NWFkYjk3ZWI3NjllMWQxMTE5NGNiYmQyZTk2NGE4ODk3OGMiCiAgICB9CiAgfQp9" ) ); + put("MYCEL", Utils.createItemStack(Item.getItemFromBlock(Blocks.mycelium), EnumChatFormatting.GRAY + "Mycelium")); + put("SAND:1", Utils.createItemStack(Item.getItemFromBlock(Blocks.sand), EnumChatFormatting.GRAY + "Red Sand", 1)); + put("SULPHUR_ORE", Utils.createItemStack(Items.glowstone_dust, EnumChatFormatting.GRAY + "Sulphur")); /* COMBAT COLLECTIONS */ put("ROTTEN_FLESH", Utils.createItemStack(Items.rotten_flesh, EnumChatFormatting.RED + "Rotten Flesh")); @@ -218,50 +331,32 @@ public class ProfileViewer { put("SLIME_BALL", Utils.createItemStack(Items.slime_ball, EnumChatFormatting.RED + "Slimeball")); put("BLAZE_ROD", Utils.createItemStack(Items.blaze_rod, EnumChatFormatting.RED + "Blaze Rod")); put("MAGMA_CREAM", Utils.createItemStack(Items.magma_cream, EnumChatFormatting.RED + "Magma Cream")); - put("CHILI_PEPPER", Utils.createSkull( - EnumChatFormatting.RED + "Chili Pepper", - "3d47abaa-b40b-3826-b20c-d83a7f053bd9", - "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjg1OWM4ZGYxMTA5YzA4YTc1NjI3NWYxZDI4ODdjMjc0ODA0OWZlMzM4Nzc3NjlhN2I0MTVkNTZlZGE0NjlkOCJ9fX0" - )); + put( + "CHILI_PEPPER", + Utils.createSkull( + EnumChatFormatting.RED + "Chili Pepper", + "3d47abaa-b40b-3826-b20c-d83a7f053bd9", + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjg1OWM4ZGYxMTA5YzA4YTc1NjI3NWYxZDI4ODdjMjc0ODA0OWZlMzM4Nzc3NjlhN2I0MTVkNTZlZGE0NjlkOCJ9fX0" + ) + ); /* FORAGING COLLECTIONS */ put("LOG", Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Oak Wood")); - put( - "LOG:1", - Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Spruce Wood", 1) - ); - put( - "LOG:2", - Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Birch Wood", 2) - ); - put( - "LOG_2:1", - Utils.createItemStack(Item.getItemFromBlock(Blocks.log2), EnumChatFormatting.DARK_GREEN + "Dark Oak Wood", 1) - ); + put("LOG:1", Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Spruce Wood", 1)); + put("LOG:2", Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Birch Wood", 2)); + put("LOG_2:1", Utils.createItemStack(Item.getItemFromBlock(Blocks.log2), EnumChatFormatting.DARK_GREEN + "Dark Oak Wood", 1)); put("LOG_2", Utils.createItemStack(Item.getItemFromBlock(Blocks.log2), EnumChatFormatting.DARK_GREEN + "Acacia Wood")); - put( - "LOG:3", - Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Jungle Wood", 3) - ); + put("LOG:3", Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Jungle Wood", 3)); /* FISHING COLLECTIONS */ put("RAW_FISH", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Raw Fish")); put("RAW_FISH:1", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Salmon", 1)); put("RAW_FISH:2", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Clownfish", 2)); put("RAW_FISH:3", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Pufferfish", 3)); - put( - "PRISMARINE_SHARD", - Utils.createItemStack(Items.prismarine_shard, EnumChatFormatting.AQUA + "Prismarine Shard") - ); - put( - "PRISMARINE_CRYSTALS", - Utils.createItemStack(Items.prismarine_crystals, EnumChatFormatting.AQUA + "Prismarine Crystals") - ); + put("PRISMARINE_SHARD", Utils.createItemStack(Items.prismarine_shard, EnumChatFormatting.AQUA + "Prismarine Shard")); + put("PRISMARINE_CRYSTALS", Utils.createItemStack(Items.prismarine_crystals, EnumChatFormatting.AQUA + "Prismarine Crystals")); put("CLAY_BALL", Utils.createItemStack(Items.clay_ball, EnumChatFormatting.AQUA + "Clay")); - put( - "WATER_LILY", - Utils.createItemStack(Item.getItemFromBlock(Blocks.waterlily), EnumChatFormatting.AQUA + "Lilypad") - ); + put("WATER_LILY", Utils.createItemStack(Item.getItemFromBlock(Blocks.waterlily), EnumChatFormatting.AQUA + "Lilypad")); put("INK_SACK", Utils.createItemStack(Items.dye, EnumChatFormatting.AQUA + "Ink Sack")); put("SPONGE", Utils.createItemStack(Item.getItemFromBlock(Blocks.sponge), EnumChatFormatting.AQUA + "Sponge")); put( @@ -272,11 +367,11 @@ public class ProfileViewer { "ewogICJ0aW1lc3RhbXAiIDogMTY0MjQ4ODA3MDY2NiwKICAicHJvZmlsZUlkIiA6ICIzNDkxZjJiOTdjMDE0MWE2OTM2YjFjMjJhMmEwMGZiNyIsCiAgInByb2ZpbGVOYW1lIiA6ICJKZXNzc3N1aGgiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjU2YjU5NTViMjk1NTIyYzk2ODk0ODE5NjBjMDFhOTkyY2ExYzc3NTRjZjRlZTMxM2M4ZGQwYzM1NmQzMzVmIgogICAgfQogIH0KfQ" ) ); - }}; + } + }; private static final AtomicBoolean updatingResourceCollection = new AtomicBoolean(false); private static JsonObject resourceCollection = null; private final NEUManager manager; - private final HashMap<String, JsonObject> nameToHypixelProfile = new HashMap<>(); private final HashMap<String, JsonObject> uuidToHypixelProfile = new HashMap<>(); private final HashMap<String, Profile> uuidToProfileMap = new HashMap<>(); private final HashMap<String, String> nameToUuid = new HashMap<>(); @@ -303,31 +398,36 @@ public class ProfileViewer { public static Level getLevel(JsonArray levelingArray, float xp, int levelCap, boolean cumulative) { Level levelObj = new Level(); + levelObj.totalXp = xp; + levelObj.maxLevel = levelCap; + for (int level = 0; level < levelingArray.size(); level++) { float levelXp = levelingArray.get(level).getAsFloat(); + if (levelXp > xp) { if (cumulative) { - float previous = 0; - if (level > 0) previous = levelingArray.get(level - 1).getAsFloat(); + float previous = level > 0 ? levelingArray.get(level - 1).getAsFloat() : 0; levelObj.maxXpForLevel = (levelXp - previous); levelObj.level = 1 + level + (xp - levelXp) / levelObj.maxXpForLevel; } else { levelObj.maxXpForLevel = levelXp; levelObj.level = level + xp / levelXp; } + if (levelObj.level > levelCap) { levelObj.level = levelCap; levelObj.maxed = true; } + return levelObj; } else { - if (!cumulative) xp -= levelXp; + if (!cumulative) { + xp -= levelXp; + } } } - levelObj.level = levelingArray.size(); - if (levelObj.level > levelCap) { - levelObj.level = levelCap; - } + + levelObj.level = Math.min(levelingArray.size(), levelCap); levelObj.maxed = true; return levelObj; } @@ -359,10 +459,17 @@ public class ProfileViewer { String nameF = name.toLowerCase(); HashMap<String, String> args = new HashMap<>(); args.put("name", "" + nameF); - manager.hypixelApi.getHypixelApiAsync(NotEnoughUpdates.INSTANCE.config.apiData.apiKey, "player", - args, jsonObject -> { - if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean() - && jsonObject.get("player").isJsonObject()) { + manager.hypixelApi.getHypixelApiAsync( + NotEnoughUpdates.INSTANCE.config.apiData.apiKey, + "player", + args, + jsonObject -> { + if ( + jsonObject != null && + jsonObject.has("success") && + jsonObject.get("success").getAsBoolean() && + jsonObject.get("player").isJsonObject() + ) { nameToUuid.put(nameF, jsonObject.get("player").getAsJsonObject().get("uuid").getAsString()); uuidToHypixelProfile.put( jsonObject.get("player").getAsJsonObject().get("uuid").getAsString(), @@ -387,17 +494,18 @@ public class ProfileViewer { return; } - manager.hypixelApi.getApiAsync("https://api.mojang.com/users/profiles/minecraft/" + nameF, - (jsonObject) -> { - if (jsonObject.has("id") && jsonObject.get("id").isJsonPrimitive() && - ((JsonPrimitive) jsonObject.get("id")).isString()) { + manager.hypixelApi.getApiAsync( + "https://api.mojang.com/users/profiles/minecraft/" + nameF, + jsonObject -> { + if (jsonObject.has("id") && jsonObject.get("id").isJsonPrimitive() && ((JsonPrimitive) jsonObject.get("id")).isString()) { String uuid = jsonObject.get("id").getAsString(); nameToUuid.put(nameF, uuid); uuidCallback.accept(uuid); return; } uuidCallback.accept(null); - }, () -> uuidCallback.accept(null) + }, + () -> uuidCallback.accept(null) ); } @@ -409,40 +517,37 @@ public class ProfileViewer { return; } - getPlayerUUID(nameF, (uuid) -> { - if (uuid == null) { - getHypixelProfile(nameF, jsonObject -> { - if (jsonObject != null) { - callback.accept(getProfileReset(nameToUuid.get(nameF), ignored -> { - })); - } else { - callback.accept(null); - nameToUuid.put(nameF, null); + getPlayerUUID( + nameF, + uuid -> { + if (uuid == null) { + getHypixelProfile( + nameF, + jsonObject -> { + if (jsonObject != null) { + callback.accept(getProfileReset(nameToUuid.get(nameF), ignored -> {})); + } else { + callback.accept(null); + nameToUuid.put(nameF, null); + } + } + ); + } else { + if (!uuidToHypixelProfile.containsKey(uuid)) { + getHypixelProfile(nameF, jsonObject -> {}); } - }); - } else { - if (!uuidToHypixelProfile.containsKey(uuid)) { - getHypixelProfile(nameF, jsonObject -> { - }); + callback.accept(getProfileReset(uuid, ignored -> {})); } - callback.accept(getProfileReset(uuid, ignored -> { - })); } - }); - - return; - } - - public Profile getProfileRaw(String uuid) { - return uuidToProfileMap.get(uuid); + ); } public Profile getProfile(String uuid, Consumer<Profile> callback) { Profile profile = uuidToProfileMap.computeIfAbsent(uuid, k -> new Profile(uuid)); - if (profile.playerInformation != null) { + if (profile.skyblockProfiles != null) { callback.accept(profile); } else { - profile.getPlayerInformation(() -> callback.accept(profile)); + profile.getSkyblockProfiles(() -> callback.accept(profile)); } return profile; } @@ -453,34 +558,35 @@ public class ProfileViewer { } public static class Level { + public float level = 0; public float maxXpForLevel = 0; public boolean maxed = false; - public double totalXp; + public int maxLevel; + public float totalXp; } public class Profile { + private final String uuid; private final HashMap<String, JsonObject> profileMap = new HashMap<>(); private final HashMap<String, JsonObject> petsInfoMap = new HashMap<>(); private final HashMap<String, List<JsonObject>> coopProfileMap = new HashMap<>(); - private final HashMap<String, JsonObject> skillInfoMap = new HashMap<>(); - private final HashMap<String, JsonObject> inventoryInfoMap = new HashMap<>(); + private final HashMap<String, Map<String, Level>> skyblockInfoCache = new HashMap<>(); + private final HashMap<String, JsonObject> inventoryCacheMap = new HashMap<>(); private final HashMap<String, JsonObject> collectionInfoMap = new HashMap<>(); - private final List<String> profileIds = new ArrayList<>(); + private final List<String> profileNames = new ArrayList<>(); private final HashMap<String, PlayerStats.Stats> stats = new HashMap<>(); private final HashMap<String, PlayerStats.Stats> passiveStats = new HashMap<>(); private final HashMap<String, Long> networth = new HashMap<>(); - private final AtomicBoolean updatingPlayerInfoState = new AtomicBoolean(false); - private final AtomicBoolean updatingPlayerStatusState = new AtomicBoolean(false); + private final AtomicBoolean updatingSkyblockProfilesState = new AtomicBoolean(false); private final AtomicBoolean updatingGuildInfoState = new AtomicBoolean(false); - private final AtomicBoolean updatingGuildStatusState = new AtomicBoolean(false); + private final AtomicBoolean updatingPlayerStatusState = new AtomicBoolean(false); private final AtomicBoolean updatingBingoInfo = new AtomicBoolean(false); - private final Pattern COLL_TIER_PATTERN = Pattern.compile("_(-?[0-9]+)"); + private final Pattern COLL_TIER_PATTERN = Pattern.compile("_(-?\\d+)"); private String latestProfile = null; - private JsonArray playerInformation = null; + private JsonArray skyblockProfiles = null; private JsonObject guildInformation = null; - private JsonObject basicInfo = null; private JsonObject playerStatus = null; private JsonObject bingoInformation = null; private long lastPlayerInfoState = 0; @@ -499,18 +605,22 @@ public class ProfileViewer { long currentTime = System.currentTimeMillis(); if (currentTime - lastStatusInfoState < 15 * 1000) return null; lastStatusInfoState = currentTime; + updatingPlayerStatusState.set(true); HashMap<String, String> args = new HashMap<>(); args.put("uuid", "" + uuid); - manager.hypixelApi.getHypixelApiAsync(NotEnoughUpdates.INSTANCE.config.apiData.apiKey, "status", - args, jsonObject -> { - if (jsonObject == null) return; - + manager.hypixelApi.getHypixelApiAsync( + NotEnoughUpdates.INSTANCE.config.apiData.apiKey, + "status", + args, + jsonObject -> { updatingPlayerStatusState.set(false); - if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { + + if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { playerStatus = jsonObject.get("session").getAsJsonObject(); } - }, () -> updatingPlayerStatusState.set(false) + }, + () -> updatingPlayerStatusState.set(false) ); return null; @@ -532,26 +642,27 @@ public class ProfileViewer { "skyblock/bingo", args, jsonObject -> { - if (jsonObject == null) return; - if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { + updatingBingoInfo.set(false); + + if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { bingoInformation = jsonObject; } else { bingoInformation = null; } - updatingBingoInfo.set(false); - }, () -> updatingBingoInfo.set(false) + }, + () -> updatingBingoInfo.set(false) ); return bingoInformation != null ? bingoInformation : null; } - public long getNetWorth(String profileId) { - if (profileId == null) profileId = latestProfile; - if (networth.get(profileId) != null) return networth.get(profileId); - if (getProfileInformation(profileId) == null) return -1; - if (getInventoryInfo(profileId) == null) return -1; + public long getNetWorth(String profileName) { + if (profileName == null) profileName = latestProfile; + if (networth.get(profileName) != null) return networth.get(profileName); + if (getProfileInformation(profileName) == null) return -1; + if (getInventoryInfo(profileName) == null) return -1; - JsonObject inventoryInfo = getInventoryInfo(profileId); - JsonObject profileInfo = getProfileInformation(profileId); + JsonObject inventoryInfo = getInventoryInfo(profileName); + JsonObject profileInfo = getProfileInformation(profileName); HashMap<String, Long> mostExpensiveInternal = new HashMap<>(); @@ -616,8 +727,7 @@ public class ProfileViewer { } } } - } catch (IOException ignored) { - } + } catch (IOException ignored) {} int count = 1; if (element.getAsJsonObject().has("count")) { @@ -636,7 +746,7 @@ public class ProfileViewer { networth = (int) (networth * 1.3f); - JsonObject petsInfo = getPetsInfo(profileId); + JsonObject petsInfo = getPetsInfo(profileName); if (petsInfo != null && petsInfo.has("pets")) { if (petsInfo.get("pets").isJsonArray()) { JsonArray pets = petsInfo.get("pets").getAsJsonArray(); @@ -665,7 +775,7 @@ public class ProfileViewer { networth += bankBalance + purseBalance; - this.networth.put(profileId, networth); + this.networth.put(profileName, networth); return networth; } @@ -673,33 +783,35 @@ public class ProfileViewer { return latestProfile; } - public JsonArray getPlayerInformation(Runnable runnable) { - if (playerInformation != null) return playerInformation; + public JsonArray getSkyblockProfiles(Runnable runnable) { + if (skyblockProfiles != null) return skyblockProfiles; long currentTime = System.currentTimeMillis(); - if (currentTime - lastPlayerInfoState < 15 * 1000 && updatingPlayerInfoState.get()) return null; - + if (currentTime - lastPlayerInfoState < 15 * 1000 && updatingSkyblockProfilesState.get()) return null; lastPlayerInfoState = currentTime; - updatingPlayerInfoState.set(true); + updatingSkyblockProfilesState.set(true); HashMap<String, String> args = new HashMap<>(); args.put("uuid", "" + uuid); - manager.hypixelApi.getHypixelApiAsync(NotEnoughUpdates.INSTANCE.config.apiData.apiKey, "skyblock/profiles", - args, jsonObject -> { - updatingPlayerInfoState.set(false); + manager.hypixelApi.getHypixelApiAsync( + NotEnoughUpdates.INSTANCE.config.apiData.apiKey, + "skyblock/profiles", + args, + jsonObject -> { + updatingSkyblockProfilesState.set(false); - if (jsonObject == null) return; - if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { - playerInformation = jsonObject.get("profiles").getAsJsonArray(); - if (playerInformation == null) return; - String backup = null; - long backupLastSave = 0; + if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { + if (!jsonObject.has("profiles")) return; + skyblockProfiles = jsonObject.get("profiles").getAsJsonArray(); - profileIds.clear(); + String lastCuteName = null; + long lastLastSave = 0; - for (int i = 0; i < playerInformation.size(); i++) { - JsonObject profile = playerInformation.get(i).getAsJsonObject(); + profileNames.clear(); + + for (JsonElement profileEle : skyblockProfiles) { + JsonObject profile = profileEle.getAsJsonObject(); if (!profile.has("members")) continue; JsonObject members = profile.get("members").getAsJsonObject(); @@ -708,80 +820,83 @@ public class ProfileViewer { JsonObject member = members.get(uuid).getAsJsonObject(); if (member.has("coop_invitation")) { - JsonObject coop_invitation = member.get("coop_invitation").getAsJsonObject(); - if (!coop_invitation.get("confirmed").getAsBoolean()) { + if (!member.get("coop_invitation").getAsJsonObject().get("confirmed").getAsBoolean()) { continue; } } - String cute_name = profile.get("cute_name").getAsString(); - if (backup == null) backup = cute_name; - profileIds.add(cute_name); + String cuteName = profile.get("cute_name").getAsString(); + if (lastCuteName == null) lastCuteName = cuteName; + profileNames.add(cuteName); if (member.has("last_save")) { - long last_save = member.get("last_save").getAsLong(); - if (last_save > backupLastSave) { - backupLastSave = last_save; - backup = cute_name; + long lastSave = member.get("last_save").getAsLong(); + if (lastSave > lastLastSave) { + lastLastSave = lastSave; + lastCuteName = cuteName; } } - } } - latestProfile = backup; + latestProfile = lastCuteName; + if (runnable != null) runnable.run(); } - }, () -> updatingPlayerInfoState.set(false) + }, + () -> updatingSkyblockProfilesState.set(false) ); return null; } - public JsonObject getGuildInfo(Runnable runnable) { + public JsonObject getGuildInformation(Runnable runnable) { if (guildInformation != null) return guildInformation; long currentTime = System.currentTimeMillis(); - if (currentTime - lastGuildInfoState < 15 * 1000) return null; + if (currentTime - lastGuildInfoState < 15 * 1000 && updatingGuildInfoState.get()) return null; lastGuildInfoState = currentTime; - updatingGuildInfoState.set(true); HashMap<String, String> args = new HashMap<>(); args.put("player", "" + uuid); - manager.hypixelApi.getHypixelApiAsync(NotEnoughUpdates.INSTANCE.config.apiData.apiKey, "guild", - args, jsonObject -> { + manager.hypixelApi.getHypixelApiAsync( + NotEnoughUpdates.INSTANCE.config.apiData.apiKey, + "guild", + args, + jsonObject -> { updatingGuildInfoState.set(false); - if (jsonObject == null) return; - if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { + if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) { + if (!jsonObject.has("guild")) return; + guildInformation = jsonObject.get("guild").getAsJsonObject(); - if (guildInformation == null) return; + if (runnable != null) runnable.run(); } - }, () -> updatingGuildInfoState.set(false) + }, + () -> updatingGuildInfoState.set(false) ); return null; } - public List<String> getProfileIds() { - return profileIds; + public List<String> getProfileNames() { + return profileNames; } - public JsonObject getProfileInformation(String profileId) { - JsonArray playerInfo = getPlayerInformation(() -> { - }); + public JsonObject getProfileInformation(String profileName) { + JsonArray playerInfo = getSkyblockProfiles(() -> {}); if (playerInfo == null) return null; - if (profileId == null) profileId = latestProfile; - if (profileMap.containsKey(profileId)) return profileMap.get(profileId); + if (profileName == null) profileName = latestProfile; + if (profileMap.containsKey(profileName)) return profileMap.get(profileName); - for (int i = 0; i < playerInformation.size(); i++) { - if (!playerInformation.get(i).isJsonObject()) { - playerInformation = null; + for (int i = 0; i < skyblockProfiles.size(); i++) { + if (!skyblockProfiles.get(i).isJsonObject()) { + skyblockProfiles = null; return null; } - JsonObject profile = playerInformation.get(i).getAsJsonObject(); - if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileId)) { + JsonObject profile = skyblockProfiles.get(i).getAsJsonObject(); + if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileName)) { if (!profile.has("members")) return null; JsonObject members = profile.get("members").getAsJsonObject(); if (!members.has(uuid)) continue; @@ -792,7 +907,7 @@ public class ProfileViewer { if (profile.has("game_mode")) { profileInfo.add("game_mode", profile.get("game_mode")); } - profileMap.put(profileId, profileInfo); + profileMap.put(profileName, profileInfo); return profileInfo; } } @@ -800,20 +915,19 @@ public class ProfileViewer { return null; } - public List<JsonObject> getCoopProfileInformation(String profileId) { - JsonArray playerInfo = getPlayerInformation(() -> { - }); + public List<JsonObject> getCoopProfileInformation(String profileName) { + JsonArray playerInfo = getSkyblockProfiles(() -> {}); if (playerInfo == null) return null; - if (profileId == null) profileId = latestProfile; - if (coopProfileMap.containsKey(profileId)) return coopProfileMap.get(profileId); + if (profileName == null) profileName = latestProfile; + if (coopProfileMap.containsKey(profileName)) return coopProfileMap.get(profileName); - for (int i = 0; i < playerInformation.size(); i++) { - if (!playerInformation.get(i).isJsonObject()) { - playerInformation = null; + for (int i = 0; i < skyblockProfiles.size(); i++) { + if (!skyblockProfiles.get(i).isJsonObject()) { + skyblockProfiles = null; return null; } - JsonObject profile = playerInformation.get(i).getAsJsonObject(); - if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileId)) { + JsonObject profile = skyblockProfiles.get(i).getAsJsonObject(); + if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileName)) { if (!profile.has("members")) return null; JsonObject members = profile.get("members").getAsJsonObject(); if (!members.has(uuid)) return null; @@ -824,7 +938,7 @@ public class ProfileViewer { coopList.add(coopProfileInfo); } } - coopProfileMap.put(profileId, coopList); + coopProfileMap.put(profileName, coopList); return coopList; } } @@ -833,240 +947,142 @@ public class ProfileViewer { } public void resetCache() { - playerInformation = null; + skyblockProfiles = null; guildInformation = null; - basicInfo = null; playerStatus = null; stats.clear(); passiveStats.clear(); - profileIds.clear(); + profileNames.clear(); profileMap.clear(); coopProfileMap.clear(); petsInfoMap.clear(); - skillInfoMap.clear(); - inventoryInfoMap.clear(); + skyblockInfoCache.clear(); + inventoryCacheMap.clear(); collectionInfoMap.clear(); networth.clear(); } public int getCap(JsonObject leveling, String skillName) { JsonElement capsElement = Utils.getElement(leveling, "leveling_caps"); - if (capsElement == null || !capsElement.isJsonObject()) { - return 50; - } - JsonObject caps = capsElement.getAsJsonObject(); - if (caps.has(skillName)) { - return caps.get(skillName).getAsInt(); - } - return 50; + return capsElement != null && capsElement.isJsonObject() && capsElement.getAsJsonObject().has(skillName) + ? capsElement.getAsJsonObject().get(skillName).getAsInt() + : 50; } - public JsonObject getSkillInfo(String profileId) { - JsonObject profileInfo = getProfileInformation(profileId); + public Map<String, Level> getSkyblockInfo(String profileName) { + JsonObject profileInfo = getProfileInformation(profileName); + if (profileInfo == null) return null; - if (profileId == null) profileId = latestProfile; - if (skillInfoMap.containsKey(profileId)) return skillInfoMap.get(profileId); + if (profileName == null) profileName = latestProfile; + if (skyblockInfoCache.containsKey(profileName)) return skyblockInfoCache.get(profileName); + JsonObject leveling = Constants.LEVELING; if (leveling == null || !leveling.has("social")) { Utils.showOutdatedRepoNotification(); return null; } - float experience_skill_taming = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_taming"), 0); - float experience_skill_mining = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_mining"), 0); - float experience_skill_foraging = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_foraging"), 0); - float experience_skill_enchanting = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_enchanting"), 0); - float experience_skill_carpentry = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_carpentry"), 0); - float experience_skill_farming = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_farming"), 0); - float experience_skill_combat = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_combat"), 0); - float experience_skill_fishing = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_fishing"), 0); - float experience_skill_alchemy = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_alchemy"), 0); - float experience_skill_runecrafting = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_runecrafting"), 0); - float experience_skill_social = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_social2"), 0); - float experience_skill_hotm = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.experience"), 0); - - float experience_skill_catacombs = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.experience"), 0); - float experience_skill_healer = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.player_classes.healer.experience"), 0); - float experience_skill_archer = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.player_classes.archer.experience"), 0); - float experience_skill_tank = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.player_classes.tank.experience"), 0); - float experience_skill_mage = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.player_classes.mage.experience"), 0); - float experience_skill_berserk = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.player_classes.berserk.experience"), 0); - - float experience_slayer_zombie = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.xp"), 0); - float experience_slayer_spider = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.spider.xp"), 0); - float experience_slayer_wolf = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.wolf.xp"), 0); - float experience_slayer_enderman = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.enderman.xp"), 0); - float experience_slayer_blaze = - Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.blaze.xp"), 0); - - float totalSkillXP = experience_skill_taming + experience_skill_mining + experience_skill_foraging - + experience_skill_enchanting + experience_skill_carpentry + experience_skill_farming - + experience_skill_combat + experience_skill_fishing + experience_skill_alchemy - + experience_skill_runecrafting + experience_skill_social; + Map<String, Level> out = new HashMap<>(); + + List<String> skills = Arrays.asList( + "taming", + "mining", + "foraging", + "enchanting", + "carpentry", + "farming", + "combat", + "fishing", + "alchemy", + "runecrafting", + "social" + ); + float totalSkillXP = 0; + for (String skillName : skills) { + float skillExperience = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "experience_skill_" + (skillName.equals("social") ? "social2" : skillName)), + 0 + ); + totalSkillXP += skillExperience; + + JsonArray levelingArray = Utils.getElement(leveling, "leveling_xp").getAsJsonArray(); + if (skillName.equals("runecrafting")) { + levelingArray = Utils.getElement(leveling, "runecrafting_xp").getAsJsonArray(); + } else if (skillName.equals("social")) { + levelingArray = Utils.getElement(leveling, "social").getAsJsonArray(); + } + + int maxLevel = + getCap(leveling, skillName) + + ( + skillName.equals("farming") + ? Utils.getElementAsInt(Utils.getElement(profileInfo, "jacob2.perks.farming_level_cap"), 0) + : 0 + ); + out.put(skillName, getLevel(levelingArray, skillExperience, maxLevel, false)); + } + + // Skills API disabled? if (totalSkillXP <= 0) { return null; } - JsonObject skillInfo = new JsonObject(); - - skillInfo.addProperty("experience_skill_taming", experience_skill_taming); - skillInfo.addProperty("experience_skill_mining", experience_skill_mining); - skillInfo.addProperty("experience_skill_foraging", experience_skill_foraging); - skillInfo.addProperty("experience_skill_enchanting", experience_skill_enchanting); - skillInfo.addProperty("experience_skill_carpentry", experience_skill_carpentry); - skillInfo.addProperty("experience_skill_farming", experience_skill_farming); - skillInfo.addProperty("experience_skill_combat", experience_skill_combat); - skillInfo.addProperty("experience_skill_fishing", experience_skill_fishing); - skillInfo.addProperty("experience_skill_alchemy", experience_skill_alchemy); - skillInfo.addProperty("experience_skill_runecrafting", experience_skill_runecrafting); - skillInfo.addProperty("experience_skill_social2", experience_skill_social); - skillInfo.addProperty("experience_skill_hotm", experience_skill_hotm); - - skillInfo.addProperty("experience_skill_catacombs", experience_skill_catacombs); - skillInfo.addProperty("experience_skill_healer", experience_skill_healer); - skillInfo.addProperty("experience_skill_tank", experience_skill_tank); - skillInfo.addProperty("experience_skill_mage", experience_skill_mage); - skillInfo.addProperty("experience_skill_archer", experience_skill_archer); - skillInfo.addProperty("experience_skill_berserk", experience_skill_berserk); - - skillInfo.addProperty("experience_slayer_zombie", experience_slayer_zombie); - skillInfo.addProperty("experience_slayer_spider", experience_slayer_spider); - skillInfo.addProperty("experience_slayer_wolf", experience_slayer_wolf); - skillInfo.addProperty("experience_slayer_enderman", experience_slayer_enderman); - skillInfo.addProperty("experience_slayer_blaze", experience_slayer_blaze); - - JsonArray levelingArray = Utils.getElement(leveling, "leveling_xp").getAsJsonArray(); - int farmingCap = getCap(leveling, "farming") + (int) Utils.getElementAsFloat( - Utils.getElement(profileInfo, "jacob2.perks.farming_level_cap"), 0); - Level level_skill_taming = getLevel(levelingArray, experience_skill_taming, getCap(leveling, "taming"), false); - Level level_skill_mining = getLevel(levelingArray, experience_skill_mining, getCap(leveling, "mining"), false); - Level level_skill_foraging = - getLevel(levelingArray, experience_skill_foraging, getCap(leveling, "foraging"), false); - Level level_skill_enchanting = - getLevel(levelingArray, experience_skill_enchanting, getCap(leveling, "enchanting"), false); - Level level_skill_carpentry = - getLevel(levelingArray, experience_skill_carpentry, getCap(leveling, "carpentry"), false); - Level level_skill_farming = getLevel(levelingArray, experience_skill_farming, farmingCap, false); - Level level_skill_combat = getLevel(levelingArray, experience_skill_combat, getCap(leveling, "combat"), false); - Level level_skill_fishing = getLevel(levelingArray, experience_skill_fishing, getCap(leveling, "fishing"), false); - Level level_skill_alchemy = getLevel(levelingArray, experience_skill_alchemy, getCap(leveling, "alchemy"), false); - Level level_skill_hotm = getLevel(levelingArray, experience_skill_hotm, getCap(leveling, "HOTM"), false); - Level level_skill_runecrafting = getLevel(Utils.getElement(leveling, "runecrafting_xp").getAsJsonArray(), - experience_skill_runecrafting, getCap(leveling, "runecrafting"), false - ); - Level level_skill_social = getLevel(Utils - .getElementOrDefault(leveling, "social", new JsonArray()) - .getAsJsonArray(), - experience_skill_social, getCap(leveling, "social"), false - ); - Level level_skill_catacombs = getLevel(Utils.getElement(leveling, "catacombs").getAsJsonArray(), - experience_skill_catacombs, getCap(leveling, "catacombs"), false + out.put( + "hotm", + getLevel( + Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), + Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.experience"), 0), + getCap(leveling, "HOTM"), + false + ) ); - Level level_slayer_zombie = getLevel(Utils.getElement(leveling, "slayer_xp.zombie").getAsJsonArray(), - experience_slayer_zombie, 9, true - ); - Level level_slayer_spider = getLevel(Utils.getElement(leveling, "slayer_xp.spider").getAsJsonArray(), - experience_slayer_spider, 9, true - ); - Level level_slayer_wolf = getLevel(Utils.getElement(leveling, "slayer_xp.wolf").getAsJsonArray(), - experience_slayer_wolf, 9, true - ); - Level level_slayer_enderman = getLevel(Utils.getElement(leveling, "slayer_xp.enderman").getAsJsonArray(), - experience_slayer_enderman, 9, true - ); - Level level_slayer_blaze = getLevel(Utils.getElement(leveling, "slayer_xp.blaze").getAsJsonArray(), - experience_slayer_blaze, 9, true + out.put( + "catacombs", + getLevel( + Utils.getElement(leveling, "catacombs").getAsJsonArray(), + Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.experience"), 0), + getCap(leveling, "catacombs"), + false + ) ); - skillInfo.addProperty("level_skill_taming", level_skill_taming.level); - skillInfo.addProperty("level_skill_mining", level_skill_mining.level); - skillInfo.addProperty("level_skill_foraging", level_skill_foraging.level); - skillInfo.addProperty("level_skill_enchanting", level_skill_enchanting.level); - skillInfo.addProperty("level_skill_carpentry", level_skill_carpentry.level); - skillInfo.addProperty("level_skill_farming", level_skill_farming.level); - skillInfo.addProperty("level_skill_combat", level_skill_combat.level); - skillInfo.addProperty("level_skill_fishing", level_skill_fishing.level); - skillInfo.addProperty("level_skill_alchemy", level_skill_alchemy.level); - skillInfo.addProperty("level_skill_runecrafting", level_skill_runecrafting.level); - skillInfo.addProperty("level_skill_social2", level_skill_social.level); - - skillInfo.addProperty("level_skill_catacombs", level_skill_catacombs.level); - - skillInfo.addProperty("level_slayer_zombie", level_slayer_zombie.level); - skillInfo.addProperty("level_slayer_spider", level_slayer_spider.level); - skillInfo.addProperty("level_slayer_wolf", level_slayer_wolf.level); - skillInfo.addProperty("level_slayer_enderman", level_slayer_enderman.level); - skillInfo.addProperty("level_slayer_blaze", level_slayer_blaze.level); - - skillInfo.addProperty("maxed_skill_taming", level_skill_taming.maxed); - skillInfo.addProperty("maxed_skill_mining", level_skill_mining.maxed); - skillInfo.addProperty("maxed_skill_foraging", level_skill_foraging.maxed); - skillInfo.addProperty("maxed_skill_enchanting", level_skill_enchanting.maxed); - skillInfo.addProperty("maxed_skill_carpentry", level_skill_carpentry.maxed); - skillInfo.addProperty("maxed_skill_farming", level_skill_farming.maxed); - skillInfo.addProperty("maxed_skill_combat", level_skill_combat.maxed); - skillInfo.addProperty("maxed_skill_fishing", level_skill_fishing.maxed); - skillInfo.addProperty("maxed_skill_alchemy", level_skill_alchemy.maxed); - skillInfo.addProperty("maxed_skill_runecrafting", level_skill_runecrafting.maxed); - skillInfo.addProperty("maxed_skill_social2", level_skill_social.maxed); - - skillInfo.addProperty("maxed_skill_catacombs", level_skill_catacombs.maxed); - - skillInfo.addProperty("maxed_slayer_zombie", level_slayer_zombie.maxed); - skillInfo.addProperty("maxed_slayer_spider", level_slayer_spider.maxed); - skillInfo.addProperty("maxed_slayer_wolf", level_slayer_wolf.maxed); - skillInfo.addProperty("maxed_slayer_enderman", level_slayer_enderman.maxed); - skillInfo.addProperty("maxed_slayer_blaze", level_slayer_blaze.maxed); - - skillInfo.addProperty("maxxp_skill_taming", level_skill_taming.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_mining", level_skill_mining.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_foraging", level_skill_foraging.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_enchanting", level_skill_enchanting.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_carpentry", level_skill_carpentry.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_farming", level_skill_farming.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_combat", level_skill_combat.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_fishing", level_skill_fishing.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_alchemy", level_skill_alchemy.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_runecrafting", level_skill_runecrafting.maxXpForLevel); - skillInfo.addProperty("maxxp_skill_social2", level_skill_social.maxXpForLevel); - - skillInfo.addProperty("maxxp_skill_catacombs", level_skill_catacombs.maxXpForLevel); - - skillInfo.addProperty("maxxp_slayer_zombie", level_slayer_zombie.maxXpForLevel); - skillInfo.addProperty("maxxp_slayer_spider", level_slayer_spider.maxXpForLevel); - skillInfo.addProperty("maxxp_slayer_wolf", level_slayer_wolf.maxXpForLevel); - skillInfo.addProperty("maxxp_slayer_enderman", level_slayer_enderman.maxXpForLevel); - skillInfo.addProperty("maxxp_slayer_blaze", level_slayer_blaze.maxXpForLevel); - - return skillInfo; + List<String> dungeonClasses = Arrays.asList("healer", "tank", "mage", "archer", "berserk"); + for (String className : dungeonClasses) { + float classExperience = Utils.getElementAsFloat( + Utils.getElement(profileInfo, "dungeons.player_classes." + className + ".experience"), + 0 + ); + out.put( + className, + getLevel( + Utils.getElement(leveling, "catacombs").getAsJsonArray(), + classExperience, + getCap(leveling, "catacombs"), + false + ) + ); + } + + List<String> slayers = Arrays.asList("zombie", "spider", "wolf", "enderman", "blaze"); + for (String slayerName : slayers) { + float slayerExperience = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses." + slayerName + ".xp"), 0); + out.put( + slayerName, + getLevel(Utils.getElement(leveling, "slayer_xp." + slayerName).getAsJsonArray(), slayerExperience, 9, true) + ); + } + + skyblockInfoCache.put(profileName, out); + + return out; } - public JsonObject getInventoryInfo(String profileId) { - JsonObject profileInfo = getProfileInformation(profileId); + public JsonObject getInventoryInfo(String profileName) { + JsonObject profileInfo = getProfileInformation(profileName); if (profileInfo == null) return null; - if (profileId == null) profileId = latestProfile; - if (inventoryInfoMap.containsKey(profileId)) return inventoryInfoMap.get(profileId); + if (profileName == null) profileName = latestProfile; + if (inventoryCacheMap.containsKey(profileName)) return inventoryCacheMap.get(profileName); String inv_armor_bytes = Utils.getElementAsString( Utils.getElement(profileInfo, "inv_armor.data"), @@ -1120,7 +1136,7 @@ public class ProfileViewer { JsonObject inventoryInfo = new JsonObject(); - String[] inv_names = new String[]{ + String[] inv_names = new String[] { "inv_armor", "fishing_bag", "quiver", @@ -1132,9 +1148,9 @@ public class ProfileViewer { "inv_contents", "talisman_bag", "candy_inventory_contents", - "equippment_contents" + "equippment_contents", }; - String[] inv_bytes = new String[]{ + String[] inv_bytes = new String[] { inv_armor_bytes, fishing_bag_bytes, quiver_bytes, @@ -1146,7 +1162,7 @@ public class ProfileViewer { inv_contents_bytes, talisman_bag_bytes, candy_inventory_contents_bytes, - equipment_contents_bytes + equipment_contents_bytes, }; for (int i = 0; i < inv_bytes.length; i++) { try { @@ -1158,11 +1174,10 @@ public class ProfileViewer { JsonObject temp = getBackpackData(backpack_contents_json, backpack_icons); contents = (JsonArray) temp.get("contents"); inventoryInfo.add("backpack_sizes", temp.get("backpack_sizes")); - } else { - - NBTTagCompound inv_contents_nbt = - CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(bytes))); + NBTTagCompound inv_contents_nbt = CompressedStreamTools.readCompressed( + new ByteArrayInputStream(Base64.getDecoder().decode(bytes)) + ); NBTTagList items = inv_contents_nbt.getTagList("i", 10); for (int j = 0; j < items.tagCount(); j++) { JsonObject item = manager.getJsonFromNBTEntry(items.getCompoundTagAt(j)); @@ -1175,19 +1190,13 @@ public class ProfileViewer { } } - inventoryInfoMap.put(profileId, inventoryInfo); + inventoryCacheMap.put(profileName, inventoryInfo); return inventoryInfo; } - public boolean checkIfValidJson(JsonElement element) { - return element != null; - } - - public JsonObject getBackpackData(JsonObject backpack_contents_json, JsonObject backpack_icons) { - - JsonArray contents = new JsonArray(); - if (!(checkIfValidJson(backpack_contents_json) && checkIfValidJson(backpack_icons))) { + public JsonObject getBackpackData(JsonObject backpackContentsJson, JsonObject backpackIcons) { + if (backpackContentsJson == null || backpackIcons == null) { JsonObject bundledReturn = new JsonObject(); bundledReturn.add("contents", new JsonArray()); bundledReturn.add("backpack_sizes", new JsonArray()); @@ -1198,9 +1207,9 @@ public class ProfileViewer { String[] backpackArray = new String[0]; //Create backpack array which sizes up - for (Map.Entry<String, JsonElement> backpackIcon : backpack_icons.entrySet()) { + for (Map.Entry<String, JsonElement> backpackIcon : backpackIcons.entrySet()) { if (backpackIcon.getValue() instanceof JsonObject) { - JsonObject backpackData = (JsonObject) backpack_contents_json.get(backpackIcon.getKey()); + JsonObject backpackData = (JsonObject) backpackContentsJson.get(backpackIcon.getKey()); String bytes = Utils.getElementAsString(backpackData.get("data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="); backpackArray = growArray(bytes, Integer.parseInt(backpackIcon.getKey()), backpackArray); } @@ -1208,11 +1217,9 @@ public class ProfileViewer { //reduce backpack array to filter out not existent backpacks { - int backpackCount = 0; String[] tempBackpackArray = new String[0]; for (String s : backpackArray) { if (s != null) { - backpackCount++; String[] veryTempBackpackArray = new String[tempBackpackArray.length + 1]; System.arraycopy(tempBackpackArray, 0, veryTempBackpackArray, 0, tempBackpackArray.length); @@ -1224,11 +1231,13 @@ public class ProfileViewer { } JsonArray backpackSizes = new JsonArray(); + JsonArray contents = new JsonArray(); for (String backpack : backpackArray) { try { - NBTTagCompound inv_contents_nbt = - CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(backpack))); + NBTTagCompound inv_contents_nbt = CompressedStreamTools.readCompressed( + new ByteArrayInputStream(Base64.getDecoder().decode(backpack)) + ); NBTTagList items = inv_contents_nbt.getTagList("i", 10); backpackSizes.add(new JsonPrimitive(items.tagCount())); @@ -1236,8 +1245,7 @@ public class ProfileViewer { JsonObject item = manager.getJsonFromNBTEntry(items.getCompoundTagAt(j)); contents.add(item); } - } catch (IOException ignored) { - } + } catch (IOException ignored) {} } JsonObject bundledReturn = new JsonObject(); @@ -1251,18 +1259,16 @@ public class ProfileViewer { int newSize = Math.max(index + 1, oldArray.length); String[] newArray = new String[newSize]; - for (int i = 0; i < oldArray.length; i++) { - newArray[i] = oldArray[i]; - } + System.arraycopy(oldArray, 0, newArray, 0, oldArray.length); newArray[index] = bytes; return newArray; } - public JsonObject getPetsInfo(String profileId) { - JsonObject profileInfo = getProfileInformation(profileId); + public JsonObject getPetsInfo(String profileName) { + JsonObject profileInfo = getProfileInformation(profileName); if (profileInfo == null) return null; - if (petsInfoMap.containsKey(profileId)) return petsInfoMap.get(profileId); + if (petsInfoMap.containsKey(profileName)) return petsInfoMap.get(profileName); JsonObject petsInfo = new JsonObject(); JsonElement petsElement = profileInfo.get("pets"); @@ -1271,28 +1277,28 @@ public class ProfileViewer { JsonArray pets = petsElement.getAsJsonArray(); for (int i = 0; i < pets.size(); i++) { JsonObject pet = pets.get(i).getAsJsonObject(); - if (pet.has("active") && pet.get("active").getAsJsonPrimitive().getAsBoolean()) { + if (pet.has("active") && pet.get("active").getAsBoolean()) { activePet = pet; break; } } petsInfo.add("active_pet", activePet); petsInfo.add("pets", pets); - petsInfoMap.put(profileId, petsInfo); + petsInfoMap.put(profileName, petsInfo); return petsInfo; } return null; } - public JsonObject getCollectionInfo(String profileId) { - JsonObject profileInfo = getProfileInformation(profileId); + public JsonObject getCollectionInfo(String profileName) { + JsonObject profileInfo = getProfileInformation(profileName); if (profileInfo == null) return null; JsonObject resourceCollectionInfo = getResourceCollectionInformation(); if (resourceCollectionInfo == null) return null; - if (profileId == null) profileId = latestProfile; - if (collectionInfoMap.containsKey(profileId)) return collectionInfoMap.get(profileId); + if (profileName == null) profileName = latestProfile; + if (collectionInfoMap.containsKey(profileName)) return collectionInfoMap.get(profileName); - List<JsonObject> coopMembers = getCoopProfileInformation(profileId); + List<JsonObject> coopMembers = getCoopProfileInformation(profileName); JsonElement unlocked_coll_tiers_element = Utils.getElement(profileInfo, "unlocked_coll_tiers"); JsonElement crafted_generators_element = Utils.getElement(profileInfo, "crafted_generators"); JsonObject fakeMember = new JsonObject(); @@ -1318,7 +1324,7 @@ public class ProfileViewer { totalAmounts.addProperty(entry.getKey(), entry.getValue().getAsLong()); } - List<JsonObject> coopProfiles = getCoopProfileInformation(profileId); + List<JsonObject> coopProfiles = getCoopProfileInformation(profileName); if (coopProfiles != null) { for (JsonObject coopProfile : coopProfiles) { JsonElement coopCollectionInfoElement = Utils.getElement(coopProfile, "collection"); @@ -1349,8 +1355,9 @@ public class ProfileViewer { } } for (JsonObject current_member_info : coopMembers) { - if (!current_member_info.has("crafted_generators") || - !current_member_info.get("crafted_generators").isJsonArray()) continue; + if ( + !current_member_info.has("crafted_generators") || !current_member_info.get("crafted_generators").isJsonArray() + ) continue; JsonArray crafted_generators = Utils.getElement(current_member_info, "crafted_generators").getAsJsonArray(); for (int j = 0; j < crafted_generators.size(); j++) { String unlocked = crafted_generators.get(j).getAsString(); @@ -1411,35 +1418,38 @@ public class ProfileViewer { return collectionInfo; } - public PlayerStats.Stats getPassiveStats(String profileId) { - if (passiveStats.get(profileId) != null) return passiveStats.get(profileId); - JsonObject profileInfo = getProfileInformation(profileId); + public PlayerStats.Stats getPassiveStats(String profileName) { + if (passiveStats.get(profileName) != null) return passiveStats.get(profileName); + JsonObject profileInfo = getProfileInformation(profileName); if (profileInfo == null) return null; - PlayerStats.Stats passiveStats = PlayerStats.getPassiveBonuses(getSkillInfo(profileId), profileInfo); + PlayerStats.Stats passiveStats = PlayerStats.getPassiveBonuses(getSkyblockInfo(profileName), profileInfo); if (passiveStats != null) { passiveStats.add(PlayerStats.getBaseStats()); } - this.passiveStats.put(profileId, passiveStats); + this.passiveStats.put(profileName, passiveStats); return passiveStats; } - public PlayerStats.Stats getStats(String profileId) { - if (stats.get(profileId) != null) return stats.get(profileId); - JsonObject profileInfo = getProfileInformation(profileId); + public PlayerStats.Stats getStats(String profileName) { + if (stats.get(profileName) != null) return stats.get(profileName); + JsonObject profileInfo = getProfileInformation(profileName); if (profileInfo == null) { return null; } - PlayerStats.Stats stats = - PlayerStats.getStats(getSkillInfo(profileId), getInventoryInfo(profileId), getCollectionInfo(profileId), - getPetsInfo(profileId), profileInfo - ); + PlayerStats.Stats stats = PlayerStats.getStats( + getSkyblockInfo(profileName), + getInventoryInfo(profileName), + getCollectionInfo(profileName), + getPetsInfo(profileName), + profileInfo + ); if (stats == null) return null; - this.stats.put(profileId, stats); + this.stats.put(profileName, stats); return stats; } @@ -1447,10 +1457,8 @@ public class ProfileViewer { return uuid; } - public @Nullable - JsonObject getHypixelProfile() { - if (uuidToHypixelProfile.containsKey(uuid)) return uuidToHypixelProfile.get(uuid); - return null; + public @Nullable JsonObject getHypixelProfile() { + return uuidToHypixelProfile.getOrDefault(uuid, null); } } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java index 1e18f825..6f541833 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java @@ -30,8 +30,9 @@ import java.util.LinkedHashMap; import java.util.List; public class BestiaryData { - private static final LinkedHashMap<ItemStack, List<String>> bestiaryLocations = - new LinkedHashMap<ItemStack, List<String>>() {{ + + private static final LinkedHashMap<ItemStack, List<String>> bestiaryLocations = new LinkedHashMap<ItemStack, List<String>>() { + { put( Utils.createSkull( EnumChatFormatting.AQUA + "Private Island", @@ -54,143 +55,153 @@ public class BestiaryData { "88208736-41cd-4ed8-8ed7-53179140a7fa", "eyJ0aW1lc3RhbXAiOjE1NTkyMTU0MTY5MDksInByb2ZpbGVJZCI6IjQxZDNhYmMyZDc0OTQwMGM5MDkwZDU0MzRkMDM4MzFiIiwicHJvZmlsZU5hbWUiOiJNZWdha2xvb24iLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Q3Y2M2Njg3NDIzZDA1NzBkNTU2YWM1M2UwNjc2Y2I1NjNiYmRkOTcxN2NkODI2OWJkZWJlZDZmNmQ0ZTdiZjgifX19" ), + Utils.createList("family_unburried_zombie", "family_old_wolf", "family_ruin_wolf", "family_zombie_villager") + ); + put( + Utils.createSkull( + EnumChatFormatting.AQUA + "Spiders Den", + "acbeaf98-2081-40c5-b5a3-221a2957d532", + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzc1NDMxOGEzMzc2ZjQ3MGU0ODFkZmNkNmM4M2E1OWFhNjkwYWQ0YjRkZDc1NzdmZGFkMWMyZWYwOGQ4YWVlNiJ9fX0" + ), Utils.createList( - "family_unburried_zombie", - "family_old_wolf", - "family_ruin_wolf", - "family_zombie_villager" + "family_arachne", + "family_arachne_brood", + "family_arachne_keeper", + "family_brood_mother_spider", + "family_dasher_spider", + "family_respawning_skeleton", + "family_random_slime", + "family_spider_jockey", + "family_splitter_spider", + "family_voracious_spider", + "family_weaver_spider" ) ); - put(Utils.createSkull( - EnumChatFormatting.AQUA + "Spiders Den", - "acbeaf98-2081-40c5-b5a3-221a2957d532", - "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzc1NDMxOGEzMzc2ZjQ3MGU0ODFkZmNkNmM4M2E1OWFhNjkwYWQ0YjRkZDc1NzdmZGFkMWMyZWYwOGQ4YWVlNiJ9fX0" - ), Utils.createList( - "family_arachne", - "family_arachne_brood", - "family_arachne_keeper", - "family_brood_mother_spider", - "family_dasher_spider", - "family_respawning_skeleton", - "family_random_slime", - "family_spider_jockey", - "family_splitter_spider", - "family_voracious_spider", - "family_weaver_spider" - )); - put(Utils.createSkull( - EnumChatFormatting.AQUA + "The End", - "e39ea8b1-a267-48a9-907a-1b97b85342bc", - "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg0MGI4N2Q1MjI3MWQyYTc1NWRlZGM4Mjg3N2UwZWQzZGY2N2RjYzQyZWE0NzllYzE0NjE3NmIwMjc3OWE1In19fQ" - ), Utils.createList( - "family_dragon", - "family_enderman", - "family_endermite", - "family_corrupted_protector", - "family_obsidian_wither", - "family_voidling_extremist", - "family_voidling_fanatic", - "family_watcher", - "family_zealot_enderman" - )); - put(Utils.createSkull( - EnumChatFormatting.AQUA + "Crimson Isles", - "d8489bfe-dcd7-41f0-bfbd-fb482bf61ecb", - "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzM2ODdlMjVjNjMyYmNlOGFhNjFlMGQ2NGMyNGU2OTRjM2VlYTYyOWVhOTQ0ZjRjZjMwZGNmYjRmYmNlMDcxIn19fQ" - ), Utils.createList( - "family_ashfang", - "family_barbarian_duke_x", - "family_bladesoul", - "family_blaze", - "family_flaming_spider", - "family_ghast", - "family_mage_outlaw", - "family_magma_cube", - "family_magma_cube_boss", - "family_matcho", - "family_charging_mushroom_cow", - "family_pigman", - "family_wither_skeleton", - "family_wither_spectre" - )); - put(Utils.createSkull( - EnumChatFormatting.AQUA + "Deep Caverns", - "896b5137-a2dd-4de2-8c63-d5a5649bfc70", - "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTY5YTFmMTE0MTUxYjQ1MjEzNzNmMzRiYzE0YzI5NjNhNTAxMWNkYzI1YTY1NTRjNDhjNzA4Y2Q5NmViZmMifX19" - ), Utils.createList( - "family_automaton", - "family_butterfly", - "family_emerald_slime", - "family_caverns_ghost", - "family_goblin", - "family_team_treasurite", - "family_ice_walker", - "family_lapis_zombie", - "family_diamond_skeleton", - "family_diamond_zombie", - "family_redstone_pigman", - "family_sludge", - "family_invisible_creeper", - "family_thyst", - "family_treasure_hoarder", - "family_worms", - "family_yog" - )); - put(Utils.createSkull( - EnumChatFormatting.AQUA + "The Park", - "6473b2ff-0575-4aec-811f-5f0dca2131b6", - "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTIyMWY4MTNkYWNlZTBmZWY4YzU5Zjc2ODk0ZGJiMjY0MTU0NzhkOWRkZmM0NGMyZTcwOGE2ZDNiNzU0OWIifX19" - ), Utils.createList("family_howling_spirit", "family_pack_spirit", "family_soul_of_the_alpha" - )); - put(Utils.createItemStack(Item.getItemFromBlock(Blocks.lit_pumpkin), EnumChatFormatting.AQUA + "Spooky" - ), Utils.createList( - "family_batty_witch", - "family_headless_horseman", - "family_phantom_spirit", - "family_scary_jerry", - "family_trick_or_treater", - "family_wither_gourd", - "family_wraith" - )); - put(Utils.createSkull( - EnumChatFormatting.AQUA + "Catacombs", - "00b3837d-9275-304c-8bf9-656659087e6b", - "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTY0ZTFjM2UzMTVjOGQ4ZmZmYzM3OTg1YjY2ODFjNWJkMTZhNmY5N2ZmZDA3MTk5ZThhMDVlZmJlZjEwMzc5MyJ9fX0" - ), Utils.createList( - "family_diamond_guy", - "family_cellar_spider", - "family_crypt_dreadlord", - "family_crypt_lurker", - "family_crypt_souleater", - "family_king_midas", - "family_lonely_spider", - "family_lost_adventurer", - "family_scared_skeleton", - "family_shadow_assassin", - "family_skeleton_grunt", - "family_skeleton_master", - "family_skeleton_soldier", - "family_skeletor", - "family_sniper_skeleton", - "family_super_archer", - "family_super_tank_zombie", - "family_crypt_tank_zombie", - "family_watcher_summon_undead", - "family_dungeon_respawning_skeleton", - "family_crypt_witherskeleton", - "family_zombie_commander", - "family_zombie_grunt", - "family_zombie_knight", - "family_zombie_soldier" - )); - }}; - - public static LinkedHashMap<ItemStack, List<String>> getBestiaryLocations() { - return bestiaryLocations; - } - - private static final LinkedHashMap<String, ItemStack> bestiaryMobs = - new LinkedHashMap<String, ItemStack>() {{ + put( + Utils.createSkull( + EnumChatFormatting.AQUA + "The End", + "e39ea8b1-a267-48a9-907a-1b97b85342bc", + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg0MGI4N2Q1MjI3MWQyYTc1NWRlZGM4Mjg3N2UwZWQzZGY2N2RjYzQyZWE0NzllYzE0NjE3NmIwMjc3OWE1In19fQ" + ), + Utils.createList( + "family_dragon", + "family_enderman", + "family_endermite", + "family_corrupted_protector", + "family_obsidian_wither", + "family_voidling_extremist", + "family_voidling_fanatic", + "family_watcher", + "family_zealot_enderman" + ) + ); + put( + Utils.createSkull( + EnumChatFormatting.AQUA + "Crimson Isles", + "d8489bfe-dcd7-41f0-bfbd-fb482bf61ecb", + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzM2ODdlMjVjNjMyYmNlOGFhNjFlMGQ2NGMyNGU2OTRjM2VlYTYyOWVhOTQ0ZjRjZjMwZGNmYjRmYmNlMDcxIn19fQ" + ), + Utils.createList( + "family_ashfang", + "family_barbarian_duke_x", + "family_bladesoul", + "family_blaze", + "family_flaming_spider", + "family_ghast", + "family_mage_outlaw", + "family_magma_cube", + "family_magma_cube_boss", + "family_matcho", + "family_charging_mushroom_cow", + "family_pigman", + "family_wither_skeleton", + "family_wither_spectre" + ) + ); + put( + Utils.createSkull( + EnumChatFormatting.AQUA + "Deep Caverns", + "896b5137-a2dd-4de2-8c63-d5a5649bfc70", + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTY5YTFmMTE0MTUxYjQ1MjEzNzNmMzRiYzE0YzI5NjNhNTAxMWNkYzI1YTY1NTRjNDhjNzA4Y2Q5NmViZmMifX19" + ), + Utils.createList( + "family_automaton", + "family_butterfly", + "family_emerald_slime", + "family_caverns_ghost", + "family_goblin", + "family_team_treasurite", + "family_ice_walker", + "family_lapis_zombie", + "family_diamond_skeleton", + "family_diamond_zombie", + "family_redstone_pigman", + "family_sludge", + "family_invisible_creeper", + "family_thyst", + "family_treasure_hoarder", + "family_worms", + "family_yog" + ) + ); + put( + Utils.createSkull( + EnumChatFormatting.AQUA + "The Park", + "6473b2ff-0575-4aec-811f-5f0dca2131b6", + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTIyMWY4MTNkYWNlZTBmZWY4YzU5Zjc2ODk0ZGJiMjY0MTU0NzhkOWRkZmM0NGMyZTcwOGE2ZDNiNzU0OWIifX19" + ), + Utils.createList("family_howling_spirit", "family_pack_spirit", "family_soul_of_the_alpha") + ); + put( + Utils.createItemStack(Item.getItemFromBlock(Blocks.lit_pumpkin), EnumChatFormatting.AQUA + "Spooky"), + Utils.createList( + "family_batty_witch", + "family_headless_horseman", + "family_phantom_spirit", + "family_scary_jerry", + "family_trick_or_treater", + "family_wither_gourd", + "family_wraith" + ) + ); + put( + Utils.createSkull( + EnumChatFormatting.AQUA + "Catacombs", + "00b3837d-9275-304c-8bf9-656659087e6b", + "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTY0ZTFjM2UzMTVjOGQ4ZmZmYzM3OTg1YjY2ODFjNWJkMTZhNmY5N2ZmZDA3MTk5ZThhMDVlZmJlZjEwMzc5MyJ9fX0" + ), + Utils.createList( + "family_diamond_guy", + "family_cellar_spider", + "family_crypt_dreadlord", + "family_crypt_lurker", + "family_crypt_souleater", + "family_king_midas", + "family_lonely_spider", + "family_lost_adventurer", + "family_scared_skeleton", + "family_shadow_assassin", + "family_skeleton_grunt", + "family_skeleton_master", + "family_skeleton_soldier", + "family_skeletor", + "family_sniper_skeleton", + "family_super_archer", + "family_super_tank_zombie", + "family_crypt_tank_zombie", + "family_watcher_summon_undead", + "family_dungeon_respawning_skeleton", + "family_crypt_witherskeleton", + "family_zombie_commander", + "family_zombie_grunt", + "family_zombie_knight", + "family_zombie_soldier" + ) + ); + } + }; + private static final LinkedHashMap<String, ItemStack> bestiaryMobs = new LinkedHashMap<String, ItemStack>() { + { // Private Island put( "family_cave_spider", @@ -250,10 +261,7 @@ public class BestiaryData { ); // Hub - put( - "family_unburried_zombie", - Utils.createItemStack(Items.golden_sword, EnumChatFormatting.AQUA + "§aCrypt Ghoul") - ); + put("family_unburried_zombie", Utils.createItemStack(Items.golden_sword, EnumChatFormatting.AQUA + "§aCrypt Ghoul")); put( "family_old_wolf", Utils.createSkull( @@ -370,10 +378,7 @@ public class BestiaryData { ); // The End - put( - "family_dragon", - Utils.createItemStack(Item.getItemFromBlock(Blocks.dragon_egg), EnumChatFormatting.AQUA + "§aDragon") - ); + put("family_dragon", Utils.createItemStack(Item.getItemFromBlock(Blocks.dragon_egg), EnumChatFormatting.AQUA + "§aDragon")); put( "family_enderman", Utils.createSkull( @@ -619,10 +624,7 @@ public class BestiaryData { "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDI4ZDlmZjU0MTg4YTFhZmVlNjViOTRmM2JmY2NlMzIxYzY0M2EzNDU5MGMxNGIxOTJiMmUzZWMyZjUyNWQzIn19fQ==" ) ); - put( - "family_redstone_pigman", - Utils.createItemStack(Items.redstone, EnumChatFormatting.AQUA + "§aRedstone Pigman") - ); + put("family_redstone_pigman", Utils.createItemStack(Items.redstone, EnumChatFormatting.AQUA + "§aRedstone Pigman")); put( "family_sludge", Utils.createSkull( @@ -957,14 +959,10 @@ public class BestiaryData { "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo=" ) ); - }}; - - public static LinkedHashMap<String, ItemStack> getBestiaryMobs() { - return bestiaryMobs; - } - - private static final LinkedHashMap<String, String> mobTypeMap = - new LinkedHashMap<String, String>() {{ + } + }; + private static final LinkedHashMap<String, String> mobTypeMap = new LinkedHashMap<String, String>() { + { // Island put("family_cave_spider", "ISLAND"); put("family_enderman_private", "ISLAND"); @@ -1079,11 +1077,18 @@ public class BestiaryData { put("family_zombie_grunt", "MOB"); put("family_zombie_knight", "MOB"); put("family_zombie_soldier", "MOB"); + } + }; - }}; + public static LinkedHashMap<ItemStack, List<String>> getBestiaryLocations() { + return bestiaryLocations; + } + + public static LinkedHashMap<String, ItemStack> getBestiaryMobs() { + return bestiaryMobs; + } public static LinkedHashMap<String, String> getMobType() { return mobTypeMap; } - } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java index 1bd3770a..1aebb290 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java @@ -22,6 +22,7 @@ package io.github.moulberry.notenoughupdates.profileviewer.bestiary; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewerPage; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; @@ -40,24 +41,26 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -public class BestiaryPage { +public class BestiaryPage extends GuiProfileViewerPage { - private static int guiLeft; - private static int guiTop; - private static final ResourceLocation BESTIARY_TEXTURE = new ResourceLocation( - "notenoughupdates:pv_bestiary_tab.png"); public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png"); - private static ItemStack selectedBestiaryLocation = null; - private static List<String> tooltipToDisplay = null; + private static final ResourceLocation BESTIARY_TEXTURE = new ResourceLocation("notenoughupdates:pv_bestiary_tab.png"); private static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US); private static final int XCOUNT = 7; private static final int YCOUNT = 5; private static final float XPADDING = (190 - XCOUNT * 20) / (float) (XCOUNT + 1); private static final float YPADDING = (202 - YCOUNT * 20) / (float) (YCOUNT + 1); + private ItemStack selectedBestiaryLocation = null; + private List<String> tooltipToDisplay = null; - public static void renderPage(int mouseX, int mouseY) { - guiLeft = GuiProfileViewer.getGuiLeft(); - guiTop = GuiProfileViewer.getGuiTop(); + public BestiaryPage(GuiProfileViewer instance) { + super(instance); + } + + @Override + public void drawPage(int mouseX, int mouseY, float partialTicks) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); JsonObject profileInfo = GuiProfileViewer.getProfile().getProfileInformation(GuiProfileViewer.getProfileId()); int bestiarySize = BestiaryData.getBestiaryLocations().size(); @@ -68,17 +71,29 @@ public class BestiaryPage { for (ItemStack stack : BestiaryData.getBestiaryLocations().keySet()) { Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); if (stack == selectedBestiaryLocation) { - Utils.drawTexturedRect(guiLeft + 30 + bestiaryXSize * yIndex, guiTop + 10, 20, 20, - 20 / 256f, 0, 20 / 256f, 0, GL11.GL_NEAREST - ); - Utils.drawItemStack( - stack, - guiLeft + 32 + bestiaryXSize * yIndex, - guiTop + 12 + Utils.drawTexturedRect( + guiLeft + 30 + bestiaryXSize * yIndex, + guiTop + 10, + 20, + 20, + 20 / 256f, + 0, + 20 / 256f, + 0, + GL11.GL_NEAREST ); + Utils.drawItemStack(stack, guiLeft + 32 + bestiaryXSize * yIndex, guiTop + 12); } else { - Utils.drawTexturedRect(guiLeft + 30 + bestiaryXSize * yIndex, guiTop + 10, 20, 20, - 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft + 30 + bestiaryXSize * yIndex, + guiTop + 10, + 20, + 20, + 0, + 20 / 256f, + 0, + 20 / 256f, + GL11.GL_NEAREST ); Utils.drawItemStack(stack, guiLeft + 32 + bestiaryXSize * yIndex, guiTop + 12); } @@ -98,9 +113,15 @@ public class BestiaryPage { List<String> mobs = BestiaryData.getBestiaryLocations().get(selectedBestiaryLocation); Color color = new Color(128, 128, 128, 255); + Utils.renderAlignedString( + EnumChatFormatting.RED + "Bestiary Level: ", + EnumChatFormatting.GRAY + "" + (float) getBestiaryTiers(profileInfo) / 10, + guiLeft + 220, + guiTop + 50, + 110 + ); if (mobs != null) { for (int i = 0; i < mobs.size(); i++) { - String mob = mobs.get(i); if (mob != null) { ItemStack mobItem = BestiaryData.getBestiaryMobs().get(mob); @@ -115,13 +136,29 @@ public class BestiaryPage { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20 * (1 - completedness), - 0, 20 / 256f, 0, 20 * (1 - completedness) / 256f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y, + 20, + 20 * (1 - completedness), + 0, + 20 / 256f, + 0, + 20 * (1 - completedness) / 256f, + GL11.GL_NEAREST ); GlStateManager.color(1, 185 / 255f, 0, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(guiLeft + x, guiTop + y + 20 * (1 - completedness), 20, 20 * (completedness), - 0, 20 / 256f, 20 * (1 - completedness) / 256f, 20 / 256f, GL11.GL_NEAREST + Utils.drawTexturedRect( + guiLeft + x, + guiTop + y + 20 * (1 - completedness), + 20, + 20 * (completedness), + 0, + 20 / 256f, + 20 * (1 - completedness) / 256f, + 20 / 256f, + GL11.GL_NEAREST ); Utils.drawItemStack(mobItem, guiLeft + (int) x + 2, guiTop + (int) y + 2); float kills = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.kills_" + mob), 0); @@ -150,34 +187,47 @@ public class BestiaryPage { if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) { if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) { tooltipToDisplay = new ArrayList<>(); - tooltipToDisplay.add(mobItem.getDisplayName() + " " + ((levelNum == -1) ? "?" : (int) Math.floor(levelNum))); - tooltipToDisplay.add(EnumChatFormatting.GRAY + "Kills: " + EnumChatFormatting.GREEN + numberFormat.format(kills)); - tooltipToDisplay.add(EnumChatFormatting.GRAY + "Deaths: " + EnumChatFormatting.GREEN + numberFormat.format(deaths)); + tooltipToDisplay.add( + mobItem.getDisplayName() + " " + ((levelNum == -1) ? "?" : (int) Math.floor(levelNum)) + ); + tooltipToDisplay.add( + EnumChatFormatting.GRAY + "Kills: " + EnumChatFormatting.GREEN + numberFormat.format(kills) + ); + tooltipToDisplay.add( + EnumChatFormatting.GRAY + "Deaths: " + EnumChatFormatting.GREEN + numberFormat.format(deaths) + ); if (level != null) { - tooltipToDisplay.add(EnumChatFormatting.GRAY + "Progress: " + EnumChatFormatting.AQUA + - GuiProfileViewer.shortNumberFormat(Math.round((levelNum % 1) * level.maxXpForLevel), 0) + "/" + - GuiProfileViewer.shortNumberFormat(level.maxXpForLevel, 0)); + String progressStr; + if (level.maxed) { + progressStr = EnumChatFormatting.GOLD + "MAXED!"; + } else { + progressStr = EnumChatFormatting.AQUA + + GuiProfileViewer.shortNumberFormat(Math.round((levelNum % 1) * level.maxXpForLevel), 0) + + "/" + + GuiProfileViewer.shortNumberFormat(level.maxXpForLevel, 0); + } + tooltipToDisplay.add(EnumChatFormatting.GRAY + "Progress: " + progressStr); } } } GlStateManager.color(1, 1, 1, 1); -// if (tier >= 0) { -// Utils.drawStringCentered(tierString, Minecraft.getMinecraft().fontRendererObj, -// guiLeft + x + 10, guiTop + y - 4, true, -// tierStringColour -// ); -// } - Utils.drawStringCentered((int) Math.floor(levelNum) + "", Minecraft.getMinecraft().fontRendererObj, - guiLeft + x + 10, guiTop + y + 26, true, + // if (tier >= 0) { + // Utils.drawStringCentered(tierString, Minecraft.getMinecraft().fontRendererObj, + // guiLeft + x + 10, guiTop + y - 4, true, + // tierStringColour + // ); + // } + Utils.drawStringCentered( + (int) Math.floor(levelNum) + "", + Minecraft.getMinecraft().fontRendererObj, + guiLeft + x + 10, + guiTop + y + 26, + true, color.getRGB() ); } } - Utils.renderAlignedString(EnumChatFormatting.RED + "Bestiary Level: ", - EnumChatFormatting.GRAY + "" + (float) getBeTiers(profileInfo) / 10, - guiLeft + 220, guiTop + 50, 110 - ); } } if (tooltipToDisplay != null) { @@ -190,13 +240,16 @@ public class BestiaryPage { } } - public static void mouseReleased(int mouseX, int mouseY, int mouseButton) { + @Override + public void mouseReleased(int mouseX, int mouseY, int mouseButton) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); + int bestiarySize = BestiaryData.getBestiaryLocations().size(); int bestiaryYSize = (int) (350f / (bestiarySize - 1 + 0.0000001f)); int yIndex = 0; for (ItemStack stack : BestiaryData.getBestiaryLocations().keySet()) { - if (mouseX > guiLeft + 30 + bestiaryYSize * yIndex && - mouseX < guiLeft + 30 + bestiaryYSize * yIndex + 20) { + if (mouseX > guiLeft + 30 + bestiaryYSize * yIndex && mouseX < guiLeft + 30 + bestiaryYSize * yIndex + 20) { if (mouseY > guiTop + 10 && mouseY < guiTop + 10 + 20) { selectedBestiaryLocation = stack; Utils.playPressSound(); @@ -207,14 +260,12 @@ public class BestiaryPage { } } - public static int getBeTiers(JsonObject profileInfo) { + private int getBestiaryTiers(JsonObject profileInfo) { int beLevel = 0; for (ItemStack items : BestiaryData.getBestiaryLocations().keySet()) { List<String> mobs = BestiaryData.getBestiaryLocations().get(items); if (mobs != null) { - for (int i = 0; i < mobs.size(); i++) { - - String mob = mobs.get(i); + for (String mob : mobs) { if (mob != null) { float kills = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.kills_" + mob), 0); String type; @@ -242,38 +293,4 @@ public class BestiaryPage { } return beLevel; } - - public static int getBeTiersFromPage(JsonObject profileInfo) { - int beLevel = 0; - List<String> mobs = BestiaryData.getBestiaryLocations().get(selectedBestiaryLocation); - if (mobs != null) { - for (int i = 0; i < mobs.size(); i++) { - - String mob = mobs.get(i); - if (mob != null) { - float kills = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.kills_" + mob), 0); - String type; - if (BestiaryData.getMobType().get(mob) != null) { - type = BestiaryData.getMobType().get(mob); - } else { - type = "MOB"; - } - JsonObject leveling = Constants.LEVELING; - ProfileViewer.Level level = null; - if (leveling != null) { - JsonArray levelingArray = Utils.getElement(leveling, "bestiary." + type).getAsJsonArray(); - int levelCap = Utils.getElementAsInt(Utils.getElement(leveling, "bestiary.caps." + type), 0); - level = ProfileViewer.getLevel(levelingArray, kills, levelCap, false); - } - - float levelNum = 0; - if (level != null) { - levelNum = level.level; - } - beLevel += (int) Math.floor(levelNum); - } - } - } - return beLevel; - } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/info/QuiverInfo.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/info/QuiverInfo.java new file mode 100644 index 00000000..b4d92325 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/info/QuiverInfo.java @@ -0,0 +1,62 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.profileviewer.info; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import net.minecraft.util.EnumChatFormatting; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class QuiverInfo { + public String selectedArrow; + public Map<String, Integer> arrows; + + public List<String> generateProfileViewerTooltip() { + List<String> list = new ArrayList<>(); + int totalCount = 0; + list.add(EnumChatFormatting.AQUA + "Quiver:"); + for (Map.Entry<String, Integer> arrow : arrows.entrySet()) { + JsonObject repoInfo = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(arrow.getKey()); + if (repoInfo == null || repoInfo.isJsonNull()) { + continue; + } + list.add( + " " + repoInfo.get("displayname").getAsString() + EnumChatFormatting.RESET + ": " + EnumChatFormatting.GREEN + + EnumChatFormatting.BOLD + arrow.getValue()); + totalCount += arrow.getValue(); + } + + list.add(""); + list.add(EnumChatFormatting.AQUA + "Total: " + EnumChatFormatting.GREEN + EnumChatFormatting.BOLD + totalCount); + if (selectedArrow != null) { + JsonObject repoInfo = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(selectedArrow); + if (repoInfo == null) { + list.add(EnumChatFormatting.AQUA + "Selected Arrow: " + EnumChatFormatting.RED + "ERROR"); + } else { + list.add(EnumChatFormatting.AQUA + "Selected Arrow: " + repoInfo.get("displayname").getAsString()); + } + } + + return list; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFish.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFish.java index 9951511d..5a3027c3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFish.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFish.java @@ -23,19 +23,17 @@ import java.util.Map; public class TrophyFish { + public final Map<TrophyFishRarity, Integer> trophyFishRarityIntegerMap; private final String name; - private int total = 0; - public final Map<TrophyFishRarity, Integer> trophyFishRarityIntegerMap; - public TrophyFish(String name, Map<TrophyFishRarity, Integer> trophyFishRarityIntegerMap) { this.name = name; this.trophyFishRarityIntegerMap = trophyFishRarityIntegerMap; } public void addTotal(int n) { - total +=n; + total += n; } public int getTotal() { @@ -43,7 +41,7 @@ public class TrophyFish { } public void removeTotal(int n) { - total -=n; + total -= n; } public String getName() { @@ -55,20 +53,19 @@ public class TrophyFish { } public void add(TrophyFishRarity rarity, int value) { - if(!trophyFishRarityIntegerMap.containsKey(rarity)) { + if (!trophyFishRarityIntegerMap.containsKey(rarity)) { trophyFishRarityIntegerMap.put(rarity, value); } } + public String getInternalName() { + return name.toLowerCase().replace(" ", "_"); + } + public enum TrophyFishRarity { BRONZE, SILVER, GOLD, - DIAMOND; - } - - public String getInternalName() { - return name.toLowerCase().replace(" ", "_"); + DIAMOND, } } - diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFishingPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFishPage.java index 3b595588..2481b841 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFishingPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFishPage.java @@ -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.profileviewer.GuiProfileViewer; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewerPage; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; @@ -43,9 +44,10 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -public class TrophyFishingPage { +public class TrophyFishPage extends GuiProfileViewerPage { - public static Map<String, EnumChatFormatting> internalTrophyFish = new HashMap<String, EnumChatFormatting>() { + public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png"); + private static final Map<String, EnumChatFormatting> internalTrophyFish = new HashMap<String, EnumChatFormatting>() { { put("gusher", EnumChatFormatting.WHITE); put("flyfish", EnumChatFormatting.GREEN); @@ -67,26 +69,35 @@ public class TrophyFishingPage { put("steaming_hot_flounder", EnumChatFormatting.WHITE); } }; - - private static LinkedHashMap<ItemStack, Pair<String, Integer>> armorHelmets = - new LinkedHashMap<ItemStack, Pair<String, Integer>>() { - { - put(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("BRONZE_HUNTER_HELMET")), Pair.of(EnumChatFormatting.GREEN + "Novice Fisher", 1)); - put(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("SILVER_HUNTER_HELMET")), Pair.of(EnumChatFormatting.BLUE + "Adept Fisher", 2)); - put(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("GOLD_HUNTER_HELMET")), Pair.of(EnumChatFormatting.DARK_PURPLE + "Expert Fisher", 3)); - put(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("DIAMOND_HUNTER_HELMET")), Pair.of(EnumChatFormatting.GOLD + "Master Fisher", 4)); - } - }; - - private static Map<Integer, Pair<Integer, Integer>> slotLocations = new HashMap<Integer, Pair<Integer, Integer>>() { + private static final LinkedHashMap<ItemStack, Pair<String, Integer>> armorHelmets = new LinkedHashMap<ItemStack, Pair<String, Integer>>() { + { + put( + NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("BRONZE_HUNTER_HELMET") + ), + Pair.of(EnumChatFormatting.GREEN + "Novice Fisher", 1) + ); + put( + NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("SILVER_HUNTER_HELMET") + ), + Pair.of(EnumChatFormatting.BLUE + "Adept Fisher", 2) + ); + put( + NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("GOLD_HUNTER_HELMET") + ), + Pair.of(EnumChatFormatting.DARK_PURPLE + "Expert Fisher", 3) + ); + put( + NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("DIAMOND_HUNTER_HELMET") + ), + Pair.of(EnumChatFormatting.GOLD + "Master Fisher", 4) + ); + } + }; + private static final Map<Integer, Pair<Integer, Integer>> slotLocations = new HashMap<Integer, Pair<Integer, Integer>>() { { put(0, Pair.of(277, 46)); put(1, Pair.of(253, 58)); @@ -108,26 +119,28 @@ public class TrophyFishingPage { put(17, Pair.of(277, 142)); } }; - private static long totalCount = 0; - private static int guiLeft; - private static int guiTop; - - private static final ResourceLocation TROPHY_FISH_TEXTURE = new ResourceLocation( - "notenoughupdates:pv_trophy_fish_tab.png"); - public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png"); - private static final Map<String, TrophyFish> trophyFishList = new HashMap<>(); + private static final ResourceLocation TROPHY_FISH_TEXTURE = new ResourceLocation("notenoughupdates:pv_trophy_fish_tab.png"); + private static final String checkX = "§c✖"; + private static final String check = "§a✔"; + private final Map<String, Integer> total = new HashMap<>(); + private final Map<String, TrophyFish> trophyFishList = new HashMap<>(); + private long totalCount = 0; - private static final Map<String, Integer> total = new HashMap<>(); + public TrophyFishPage(GuiProfileViewer instance) { + super(instance); + } - public static void renderPage(int mouseX, int mouseY) { - guiLeft = GuiProfileViewer.getGuiLeft(); - guiTop = GuiProfileViewer.getGuiTop(); + @Override + public void drawPage(int mouseX, int mouseY, float partialTicks) { + int guiLeft = GuiProfileViewer.getGuiLeft(); + int guiTop = GuiProfileViewer.getGuiTop(); trophyFishList.clear(); JsonObject profileInformation = GuiProfileViewer.getProfile().getProfileInformation(GuiProfileViewer.getProfileId()); if (profileInformation == null || !profileInformation.has("trophy_fish")) { - Utils.drawStringCentered(EnumChatFormatting.RED + "No data found", + Utils.drawStringCentered( + EnumChatFormatting.RED + "No data found", Minecraft.getMinecraft().fontRendererObj, guiLeft + 431 / 2f, guiTop + 101, @@ -138,7 +151,7 @@ public class TrophyFishingPage { } JsonObject trophyObject = profileInformation.get("trophy_fish").getAsJsonObject(); - loadTrophyInformation(trophyObject); + loadTrophyInformation(trophyObject); ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); int width = scaledResolution.getScaledWidth(); @@ -157,9 +170,9 @@ public class TrophyFishingPage { if (stats.has("kills_thunder")) { thunderKills = stats.getAsJsonObject().get("kills_thunder").getAsInt(); } - ItemStack thunder_sc = NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("THUNDER_SC")); + ItemStack thunder_sc = NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("THUNDER_SC") + ); Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(thunder_sc, guiLeft + 16, guiTop + 108); Utils.drawStringF( @@ -171,9 +184,9 @@ public class TrophyFishingPage { 0 ); - ItemStack lord_jawbus_sc = NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("LORD_JAWBUS_SC")); + ItemStack lord_jawbus_sc = NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("LORD_JAWBUS_SC") + ); Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(lord_jawbus_sc, guiLeft + 16, guiTop + 120); int jawbusKills = 0; if (stats.has("kills_lord_jawbus")) { @@ -189,9 +202,9 @@ public class TrophyFishingPage { 0 ); - ItemStack fishing_rod = NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager - .getItemInformation() - .get("FISHING_ROD")); + ItemStack fishing_rod = NotEnoughUpdates.INSTANCE.manager.jsonToStack( + NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("FISHING_ROD") + ); Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(fishing_rod, guiLeft + 20, guiTop + 21); Utils.drawStringF( @@ -215,24 +228,20 @@ public class TrophyFishingPage { Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); Map<TrophyFish.TrophyFishRarity, Integer> trophyFishRarityIntegerMap = value.getTrophyFishRarityIntegerMap(); if (trophyFishRarityIntegerMap.containsKey(TrophyFish.TrophyFishRarity.BRONZE)) { - GlStateManager.color(255/255f, 130/255f, 0/255f, 1); + GlStateManager.color(255 / 255f, 130 / 255f, 0 / 255f, 1); } if (trophyFishRarityIntegerMap.containsKey(TrophyFish.TrophyFishRarity.SILVER)) { - GlStateManager.color(192/255f, 192/255f, 192/255f, 1); + GlStateManager.color(192 / 255f, 192 / 255f, 192 / 255f, 1); } if (trophyFishRarityIntegerMap.containsKey(TrophyFish.TrophyFishRarity.GOLD)) { GlStateManager.color(1, 0.82F, 0, 1); } if (trophyFishRarityIntegerMap.containsKey(TrophyFish.TrophyFishRarity.DIAMOND)) { - GlStateManager.color(31/255f, 216/255f, 241/255f, 1); + GlStateManager.color(31 / 255f, 216 / 255f, 241 / 255f, 1); } - Utils.drawTexturedRect(x - 2 , y - 2, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST); + Utils.drawTexturedRect(x - 2, y - 2, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST); GlStateManager.color(1, 1, 1, 1); - Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI( - getItem(value.getName()), - x, - y - ); + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(getItem(value.getName()), x, y); if (mouseX >= x && mouseX < x + 24) { if (mouseY >= y && mouseY <= y + 24) { @@ -258,11 +267,7 @@ public class TrophyFishingPage { x = guiLeft + slotLocations.get(clonedList.indexOf(difference) + (trophyFishList.keySet().size())).getLeft(); y = guiTop + slotLocations.get(clonedList.indexOf(difference) + (trophyFishList.keySet().size())).getRight(); ItemStack itemStack = new ItemStack(Items.dye, 1, 8); - Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI( - itemStack, - x, - y - ); + Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, x, y); if (mouseX >= x && mouseX < x + 24) { if (mouseY >= y && mouseY <= y + 24) { Utils.drawHoveringText( @@ -278,7 +283,7 @@ public class TrophyFishingPage { } } Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements); - Utils.drawTexturedRect(x - 2 , y - 2, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST); + Utils.drawTexturedRect(x - 2, y - 2, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST); } } @@ -294,9 +299,7 @@ public class TrophyFishingPage { y = guiTop + 50 + i; Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, x, y); - Utils.drawStringF(armorHelmets.get(itemStack).getLeft(), Minecraft.getMinecraft().fontRendererObj, - x + 20, y + 4, true, 0 - ); + Utils.drawStringF(armorHelmets.get(itemStack).getLeft(), Minecraft.getMinecraft().fontRendererObj, x + 20, y + 4, true, 0); int hasValue = trophiesPerTier[integer - 1]; int neededValue = integer == 1 ? 15 : 18; @@ -305,18 +308,12 @@ public class TrophyFishingPage { try { JsonElement jsonElement = rewards.get(integer - 1); if (!jsonElement.isJsonNull()) { - Utils.drawStringF(check, Minecraft.getMinecraft().fontRendererObj, - x + 100, y + 2, true, 0 - ); + Utils.drawStringF(check, Minecraft.getMinecraft().fontRendererObj, x + 100, y + 2, true, 0); } else { - Utils.drawStringF(neededText, Minecraft.getMinecraft().fontRendererObj, - x + 100, y + 4, true, 0 - ); + Utils.drawStringF(neededText, Minecraft.getMinecraft().fontRendererObj, x + 100, y + 4, true, 0); } } catch (IndexOutOfBoundsException exception) { - Utils.drawStringF(neededText, Minecraft.getMinecraft().fontRendererObj, - x + 100, y + 4, true, 0 - ); + Utils.drawStringF(neededText, Minecraft.getMinecraft().fontRendererObj, x + 100, y + 4, true, 0); } i += 10; } @@ -324,8 +321,8 @@ public class TrophyFishingPage { GlStateManager.enableLighting(); } - private static int[] getTrophiesPerTier(JsonObject trophyFish) { - int[] trophiesPerTier = new int[] {0, 0, 0, 0}; + private int[] getTrophiesPerTier(JsonObject trophyFish) { + int[] trophiesPerTier = new int[] { 0, 0, 0, 0 }; for (String fishType : internalTrophyFish.keySet()) { int highestTier = 0; if (trophyFish.has((fishType + "_bronze"))) highestTier = 1; @@ -341,13 +338,9 @@ public class TrophyFishingPage { return trophiesPerTier; } - private static List<String> getTooltip( - String name, - Map<TrophyFish.TrophyFishRarity, Integer> trophyFishRarityIntegerMap - ) { + private List<String> getTooltip(String name, Map<TrophyFish.TrophyFishRarity, Integer> trophyFishRarityIntegerMap) { List<String> tooltip = new ArrayList<>(); - tooltip.add( - internalTrophyFish.get(name.toLowerCase().replace(" ", "_")) + WordUtils.capitalize(name.replace("_", " "))); + tooltip.add(internalTrophyFish.get(name.toLowerCase().replace(" ", "_")) + WordUtils.capitalize(name.replace("_", " "))); List<String> lore = readLoreFromRepo(name.toUpperCase()); List<String> description = readDescriptionFromLore(lore); @@ -362,17 +355,14 @@ public class TrophyFishingPage { tooltip.add(display(trophyFishRarityIntegerMap, TrophyFish.TrophyFishRarity.DIAMOND, EnumChatFormatting.AQUA)); tooltip.add(display(trophyFishRarityIntegerMap, TrophyFish.TrophyFishRarity.GOLD, EnumChatFormatting.GOLD)); tooltip.add(display(trophyFishRarityIntegerMap, TrophyFish.TrophyFishRarity.SILVER, EnumChatFormatting.GRAY)); - tooltip.add(display(trophyFishRarityIntegerMap, TrophyFish.TrophyFishRarity.BRONZE, EnumChatFormatting.DARK_GRAY - )); + tooltip.add(display(trophyFishRarityIntegerMap, TrophyFish.TrophyFishRarity.BRONZE, EnumChatFormatting.DARK_GRAY)); return tooltip; } - private static final String checkX = "§c✖"; - private static final String check = "§a✔"; - - private static String display( + private String display( Map<TrophyFish.TrophyFishRarity, Integer> trophyFishRarityIntegerMap, - TrophyFish.TrophyFishRarity rarity, EnumChatFormatting color + TrophyFish.TrophyFishRarity rarity, + EnumChatFormatting color ) { String name = WordUtils.capitalize(rarity.name().toLowerCase()); if (trophyFishRarityIntegerMap == null) { @@ -380,20 +370,19 @@ public class TrophyFishingPage { } if (trophyFishRarityIntegerMap.containsKey(rarity)) { - return color + name + ": " + EnumChatFormatting.GOLD + - trophyFishRarityIntegerMap.get(rarity); + return color + name + ": " + EnumChatFormatting.GOLD + trophyFishRarityIntegerMap.get(rarity); } else { return color + name + ": " + checkX; } } - private static ItemStack getItem(String name) { + private ItemStack getItem(String name) { String repoName = name.toUpperCase().replace(" ", "_") + "_BRONZE"; JsonObject jsonItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(repoName); return NotEnoughUpdates.INSTANCE.manager.jsonToStack(jsonItem); } - private static void loadTrophyInformation(JsonObject trophyObject) { + private void loadTrophyInformation(JsonObject trophyObject) { Map<String, List<Pair<TrophyFish.TrophyFishRarity, Integer>>> trophyFishRarityIntegerMap = new HashMap<>(); totalCount = 0; for (Map.Entry<String, JsonElement> stringJsonElementEntry : trophyObject.entrySet()) { @@ -434,11 +423,10 @@ public class TrophyFishingPage { } trophyFishRarityIntegerMap.forEach((name, pair) -> { - if (!TrophyFishingPage.trophyFishList.containsKey(name)) { + if (!trophyFishList.containsKey(name)) { TrophyFish trophyFish = new TrophyFish(name, new HashMap<>()); - trophyFish.addTotal(TrophyFishingPage.total.get(name)); + trophyFish.addTotal(total.get(name)); for (Pair<TrophyFish.TrophyFishRarity, Integer> pair1 : pair) { - trophyFish.add(pair1.getKey(), pair1.getValue()); } trophyFishList.put(name, trophyFish); @@ -451,7 +439,7 @@ public class TrophyFishingPage { }); } - private static List<String> fixStringName(List<String> list) { + private List<String> fixStringName(List<String> list) { List<String> fixedList = new ArrayList<>(); for (String s : list) { fixedList.add(s.toLowerCase().replace(" ", "_")); @@ -459,7 +447,7 @@ public class TrophyFishingPage { return fixedList; } - private static List<String> readDescriptionFromLore(List<String> lore) { + private List<String> readDescriptionFromLore(List<String> lore) { List<String> description = new ArrayList<>(); boolean found = false; @@ -475,7 +463,7 @@ public class TrophyFishingPage { return description; } - private static List<String> readLoreFromRepo(String name) { + private List<String> readLoreFromRepo(String name) { String repoName = name.toUpperCase().replace(" ", "_") + "_BRONZE"; JsonObject jsonItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(repoName); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java index 31748535..819c16de 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java @@ -21,38 +21,42 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.lily; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.DungeonsWeight; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; + import java.util.Map; public class LilyDungeonsWeight extends DungeonsWeight { private final JsonObject profileJson; - public LilyDungeonsWeight(JsonObject player, JsonObject profileJson) { + public LilyDungeonsWeight(Map<String, ProfileViewer.Level> player, JsonObject profileJson) { super(player); this.profileJson = profileJson; } @Override public void getDungeonWeight() { - double level = Utils.getElementAsFloat(Utils.getElement(player, "level_skill_catacombs"), 0); - float cataXP = Utils.getElementAsFloat(Utils.getElement(player, "experience_skill_catacombs"), 0); + ProfileViewer.Level catacombs = player.get("catacombs"); double extra = 0; double n = 0; - if (cataXP < 569809640) { - n = 0.2 * Math.pow(level / 50, 1.538679118869934); + if (catacombs.totalXp < CATACOMBS_LEVEL_50_XP) { + n = 0.2 * Math.pow(catacombs.level / 50, 1.538679118869934); } else { - extra = 500.0 * Math.pow((cataXP - CATACOMBS_LEVEL_50_XP) / 142452410.0, 1.0 / 1.781925776625157); + extra = 500.0 * Math.pow((catacombs.totalXp - CATACOMBS_LEVEL_50_XP) / 142452410.0, 1.0 / 1.781925776625157); } - if (level != 0) { - if (cataXP < 569809640) { + if (catacombs.level != 0) { + if (catacombs.totalXp < CATACOMBS_LEVEL_50_XP) { weightStruct.add( - new WeightStruct(1.2733079672009226 * ((Math.pow(1.18340401286164044, (level + 1)) - 1.05994990217254) * (1 + n))) + new WeightStruct( + Utils.getElement(Constants.WEIGHT, "lily.dungeons.overall").getAsDouble() * + ((Math.pow(1.18340401286164044, (catacombs.level + 1)) - 1.05994990217254) * (1 + n)) + ) ); } else { weightStruct.add(new WeightStruct((4100 + extra) * 2)); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java index bbe07a5a..f47032a4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java @@ -19,19 +19,20 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.lily; -import static io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight.SKILL_NAMES; - import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SkillsWeight; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; +import java.util.Map; + +import static io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight.SKILL_NAMES; + public class LilySkillsWeight extends SkillsWeight { - public LilySkillsWeight(JsonObject player) { + public LilySkillsWeight(Map<String, ProfileViewer.Level> player) { super(player); } @@ -42,7 +43,7 @@ public class LilySkillsWeight extends SkillsWeight { skillAverage += (int) ProfileViewer.getLevel( Utils.getElement(Constants.LEVELING, "leveling_xp").getAsJsonArray(), - Utils.getElementAsInt(Utils.getElement(player, "experience_skill_" + skill), 0), + player.get(skill).totalXp, 60, false ) @@ -50,7 +51,7 @@ public class LilySkillsWeight extends SkillsWeight { } skillAverage /= SKILL_NAMES.size(); - float currentExp = Utils.getElementAsFloat(Utils.getElement(player, "experience_skill_" + skillName), 0); + float currentExp = player.get(skillName).totalXp; int currentLevel = (int) ProfileViewer.getLevel( Utils.getElement(Constants.LEVELING, "leveling_xp").getAsJsonArray(), currentExp, @@ -67,16 +68,16 @@ public class LilySkillsWeight extends SkillsWeight { srwTable.get(srwTable.size() - 1).getAsDouble() ) + (srwTable.get(srwTable.size() - 1).getAsDouble() * Math.pow(currentLevel / 60.0, Math.pow(2, 0.5))); - base *= 1.8162162162162162; + base *= Utils.getElement(Constants.WEIGHT, "lily.skills.overall").getAsDouble(); double overflow = 0; - if (currentExp > 111672425) { + if (currentExp > SKILLS_LEVEL_60) { double factor = Utils.getElementAsFloat(Utils.getElement(Constants.WEIGHT, "lily.skills.factors." + skillName), 0); - double effectiveOver = effectiveXP(currentExp - 111672425, factor); + double effectiveOver = effectiveXP(currentExp - SKILLS_LEVEL_60, factor); double t = - (effectiveOver / 111672425) * + (effectiveOver / SKILLS_LEVEL_60) * Utils.getElementAsFloat(Utils.getElement(Constants.WEIGHT, "lily.skills.overflow_multipliers." + skillName), 0); if (t > 0) { - overflow += 1.8162162162162162 * t; + overflow += Utils.getElement(Constants.WEIGHT, "lily.skills.overall").getAsDouble() * t; } } @@ -84,18 +85,6 @@ public class LilySkillsWeight extends SkillsWeight { } private double effectiveXP(double xp, double factor) { - if (xp < 111672425) { - return xp; - } else { - double remainingXP = xp; - double z = 0; - for (int i = 0; i <= (int) (xp / 111672425); i++) { - if (remainingXP >= 111672425) { - remainingXP -= 111672425; - z += Math.pow(factor, i); - } - } - return z * 111672425; - } + return Math.pow(xp, factor); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java index 5c55633a..12cb01e2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java @@ -19,20 +19,22 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.lily; -import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SlayerWeight; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; +import java.util.Map; + public class LilySlayerWeight extends SlayerWeight { - public LilySlayerWeight(JsonObject player) { + public LilySlayerWeight(Map<String, ProfileViewer.Level> player) { super(player); } public void getSlayerWeight(String slayerName) { - int currentSlayerXp = Utils.getElementAsInt(Utils.getElement(player, "experience_slayer_" + slayerName), 0); + int currentSlayerXp = (int) player.get(slayerName).totalXp; double score; double d = currentSlayerXp / 100000.0; @@ -56,7 +58,7 @@ public class LilySlayerWeight extends SlayerWeight { double weight; switch (slayerName) { case "zombie": - weight = (effectiveScore / 8390.64) + (currentSlayerXp / 1000000.0); + weight = (effectiveScore / 9250) + (currentSlayerXp / 1000000.0); break; case "spider": weight = (effectiveScore / 7019.57) + ((currentSlayerXp * 1.6) / 1000000); @@ -65,10 +67,10 @@ public class LilySlayerWeight extends SlayerWeight { weight = (effectiveScore / 2982.06) + ((currentSlayerXp * 3.6) / 1000000); break; case "enderman": - weight = (effectiveScore / 1118.81) + ((currentSlayerXp * 10.0) / 1000000); + weight = (effectiveScore / 996.3003) + ((currentSlayerXp * 10.0) / 1000000); break; case "blaze": - weight = (effectiveScore / 751.281) + ((currentSlayerXp * 15.0) / 1000000); + weight = (effectiveScore / 935.0455) + ((currentSlayerXp * 10.0) / 1000000); break; default: return; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java index 9a851f12..03c5cfbf 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java @@ -20,11 +20,14 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.lily; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight; +import java.util.Map; + public class LilyWeight extends Weight { - public LilyWeight(JsonObject player, JsonObject profileJson) { + public LilyWeight(Map<String, ProfileViewer.Level> player, JsonObject profileJson) { super(new LilySlayerWeight(player), new LilySkillsWeight(player), new LilyDungeonsWeight(player, profileJson)); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java index 198d34c8..e41b0ff4 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java @@ -19,61 +19,48 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.senither; -import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.DungeonsWeight; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; +import java.util.Map; + public class SenitherDungeonsWeight extends DungeonsWeight { - public SenitherDungeonsWeight(JsonObject player) { + public SenitherDungeonsWeight(Map<String, ProfileViewer.Level> player) { super(player); } public void getClassWeight(String className) { - float currentClassXp = Utils.getElementAsFloat(Utils.getElement(player, "experience_skill_" + className), 0); - double currentClassLevel = ProfileViewer.getLevel( - Utils.getElement(Constants.LEVELING, "catacombs").getAsJsonArray(), - currentClassXp, - Utils.getElementAsInt(Utils.getElement(Constants.LEVELING, "leveling_caps.catacombs"), 50), - false - ) - .level; + ProfileViewer.Level currentClass = player.get(className); double base = - Math.pow(currentClassLevel, 4.5) * + Math.pow(currentClass.level, 4.5) * Utils.getElementAsFloat(Utils.getElement(Constants.WEIGHT, "senither.dungeons.classes." + className), 0); - if (currentClassXp <= CATACOMBS_LEVEL_50_XP) { + if (currentClass.totalXp <= CATACOMBS_LEVEL_50_XP) { weightStruct.add(new WeightStruct(base)); return; } - double remaining = currentClassXp - CATACOMBS_LEVEL_50_XP; + double remaining = currentClass.totalXp - CATACOMBS_LEVEL_50_XP; double splitter = (4 * CATACOMBS_LEVEL_50_XP) / base; weightStruct.add(new WeightStruct(Math.floor(base), Math.pow(remaining / splitter, 0.968))); } @Override public void getDungeonWeight() { - float catacombsSkillXp = Utils.getElementAsFloat(Utils.getElement(player, "experience_skill_catacombs"), 0); - - double level = ProfileViewer.getLevel( - Utils.getElement(Constants.LEVELING, "catacombs").getAsJsonArray(), - catacombsSkillXp, - Utils.getElementAsInt(Utils.getElement(Constants.LEVELING, "leveling_caps.catacombs"), 50), - false - ) - .level; - double base = Math.pow(level, 4.5) * Utils.getElementAsFloat(Utils.getElement(Constants.WEIGHT, "senither.dungeons.catacombs"), 0); + ProfileViewer.Level catacombs = player.get("catacombs"); + double base = + Math.pow(catacombs.level, 4.5) * Utils.getElementAsFloat(Utils.getElement(Constants.WEIGHT, "senither.dungeons.catacombs"), 0); - if (catacombsSkillXp <= CATACOMBS_LEVEL_50_XP) { + if (catacombs.totalXp <= CATACOMBS_LEVEL_50_XP) { weightStruct.add(new WeightStruct(base)); return; } - double remaining = catacombsSkillXp - CATACOMBS_LEVEL_50_XP; + double remaining = catacombs.totalXp - CATACOMBS_LEVEL_50_XP; double splitter = (4 * CATACOMBS_LEVEL_50_XP) / base; weightStruct.add(new WeightStruct(Math.floor(base), Math.pow(remaining / splitter, 0.968))); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java index 081cab6d..7ac717f7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java @@ -20,16 +20,17 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.senither; import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SkillsWeight; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; +import java.util.Map; + public class SenitherSkillsWeight extends SkillsWeight { - public SenitherSkillsWeight(JsonObject player) { + public SenitherSkillsWeight(Map<String, ProfileViewer.Level> player) { super(player); } @@ -39,7 +40,7 @@ public class SenitherSkillsWeight extends SkillsWeight { double exponent = curWeights.get(0).getAsDouble(); double divider = curWeights.get(1).getAsDouble(); - float currentSkillXp = Utils.getElementAsFloat(Utils.getElement(player, "experience_skill_" + skillName), 0); + float currentSkillXp = player.get(skillName).totalXp; if (currentSkillXp > 0) { int maxLevel = skillName.equals("farming") @@ -53,7 +54,7 @@ public class SenitherSkillsWeight extends SkillsWeight { ) .level; - double maxLevelExp = maxLevel == 50 ? 55172425 : 111672425; + double maxLevelExp = maxLevel == 50 ? SKILLS_LEVEL_50 : SKILLS_LEVEL_60; double base = Math.pow(level * 10, 0.5 + exponent + (level / 100)) / 1250; if (currentSkillXp <= maxLevelExp) { weightStruct.add(new WeightStruct(base)); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java index 3b7b2498..e9fd5b41 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java @@ -20,15 +20,17 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.senither; import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SlayerWeight; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.Utils; +import java.util.Map; + public class SenitherSlayerWeight extends SlayerWeight { - public SenitherSlayerWeight(JsonObject player) { + public SenitherSlayerWeight(Map<String, ProfileViewer.Level> player) { super(player); } @@ -41,7 +43,7 @@ public class SenitherSlayerWeight extends SlayerWeight { double divider = curWeights.get(0).getAsDouble(); double modifier = curWeights.get(1).getAsDouble(); - int currentSlayerXp = Utils.getElementAsInt(Utils.getElement(player, "experience_slayer_" + slayerName), 0); + int currentSlayerXp = (int) player.get(slayerName).totalXp; if (currentSlayerXp <= 1000000) { weightStruct.add(new WeightStruct(currentSlayerXp == 0 ? 0 : currentSlayerXp / divider)); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java index e0a2cf36..532db942 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java @@ -19,12 +19,14 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.senither; -import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight; +import java.util.Map; + public class SenitherWeight extends Weight { - public SenitherWeight(JsonObject player) { + public SenitherWeight(Map<String, ProfileViewer.Level> player) { super(new SenitherSlayerWeight(player), new SenitherSkillsWeight(player), new SenitherDungeonsWeight(player)); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java index bab0346c..661c3c9f 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java @@ -19,16 +19,18 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.weight; -import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; + +import java.util.Map; public abstract class DungeonsWeight { protected static final long CATACOMBS_LEVEL_50_XP = 569809640; - protected final JsonObject player; + protected final Map<String, ProfileViewer.Level> player; protected final WeightStruct weightStruct; - public DungeonsWeight(JsonObject player) { + public DungeonsWeight(Map<String, ProfileViewer.Level> player) { this.player = player; this.weightStruct = new WeightStruct(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java index b5e4e2b5..b7fe27ac 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java @@ -19,14 +19,18 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.weight; -import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; + +import java.util.Map; public abstract class SkillsWeight { - protected final JsonObject player; + protected static final long SKILLS_LEVEL_50 = 55172425; + protected static final long SKILLS_LEVEL_60 = 111672425; + protected final Map<String, ProfileViewer.Level> player; protected final WeightStruct weightStruct; - public SkillsWeight(JsonObject player) { + public SkillsWeight(Map<String, ProfileViewer.Level> player) { this.player = player; this.weightStruct = new WeightStruct(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java index 1ec83689..bab8a154 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java @@ -19,14 +19,16 @@ package io.github.moulberry.notenoughupdates.profileviewer.weight.weight; -import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; + +import java.util.Map; public abstract class SlayerWeight { - protected final JsonObject player; + protected final Map<String, ProfileViewer.Level> player; protected final WeightStruct weightStruct; - public SlayerWeight(JsonObject player) { + public SlayerWeight(Map<String, ProfileViewer.Level> player) { this.player = player; this.weightStruct = new WeightStruct(); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/Weight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/Weight.java index f3e0cef3..129f53fc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/Weight.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/Weight.java @@ -24,8 +24,6 @@ import java.util.List; public abstract class Weight { - protected static final List<String> SLAYER_NAMES = Arrays.asList("wolf", "zombie", "spider", "enderman", "blaze"); - protected static final List<String> DUNGEON_CLASS_NAMES = Arrays.asList("healer", "mage", "berserk", "archer", "tank"); public static final List<String> SKILL_NAMES = Arrays.asList( "taming", "mining", @@ -36,6 +34,8 @@ public abstract class Weight { "fishing", "alchemy" ); + protected static final List<String> SLAYER_NAMES = Arrays.asList("wolf", "zombie", "spider", "enderman", "blaze"); + protected static final List<String> DUNGEON_CLASS_NAMES = Arrays.asList("healer", "mage", "berserk", "archer", "tank"); protected final SlayerWeight slayerWeight; protected final SkillsWeight skillsWeight; protected final DungeonsWeight dungeonsWeight; @@ -48,7 +48,10 @@ public abstract class Weight { } public WeightStruct getTotalWeight() { - return new WeightStruct().add(slayerWeight.getWeightStruct()).add(skillsWeight.getWeightStruct()).add(dungeonsWeight.getWeightStruct()); + return new WeightStruct() + .add(slayerWeight.getWeightStruct()) + .add(skillsWeight.getWeightStruct()) + .add(dungeonsWeight.getWeightStruct()); } public SlayerWeight getSlayerWeight() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java index 0d891071..61749593 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java @@ -26,6 +26,7 @@ import com.google.gson.JsonPrimitive; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.miscfeatures.entityviewer.EntityViewer; import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.Panorama; import io.github.moulberry.notenoughupdates.util.ItemUtils; import io.github.moulberry.notenoughupdates.util.JsonUtils; @@ -64,11 +65,32 @@ public class MobLootRecipe implements NeuRecipe { if (itemStack == null) { itemStack = drop.getItemStack().copy(); List<String> arrayList = new ArrayList<>(extra); - arrayList.add("§r§e§lDrop Chance: §6" + chance); + arrayList.add("§r§e§lDrop Chance: §6" + formatDropChance()); ItemUtils.appendLore(itemStack, arrayList); } return itemStack; } + + private String formatDropChance() { + if (chance == null) { + return ""; + } + + if (!chance.endsWith("%")) { + return chance; + } + + String chanceText = chance.substring(0, chance.length() - 1); + int chanceIn; + try { + chanceIn = (int) (100.0 / Double.parseDouble(chanceText)); + } catch (NumberFormatException e) { + return chance; + } + + String format = GuiProfileViewer.numberFormat.format(chanceIn); + return "1/" + format + " (" + chance + ")"; + } } public static ResourceLocation BACKGROUND = new ResourceLocation( diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoader.java new file mode 100644 index 00000000..37b0a187 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoader.java @@ -0,0 +1,55 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util; + +import com.google.common.base.Objects; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; + +public interface AsyncDependencyLoader<T> { + + Optional<T> peekValue(); + + public static <R, T> AsyncDependencyLoader<T> withObjectIdentity( + Supplier<R> supplier, + Function<R, CompletableFuture<T>> generator + ) { + return new AsyncDependencyLoaderImpl<>(supplier, generator, (a, b) -> a != b); + } + + public static <R, T> AsyncDependencyLoader<T> withEqualsInvocation( + Supplier<R> supplier, + Function<R, CompletableFuture<T>> generator + ) { + return new AsyncDependencyLoaderImpl<>(supplier, generator, (a, b) -> !Objects.equal(a, b)); + } + + public static <R, T> AsyncDependencyLoader<T> withEqualityFunction( + Supplier<R> supplier, + Function<R, CompletableFuture<T>> generator, + BiFunction<R, R, Boolean> isEqual + ) { + return new AsyncDependencyLoaderImpl<>(supplier, generator, (a, b) -> !isEqual.apply(a, b)); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoaderImpl.java b/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoaderImpl.java new file mode 100644 index 00000000..4b7f2fb8 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoaderImpl.java @@ -0,0 +1,59 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; + +class AsyncDependencyLoaderImpl<R, T> implements AsyncDependencyLoader<T> { + + private final Supplier<R> supplyDependency; + private final Function<R, CompletableFuture<T>> generator; + private final BiFunction<R, R, Boolean> isDifferent; + private volatile CompletableFuture<T> lastValue; + private volatile R lastDependency; + private volatile boolean isFirstFire = true; + + @Override + public synchronized Optional<T> peekValue() { + R nextDependency = supplyDependency.get(); + if (isFirstFire || isDifferent.apply(nextDependency, lastDependency)) { + isFirstFire = false; + if (lastValue != null) + lastValue.cancel(true); + lastValue = generator.apply(nextDependency); + } + lastDependency = nextDependency; + return Optional.ofNullable(lastValue.getNow(null)); + } + + AsyncDependencyLoaderImpl( + Supplier<R> supplyDependency, + Function<R, CompletableFuture<T>> generator, + BiFunction<R, R, Boolean> isDifferent + ) { + this.supplyDependency = supplyDependency; + this.generator = generator; + this.isDifferent = isDifferent; + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java b/src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java new file mode 100644 index 00000000..bf973b76 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java @@ -0,0 +1,37 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util; + +import net.minecraft.client.Minecraft; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.Executor; + +public class MinecraftExecutor implements Executor { + + public static MinecraftExecutor INSTANCE = new MinecraftExecutor(); + + private MinecraftExecutor() {} + + @Override + public void execute(@NotNull Runnable runnable) { + Minecraft.getMinecraft().addScheduledTask(runnable); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NetUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NetUtils.java new file mode 100644 index 00000000..b09dd839 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NetUtils.java @@ -0,0 +1,51 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util; + +import org.apache.commons.io.IOUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.nio.file.Files; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; + +public class NetUtils { + + public static CompletableFuture<File> downloadAsync(URL httpURL, File outputFile) { + return CompletableFuture.supplyAsync(() -> { + try { + try ( + InputStream from = httpURL.openStream(); + OutputStream to = Files.newOutputStream(outputFile.toPath()); + ) { + IOUtils.copyLarge(from, to); + } + return outputFile; + } catch (IOException e) { + throw new CompletionException(e); + } + }); + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/PronounDB.java b/src/main/java/io/github/moulberry/notenoughupdates/util/PronounDB.java new file mode 100644 index 00000000..e7286721 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/PronounDB.java @@ -0,0 +1,221 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package io.github.moulberry.notenoughupdates.util; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +public class PronounDB { + + static SSLContext ctx; + + static { + try { + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(PronounDB.class.getResourceAsStream("/pronoundb.jks"), "pronoundb".toCharArray()); + ctx = SSLContext.getInstance("TLS"); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, null); + tmf.init(ks); + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } catch (KeyStoreException | NoSuchAlgorithmException | KeyManagementException | UnrecoverableKeyException | + IOException | CertificateException e) { + System.out.println("Failed to load keystore. PronounDB requests will probably not work"); + e.printStackTrace(); + } + } + + private static boolean isDisabled() { + JsonObject disabled = Constants.DISABLE; + return disabled != null && disabled.has("pronoundb"); + } + + /** + * Returns an Optional, since JVMs can be *very* funky with KeyStore loading + */ + public static Optional<JsonObject> performPronouning(String platform, String id) { + if (isDisabled()) return Optional.empty(); + try { + URL url = new URL("https://pronoundb.org/api/v1/lookup" + + "?platform=" + StringUtils.urlEncode(platform) + + "&id=" + StringUtils.urlEncode(id)); + HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); + urlConnection.setSSLSocketFactory(ctx.getSocketFactory()); + return Optional.of(NotEnoughUpdates.INSTANCE.manager.gson.fromJson( + new InputStreamReader(urlConnection.getInputStream()), + JsonObject.class + )); + } catch (ClassCastException | IOException | JsonParseException e) { + System.out.println("Failed to contact PronounDB: " + e); + return Optional.empty(); + } + } + + public enum Pronoun { + HE("he", "him", "his"), + IT("it", "it", "its"), + SHE("she", "her", "hers"), + THEY("they", "they", "theirs"); + + private final String subject; + private final String object; + private final String possessive; + + Pronoun(String subject, String object, String possessive) { + this.subject = subject; + this.object = object; + this.possessive = possessive; + } + + public String getSubject() { + return subject; + } + + public String getObject() { + return object; + } + + public String getPossessive() { + return possessive; + } + } + + public enum PronounChoice { + UNSPECIFIED("unspecified", "Unspecified"), + HE("hh", Pronoun.HE), + HEIT("hi", Pronoun.HE, Pronoun.IT), + HESHE("hs", Pronoun.HE, Pronoun.SHE), + HETHEY("ht", Pronoun.HE, Pronoun.THEY), + ITHE("ih", Pronoun.IT, Pronoun.HE), + IT("ii", Pronoun.IT), + ITSHE("is", Pronoun.IT, Pronoun.SHE), + ITTHEY("it", Pronoun.IT, Pronoun.THEY), + SHEHE("shh", Pronoun.SHE, Pronoun.HE), + SHE("sh", Pronoun.SHE), + SHEIT("si", Pronoun.SHE, Pronoun.IT), + SHETHEY("st", Pronoun.SHE, Pronoun.THEY), + THEYHE("th", Pronoun.THEY, Pronoun.HE), + THEYIT("ti", Pronoun.THEY, Pronoun.IT), + THEYSHE("ts", Pronoun.THEY, Pronoun.SHE), + THEY("tt", Pronoun.THEY), + ANY("any", "Any pronouns"), + OTHER("other", "Other pronouns"), + ASK("ask", "Ask me my pronouns"), + AVOID("avoid", "Avoid pronouns, use my name"); + private final String id; + private List<Pronoun> pronouns = null; + private String override = null; + + PronounChoice(String id, String override) { + this.override = override; + this.id = id; + } + + PronounChoice(String id, Pronoun... pronouns) { + this.id = id; + this.pronouns = Arrays.asList(pronouns); + } + + public static Optional<PronounChoice> findPronounsForId(String id) { + for (PronounChoice value : values()) { + if (value.id.equals(id)) return Optional.of(value); + } + return Optional.empty(); + } + + public String getOverride() { + return override; + } + + public List<Pronoun> getPronounsInPreferredOrder() { + return pronouns; + } + + public String getId() { + return id; + } + + public List<String> render() { + if (override != null) + return Arrays.asList(override); + return pronouns + .stream() + .map(pronoun -> pronoun.getSubject() + "/" + pronoun.getObject()) + .collect(Collectors.toList()); + } + + public boolean isConsciousChoice() { + return this != UNSPECIFIED; + } + + } + + public static Optional<PronounChoice> parsePronouns(JsonObject pronounObject) { + if (pronounObject.has("pronouns")) { + JsonElement pronouns = pronounObject.get("pronouns"); + if (pronouns.isJsonPrimitive() && pronouns.getAsJsonPrimitive().isString()) + return PronounChoice.findPronounsForId(pronouns.getAsString()); + } + return Optional.empty(); + } + + public static Optional<PronounChoice> getPronounsFor(String platform, String name) { + return performPronouning(platform, name).flatMap(PronounDB::parsePronouns); + } + + public static Optional<PronounChoice> getPronounsFor(UUID minecraftPlayer) { + return performPronouning("minecraft", minecraftPlayer.toString() /* dashed UUID */) + .flatMap(PronounDB::parsePronouns); + } + + public static void test() { + try { + System.out.println("Pronouning..."); + PronounChoice pronounsFor = getPronounsFor(UUID.fromString("842204e6-6880-487b-ae5a-0595394f9948")).get(); + pronounsFor.render().forEach(System.out::println); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java index dd7ccbcf..fb53dba3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java @@ -27,7 +27,6 @@ import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.Locati import io.github.moulberry.notenoughupdates.miscgui.minionhelper.MinionHelperManager; import io.github.moulberry.notenoughupdates.overlays.SlayerOverlay; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.init.Blocks; @@ -88,11 +87,19 @@ public class SBInfo { public Date currentTimeDate = null; - public String lastOpenContainerName = ""; + private JsonObject mayorJson = new JsonObject(); + + /** + * Use Utils.getOpenChestName() instead + */ + @Deprecated + public String currentlyOpenChestName = ""; + public String lastOpenChestName = ""; private long lastManualLocRaw = -1; private long lastLocRaw = -1; public long joinedWorld = -1; + private long lastMayorUpdate; public long unloadedWorld = -1; private JsonObject locraw = null; public boolean isInDungeon = false; @@ -123,7 +130,8 @@ public class SBInfo { private int tickCount = 0; public String currentProfile = null; - @SubscribeEvent + //Set the priority HIGH to allow other GuiOpenEvent's to use the new currentlyOpenChestName data + @SubscribeEvent(priority = EventPriority.HIGH) public void onGuiOpen(GuiOpenEvent event) { if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return; @@ -131,19 +139,19 @@ public class SBInfo { GuiChest chest = (GuiChest) event.gui; ContainerChest container = (ContainerChest) chest.inventorySlots; - lastOpenContainerName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + currentlyOpenChestName = container.getLowerChestInventory().getDisplayName().getUnformattedText(); + lastOpenChestName = currentlyOpenChestName; + } else { + currentlyOpenChestName = ""; } } @SubscribeEvent public void onGuiTick(TickEvent event) { if (tickCount++ % 10 != 0) return; - GuiScreen currentScreen = Minecraft.getMinecraft().currentScreen; - if (currentScreen instanceof GuiChest) { - ContainerChest container = (ContainerChest) ((GuiChest) currentScreen).inventorySlots; - if ("Profile Management".equals(container.getLowerChestInventory().getDisplayName().getUnformattedText())) { - updateProfileInformation(container); - } + if (Utils.getOpenChestName().equals("Profile Management")) { + ContainerChest container = (ContainerChest) ((GuiChest) Minecraft.getMinecraft().currentScreen).inventorySlots; + updateProfileInformation(container); } } @@ -225,7 +233,8 @@ public class SBInfo { locraw = null; this.setLocation(null); joinedWorld = System.currentTimeMillis(); - lastOpenContainerName = ""; + currentlyOpenChestName = ""; + lastOpenChestName = ""; hasNewTab = false; } @@ -290,7 +299,10 @@ public class SBInfo { lastLocRaw = System.currentTimeMillis(); NotEnoughUpdates.INSTANCE.sendChatMessage("/locraw"); } - + if (currentTime - lastMayorUpdate > 300 * 1000) { + updateMayor(); + lastMayorUpdate = currentTime; + } try { for (NetworkPlayerInfo info : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info); @@ -415,6 +427,19 @@ public class SBInfo { } } + public void updateMayor() { + NotEnoughUpdates.INSTANCE.manager.hypixelApi.getHypixelApiAsync( + NotEnoughUpdates.INSTANCE.config.apiData.apiKey, + "resources/skyblock/election", + new HashMap<>() + ).thenAcceptAsync(newJson -> mayorJson = newJson); + } + + + public JsonObject getMayorJson() { + return mayorJson; + } + public void setCurrentProfile(String newProfile) { if (!newProfile.equals(currentProfile)) { currentProfile = newProfile; 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 29c039b8..ba1fcafa 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java @@ -73,6 +73,7 @@ import java.io.FileInputStream; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.math.BigInteger; import java.nio.FloatBuffer; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -81,6 +82,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -842,15 +844,15 @@ public class Utils { GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); } - public static ItemStack createItemStack(Item item, String displayname, String... lore) { - return createItemStack(item, displayname, 0, lore); + public static ItemStack createItemStack(Item item, String displayName, String... lore) { + return createItemStack(item, displayName, 0, lore); } - public static ItemStack createItemStack(Block item, String displayname, String... lore) { - return createItemStack(Item.getItemFromBlock(item), displayname, lore); + public static ItemStack createItemStack(Block item, String displayName, String... lore) { + return createItemStack(Item.getItemFromBlock(item), displayName, lore); } - public static ItemStack createItemStack(Item item, String displayname, int damage, String... lore) { + public static ItemStack createItemStack(Item item, String displayName, int damage, String... lore) { ItemStack stack = new ItemStack(item, 1, damage); NBTTagCompound tag = new NBTTagCompound(); NBTTagCompound display = new NBTTagCompound(); @@ -860,7 +862,7 @@ public class Utils { Lore.appendTag(new NBTTagString(line)); } - display.setString("Name", displayname); + display.setString("Name", displayName); display.setTag("Lore", Lore); tag.setTag("display", display); @@ -878,6 +880,8 @@ public class Utils { String... lore ) { NBTTagCompound tag = itemStack.getTagCompound(); + if (tag == null) + tag = new NBTTagCompound(); NBTTagCompound display = tag.getCompoundTag("display"); NBTTagList Lore = new NBTTagList(); @@ -1426,12 +1430,12 @@ public class Utils { file.delete(); } - public static char getPrimaryColourCode(String displayname) { + public static char getPrimaryColourCode(String displayName) { int lastColourCode = -99; int currentColour = 0; int[] mostCommon = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - for (int i = 0; i < displayname.length(); i++) { - char c = displayname.charAt(i); + for (int i = 0; i < displayName.length(); i++) { + char c = displayName.charAt(i); if (c == '\u00A7') { lastColourCode = i; } else if (lastColourCode == i - 1) { @@ -1458,8 +1462,8 @@ public class Utils { return "0123456789abcdef".charAt(currentColour); } - public static Color getPrimaryColour(String displayname) { - int colourInt = Minecraft.getMinecraft().fontRendererObj.getColorCode(getPrimaryColourCode(displayname)); + public static Color getPrimaryColour(String displayName) { + int colourInt = Minecraft.getMinecraft().fontRendererObj.getColorCode(getPrimaryColourCode(displayName)); return new Color(colourInt).darker(); } @@ -1939,8 +1943,9 @@ public class Utils { } public static void showOutdatedRepoNotification() { - NotificationHandler.displayNotification(Lists.newArrayList( - EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "Missing repo data", + if (NotEnoughUpdates.INSTANCE.config.notifications.outdatedRepo) { + NotificationHandler.displayNotification(Lists.newArrayList( + EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "Missing repo data", EnumChatFormatting.RED + "Data used for many NEU features is not up to date, this should normally not be the case.", EnumChatFormatting.RED + "You can try " + EnumChatFormatting.BOLD + "/neuresetrepo" + EnumChatFormatting.RESET + @@ -1948,11 +1953,12 @@ public class Utils { " to see if that fixes the issue.", EnumChatFormatting.RED + "If the problem persists please join " + EnumChatFormatting.BOLD + "discord.gg/moulberry" + - EnumChatFormatting.RESET + EnumChatFormatting.RED + " and message in " + EnumChatFormatting.BOLD + - "#neu-support" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " to get support" - ), - true, true - ); + EnumChatFormatting.RESET + EnumChatFormatting.RED + " and message in " + EnumChatFormatting.BOLD + + "#neu-support" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " to get support" + ), + true, true + ); + } } /** @@ -1980,6 +1986,21 @@ public class Utils { return -1; } + public static UUID parseDashlessUUID(String dashlessUuid) { + // From: https://stackoverflow.com/a/30760478/ + BigInteger most = new BigInteger(dashlessUuid.substring(0, 16), 16); + BigInteger least = new BigInteger(dashlessUuid.substring(16, 32), 16); + return new UUID(most.longValue(), least.longValue()); + } + + public static String getOpenChestName() { + return SBInfo.getInstance().currentlyOpenChestName; + } + + public static String getLastOpenChestName() { + return SBInfo.getInstance().lastOpenChestName; + } + public static void addChatMessage(String message) { EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; if (thePlayer != null) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java index 80027aff..58794e07 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java @@ -21,7 +21,6 @@ package io.github.moulberry.notenoughupdates.util; import com.google.common.base.Splitter; 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.profileviewer.ProfileViewer; @@ -31,11 +30,9 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; public class XPInformation { private static final XPInformation INSTANCE = new XPInformation(); @@ -231,15 +228,16 @@ public class XPInformation { }; private void onApiUpdated(ProfileViewer.Profile profile) { - JsonObject skillInfo = profile.getSkillInfo(null); + Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(null); for (String skill : skills) { SkillInfo info = new SkillInfo(); - float level = skillInfo.get("level_skill_" + skill).getAsFloat(); + ProfileViewer.Level levelInfo = skyblockInfo.get(skill); + float level = levelInfo.level; - info.totalXp = skillInfo.get("experience_skill_" + skill).getAsFloat(); - info.currentXpMax = skillInfo.get("maxxp_skill_" + skill).getAsFloat(); + info.totalXp = levelInfo.totalXp; + info.currentXpMax = levelInfo.maxXpForLevel; info.level = (int) level; info.currentXp = (level % 1) * info.currentXpMax; info.fromApi = true; @@ -247,41 +245,4 @@ public class XPInformation { skillInfoMap.put(skill.toLowerCase(), info); } } - - public double getPetLevel(String petId, double exp, String rarity) { - if (Constants.PETS == null || !Constants.PETS.has("pet_levels")) { - Utils.showOutdatedRepoNotification(); - return 0; - } - Stream<JsonElement> pet_levels = - StreamSupport.stream(Constants.PETS.get("pet_levels").getAsJsonArray().spliterator(), false); - if (!Constants.PETS.has("pet_rarity_offset")) { - Utils.showOutdatedRepoNotification(); - return 0; - } - int pet_rarity_offset = Constants.PETS.getAsJsonObject("pet_rarity_offset").get(rarity).getAsInt(); - if (!Constants.PETS.has("custom_pet_leveling")) { - Utils.showOutdatedRepoNotification(); - return 0; - } - JsonObject custom_pet_leveling = Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(petId); - List<Integer> xpLevelsRequired = - pet_levels.skip(pet_rarity_offset).limit(100).map(JsonElement::getAsInt).collect(Collectors.toList()); - if (custom_pet_leveling != null && custom_pet_leveling.get("type").getAsInt() == 1) - xpLevelsRequired.addAll(StreamSupport - .stream(custom_pet_leveling.getAsJsonArray("pet_levels").spliterator(), false) - .map(JsonElement::getAsInt) - .collect(Collectors.toList())); - double remainingExp = exp; - for (int i = 0; i < xpLevelsRequired.size(); i++) { - int xpForCurrentLevel = xpLevelsRequired.get(i); - if (remainingExp >= xpForCurrentLevel) { - remainingExp -= xpForCurrentLevel; - } else { - return i + 1 + remainingExp / xpForCurrentLevel; - } - } - return xpLevelsRequired.size(); - } - } diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml new file mode 100644 index 00000000..281faf65 --- /dev/null +++ b/src/main/resources/META-INF/mods.toml @@ -0,0 +1,14 @@ +# This mods.toml is loaded by forge 1.13-1.19 and is only here to make forge display an error message +modLoader = "javafml" +loaderVersion = "[12,)" +license = "LGPL" + +[[mods]] +modId="notenoughupdateserrordisplay" +version="99.99" +displayName="NotEnoughUpdates (1.8.9)" +description=''' +This mod description is only here to warn you about using the wrong version of Minecraft and Forge. +''' + + diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 00000000..8dd63bf3 --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,10 @@ +{ + "id": "notenoughupdates", + "version": "9999.0", + "schemaVersion": 1, + "entrypoints": { + "main": [ + "io.github.moulberry.notenoughupdates.envcheck.FabricEntrypoint" + ] + } +} diff --git a/src/main/resources/mixins.notenoughupdates.json b/src/main/resources/mixins.notenoughupdates.json index 8b1d4559..ed1ba55a 100644 --- a/src/main/resources/mixins.notenoughupdates.json +++ b/src/main/resources/mixins.notenoughupdates.json @@ -2,6 +2,7 @@ "package": "io.github.moulberry.notenoughupdates.mixins", "refmap": "mixins.notenoughupdates.refmap.json", "minVersion": "0.7", + "plugin": "io.github.moulberry.notenoughupdates.envcheck.NEUMixinConfigPlugin", "compatibilityLevel": "JAVA_8", "mixins": [ "AccessorEntityAgeable", diff --git a/src/main/resources/pronoundb.jks b/src/main/resources/pronoundb.jks Binary files differnew file mode 100644 index 00000000..1c279333 --- /dev/null +++ b/src/main/resources/pronoundb.jks |