From d3805f080af87eb2bc7d2a2eac6c3f8db539324f Mon Sep 17 00:00:00 2001 From: hannibal2 <24389977+hannibal00212@users.noreply.github.com> Date: Thu, 8 Sep 2022 17:00:49 +0200 Subject: 0.14 - Finished :) (#233) Co-authored-by: nopo Co-authored-by: jani270 <69345714+jani270@users.noreply.github.com> Co-authored-by: Ascynx <78341107+Ascynx@users.noreply.github.com> Co-authored-by: NopoTheGamer <40329022+NopoTheGamer@users.noreply.github.com> Co-authored-by: Lulonaut --- .../moulberry/notenoughupdates/NEUOverlay.java | 4 +- .../notenoughupdates/NotEnoughUpdates.java | 4 + .../notenoughupdates/auction/APIManager.java | 13 +- .../notenoughupdates/core/util/StringUtils.java | 20 + .../events/RepositoryReloadEvent.java | 2 +- .../notenoughupdates/listener/ChatListener.java | 4 +- .../listener/ItemTooltipEssenceShopListener.java | 84 +++ .../listener/ItemTooltipListener.java | 3 +- .../listener/ItemTooltipRngListener.java | 330 ++++++++++++ .../notenoughupdates/listener/RenderListener.java | 36 +- .../miscfeatures/AuctionProfit.java | 6 +- .../miscfeatures/BazaarSacksProfit.java | 9 +- .../miscfeatures/DamageCommas.java | 29 +- .../miscgui/AccessoryBagOverlay.java | 4 +- .../miscgui/TrophyRewardOverlay.java | 2 +- .../notenoughupdates/mixins/MixinGuiContainer.java | 2 +- .../notenoughupdates/mixins/MixinRenderItem.java | 6 +- .../mixins/MixinSkyclientCosmetics.java | 39 ++ .../notenoughupdates/options/NEUConfig.java | 10 + .../options/seperateSections/BazaarTweaks.java | 81 +++ .../options/seperateSections/Dungeons.java | 9 + .../options/seperateSections/Misc.java | 8 +- .../options/seperateSections/SkillOverlays.java | 9 +- .../options/seperateSections/TooltipTweaks.java | 40 +- .../overlays/AuctionSearchOverlay.java | 2 +- .../overlays/BazaarSearchOverlay.java | 572 +++++++++++++++++++++ .../overlays/CombatSkillOverlay.java | 82 ++- .../notenoughupdates/profileviewer/BasicPage.java | 5 +- .../profileviewer/CollectionsPage.java | 18 +- .../profileviewer/DungeonPage.java | 32 +- .../notenoughupdates/profileviewer/ExtraPage.java | 84 ++- .../profileviewer/GuiProfileViewer.java | 20 +- .../profileviewer/InventoriesPage.java | 108 ++-- .../notenoughupdates/profileviewer/MiningPage.java | 20 +- .../notenoughupdates/profileviewer/PetsPage.java | 24 +- .../profileviewer/bestiary/BestiaryPage.java | 18 +- .../notenoughupdates/util/Calculator.java | 2 + 37 files changed, 1563 insertions(+), 178 deletions(-) create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipEssenceShopListener.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinSkyclientCosmetics.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/BazaarTweaks.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java (limited to 'src/main/java') diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index 19f5a780..18be69e6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -1265,8 +1265,8 @@ public class NEUOverlay extends Gui { String internal1 = o1.get("internalname").getAsString(); String internal2 = o2.get("internalname").getAsString(); - double cost1 = manager.auctionManager.getLowestBin(internal1); - double cost2 = manager.auctionManager.getLowestBin(internal2); + double cost1 = manager.auctionManager.getBazaarOrBin(internal1); + double cost2 = manager.auctionManager.getBazaarOrBin(internal2); if (cost1 < cost2) return mult; if (cost1 > cost2) return -mult; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index dd4c01af..6732336c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -29,7 +29,9 @@ import io.github.moulberry.notenoughupdates.cosmetics.CapeManager; import io.github.moulberry.notenoughupdates.cosmetics.ShaderManager; import io.github.moulberry.notenoughupdates.dungeons.DungeonMap; import io.github.moulberry.notenoughupdates.listener.ChatListener; +import io.github.moulberry.notenoughupdates.listener.ItemTooltipEssenceShopListener; import io.github.moulberry.notenoughupdates.listener.ItemTooltipListener; +import io.github.moulberry.notenoughupdates.listener.ItemTooltipRngListener; import io.github.moulberry.notenoughupdates.listener.NEUEventListener; import io.github.moulberry.notenoughupdates.listener.OldAnimationChecker; import io.github.moulberry.notenoughupdates.listener.RenderListener; @@ -283,6 +285,8 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(CustomBiomes.INSTANCE); MinecraftForge.EVENT_BUS.register(new ChatListener(this)); MinecraftForge.EVENT_BUS.register(new ItemTooltipListener(this)); + MinecraftForge.EVENT_BUS.register(new ItemTooltipRngListener(this)); + MinecraftForge.EVENT_BUS.register(new ItemTooltipEssenceShopListener(this)); MinecraftForge.EVENT_BUS.register(new RenderListener(this)); MinecraftForge.EVENT_BUS.register(new OldAnimationChecker()); MinecraftForge.EVENT_BUS.register(new SignCalculator()); 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 74ef2483..2dc02b7e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java @@ -807,9 +807,18 @@ public class APIManager { return keys; } - public JsonObject getBazaarInfo(String internalname) { + public double getBazaarOrBin(String internalName) { + JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalName); + if (bazaarInfo != null && bazaarInfo.get("curr_buy") != null) { + return bazaarInfo.get("curr_buy").getAsFloat(); + } else { + return manager.auctionManager.getLowestBin(internalName); + } + } + + public JsonObject getBazaarInfo(String internalName) { if (bazaarJson == null) return null; - JsonElement e = bazaarJson.get(internalname); + JsonElement e = bazaarJson.get(internalName); if (e == null) { return null; } 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 6143085c..a4f814d1 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 @@ -67,6 +67,26 @@ public class StringUtils { return Integer.parseInt(str); } + public static String shortNumberFormat(double n) { + return shortNumberFormat(n, 0); + } + + private static final char[] c = new char[] { 'k', 'm', 'b', 't' }; + + public static String shortNumberFormat(double n, int iteration) { + if (n < 1000) { + if (n % 1 == 0) { + return Integer.toString((int) n); + } else { + return String.format("%.2f", n); + } + } + + double d = ((long) n / 100) / 10.0; + boolean isRound = (d * 10) % 10 == 0; + return d < 1000 ? (isRound || d > 9.99 ? (int) d * 10 / 10 : d + "") + "" + c[iteration] : shortNumberFormat(d, iteration + 1); + } + public static String urlEncode(String something) { try { return URLEncoder.encode(something, StandardCharsets.UTF_8.name()); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java index bf6448a2..ab650c54 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java @@ -23,7 +23,7 @@ import java.io.File; public class RepositoryReloadEvent extends NEUEvent { private final File baseFile; - private boolean isFirstLoad; + private final boolean isFirstLoad; public RepositoryReloadEvent(File baseFile, boolean isFirstLoad) { this.baseFile = baseFile; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java index 5bd47f3a..b59eaf17 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java @@ -198,8 +198,8 @@ public class ChatListener { timeSinceLastBoss2 = timeSinceLastBoss; timeSinceLastBoss = System.currentTimeMillis(); } - } else if (unformatted.startsWith(" RNGesus Meter:")) { - RNGMeter = unformatted.substring(" RNGesus Meter: -------------------- ".length()); + } else if (unformatted.startsWith(" RNG Meter")) { + RNGMeter = unformatted.substring(" RNG Meter - ".length()); } else if (matcher.matches()) { //matcher.group(1); SlayerOverlay.slayerLVL = matcher.group(2); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipEssenceShopListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipEssenceShopListener.java new file mode 100644 index 00000000..4b380c2f --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipEssenceShopListener.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see . + */ + +package io.github.moulberry.notenoughupdates.listener; + +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ItemTooltipEssenceShopListener { + private final NotEnoughUpdates neu; + + private final Pattern ESSENCE_PATTERN = Pattern.compile("§5§o§d([\\d,]+) (.+) Essence"); + + public ItemTooltipEssenceShopListener(NotEnoughUpdates neu) { + this.neu = neu; + } + + @SubscribeEvent + public void onItemTooltip(ItemTooltipEvent event) { + if (!neu.isOnSkyblock()) return; + if (event.toolTip == null) return; + if (!Utils.getOpenChestName().endsWith(" Essence Shop")) return; + if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.essencePriceInEssenceShop) return; + + List newToolTip = new ArrayList<>(); + boolean next = false; + for (String line : event.toolTip) { + + if (next) { + next = false; + Matcher matcher = ESSENCE_PATTERN.matcher(line); + if (matcher.matches()) { + String rawNumber = matcher.group(1).replace(",", ""); + int amount = Integer.parseInt(rawNumber); + String type = matcher.group(2); + + String essenceName = "ESSENCE_" + type.toUpperCase(); + JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(essenceName); + + if (bazaarInfo != null && bazaarInfo.has("curr_sell")) { + float bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); + double price = bazaarPrice * amount; + String format = StringUtils.shortNumberFormat(price); + newToolTip.add(line + " §7(§6" + format + " coins§7)"); + continue; + } + } + } + + if (line.contains("Cost")) { + next = true; + } + newToolTip.add(line); + } + + event.toolTip.clear(); + event.toolTip.addAll(newToolTip); + } +} 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 e5c3324f..3936ad74 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java @@ -266,8 +266,7 @@ public class ItemTooltipListener { newTooltip.add(""); } - newTooltip.add(EnumChatFormatting.BLUE + "Stats for " + rarityFormatted + - "\u00a79: [\u00a7l\u00a7m< \u00a79Switch\u00a7l\u27a1\u00a79]"); + newTooltip.add(EnumChatFormatting.BLUE + "Stats for " + rarityFormatted + "§9: [§l§m< §9Switch§l➡§9]"); if (statsE != null && statsE.isJsonObject()) { JsonObject stats = statsE.getAsJsonObject(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java new file mode 100644 index 00000000..bbbb9049 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see . + */ + +package io.github.moulberry.notenoughupdates.listener; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent; +import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; +import io.github.moulberry.notenoughupdates.util.Calculator; +import io.github.moulberry.notenoughupdates.util.Constants; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.item.ItemStack; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ItemTooltipRngListener { + private final NotEnoughUpdates neu; + private boolean showSlayerRngFractions = false; + private boolean pressedShiftLast = false; + private int currentSelected = 0; + private boolean pressedArrowLast = false; + private boolean repoReloadNeeded = true; + + private final Pattern ODDS_PATTERN = Pattern.compile("§5§o§7Odds: (.+) §7\\(§7(.*)%\\)"); + private final Pattern ODDS_SELECTED_PATTERN = Pattern.compile("§5§o§7Odds: (.+) §7\\(§8§m(.*)%§r §7(.+)%\\)"); + + private final Pattern RUNS_PATTERN = Pattern.compile("§5§o§7(Dungeon Score|Slayer XP): §d(.*)§5/§d(.+)"); + private final Pattern RUNS_SELECTED_PATTERN = Pattern.compile("§5§o§d-(.+)- §d(.*)§5/§d(.+)"); + + private final Pattern SLAYER_INVENTORY_TITLE_PATTERN = Pattern.compile("(.+) RNG Meter"); + + private final Map dungeonData = new LinkedHashMap<>(); + private final Map> slayerData = new LinkedHashMap<>(); + + public ItemTooltipRngListener(NotEnoughUpdates neu) { + this.neu = neu; + } + + @SubscribeEvent + public void onItemTooltip(ItemTooltipEvent event) { + if (!neu.isOnSkyblock()) return; + if (event.toolTip == null) return; + if (!Utils.getOpenChestName().endsWith(" RNG Meter") && !slayerData.containsKey(Utils.getOpenChestName())) return; + + List newToolTip = new ArrayList<>(); + + boolean nextLineProgress = false; + for (String line : event.toolTip) { + + if (line.contains("Odds:")) { + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterFractionDisplay) { + fractionDisplay(newToolTip, line); + continue; + } + } + + if (nextLineProgress || line.contains("Dungeon Score:") || line.contains("Slayer XP:")) { + Matcher matcher = RUNS_PATTERN.matcher(line); + Matcher matcherSelected = RUNS_SELECTED_PATTERN.matcher(line); + Matcher m = null; + if (matcher.matches()) { + m = matcher; + } else if (matcherSelected.matches()) { + m = matcherSelected; + } + + if (m != null) { + int having; + try { + having = Calculator.calculate(m.group(2).replace(",", "")).intValue(); + } catch (Calculator.CalculatorException e) { + having = -1; + } + + int needed; + try { + needed = Calculator.calculate(m.group(3).replace(",", "")).intValue(); + } catch (Calculator.CalculatorException e) { + needed = -1; + } + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterRunsNeeded) { + runsRequired(newToolTip, having, needed, nextLineProgress, event.itemStack); + } + + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterProfitPerUnit) { + if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterRunsNeeded) { + String name = Utils.getOpenChestName().contains("Catacombs") ? "Score" : "XP"; + String formatCoinsPer = getFormatCoinsPer(event.itemStack, needed, 1, name); + if (formatCoinsPer != null) { + newToolTip.add(line); + newToolTip.add(formatCoinsPer); + continue; + } + } + } + } + nextLineProgress = false; + } + + if (line.contains("Progress:")) { + nextLineProgress = true; + } + newToolTip.add(line); + } + + event.toolTip.clear(); + event.toolTip.addAll(newToolTip); + } + + private String getFormatCoinsPer(ItemStack stack, int needed, int multiplier, String name) { + String internalName = neu.manager.getInternalNameForItem(stack); + double bin = neu.manager.auctionManager.getBazaarOrBin(internalName); + if (bin <= 0) return null; + + double coinsPer = (bin / needed) * multiplier; + String format = StringUtils.shortNumberFormat(coinsPer); + return "§7Coins per " + name + ": §6" + format + " coins"; + } + + private void fractionDisplay(List newToolTip, String line) { + boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + if (!pressedShiftLast && shift) { + showSlayerRngFractions = !showSlayerRngFractions; + } + pressedShiftLast = shift; + + String result; + Matcher matcher = ODDS_PATTERN.matcher(line); + Matcher matcherSelected = ODDS_SELECTED_PATTERN.matcher(line); + if (matcher.matches()) { + String odds = matcher.group(1); + int baseChance = calculateChance(matcher.group(2)); + String baseFormat = GuiProfileViewer.numberFormat.format(baseChance); + + String fractionFormat = "§7(1/" + baseFormat + ")"; + result = odds + " " + fractionFormat; + } else if (matcherSelected.matches()) { + String odds = matcherSelected.group(1); + int baseChance = calculateChance(matcherSelected.group(2)); + String baseFormat = GuiProfileViewer.numberFormat.format(baseChance); + + int increasedChance = calculateChance(matcherSelected.group(3)); + String increased = GuiProfileViewer.numberFormat.format(increasedChance); + String fractionFormat = "§7(§8§m1/" + baseFormat + "§r §71/" + increased + ")"; + + result = odds + " " + fractionFormat; + } else { + return; + } + + if (showSlayerRngFractions) { + newToolTip.add("§7Odds: " + result); + newToolTip.add("§8[Press SHIFT to show odds as percentages]"); + } else { + newToolTip.add(line); + newToolTip.add("§8[Press SHIFT to show odds as fractions]"); + } + } + + /** + * This adds support for the /neureloadrepo command + */ + @SubscribeEvent(priority = EventPriority.LOWEST) + public void onRepoReload(RepositoryReloadEvent event) { + repoReloadNeeded = true; + } + + public void checkUpdateData() { + if (repoReloadNeeded) { + updateRepoData(); + } + } + + private void updateRepoData() { + slayerData.clear(); + dungeonData.clear(); + + JsonObject leveling = Constants.LEVELING; + if (!leveling.has("slayer_boss_xp") || + !leveling.has("slayer_highest_tier") || + !leveling.has("slayer_tier_colors") || + !leveling.has("rng_meter_dungeon_score")) { + Utils.showOutdatedRepoNotification(); + return; + } + + List slayerExp = new ArrayList<>(); + for (JsonElement element : leveling.get("slayer_boss_xp").getAsJsonArray()) { + slayerExp.add(element.getAsInt()); + } + + List slayerColors = new ArrayList<>(); + for (JsonElement element : leveling.get("slayer_tier_colors").getAsJsonArray()) { + slayerColors.add(element.getAsString()); + } + + for (Map.Entry entry : leveling.get("slayer_highest_tier").getAsJsonObject().entrySet()) { + String slayerName = entry.getKey(); + int maxTier = entry.getValue().getAsInt(); + LinkedHashMap singleSlayerData = new LinkedHashMap<>(); + for (int i = 0; i < maxTier; i++) { + String name = slayerColors.get(i) + "Tier " + (i + 1); + singleSlayerData.put(name, slayerExp.get(i)); + } + slayerData.put(slayerName, singleSlayerData); + } + + for (Map.Entry entry : leveling.get("rng_meter_dungeon_score").getAsJsonObject().entrySet()) { + String dungeonScore = entry.getKey(); + int score = entry.getValue().getAsInt(); + dungeonData.put(dungeonScore, score); + } + + repoReloadNeeded = false; + } + + private void runsRequired( + List toolTip, + int having, + int needed, + boolean nextLineProgress, + ItemStack stack + ) { + checkUpdateData(); + if (repoReloadNeeded) return; + + String openChestName = Utils.getOpenChestName(); + Map runsData; + String labelPlural; + String labelSingular; + if (openChestName.contains("Catacombs")) { + runsData = dungeonData; + labelPlural = "Runs"; + labelSingular = "Run"; + } else { // Slayer + Matcher matcher = SLAYER_INVENTORY_TITLE_PATTERN.matcher(openChestName); + if (!matcher.matches()) { + //Happens for the first 4-5 ticks after inventory opens. Thanks hypixel + return; + } + + String slayerName = matcher.group(1); + runsData = slayerData.get(slayerName); + labelPlural = "Bosses"; + labelSingular = "Boss"; + } + + handleArrowKeys(runsData); + + if (currentSelected >= runsData.keySet().size()) { + currentSelected = 0; + } + + String name = (String) runsData.keySet().toArray()[currentSelected]; + int gainPerRun = runsData.get(name); + + int runsNeeded = needed / gainPerRun; + int runsHaving = having / gainPerRun; + String runsNeededFormat = GuiProfileViewer.numberFormat.format(runsNeeded); + String runsHavingFormat = GuiProfileViewer.numberFormat.format(runsHaving); + + String progressString = null; + if (nextLineProgress) { + progressString = toolTip.remove(toolTip.size() - 1); + } + + toolTip.add("§9Stats for " + name + "§9: [§l§m< §9Switch§l➡§9]"); + toolTip.add( + " §7" + labelPlural + " completed: §e" + runsHavingFormat + " §7(of §e" + runsNeededFormat + " §7needed)"); + + if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterProfitPerUnit) { + String formatCoinsPer = getFormatCoinsPer(stack, needed, gainPerRun, labelSingular); + if (formatCoinsPer != null) { + toolTip.add(" " + formatCoinsPer); + } + } + + toolTip.add(" "); + if (progressString != null) { + toolTip.add(progressString); + } + } + + private void handleArrowKeys(Map runsData) { + boolean left = Keyboard.isKeyDown(Keyboard.KEY_LEFT); + boolean right = Keyboard.isKeyDown(Keyboard.KEY_RIGHT); + if (!pressedArrowLast && (left || right)) { + if (Utils.getOpenChestName().contains("Catacombs") ? right : left) { + currentSelected--; + } else { + currentSelected++; + } + if (currentSelected < 0) currentSelected = 0; + if (currentSelected >= runsData.size()) currentSelected = runsData.size() - 1; + } + pressedArrowLast = left || right; + } + + private int calculateChance(String string) { + return (int) (100.0 / Double.parseDouble(string)); + } +} 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 54b647e9..166e46d0 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java @@ -53,6 +53,7 @@ import io.github.moulberry.notenoughupdates.miscgui.TrophyRewardOverlay; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.overlays.AuctionSearchOverlay; +import io.github.moulberry.notenoughupdates.overlays.BazaarSearchOverlay; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; import io.github.moulberry.notenoughupdates.overlays.RancherBootOverlay; import io.github.moulberry.notenoughupdates.overlays.TextOverlay; @@ -119,6 +120,8 @@ import java.util.TreeMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import static io.github.moulberry.notenoughupdates.util.GuiTextures.dungeon_chest_worth; @@ -146,6 +149,8 @@ public class RenderListener { private boolean inDungeonPage = false; private final NumberFormat format = new DecimalFormat("#,##0.#", new DecimalFormatSymbols(Locale.US)); + private final Pattern ESSENCE_PATTERN = Pattern.compile("§d(.+) Essence §8x([\\d,]+)"); + public RenderListener(NotEnoughUpdates neu) { this.neu = neu; } @@ -420,6 +425,11 @@ public class RenderListener { event.setCanceled(true); return; } + if (BazaarSearchOverlay.shouldReplace()) { + BazaarSearchOverlay.render(); + event.setCanceled(true); + return; + } if (RancherBootOverlay.shouldReplace()) { RancherBootOverlay.render(); event.setCanceled(true); @@ -736,7 +746,7 @@ public class RenderListener { StringBuilder cost = new StringBuilder(); for (int i = 0; i < line6.length(); i++) { char c = line6.charAt(i); - if ("0123456789".indexOf(c) >= 0) { + if (Character.isDigit(c)) { cost.append(c); } } @@ -752,6 +762,20 @@ public class RenderListener { for (int i = 0; i < 5; i++) { ItemStack item = lower.getStackInSlot(11 + i); String internal = neu.manager.getInternalNameForItem(item); + String displayName = item.getDisplayName(); + Matcher matcher = ESSENCE_PATTERN.matcher(displayName); + if (neu.config.dungeons.useEssenceCostFromBazaar && matcher.matches()) { + String type = matcher.group(1).toUpperCase(); + JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo("ESSENCE_" + type); + if (bazaarInfo != null && bazaarInfo.has("curr_sell")) { + float bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat(); + int amount = Integer.parseInt(matcher.group(2)); + double price = bazaarPrice * amount; + itemValues.put(displayName, price); + totalValue += price; + } + continue; + } if (internal != null) { internal = internal.replace("\u00CD", "I").replace("\u0130", "I"); float bazaarPrice = -1; @@ -986,6 +1010,11 @@ public class RenderListener { event.setCanceled(true); return; } + if (BazaarSearchOverlay.shouldReplace()) { + BazaarSearchOverlay.mouseEvent(); + event.setCanceled(true); + return; + } if (RancherBootOverlay.shouldReplace()) { RancherBootOverlay.mouseEvent(); event.setCanceled(true); @@ -1466,6 +1495,11 @@ public class RenderListener { event.setCanceled(true); return; } + if (BazaarSearchOverlay.shouldReplace()) { + BazaarSearchOverlay.keyEvent(); + event.setCanceled(true); + return; + } if (RancherBootOverlay.shouldReplace()) { RancherBootOverlay.keyEvent(); event.setCanceled(true); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java index e1024eab..88ca0cc8 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java @@ -20,8 +20,8 @@ package io.github.moulberry.notenoughupdates.miscfeatures; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; -import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; @@ -145,10 +145,10 @@ public class AuctionProfit { String coinsToCollectStr = EnumChatFormatting.BOLD + EnumChatFormatting.DARK_GRAY.toString() + "Coins to collect: " + EnumChatFormatting.RESET + EnumChatFormatting.DARK_GREEN + "" + - GuiProfileViewer.shortNumberFormat(coinsToCollect, 0); + StringUtils.shortNumberFormat(coinsToCollect); String valueIfSoldStr = EnumChatFormatting.BOLD + EnumChatFormatting.DARK_GRAY.toString() + "Value if all sold: " + EnumChatFormatting.RESET + EnumChatFormatting.DARK_GREEN + "" + - GuiProfileViewer.shortNumberFormat(coinsIfAllSold, 0); + StringUtils.shortNumberFormat(coinsIfAllSold); fontRendererObj.drawString(coinsToCollectStr, a + 6, guiTop + 32, -1, false); fontRendererObj.drawString(valueIfSoldStr, a + 6, guiTop + 42, -1, false); 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 084fd03f..7007f39b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BazaarSacksProfit.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BazaarSacksProfit.java @@ -68,7 +68,7 @@ public class BazaarSacksProfit { @SubscribeEvent(priority = EventPriority.LOW) public void onItemTooltipLow(ItemTooltipEvent event) { - if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.bazaarSacksProfit) return; + if (!NotEnoughUpdates.INSTANCE.config.bazaarTweaks.bazaarSacksProfit) return; if (!inBazaar()) return; ItemStack itemStack = event.itemStack; @@ -89,6 +89,11 @@ public class BazaarSacksProfit { out: for (String line : ItemUtils.getLore(itemStack)) { + + if (line.equals("§8Loading...")) { + dirty = true; + return; + } if (line.contains("§7x ")) { String[] split = line.split("§7x "); String rawAmount = StringUtils.cleanColour(split[0]).replace(",", "").substring(1); @@ -108,7 +113,7 @@ public class BazaarSacksProfit { } } } - System.out.println("no bazaar item in repo found for '" + bazaarName + "'"); + System.err.println("no bazaar item in repo found for '" + bazaarName + "'"); invalidNames.add(bazaarName); } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java index 127edcde..b1ab11c1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java @@ -45,15 +45,18 @@ public class DamageCommas { }; private static final char STAR = '\u2727'; + private static final char OVERLOAD_STAR = '\u272F'; private static final Pattern PATTERN_CRIT = Pattern.compile( - "\u00a7f" + STAR + "((?:\u00a7.\\d)+)\u00a7." + STAR + "(.*)"); - private static final Pattern PATTERN_NO_CRIT = Pattern.compile("\u00a77(\\d+)(.*)"); + "\u00a7f" + STAR + "((?:\u00a7.\\d(?:§.,)?)+)\u00a7." + STAR + "(.*)"); + private static final Pattern PATTERN_NO_CRIT = Pattern.compile("(\u00a7.)([\\d+,]*)(.*)"); + private static final Pattern OVERLOAD_PATTERN = Pattern.compile("(\u00a7.)" + OVERLOAD_STAR + "((?:\u00a7.[\\d,])+)(\u00a7.)" + OVERLOAD_STAR + "\u00a7r"); public static IChatComponent replaceName(EntityLivingBase entity) { if (!entity.hasCustomName()) return entity.getDisplayName(); IChatComponent name = entity.getDisplayName(); - if (NotEnoughUpdates.INSTANCE.config.misc.damageIndicatorStyle == 0) return name; + if (!NotEnoughUpdates.INSTANCE.config.misc.damageIndicatorStyle2) return name; + if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return name; if (replacementMap.containsKey(entity)) { ChatComponentText component = replacementMap.get(entity); @@ -69,17 +72,23 @@ public class DamageCommas { String suffix; Matcher matcherCrit = PATTERN_CRIT.matcher(formatted); + Matcher matcherOverload = OVERLOAD_PATTERN.matcher(formatted); if (matcherCrit.matches()) { crit = true; - numbers = StringUtils.cleanColour(matcherCrit.group(1)); + numbers = StringUtils.cleanColour(matcherCrit.group(1)).replace(",", ""); prefix = "\u00a7f" + STAR; suffix = "\u00a7f" + STAR + matcherCrit.group(2); - } else { + } else if (matcherOverload.matches()) { + crit = true; + numbers = StringUtils.cleanColour(matcherOverload.group(2)).replace(",", ""); + prefix = matcherOverload.group(1) + OVERLOAD_STAR; + suffix = matcherOverload.group(3) + OVERLOAD_STAR + "\u00a7r"; + } else { Matcher matcherNoCrit = PATTERN_NO_CRIT.matcher(formatted); if (matcherNoCrit.matches()) { - numbers = matcherNoCrit.group(1); - prefix = "\u00A77"; - suffix = "\u00A7r" + matcherNoCrit.group(2); + numbers = matcherNoCrit.group(2).replace(",", ""); + prefix = matcherNoCrit.group(1); + suffix = "\u00A7r" + matcherNoCrit.group(3); } else { replacementMap.put(entity, null); return name; @@ -91,10 +100,10 @@ public class DamageCommas { try { int number = Integer.parseInt(numbers); - if (number > 999 && NotEnoughUpdates.INSTANCE.config.misc.damageIndicatorStyle == 2) { + if (number > 999) { newFormatted.append(Utils.shortNumberFormat(number, 0)); } else { - newFormatted.append(NumberFormat.getIntegerInstance().format(number)); + return name; } } catch (NumberFormatException e) { replacementMap.put(entity, null); 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 b6c3e763..530dcfd1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java @@ -847,7 +847,7 @@ public class AccessoryBagOverlay { if (info != null) cost1 = info.craftCost; else - cost1 = 0; + cost1 = -1; } double cost2; JsonObject o2Auc = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(o2); @@ -858,7 +858,7 @@ public class AccessoryBagOverlay { if (info != null) cost2 = info.craftCost; else - cost2 = 0; + cost2 = -1; } if (cost1 == -1 && cost2 == -1) return o1.compareTo(o2); 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 2b600d2e..e6c4dc74 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java @@ -70,7 +70,7 @@ public class TrophyRewardOverlay { * This adds support for the /neureloadrepo command */ @SubscribeEvent(priority = EventPriority.LOWEST) - public void reload(RepositoryReloadEvent event) { + public void onRepoReload(RepositoryReloadEvent event) { reloadNeeded = true; } 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 06512fa8..7c3414fa 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java @@ -125,7 +125,7 @@ public abstract class MixinGuiContainer extends GuiScreen { else if (!($this instanceof GuiChest)) BetterContainers.profileViewerStackIndex = -1; - if (slot.getStack() == null && NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen) { + if (slot.getStack() == null && NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen && NotEnoughUpdates.INSTANCE.isOnSkyblock()) { GlStateManager.pushMatrix(); GlStateManager.translate(0, 0, 100 + Minecraft.getMinecraft().getRenderItem().zLevel); GlStateManager.depthMask(false); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java index 4f193c98..dc59c0bb 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java @@ -195,7 +195,7 @@ public abstract class MixinRenderItem { @Inject(method = "renderItemIntoGUI", at = @At("HEAD")) public void renderItemHead(ItemStack stack, int x, int y, CallbackInfo ci) { - if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen) { + if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen && NotEnoughUpdates.INSTANCE.isOnSkyblock()) { boolean matches = false; GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField(); @@ -221,7 +221,7 @@ public abstract class MixinRenderItem { @Inject(method = "renderItemIntoGUI", at = @At("RETURN")) public void renderItemReturn(ItemStack stack, int x, int y, CallbackInfo ci) { if (stack != null && stack.stackSize != 1) return; - if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen) { + if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen && NotEnoughUpdates.INSTANCE.isOnSkyblock()) { boolean matches = false; GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField(); @@ -252,7 +252,7 @@ public abstract class MixinRenderItem { CallbackInfo ci ) { if (stack != null && stack.stackSize != 1) { - if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen) { + if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen && NotEnoughUpdates.INSTANCE.isOnSkyblock()) { boolean matches = false; GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinSkyclientCosmetics.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinSkyclientCosmetics.java new file mode 100644 index 00000000..32c9f418 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinSkyclientCosmetics.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see . + */ + +package io.github.moulberry.notenoughupdates.mixins; + +import net.minecraftforge.event.world.WorldEvent; +import org.spongepowered.asm.mixin.Dynamic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Pseudo +@Mixin(targets = "co.skyclient.scc.SkyclientCosmetics") +public class MixinSkyclientCosmetics { + + @Dynamic + @Inject(method = "onWorldLoad", at = @At("HEAD"), cancellable = true, remap = false) + public void onWorldLoad(WorldEvent.Load event, CallbackInfo ci) { + ci.cancel(); + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java index ade9edfe..4d04bfbc 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java @@ -37,6 +37,7 @@ import io.github.moulberry.notenoughupdates.options.seperateSections.AHGraph; import io.github.moulberry.notenoughupdates.options.seperateSections.AHTweaks; import io.github.moulberry.notenoughupdates.options.seperateSections.AccessoryBag; import io.github.moulberry.notenoughupdates.options.seperateSections.ApiData; +import io.github.moulberry.notenoughupdates.options.seperateSections.BazaarTweaks; import io.github.moulberry.notenoughupdates.options.seperateSections.Calendar; import io.github.moulberry.notenoughupdates.options.seperateSections.CustomArmour; import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig; @@ -369,6 +370,13 @@ public class NEUConfig extends Config { ) public AHTweaks ahTweaks = new AHTweaks(); + @Expose + @Category( + name = "Bazaar Tweaks", + desc = "Tweaks for the Bazaar" + ) + public BazaarTweaks bazaarTweaks = new BazaarTweaks(); + @Expose @Category( name = "AH/BZ Graph", @@ -445,6 +453,8 @@ public class NEUConfig extends Config { @Expose public ArrayList previousAuctionSearches = new ArrayList<>(); @Expose + public ArrayList previousBazaarSearches = new ArrayList<>(); + @Expose public ArrayList eventFavourites = new ArrayList<>(); @Expose public ArrayList quickCommands = createDefaultQuickCommands(); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/BazaarTweaks.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/BazaarTweaks.java new file mode 100644 index 00000000..2ba0b718 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/BazaarTweaks.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see . + */ + +package io.github.moulberry.notenoughupdates.options.seperateSections; + +import com.google.gson.annotations.Expose; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean; +import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption; + +public class BazaarTweaks { + + @ConfigOption( + name = "Search GUI", + desc = "" + ) + @ConfigEditorAccordion(id = 0) + public boolean searchAccordion = false; + + @Expose + @ConfigOption( + name = "Enable Search GUI", + desc = "Use the advanced search GUI with autocomplete and history instead of the normal sign GUI" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 0) + public boolean enableSearchOverlay = true; + + @Expose + @ConfigOption( + name = "Keep Previous Search", + desc = "Don't clear the search bar after closing the GUI" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 0) + public boolean keepPreviousSearch = false; + + @Expose + @ConfigOption( + name = "Past Searches", + desc = "Show past searches below the autocomplete box" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 0) + public boolean showPastSearches = true; + + @Expose + @ConfigOption( + name = "ESC to Full Close", + desc = "Make pressing ESCAPE close the search GUI without opening up the Bazaar again\n" + + "ENTER can still be used to search" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 0) + public boolean escFullClose = true; + + @Expose + @ConfigOption( + name = "Bazaar Sacks Profit", + desc = "Orders the items in your sacks in the bazaar inventory and adding buy order toggle" + ) + @ConfigEditorBoolean + public boolean bazaarSacksProfit = true; +} 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 e080db7d..c94bd181 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 = "Include Essence Cost", + desc = "Include Bazaar Essence Sell Cost in the Profit Calculation for Dungeon Chests" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean useEssenceCostFromBazaar = true; + @Expose @ConfigOption( name = "Warning if Derpy active", diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java index d87082b4..84e2322e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java @@ -126,13 +126,11 @@ public class Misc { @Expose @ConfigOption( name = "Damage Indicator Style", - desc = "Change the style of Skyblock damage indicators to be easier to read\n" + + desc = "Change Skyblock damage indicators to use shortened numbers\n" + "\u00A7cSome old animations mods break this feature" ) - @ConfigEditorDropdown( - values = {"Off", "Commas", "Shortened"} - ) - public int damageIndicatorStyle = 1; + @ConfigEditorBoolean + public boolean damageIndicatorStyle2 = false; @Expose @ConfigOption( 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 8b7002f9..943417e6 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 @@ -274,7 +274,7 @@ public class SkillOverlays { @Expose @ConfigOption( name = "\u00A7cWarning", - desc = "The combat display will only show if you have a Book of Stats on the item you are using" + desc = "The combat display will only show if you have a Book of Stats or the Champion enchant" ) @ConfigEditorFSR( runnableId = 12, @@ -305,11 +305,12 @@ public class SkillOverlays { "\u00a7bCurrent XP: \u00a7e6,734", "\u00a7bRemaining XP: \u00a7e3,265", "\u00a7bXP/h: \u00a7e238,129", - "\u00a7bETA: \u00a7e13h12m" + "\u00a7bETA: \u00a7e13h12m", + "\u00a7bChampion XP: \u00a7e3,523" } ) @ConfigAccordionId(id = 4) - public List combatText = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5)); + public List combatText = new ArrayList<>(Arrays.asList(0, 6, 1, 2, 3, 4, 5)); @Expose @ConfigOption( @@ -337,7 +338,7 @@ public class SkillOverlays { @Expose @ConfigOption( name = "Always show combat overlay", - desc = "Shows combat overlay even if you dont have Book of Stats" + desc = "Shows combat overlay even if you dont have Book of Stats or the Champion enchant" ) @ConfigEditorBoolean @ConfigAccordionId(id = 4) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java index 0729df97..1edc0921 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java @@ -181,11 +181,45 @@ public class TooltipTweaks { @ConfigEditorBoolean public boolean powerStoneStats = true; + @ConfigOption( + name = "RNG Meter", + desc = "" + ) + @ConfigEditorAccordion(id = 1) + public boolean rngMeter = false; + + @Expose + @ConfigOption( + name = "Fraction Display", + desc = "Show the fraction instead of the percentage in the slayer and dungeon rng meter inventory" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean rngMeterFractionDisplay = true; + + @Expose + @ConfigOption( + name = " Profit Per Score/XP", + desc = "Show the amount of coins per Score/XP in the rng meter inventory" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean rngMeterProfitPerUnit = true; + + @Expose + @ConfigOption( + name = "Dungeon/Slayer Needed Counter", + desc = "Show the amount of dungeon runs or slayer bosses needed for the rng meter to fill up" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 1) + public boolean rngMeterRunsNeeded = true; + @Expose @ConfigOption( - name = "Bazaar Sacks Profit", - desc = "Orders the items in your sacks in the bazaar inventory and adding buy order toggle" + name = "Essence Price In Shop", + desc = "Show the essence price in the essence shop in the dungeon hub" ) @ConfigEditorBoolean - public boolean bazaarSacksProfit = true; + public boolean essencePriceInEssenceShop = true; } 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 8ff3218a..fcea79dd 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java @@ -607,7 +607,7 @@ public class AuctionSearchOverlay { close(); Minecraft.getMinecraft().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow(Minecraft.getMinecraft().thePlayer.openContainer.windowId)); NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(new NEUConfigEditor( - NotEnoughUpdates.INSTANCE.config, "AH Search GUI")); + NotEnoughUpdates.INSTANCE.config, "AH Tweaks")); } } } else if (Mouse.getEventButton() == 0) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java new file mode 100644 index 00000000..66dacda3 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java @@ -0,0 +1,572 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see . + */ + +package io.github.moulberry.notenoughupdates.overlays; + +import com.google.common.base.Splitter; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.GuiElementTextField; +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.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.gui.inventory.GuiEditSign; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.client.C0DPacketCloseWindow; +import net.minecraft.tileentity.TileEntitySign; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + +public class BazaarSearchOverlay { + private static final ResourceLocation SEARCH_OVERLAY_TEXTURE = new ResourceLocation( + "notenoughupdates:auc_search/ah_search_overlay.png"); + private static final ResourceLocation SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED = new ResourceLocation( + "notenoughupdates:auc_search/ah_search_overlay_tab_completed.png"); + + private static final GuiElementTextField textField = new GuiElementTextField("", 200, 20, 0); + private static boolean searchFieldClicked = false; + private static String searchString = ""; + private static String searchStringExtra = ""; + private static final Splitter SPACE_SPLITTER = Splitter.on(" ").omitEmptyStrings().trimResults(); + private static boolean tabCompleted = false; + private static int tabCompletionIndex = -1; + + private static final int AUTOCOMPLETE_HEIGHT = 118; + + private static final Set autocompletedItems = new LinkedHashSet<>(); + + private static final Comparator salesComparator = (o1, o2) -> { + JsonObject bazaarInfo1 = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(o1); + JsonObject bazaarInfo2 = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(o2); + + boolean auc1Invalid = bazaarInfo1 == null || !bazaarInfo1.has("curr_sell"); + boolean auc2Invalid = bazaarInfo2 == null || !bazaarInfo2.has("curr_sell"); + + if (auc1Invalid && auc2Invalid) return o1.compareTo(o2); + if (auc1Invalid) return -1; + if (auc2Invalid) return 1; + + int sales1 = bazaarInfo1.get("curr_sell").getAsInt(); + int sales2 = bazaarInfo2.get("curr_sell").getAsInt(); + + if (sales1 == sales2) return o1.compareTo(o2); + if (sales1 > sales2) return -1; + return 1; + }; + + public static boolean shouldReplace() { + if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return false; + if (!NotEnoughUpdates.INSTANCE.config.bazaarTweaks.enableSearchOverlay) return false; + + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiEditSign)) { + if (!NotEnoughUpdates.INSTANCE.config.bazaarTweaks.keepPreviousSearch) searchString = ""; + return false; + } + + String lastContainer = Utils.getLastOpenChestName(); + if (!lastContainer.startsWith("Bazaar ➜ ")) return false; + + TileEntitySign tes = ((AccessorGuiEditSign) Minecraft.getMinecraft().currentScreen).getTileSign(); + + if (tes == null) return false; + if (tes.getPos().getY() != 0) return false; + if (!tes.signText[2].getUnformattedText().equals("^^^^^^^^^^^^^^^")) return false; + return tes.signText[3].getUnformattedText().equals("Enter query"); + } + + public static void render() { + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth; + int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1; + + Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680); + + int h = NotEnoughUpdates.INSTANCE.config.bazaarTweaks.showPastSearches ? 219 : 145; + + int topY = height / 4; + if (scaledResolution.getScaleFactor() >= 4) { + topY = height / 2 - h / 2 + 5; + } + + Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect(width / 2 - 100, topY - 1, 203, h, 0, 203 / 512f, 0, h / 256f, GL11.GL_NEAREST); + + Minecraft.getMinecraft().fontRendererObj.drawString("Enter Query:", width / 2 - 100, topY - 10, 0xdddddd, true); + + textField.setFocus(true); + textField.setText(searchString); + textField.setSize(149, 20); + textField.setCustomBorderColour(0xffffff); + textField.render(width / 2 - 100 + 1, topY + 1); + + if (textField.getText().trim().isEmpty()) autocompletedItems.clear(); + + List tooltipToDisplay = null; + + int num = 0; + synchronized (autocompletedItems) { + String[] autoCompletedItemsArray = autocompletedItems.toArray(new String[0]); + for (int i = 0; i < autoCompletedItemsArray.length; i++) { + String str = autoCompletedItemsArray[i]; + JsonObject obj = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(str); + if (obj != null) { + ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(obj); + if (i == tabCompletionIndex) { + Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect( + width / 2 - 96 + 1, + topY + 30 + num * 22 + 1, + 193, + 21, + 0 / 512f, + 193 / 512f, + 0, + 21 / 256f, + GL11.GL_NEAREST + ); + } else { + Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE); + GlStateManager.color(1, 1, 1, 1); + Utils.drawTexturedRect( + width / 2 - 96 + 1, + topY + 30 + num * 22 + 1, + 193, + 21, + 214 / 512f, + 407 / 512f, + 0, + 21 / 256f, + GL11.GL_NEAREST + ); + + } + String itemName = Utils.trimIgnoreColour(stack.getDisplayName().replaceAll("\\[.+]", "")); + if (itemName.contains("Enchanted Book") && str.contains(";")) { + String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound()); + itemName = lore[0].trim(); + } + + Minecraft.getMinecraft().fontRendererObj.drawString(Minecraft.getMinecraft().fontRendererObj.trimStringToWidth( + itemName, + 165 + ), + width / 2 - 74, topY + 35 + num * 22 + 1, 0xdddddd, true + ); + + GlStateManager.enableDepth(); + Utils.drawItemStack(stack, width / 2 - 94 + 2, topY + 32 + num * 22 + 1); + + if (mouseX > width / 2 - 96 && mouseX < width / 2 + 96 && mouseY > topY + 30 + num * 22 && + mouseY < topY + 30 + num * 22 + 20) { + tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false); + } + + if (++num >= 5) break; + } + } + } + + if (NotEnoughUpdates.INSTANCE.config.bazaarTweaks.showPastSearches) { + Minecraft.getMinecraft().fontRendererObj.drawString( + "Past Searches:", + width / 2 - 100, + topY + 25 + AUTOCOMPLETE_HEIGHT + 5, + 0xdddddd, + true + ); + + for (int i = 0; i < 5; i++) { + if (i >= NotEnoughUpdates.INSTANCE.config.hidden.previousBazaarSearches.size()) break; + + String s = NotEnoughUpdates.INSTANCE.config.hidden.previousBazaarSearches.get(i); + Minecraft.getMinecraft().fontRendererObj.drawString( + s, + width / 2 - 95 + 1, + topY + 45 + AUTOCOMPLETE_HEIGHT + i * 10 + 2, + 0xdddddd, + true + ); + } + + if (tooltipToDisplay != null) { + Utils.drawHoveringText( + tooltipToDisplay, + mouseX, + mouseY, + width, + height, + -1, + Minecraft.getMinecraft().fontRendererObj + ); + } + } + + } + + private static final ExecutorService searchES = Executors.newSingleThreadExecutor(); + private static final AtomicInteger searchId = new AtomicInteger(0); + + private static String getItemIdAtIndex(int i) { + if (!autocompletedItems.isEmpty()) { + if ((i > autocompletedItems.size() - 1) || i < 0 || i > 4) { + return ""; + } + String searchString = autocompletedItems.toArray()[i].toString(); + JsonObject repoObject = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(searchString); + if (repoObject != null) { + ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(repoObject); + return Utils.cleanColour(stack.getDisplayName().replaceAll("\\[.+]", "")); + } + + } + return null; + } + + public static void close() { + if (tabCompleted) { + tabCompletionIndex = -1; + tabCompleted = false; + } + if (NotEnoughUpdates.INSTANCE.config.bazaarTweaks.keepPreviousSearch) { + search(); + } else { + synchronized (autocompletedItems) { + autocompletedItems.clear(); + } + } + + TileEntitySign tes = ((AccessorGuiEditSign) Minecraft.getMinecraft().currentScreen).getTileSign(); + + StringBuilder stringBuilder = new StringBuilder(searchString.trim()); + if (!searchStringExtra.isEmpty()) { + stringBuilder.append(searchStringExtra); + } + + String search = stringBuilder.toString(); + + if (search.length() <= 15) { + tes.signText[0] = new ChatComponentText(search.substring(0, Math.min(search.length(), 15))); + } else { + List words = SPACE_SPLITTER.splitToList(search); + + StringBuilder line0 = new StringBuilder(); + StringBuilder line1 = new StringBuilder(); + + int currentLine = 0; + for (String word : words) { + if (currentLine == 0) { + if (line0.length() + word.lengt