diff options
author | Fluboxer <fluboxer@gmail.com> | 2024-02-21 15:04:59 +0300 |
---|---|---|
committer | Fluboxer <fluboxer@gmail.com> | 2024-02-21 15:04:59 +0300 |
commit | b10906fc55a480675c9dcea9e402792791af6916 (patch) | |
tree | f94c6e41d263e4f0c5848b101a4f9697358746d5 /src/main/java | |
parent | 7b6eac893985c42aa10d7596eb55eb6a72e8d185 (diff) | |
download | Skyblocker-b10906fc55a480675c9dcea9e402792791af6916.tar.gz Skyblocker-b10906fc55a480675c9dcea9e402792791af6916.tar.bz2 Skyblocker-b10906fc55a480675c9dcea9e402792791af6916.zip |
1st iteration of calculator for Croesus
I did testings on M5 and M6 drops and so far it were working properly. Only thing I'm unsure is spirit pet
and yes it does use big map for every dungeon drop lmao
Diffstat (limited to 'src/main/java')
5 files changed, 291 insertions, 2 deletions
diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java index 78458291..f8bd61d4 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java @@ -684,6 +684,9 @@ public class SkyblockerConfig { public boolean croesusHelper = true; @SerialEntry + public boolean croesusProfit = true; + + @SerialEntry public boolean enableMap = true; @SerialEntry diff --git a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java index 3ebd5d76..f22d9584 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java @@ -328,6 +328,14 @@ public class DungeonsCategory { .controller(ConfigUtils::createBooleanController) .build()) .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.croesusProfit")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.croesusProfit.@Tooltip"))) + .binding(defaults.locations.dungeons.croesusProfit, + () -> config.locations.dungeons.croesusProfit, + newValue -> config.locations.dungeons.croesusProfit = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Boolean>createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.enableMap")) .binding(defaults.locations.dungeons.enableMap, () -> config.locations.dungeons.enableMap, diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusHelper.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusHelper.java index e95b47c9..01422770 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusHelper.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusHelper.java @@ -25,8 +25,12 @@ public class CroesusHelper extends ContainerSolver { List<ColorHighlight> highlights = new ArrayList<>(); for (Map.Entry<Integer, ItemStack> entry : slots.entrySet()) { ItemStack stack = entry.getValue(); - if (stack != null && stack.getNbt() != null && (stack.getNbt().toString().contains("No more Chests to open!") || stack.getNbt().toString().contains("Opened Chest:"))) { - highlights.add(ColorHighlight.gray(entry.getKey())); + if (stack != null && stack.getNbt() != null) { + if (stack.getNbt().toString().contains("Opened Chest:")) { + highlights.add(ColorHighlight.gray(entry.getKey())); + } else if (stack.getNbt().toString().contains("No more Chests to open!")) { + highlights.add(ColorHighlight.red(entry.getKey())); + } } } return highlights; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusProfit.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusProfit.java new file mode 100644 index 00000000..a2a82aee --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/CroesusProfit.java @@ -0,0 +1,272 @@ +package de.hysky.skyblocker.skyblock.dungeon; + +import com.google.gson.JsonObject; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip; +import de.hysky.skyblocker.skyblock.item.tooltip.TooltipInfoType; +import de.hysky.skyblocker.utils.render.gui.ColorHighlight; +import de.hysky.skyblocker.utils.render.gui.ContainerSolver; +import it.unimi.dsi.fastutil.longs.LongBooleanPair; +import net.minecraft.client.item.TooltipContext; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CroesusProfit extends ContainerSolver { + private static final Logger LOGGER = LogManager.getLogger(); + private static final Pattern ESSENCE_PATTERN = Pattern.compile("(?<type>[A-Za-z]+) Essence x(?<amount>[0-9]+)"); + private static final Pattern CHEST_PATTERN = Pattern.compile("literal\\{(.*?) Chest}"); + public CroesusProfit() { + super(".*Catacombs - Floor.*"); + } + + @Override + protected boolean isEnabled() { + return SkyblockerConfigManager.get().locations.dungeons.croesusProfit; + } + + @Override + protected List<ColorHighlight> getColors(String[] groups, Map<Integer, ItemStack> slots) { + List<ColorHighlight> highlights = new ArrayList<>(); + ItemStack bestChest = null, secondBestChest = null; + long bestValue = 0, secondBestValue = 0; // If negative value of chest - it is out of the question + long dungeonKeyPriceData = getItemPrice("DUNGEON_CHEST_KEY")*2; // lesser ones don't worth the hassle + + for (Map.Entry<Integer, ItemStack> entry : slots.entrySet()) { + ItemStack stack = entry.getValue(); + if (stack != null && stack.getNbt() != null && stack.getName().toString().contains("Chest")) { + long value = valueChest(stack); + if (value > bestValue) { + secondBestChest = bestChest; + secondBestValue = bestValue; + bestChest = stack; + bestValue = value; + } else if (value > secondBestValue) { + secondBestChest = stack; + secondBestValue = value; + } + } + } + + for (Map.Entry<Integer, ItemStack> entry : slots.entrySet()) { + ItemStack stack = entry.getValue(); + if (stack != null && stack.getNbt() != null) { + if (stack.equals(bestChest)) { + highlights.add(ColorHighlight.green(entry.getKey())); + } else if (stack.equals(secondBestChest) && secondBestValue > dungeonKeyPriceData) { + highlights.add(ColorHighlight.yellow(entry.getKey())); + } + } + } + return highlights; + } + + + private long valueChest(@NotNull ItemStack chest) { + long chestValue = 0; + int chestPrice = 0; + List<String> chestItems = new ArrayList<>(); + + Matcher matcher = CHEST_PATTERN.matcher(chest.getName().toString()); + String chestType = (matcher.find() ? matcher.group(1) : "Error"); // we are doing it for sole reason of saving us headache of a spirit pet rarity + + boolean processingContents = false; + for (Text line : chest.getTooltip(null, TooltipContext.BASIC)) { + String lineString = line.getString(); + if (lineString.contains("Contents")) { + processingContents = true; + continue; + } else if (lineString.isEmpty()) { + processingContents = false; + } else if (lineString.contains("Coins") && !processingContents) { + chestPrice = Integer.parseInt(lineString.replaceAll(",", "").replaceAll("\\D", "")); + } + + if (processingContents) { + if (lineString.contains("Essence")) { + matcher = ESSENCE_PATTERN.matcher(lineString); + if (matcher.matches()) { // add to chest value result of multiplying price of essence on it's amount + chestValue += getItemPrice(("ESSENCE_" + matcher.group("type")).toUpperCase()) * Integer.parseInt(matcher.group("amount")); + } + } else { + if (lineString.contains("Spirit")) { // I hate pets in chests. Speaking of which, this is only part of code I'm really not sure of + if (Objects.equals(chestType, "Diamond")) { + chestValue += getItemPrice("Spirit Epic"); // Diamond chest containts epic spirit + } else { + chestValue += getItemPrice(lineString); + } + } else { + chestItems.add(lineString); + } + } + } + } + for (String item : chestItems){ + chestValue += getItemPrice(item); + } + return chestValue-chestPrice; + } + + private long getItemPrice(String itemDisplayName) { + JsonObject bazaarPrices = TooltipInfoType.BAZAAR.getData(); + JsonObject lbinPrices = TooltipInfoType.LOWEST_BINS.getData(); + long itemValue = 0; + String id = dungeonDropsNameToId.get(itemDisplayName); + + if (bazaarPrices == null || lbinPrices == null) return 0; + + if (bazaarPrices.has(id)) { + JsonObject item = bazaarPrices.get(id).getAsJsonObject(); + boolean isPriceNull = item.get("sellPrice").isJsonNull(); + return (isPriceNull ? 0L : item.get("sellPrice").getAsLong()); + } else if (lbinPrices.has(id)) { + return lbinPrices.get(id).getAsLong(); + } + return itemValue; + } + + private String getChestType(String name) { + Matcher matcher = CHEST_PATTERN.matcher(name); + if (matcher.find()) { // add to chest value result of multiplying price of essence on it's amount + return matcher.group(); + } + return name; + } + + // I did a thing :( + final Map<String, String> dungeonDropsNameToId = new HashMap<>() {{ + put("Enchanted Book (Ultimate Jerry I)", "ENCHANTMENT_ULTIMATE_JERRY_1"); // ultimate books start + put("Enchanted Book (Ultimate Jerry II)", "ENCHANTMENT_ULTIMATE_JERRY_2"); + put("Enchanted Book (Ultimate Jerry III)", "ENCHANTMENT_ULTIMATE_JERRY_3"); + put("Enchanted Book (Bank I)", "ENCHANTMENT_ULTIMATE_BANK_1"); + put("Enchanted Book (Bank II)", "ENCHANTMENT_ULTIMATE_BANK_2"); + put("Enchanted Book (Bank III)", "ENCHANTMENT_ULTIMATE_BANK_3"); + put("Enchanted Book (Combo I)", "ENCHANTMENT_ULTIMATE_COMBO_1"); + put("Enchanted Book (Combo II)", "ENCHANTMENT_ULTIMATE_COMBO_2"); + put("Enchanted Book (No Pain No Gain I)", "ENCHANTMENT_ULTIMATE_NO_PAIN_NO_GAIN_1"); + put("Enchanted Book (No Pain No Gain II)", "ENCHANTMENT_ULTIMATE_NO_PAIN_NO_GAIN_2"); + put("Enchanted Book (Ultimate Wise I)", "ENCHANTMENT_ULTIMATE_WISE_1"); + put("Enchanted Book (Ultimate Wise II)", "ENCHANTMENT_ULTIMATE_WISE_2"); + put("Enchanted Book (Wisdom I)", "ENCHANTMENT_ULTIMATE_WISDOM_1"); + put("Enchanted Book (Wisdom II)", "ENCHANTMENT_ULTIMATE_WISDOM_2"); + put("Enchanted Book (Last Stand I)", "ENCHANTMENT_ULTIMATE_LAST_STAND_1"); + put("Enchanted Book (Last Stand II)", "ENCHANTMENT_ULTIMATE_LAST_STAND_2"); + put("Enchanted Book (Rend I)", "ENCHANTMENT_ULTIMATE_REND_1"); + put("Enchanted Book (Rend II)", "ENCHANTMENT_ULTIMATE_REND_2"); + put("Enchanted Book (Legion I)", "ENCHANTMENT_ULTIMATE_LEGION_1"); + put("Enchanted Book (Swarm I)", "ENCHANTMENT_ULTIMATE_SWARM_1"); + put("Enchanted Book (One For All I)", "ENCHANTMENT_ULTIMATE_ONE_FOR_ALL_1"); + put("Enchanted Book (Soul Eater I)", "ENCHANTMENT_ULTIMATE_SOUL_EATER_1"); // ultimate books end + put("Enchanted Book (Infinite Quiver VI)", "ENCHANTMENT_INFINITE_QUIVER_6"); // enchanted books start + put("Enchanted Book (Infinite Quiver VII)", "ENCHANTMENT_INFINITE_QUIVER_7"); + put("Enchanted Book (Feather Falling VI)", "ENCHANTMENT_FEATHER_FALLING_6"); + put("Enchanted Book (Feather Falling VII)", "ENCHANTMENT_FEATHER_FALLING_7"); + put("Enchanted Book (Rejuvenate I)", "ENCHANTMENT_REJUVENATE_1"); + put("Enchanted Book (Rejuvenate II)", "ENCHANTMENT_REJUVENATE_2"); + put("Enchanted Book (Rejuvenate III)", "ENCHANTMENT_REJUVENATE_3"); + put("Enchanted Book (Overload)", "ENCHANTMENT_OVERLOAD_1"); + put("Enchanted Book (Lethality VI)", "ENCHANTMENT_LETHALITY_6"); + put("Enchanted Book (Thunderlord VII)", "ENCHANTMENT_THUNDERLORD_7"); // enchanted books end + + put("Hot Potato Book", "HOT_POTATO_BOOK"); // HPB, FPB, Recomb (universal drops) + put("Fuming Potato Book", "FUMING_POTATO_BOOK"); + put("Recombobulator 3000", "RECOMBOBULATOR_3000"); + put("Necromancer's Brooch", "NECROMANCER_BROOCH"); + put("ESSENCE_WITHER","ESSENCE_WITHER"); // Essences. Really stupid way of doing this + put("ESSENCE_UNDEAD", "ESSENCE_UNDEAD"); + put("ESSENCE_DRAGON", "ESSENCE_DRAGON"); + put("ESSENCE_SPIDER", "ESSENCE_SPIDER"); + put("ESSENCE_ICE", "ESSENCE_ICE"); + put("ESSENCE_DIAMOND", "ESSENCE_DIAMOND"); + put("ESSENCE_GOLD", "ESSENCE_GOLD"); + put("ESSENCE_CRIMSON", "ESSENCE_CRIMSON"); + put("DUNGEON_CHEST_KEY", "DUNGEON_CHEST_KEY"); + + put("Bonzo's Staff", "BONZO_STAFF"); // F1 M1 + put("Master Skull - Tier 1", "MASTER_SKULL_TIER_1"); + put("Bonzo's Mask", "BONZO_MASK"); + put("Balloon Snake", "BALLOON_SNAKE"); + put("Red Nose", "RED_NOSE"); + + put("Red Scarf", "RED_SCARF"); // F2 M2 + put("Adaptive Blade", "STONE_BLADE"); + put("Master Skull - Tier 2", "MASTER_SKULL_TIER_2"); + put("Adaptive Belt", "ADAPTIVE_BELT"); + put("Scarf's Studies", "SCARF_STUDIES"); + + put("First Master Star", "FIRST_MASTER_STAR"); // F3 M3 + put("Adaptive Helmet", "ADAPTIVE_HELMET"); + put("Adaptive Chestplate", "ADAPTIVE_CHESTPLATE"); + put("Adaptive Leggings", "ADAPTIVE_LEGGINGS"); + put("Adaptive Boots", "ADAPTIVE_BOOTS"); + put("Master Skull - Tier 3", "MASTER_SKULL_TIER_3"); + put("Suspicious Vial", "SUSPICIOUS_VIAL"); + + put("Spirit Sword", "SPIRIT_SWORD"); // F4 M4 + put("Spirit Shortbow", "ITEM_SPIRIT_BOW"); + put("Spirit Boots", "THORNS_BOOTS"); + put("Spirit", "SPIRIT;4"); // Spirit pet (Legendary) + put("Spirit Epic", "SPIRIT;3"); + + put("Second Master Star", "SECOND_MASTER_STAR"); + put("Spirit Wing", "SPIRIT_WING"); + put("Spirit Bone", "SPIRIT_BONE"); + put("Spirit Stone", "SPIRIT_DECOY"); + + put("Shadow Fury", "SHADOW_FURY"); // F5 M5 + put("Last Breath", "LAST_BREATH"); + put("Third Master Star", "THIRD_MASTER_STAR"); + put("Warped Stone", "AOTE_STONE"); + put("Livid Dagger", "LIVID_DAGGER"); + put("Shadow Assassin Helmet", "SHADOW_ASSASSIN_HELMET"); + put("Shadow Assassin Chestplate", "SHADOW_ASSASSIN_CHESTPLATE"); + put("Shadow Assassin Leggings", "SHADOW_ASSASSIN_LEGGINGS"); + put("Shadow Assassin Boots", "SHADOW_ASSASSIN_BOOTS"); + put("Shadow Assassin Cloak", "SHADOW_ASSASSIN_CLOAK"); + put("Master Skull - Tier 4", "MASTER_SKULL_TIER_4"); + put("Dark Orb", "DARK_ORB"); + + put("Precursor Eye", "PRECURSOR_EYE"); // F6 M6 + put("Giant's Sword", "GIANTS_SWORD"); + put("Necromancer Lord Helmet", "NECROMANCER_LORD_HELMET"); + put("Necromancer Lord Chestplate", "NECROMANCER_LORD_CHESTPLATE"); + put("Necromancer Lord Leggings", "NECROMANCER_LORD_LEGGINGS"); + put("Necromancer Lord Boots", "NECROMANCER_LORD_BOOTS"); + put("Fourth Master Star", "FOURTH_MASTER_STAR"); + put("Summoning Ring", "SUMMONING_RING"); + put("Fel Skull", "FEL_SKULL"); + put("Necromancer Sword", "NECROMANCER_SWORD"); + put("Soulweaver Gloves", "SOULWEAVER_GLOVES"); + put("Sadan's Brooch", "SADAN_BROOCH"); + put("Giant Tooth", "GIANT_TOOTH"); + + put("Precursor Gear", "PRECURSOR_GEAR"); // F7 M7 + put("Necron Dye", "DYE_NECRON"); + put("Storm the Fish", "STORM_THE_FISH"); + put("Maxor the Fish", "MAXOR_THE_FISH"); + put("Goldor the Fish", "GOLDOR_THE_FISH"); + put("Dark Claymore", "DARK_CLAYMORE"); + put("Necron's Handle", "NECRON_HANDLE"); + put("Master Skull - Tier 5", "MASTER_SKULL_TIER_5"); + put("Shadow Warp", "SHADOW_WARP_SCROLL"); + put("Wither Shield", "WITHER_SHIELD_SCROLL"); + put("Implosion", "IMPLOSION_SCROLL"); + put("Fifth Master Star", "FIFTH_MASTER_STAR"); + put("Auto Recombobulator", "AUTO_RECOMBOBULATOR"); + put("Wither Helmet", "WITHER_HELMET"); + put("Wither Chestplate", "WITHER_CHESTPLATE"); + put("Wither Leggings", "WITHER_LEGGINGS"); + put("Wither Boots", "WITHER_BOOTS"); + put("Wither Catalyst", "WITHER_CATALYST"); + put("Wither Cloak Sword", "WITHER_CLOAK"); + put("Wither Blood", "WITHER_BLOOD"); + }}; +} + diff --git a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java index 60e2b4e4..a81c25f7 100644 --- a/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java +++ b/src/main/java/de/hysky/skyblocker/utils/render/gui/ContainerSolverManager.java @@ -3,6 +3,7 @@ package de.hysky.skyblocker.utils.render.gui; import com.mojang.blaze3d.systems.RenderSystem; import de.hysky.skyblocker.mixin.accessor.HandledScreenAccessor; import de.hysky.skyblocker.skyblock.dungeon.CroesusHelper; +import de.hysky.skyblocker.skyblock.dungeon.CroesusProfit; import de.hysky.skyblocker.skyblock.dungeon.terminal.ColorTerminal; import de.hysky.skyblocker.skyblock.dungeon.terminal.OrderTerminal; import de.hysky.skyblocker.skyblock.dungeon.terminal.StartsWithTerminal; @@ -40,6 +41,7 @@ public class ContainerSolverManager { new OrderTerminal(), new StartsWithTerminal(), new CroesusHelper(), + new CroesusProfit(), new ChronomatronSolver(), new SuperpairsSolver(), new UltrasequencerSolver() |