From 5d77f2c5d873c37a88ede101b952d26f83f07a39 Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Sat, 13 Jul 2024 18:17:44 +0200 Subject: Add Glacite Tunnels info to /pv (#1138) Co-authored-by: jani270 <69345714+jani270@users.noreply.github.com> --- .../notenoughupdates/core/GlScissorStack.java | 23 +- .../notenoughupdates/profileviewer/MiningPage.java | 1406 +++----------------- .../profileviewer/data/APIDataJson.java | 41 +- .../profileviewer/hotm/ExtraLispMethods.kt | 55 + .../profileviewer/hotm/HotmTreeLayout.kt | 114 ++ .../profileviewer/hotm/HotmTreeScreen.kt | 220 +++ .../level/task/SkillRelatedTaskLevel.java | 22 +- .../moulberry/notenoughupdates/util/Utils.java | 9 +- 8 files changed, 613 insertions(+), 1277 deletions(-) create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/ExtraLispMethods.kt create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/HotmTreeLayout.kt create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/HotmTreeScreen.kt (limited to 'src/main/java') diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java index 40b9fe7a..2da8a1fc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java @@ -80,21 +80,30 @@ public class GlScissorStack { } else { boundsStack.push(boundsStack.peek().createSubBound(left, top, right, bottom)); } - if (!boundsStack.isEmpty()) { + refresh(scaledResolution); + } + + /** + * Disable scissors temporarily. Can be reenabled with {@link #refresh(ScaledResolution)} + */ + public static void disableTemporary() { + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } + + public static void refresh(ScaledResolution scaledResolution) { + if (boundsStack.isEmpty()) { + GL11.glDisable(GL11.GL_SCISSOR_TEST); + } else { boundsStack.peek().set(scaledResolution); + GL11.glEnable(GL11.GL_SCISSOR_TEST); } - GL11.glEnable(GL11.GL_SCISSOR_TEST); } public static void pop(ScaledResolution scaledResolution) { if (!boundsStack.isEmpty()) { boundsStack.pop(); } - if (boundsStack.isEmpty()) { - GL11.glDisable(GL11.GL_SCISSOR_TEST); - } else { - boundsStack.peek().set(scaledResolution); - } + refresh(scaledResolution); } public static void clear() { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java index cbfcd60f..b0d7c637 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java @@ -19,14 +19,17 @@ package io.github.moulberry.notenoughupdates.profileviewer; -import com.google.common.collect.Lists; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.core.GlScissorStack; import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils; import io.github.moulberry.notenoughupdates.profileviewer.data.APIDataJson; +import io.github.moulberry.notenoughupdates.profileviewer.hotm.HotmTreeRenderer; import io.github.moulberry.notenoughupdates.util.Utils; import lombok.var; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.init.Blocks; @@ -36,27 +39,37 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ResourceLocation; import org.apache.commons.lang3.text.WordUtils; +import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Supplier; import java.util.stream.Stream; public class MiningPage extends GuiProfileViewerPage { - private static final ResourceLocation miningPageTexture = new ResourceLocation("notenoughupdates:pv_mining.png"); + private static final ResourceLocation miningPageTexture = new ResourceLocation( + "notenoughupdates:profile_viewer/mining/background.png"); private static final ItemStack hotmSkillIcon = new ItemStack(Items.iron_pickaxe); - private static final Map crystalToColor = new HashMap() {{ - put("jade", EnumChatFormatting.GREEN); - put("amethyst", EnumChatFormatting.DARK_PURPLE); - put("amber", EnumChatFormatting.GOLD); - put("sapphire", EnumChatFormatting.AQUA); - put("topaz", EnumChatFormatting.YELLOW); - put("jasper", EnumChatFormatting.LIGHT_PURPLE); - put("ruby", EnumChatFormatting.RED); - }}; + private static final Map crystalToColor = + new LinkedHashMap() {{ + put("jade", EnumChatFormatting.GREEN); + put("amethyst", EnumChatFormatting.DARK_PURPLE); + put("amber", EnumChatFormatting.GOLD); + put("sapphire", EnumChatFormatting.AQUA); + put("topaz", EnumChatFormatting.YELLOW); + put("jasper", EnumChatFormatting.LIGHT_PURPLE); + put("ruby", EnumChatFormatting.RED); + put("opal", EnumChatFormatting.WHITE); + put("aquamarine", EnumChatFormatting.BLUE); + put("peridot", EnumChatFormatting.DARK_GREEN); + put("onyx", EnumChatFormatting.DARK_GRAY); + put("citrine", EnumChatFormatting.DARK_RED); + }}; public MiningPage(GuiProfileViewer instance) { super(instance); @@ -95,1269 +108,210 @@ public class MiningPage extends GuiProfileViewerPage { float mithrilPowder = core.powder_mithril; float gemstonePowder = core.powder_gemstone; + float glacitePowder = core.powder_glacite; float mithrilPowderTotal = core.powder_spent_mithril; float gemstonePowderTotal = core.powder_spent_gemstone; + float glacitePowderTotal = core.powder_spent_glacite; double nucleusRunsCompleted = Stream.of("amber", "amethyst", "jade", "sapphire", "topaz") - .mapToDouble(crystal -> Utils.getElementAsFloat(Utils.getElement(miningCore, "crystals." + crystal + "_crystal.total_placed"), 0)) - .min() - .orElse(0); - - int miningFortune = nodes.mining_fortune; - int miningFortuneStat = miningFortune * 5; - int miningSpeed = nodes.mining_speed; - int miningSpeedStat = miningSpeed * 20; - int dailyPowder = nodes.daily_powder; - int dailyPowderStat = dailyPowder * 36 + 364; - int effMiner = nodes.efficient_miner; - float effMinerStat = (float) (effMiner * 0.4 + 10.4); - float effMinerStat2 = Math.max(1, (float) (effMiner * .06 + 0.31)); - int tittyInsane = nodes.titanium_insanium; - float tittyInsaneStat = (float) (tittyInsane * .1 + 2); - int luckOfCave = nodes.random_event; - int madMining = nodes.mining_madness; - int skyMall = nodes.daily_effect; - int goblinKiller = nodes.goblin_killer; - int seasonMine = nodes.mining_experience; - float seasonMineStat = (float) (seasonMine * 0.1 + 5); - int quickForge = nodes.forge_time; - float quickForgeStat = (float) (quickForge * .5 + 10); - int frontLoad = nodes.front_loaded; - int orbit = nodes.experience_orbs; - float orbitStat = (float) (orbit * .01 + 0.2); - int crystallized = nodes.fallen_star_bonus; - int crystallizedStat = (crystallized - 1) * 6 + 20; - int crystallizedStat2 = (crystallized - 1) * 5 + 20; - int professional = nodes.professional; - int professionalStat = professional * 5 + 50; - int greatExplorer = nodes.great_explorer; - int greatExplorerStat = greatExplorer * 4 + 16; - int greatExplorerStat2 = greatExplorer / 5 + 1; - int fortunate = nodes.fortunate; - int fortunateStat = fortunate * 4 + 20; - int lonesomeMiner = nodes.lonesome_miner; - float lonesomeMinerStat = (float) (lonesomeMiner * .5 + 5); - int miningFortune2 = nodes.mining_fortune_2; - int miningFortune2Stat = miningFortune2 * 5; - int miningSpeed2 = nodes.mining_speed_2; - int miningSpeed2Stat = miningSpeed2 * 40; - int miningSpeedBoost = nodes.mining_speed_boost; - int veinSeeker = nodes.vein_seeker; - int powderBuff = nodes.powder_buff; - int potm = nodes.special_0; - int fortnite = nodes.precision_mining; - int starPowder = nodes.star_powder; - int pickoblus = nodes.pickaxe_toss; - int maniacMiner = nodes.maniac_miner; - int mole = nodes.mole; - float moleStat = (float) (mole * 0.051); - double molePerkStat = (double) mole / 20 - 0.55 + 50; - double molePerkStat2 = (double) Math.round(molePerkStat * 100) / 100; - float molePerkPct = Math.round((float) (molePerkStat2 % 1) * 100); - if (molePerkPct == 0) { - molePerkPct = 100; - } + .mapToDouble(crystal -> Utils.getElementAsFloat(Utils.getElement( + miningCore, + "crystals." + crystal + "_crystal.total_placed" + ), 0)) + .min() + .orElse(0); // Render stats Map levelingInfo = selectedProfile.getLevelingInfo(); if (levelingInfo != null) { ProfileViewer.Level hotmLevelingInfo = levelingInfo.get("hotm"); - + // HOTM - getInstance().renderXpBar(EnumChatFormatting.RED + "HOTM", hotmSkillIcon, x, y, sectionWidth, hotmLevelingInfo, mouseX, mouseY); + getInstance().renderXpBar( + EnumChatFormatting.RED + "HOTM", + hotmSkillIcon, + x, + y, + sectionWidth, + hotmLevelingInfo, + mouseX, + mouseY + ); } - // Powder Utils.renderAlignedString( - EnumChatFormatting.DARK_GREEN + "Mithril Powder", - EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(mithrilPowder), - guiLeft + xStart, + EnumChatFormatting.DARK_GREEN + "Mithril", + "", + guiLeft + xStart + 45, guiTop + yStartTop + 24, 115 ); Utils.renderAlignedString( - EnumChatFormatting.LIGHT_PURPLE + "Gemstone Powder", - EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(gemstonePowder), - guiLeft + xStart, - guiTop + yStartTop + 44, + EnumChatFormatting.LIGHT_PURPLE + "Gemstone", + "", + guiLeft + xStart + 85, + guiTop + yStartTop + 24, 115 ); Utils.renderAlignedString( - EnumChatFormatting.DARK_GREEN + "Total Mithril Powder", - EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(mithrilPowderTotal + mithrilPowder), - guiLeft + xStart, - guiTop + yStartTop + 34, + EnumChatFormatting.AQUA + "Glacite", + "", + guiLeft + xStart + 145, + guiTop + yStartTop + 24, 115 ); Utils.renderAlignedString( - EnumChatFormatting.LIGHT_PURPLE + "Total Gemstone Powder", - EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(gemstonePowderTotal + gemstonePowder), + EnumChatFormatting.WHITE + "Powder:", + "", guiLeft + xStart, - guiTop + yStartTop + 54, + guiTop + yStartTop + 44, 115 ); - - // Crystals - int idx = 0; - for (Map.Entry crystal : crystalToColor.entrySet()) { - String crystalState = Utils.getElementAsString(Utils.getElement(miningCore, "crystals." + crystal.getKey() + "_crystal.state"), "NOT_FOUND"); - String crystalStr = crystalState.equals("FOUND") ? "§a✔" : "§c✖"; - Utils.renderAlignedString( - crystal.getValue() + WordUtils.capitalizeFully(crystal.getKey()) + " Crystal:", - EnumChatFormatting.WHITE + crystalStr, - guiLeft + xStart, - guiTop + yStartTop + 74 + idx * 10, - 110 - ); - idx ++; // Move text down 10 px every crystal - } - Utils.renderAlignedString( - EnumChatFormatting.BLUE + "Nucleus Runs Completed:", - EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(nucleusRunsCompleted), - guiLeft + xStart, - guiTop + yStartTop + 149, - 110 - ); - - // HOTM tree - 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 + - StringUtils.formatNumber(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 + - StringUtils.formatNumber((int) Math.pow(miningFortune + 2, 3.05)) + - " 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 + EnumChatFormatting.DARK_GREEN + StringUtils.shortNumberFormat(mithrilPowder), + "", + guiLeft + xStart + 50, + guiTop + yStartTop + 44, + 115 ); - - 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 + - StringUtils.formatNumber((int) Math.pow(tittyInsane + 2, 3.1)) + - " 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 + Utils.renderAlignedString( + EnumChatFormatting.LIGHT_PURPLE + StringUtils.shortNumberFormat(gemstonePowder), + "", + guiLeft + xStart + 100, + guiTop + yStartTop + 44, + 115 ); - - 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" - ) + Utils.renderAlignedString( + EnumChatFormatting.AQUA + StringUtils.shortNumberFormat(glacitePowder), + "", + guiLeft + xStart + 150, + guiTop + yStartTop + 44, + 115 ); - - 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" - ) + Utils.renderAlignedString( + EnumChatFormatting.WHITE + "Total:", + "", + guiLeft + xStart, + guiTop + yStartTop + 54, + 115 ); - - 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 in", - "§2Dwarven Mines " + EnumChatFormatting.GRAY + "by " + EnumChatFormatting.GREEN + luckOfCave + "%§7.", - "", - EnumChatFormatting.GRAY + "Rare occurences include:", - EnumChatFormatting.GRAY + " • " + EnumChatFormatting.GOLD + "Golden Goblins", - EnumChatFormatting.GRAY + " • " + EnumChatFormatting.DARK_PURPLE + "Fallen Stars", - EnumChatFormatting.GRAY + " • " + EnumChatFormatting.GOLD + "Powder Ghasts", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + - StringUtils.formatNumber((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 in", - "§2Dwarven Mines " + EnumChatFormatting.GRAY + "by " + EnumChatFormatting.GREEN + luckOfCave + "%§7.", - "", - EnumChatFormatting.GRAY + "Rare occurrences include:", - EnumChatFormatting.GRAY + " • " + EnumChatFormatting.GOLD + "Golden Goblins", - EnumChatFormatting.GRAY + " • " + EnumChatFormatting.DARK_PURPLE + "Fallen Stars", - EnumChatFormatting.GRAY + " • " + EnumChatFormatting.GOLD + "Powder Ghasts" - ), - 45 + Utils.renderAlignedString( + EnumChatFormatting.DARK_GREEN + StringUtils.shortNumberFormat(mithrilPowder + mithrilPowderTotal), + "", + guiLeft + xStart + 50, + guiTop + yStartTop + 54, + 115 ); - - 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 + String.valueOf(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 + Utils.renderAlignedString( + EnumChatFormatting.LIGHT_PURPLE + StringUtils.shortNumberFormat(gemstonePowder + gemstonePowderTotal), + "", + guiLeft + xStart + 100, + guiTop + yStartTop + 54, + 115 ); - - 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 + - String.valueOf(effMinerStat) + - "%" + - EnumChatFormatting.GRAY + - " chance to mine " + - EnumChatFormatting.GREEN + - Math.round(effMinerStat2), - EnumChatFormatting.GRAY + "adjacent ores.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + - StringUtils.formatNumber((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 + - String.valueOf(effMinerStat) + - "%" + - EnumChatFormatting.GRAY + - " chance to mine " + - EnumChatFormatting.GREEN + - Math.round(effMinerStat2), - EnumChatFormatting.GRAY + "adjacent ores." - ), - 100 + Utils.renderAlignedString( + EnumChatFormatting.AQUA + StringUtils.shortNumberFormat(glacitePowder + glacitePowderTotal), + "", + guiLeft + xStart + 150, + guiTop + yStartTop + 54, + 115 ); - - 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 + "/7", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "50,000 Mithril Powder" - ); - case 1: - return Lists.newArrayList( - EnumChatFormatting.YELLOW + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7", - "", - "§7§8+§c1 Pickaxe Ability Level", - "§7§8+§51 Token of the Mountain", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "50,000 Mithril Powder" - ); - case 2: - return Lists.newArrayList( - EnumChatFormatting.YELLOW + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7", - "", - "§7§8+§c1 Pickaxe Ability Level", - "§7§8+§51 Token of the Mountain", - "§7§8+§a1 Forge Slot", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + "75,000 Mithril Powder" - ); - case 3: - return Lists.newArrayList( - EnumChatFormatting.YELLOW + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7", - "", - "§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 + "100,000 Mithril Powder" - ); - case 4: - return Lists.newArrayList( - EnumChatFormatting.YELLOW + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7", - "", - "§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 + "125,000 Mithril Powder" - ); - case 5: - return Lists.newArrayList( - EnumChatFormatting.GREEN + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7", - "", - "§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", - "", - "§7Cost", - "§d500,000 Gemstone Powder" - ); - case 6: - return Lists.newArrayList( - EnumChatFormatting.GREEN + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7", - "", - "§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", - "§7§8+§d2 Gemstone Powder §7when", - "§7mining §dGemstones", - "", - "§7Cost", - "§d750,000 Gemstone Powder" - ); - case 7: - return Lists.newArrayList( - EnumChatFormatting.GREEN + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7", - "", - "§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", - "§7§8+§d2 Gemstone Powder §7when", - "§7mining §dGemstones", - "§7§8+§51 Token of the Mountain" - ); - } - return Lists.newArrayList( - EnumChatFormatting.GREEN + "Peak of the Mountain", - EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/???", - EnumChatFormatting.RED + "It looks like your NEU doesn't understand your peak of the mountain perks.", - EnumChatFormatting.RED + "Please patiently await an update to your NEU installation." + { + // Crystals + int padding = 4; + int rectStartX = 16; + rectStartX += padding; + int rectStartY = 97; + rectStartY += padding; + int rectXSize = 214; + rectXSize -= padding * 2; + int rectYSize = 89; + int originalRectYSize = rectYSize; + rectYSize -= padding * 2; + int rowHeight = 10; + int totalColumns = 2; + rectYSize = rowHeight * (int) Math.ceil((((double) crystalToColor.size()) / totalColumns)); + int totalRows = rectYSize / rowHeight; + + int idx = 0; + for (Map.Entry crystal : crystalToColor.entrySet()) { + + int currentRow = idx % totalRows; + int currentCol = idx / totalRows; + int columnWidth = rectXSize / totalColumns - padding / totalColumns; + int columnOffset = columnWidth + padding; + + String crystalState = Utils.getElementAsString(Utils.getElement( + miningCore, + "crystals." + crystal.getKey() + "_crystal.state" + ), "NOT_FOUND"); + String crystalStr = crystalState.equals("FOUND") ? "§a✔" : "§c✖"; + Utils.renderAlignedString( + crystal.getValue() + WordUtils.capitalizeFully(crystal.getKey()) + ":", + EnumChatFormatting.WHITE + crystalStr, + guiLeft + rectStartX + currentCol * columnOffset, + guiTop + rectStartY + currentRow * rowHeight, + columnWidth ); - }, - 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 finalMolePerkPct = molePerkPct; - 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 + - finalMolePerkPct + - "% " + - EnumChatFormatting.GRAY + - "chance to mine " + - EnumChatFormatting.GREEN, - EnumChatFormatting.GREEN + - String.valueOf(Math.round(moleStat)) + - EnumChatFormatting.GRAY + - " adjacent hard stone block" + - (moleStat == 1.0 ? "." : "s."), - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.LIGHT_PURPLE + - StringUtils.formatNumber((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 + - finalMolePerkPct + - "% " + - EnumChatFormatting.GRAY + - "chance to mine " + - EnumChatFormatting.GREEN, - EnumChatFormatting.GREEN + - String.valueOf(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 + - StringUtils.formatNumber((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 Golden", - " §7and Diamond Goblins.", - "§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 §7or", - "§7§bDiamond Goblin §7gives §2200", - "§7extra §2Mithril Powder§7,", - "§7while killing other Goblins", - "§7gives some based on their 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", - "", - "§7Grants §3+" + EnumChatFormatting.DARK_AQUA + seasonMineStat + "☯ Mining Wisdom§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + - StringUtils.formatNumber((int) Math.pow(seasonMine + 2, 2.3)) + - " Mithril Powder" - ) - : Lists.newArrayList( - "Seasoned Mineman", - "§7Level " + seasonMine + "§8/100", - "", - "§7Grants §3+" + EnumChatFormatting.DARK_AQUA + seasonMineStat + "☯ Mining Wisdom§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 + - StringUtils.formatNumber((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 + - StringUtils.formatNumber((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 + - StringUtils.formatNumber((int) Math.pow(miningSpeed2 + 2, 3.2)) + - " 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 + - StringUtils.formatNumber((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 + - StringUtils.formatNumber((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", - "", - "§7Boosts the chance to find", - "§7treasure chests while mining in", - "§7the §5Crystal Hollows §7by", - EnumChatFormatting.GREEN + "+" + greatExplorerStat + "%" + " §7and reduces the", - "§7amount of locks on the chests by", - EnumChatFormatting.GREEN.toString() + greatExplorerStat2 + "§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.LIGHT_PURPLE + - StringUtils.formatNumber((int) Math.pow(greatExplorer + 2, 4)) + - " Gemstone Powder" - ) - : Lists.newArrayList( - "Great Explorer", - "§7Level " + greatExplorer + EnumChatFormatting.DARK_GRAY + "/20", - "", - "§7Boosts the chance to find", - "§7treasure chests while mining in", - "§7the §5Crystal Hollows §7by", - EnumChatFormatting.GREEN + "+" + greatExplorerStat + "%" + " §7and reduces the", - "§7amount of locks on the chests by", - EnumChatFormatting.GREEN.toString() + greatExplorerStat2 + "§7." - ), - 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 + - StringUtils.formatNumber((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 + String.valueOf(orbitStat) + "%" + EnumChatFormatting.GRAY + " chance to get a random", - "§7amount of experience orbs.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + String.valueOf((orbit + 1) * 70) + " Mithril Powder" - ) - : Lists.newArrayList( - "Orbiter", - "§7Level " + orbit + EnumChatFormatting.DARK_GRAY + "/80", - "", - "§7When mining ores, you have a", - EnumChatFormatting.GREEN + String.valueOf(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 §7as", - "§7well as §a+2 base powder §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 §ax3 §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 Speed", - "§7and §a+" + crystallizedStat + "§7 §6☘ Mining Fortune", - "§7near §5Fallen Stars§7.", - "", - EnumChatFormatting.GRAY + "Cost", - EnumChatFormatting.DARK_GREEN + - StringUtils.formatNumber((int) Math.pow(crystallized + 2, 3.4)) + - " Mithril Powder" - ) - : Lists.newArrayList( - "Crystallized", - "§7Level " + crystallized + EnumChatFormatting.DARK_GRAY + "/30", - "", - "§7Grants §a+§a" + crystallizedStat + "§7 §6⸕ Mining Speed", - "§7and §a+" + crystallizedStat + "§7 §6☘ Mining Fortune", - "§7near §5Fallen Stars§7." - ), - 30 - ); + idx++; + } - 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") - ) - ); + Utils.renderAlignedString( + EnumChatFormatting.BLUE + "Nucleus Runs Completed:", + EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(nucleusRunsCompleted), + guiLeft + rectStartX, + guiTop + rectStartY + originalRectYSize - padding - 1.5F * Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT, + rectXSize + ); + } - renderPickaxeAbility( - maniacMiner, - (int) (guiLeft + xStart + 327), - (int) (guiTop + yStartTop + 18), + renderHotmTree( + guiLeft + 249, + guiTop + 16, + guiLeft + 412, + guiTop + 185, + nodes, 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 §b10 Mana §7spent, for", - "§7§a15s§7.", - "§8Cooldown: §a59s" - ) + mouseY ); } - /** - * Renders a standard HOTM perk that can be levelled. - */ - private void renderHotmPerk( - int perkLevel, - int xPosition, - int yPosition, - int mouseX, - int mouseY, - Supplier> tooltipSupplier, - int maxLevel - ) { - renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, false, maxLevel); - } + int scroll = 0; - /** - * 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> tooltipSupplier - ) { - renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, true, -1); + @Override + public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + return super.mouseClicked(mouseX, mouseY, mouseButton); } - /** - * Renders a HOTM perk. This method is only called from its overloads above. - */ - private void renderHotmPerk( - int perkLevel, - int xPosition, - int yPosition, + private void renderHotmTree( + int left, int top, int right, int bottom, Map levels, int mouseX, - int mouseY, - Supplier> tooltipSupplier, - boolean isPickaxeAbility, - int maxLevel + int mouseY ) { - 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 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); - } + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + GlScissorStack.push(left, top, right, bottom, sr); + var isHovered = left < mouseX && mouseX < right && + top < mouseY && mouseY < bottom; + var renderer = HotmTreeRenderer.Companion + .getRenderer(); + if (isHovered) { + scroll += Mouse.getDWheel(); } - } - - /** - * 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> 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> tooltipSupplier, - ItemStack itemStack, - boolean isRenderingBlock - ) { - boolean unlocked = perkLevel > 0; - GlStateManager.color(1, 1, 1, 1); - GlStateManager.disableLighting(); - if (isRenderingBlock) RenderHelper.enableGUIStandardItemLighting(); - - ArrayList 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); - } + if (renderer != null) { + var maxScroll = renderer.getYSize() * 24 - (bottom - top) - 24 / 2; + scroll = Math.min(maxScroll + 4, Math.max(0, scroll)); + renderer.renderPerks( + levels, + left + (right - left) / 2 - renderer.getXSize() * 24 / 2 + 4 / 2, + top - maxScroll + scroll, mouseX, mouseY, + isHovered, + 20, + 4 + ); + } else { + Utils.showOutdatedRepoNotification("hotmLayout.json"); } + GlScissorStack.pop(sr); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/data/APIDataJson.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/data/APIDataJson.java index 6da37043..9499b1b2 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/data/APIDataJson.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/data/APIDataJson.java @@ -20,11 +20,15 @@ package io.github.moulberry.notenoughupdates.profileviewer.data; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Objects; import static io.github.moulberry.notenoughupdates.profileviewer.rift.RiftPage.readBase64; @@ -132,42 +136,12 @@ public class APIDataJson { public static class MiningCore { public float powder_mithril = 0; public float powder_gemstone = 0; + public float powder_glacite = 0; public float powder_spent_mithril = 0; public float powder_spent_gemstone = 0; + public float powder_spent_glacite = 0; - public Nodes nodes = new Nodes(); - - public static class Nodes { - public int mining_fortune = 0; - public int mining_speed = 0; - public int daily_powder = 0; - public int efficient_miner = 0; - public int titanium_insanium = 0; - public int random_event = 0; - public int mining_madness = 0; - public int daily_effect = 0; - public int goblin_killer = 0; - public int mining_experience = 0; - public int forge_time = 0; - public int front_loaded = 0; - public int experience_orbs = 0; - public int fallen_star_bonus = 0; - public int professional = 0; - public int great_explorer = 0; - public int fortunate = 0; - public int lonesome_miner = 0; - public int mining_fortune_2 = 0; - public int mining_speed_2 = 0; - public int mining_speed_boost = 0; - public int vein_seeker = 0; - public int powder_buff = 0; - public int special_0 = 0; - public int precision_mining = 0; - public int star_powder = 0; - public int pickaxe_toss = 0; - public int maniac_miner = 0; - public int mole = 0; - } + public Map nodes = new HashMap<>(); } public @Nullable Rift rift; @@ -286,6 +260,7 @@ public class APIDataJson { public long last_charge_time = 0; public long activation_time = 0; } + public static class HoppityShoppity { public long chocolate_spent = 0; } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/ExtraLispMethods.kt b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/ExtraLispMethods.kt new file mode 100644 index 00000000..eb774659 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/ExtraLispMethods.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see . + */ + +package io.github.moulberry.notenoughupdates.profileviewer.hotm + +import io.github.moulberry.notenoughupdates.core.util.StringUtils +import moe.nea.lisp.LispData +import moe.nea.lisp.bind.LispBinding +import kotlin.math.ceil +import kotlin.math.floor +import kotlin.math.pow +import kotlin.math.round + +class ExtraLispMethods { + @LispBinding("pow") + fun powFunc(base: Double, exponent: Double): LispData.LispNumber { + return LispData.LispNumber(base.pow(exponent)) + } + + @LispBinding("round") + fun roundFunc(value: Double): LispData.LispNumber { + return LispData.LispNumber(round(value)) + } + + @LispBinding("ceil") + fun ceilFunc(value: Double): LispData.LispNumber { + return LispData.LispNumber(ceil(value)) + } + + @LispBinding("floor") + fun floorFunc(value: Double): LispData.LispNumber { + return LispData.LispNumber(floor(value)) + } + + @LispBinding("format-int") + fun intToString(base: Double): LispData.LispString { + return LispData.LispString(StringUtils.formatNumber(base.toInt())) + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/HotmTreeLayout.kt b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/HotmTreeLayout.kt new file mode 100644 index 00000000..58866638 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/HotmTreeLayout.kt @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2024 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see . + */ + +package io.github.moulberry.notenoughupdates.profileviewer.hotm + +import com.google.gson.* +import com.google.gson.reflect.TypeToken +import com.google.gson.stream.JsonReader +import com.google.gson.stream.JsonToken +import com.google.gson.stream.JsonWriter +import io.github.moulberry.notenoughupdates.util.kotlin.ExtraData +import io.github.moulberry.notenoughupdates.util.kotlin.KSerializable +import io.github.moulberry.notenoughupdates.util.kotlin.fromJson +import moe.nea.lisp.LispAst +import moe.nea.lisp.LispParser + +@KSerializable +data class HotmTreeLayoutFile( + val hotm: HotmTreeLayout, + val prelude: List = listOf() +) + +data class LoreLine(val text: String, val condition: LispAst.Program?) + +object LoreLineSerializer : TypeAdapterFactory { + override fun create(gson: Gson, type: TypeToken): TypeAdapter? { + if (type.rawType.isAssignableFrom(LoreLine::class.java)) { + return object : TypeAdapter() { + override fun write(out: JsonWriter?, value: LoreLine?) { + TODO("Not yet implemented") + } + + override fun read(reader: JsonReader): LoreLine { + when (reader.peek()) { + JsonToken.BEGIN_OBJECT -> { + val obj = gson.fromJson(reader) + return LoreLine(obj["text"].asString, LispParser.parse("", obj["onlyIf"].asString)) + } + + JsonToken.STRING -> return LoreLine(reader.nextString(), null) + else -> throw JsonParseException("Expected object or string when parsing lore line") + } + } + + } as TypeAdapter + } + return null + } +} + +object LispProgramSerializer : TypeAdapterFactory { + override fun create(gson: Gson, type: TypeToken): TypeAdapter? { + if (type.rawType.isAssignableFrom(LispAst.Program::class.java)) { + return object : TypeAdapter() { + override fun write(out: JsonWriter, value: LispAst.Program) { + out.value(value.toSource()) + } + + override fun read(reader: JsonReader): LispAst.Program { + return LispParser.parse("", reader.nextString()) + } + + } as TypeAdapter + } + return null + } +} + +@KSerializable +data class HotmTreeLayout( + val perks: Map, + val powders: Map, +) + +@KSerializable +data class PowderType( + val costLine: String, +) + +@KSerializable +data class LayoutedHotmPerk( + val name: String, + val x: Int, + val y: Int, + val maxLevel: Int, + val powder: LispAst.Program, + val cost: LispAst.Program, + val lore: List, + @ExtraData + val extras: Map +) { + + val compiledFunctions: Map = extras.mapValues { + LispParser.parse("hotmlayout.json:perk:$name:${it.key}", it.value.asString) + } + mapOf( + "cost" to cost + ) +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/HotmTreeScreen.kt b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/HotmTreeScreen.kt new file mode 100644 index 00000000..c64b4706 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/hotm/HotmTreeScreen.kt @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2024 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see . + */ + +package io.github.moulberry.notenoughupdates.profileviewer.hotm + +import com.google.gson.GsonBuilder +import com.google.gson.JsonElement +import io.github.moulberry.notenoughupdates.NotEnoughUpdates +import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe +import io.github.moulberry.notenoughupdates.core.GlScissorStack +import io.github.moulberry.notenoughupdates.core.util.StringUtils +import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent +import io.github.moulberry.notenoughupdates.util.ItemUtils +import io.github.moulberry.notenoughupdates.util.Utils +import io.github.moulberry.notenoughupdates.util.kotlin.KotlinTypeAdapterFactory +import moe.nea.lisp.* +import moe.nea.lisp.bind.AutoBinder +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.ScaledResolution +import net.minecraft.init.Items +import net.minecraft.item.ItemStack +import net.minecraft.util.ResourceLocation +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.math.floor +import kotlin.math.roundToInt + +class HotmTreeRenderer(val hotmLayout: HotmTreeLayout, val prelude: List) { + val lec = LispExecutionContext() + + init { + lec.setupStandardBindings() + AutoBinder().bindTo(ExtraLispMethods(), lec.rootStackFrame) + prelude.forEachIndexed { index, it -> + lec.executeProgram(lec.rootStackFrame, LispParser.parse("hotmlayout.json:prelude[$index]", it)) + } + } + + @NEUAutoSubscribe + companion object { + + val gson = GsonBuilder() + .registerTypeAdapterFactory(KotlinTypeAdapterFactory) + .registerTypeAdapterFactory(LoreLineSerializer) + .registerTypeAdapterFactory(LispProgramSerializer) + .create() + + var renderer: HotmTreeRenderer? = null + + @SubscribeEvent + fun onRepoReload(event: RepositoryReloadEvent) { + renderer = runCatching { + val hotmLayoutFile = NotEnoughUpdates.INSTAN