From beeb590496dd92a4f6839da9a25c49562b9cb32e Mon Sep 17 00:00:00 2001 From: Westsi <76999267+Westsi@users.noreply.github.com> Date: Sat, 23 Nov 2024 00:59:07 +0000 Subject: [PATCH] Added Purse API and Purse Change Event (#950) * Created Purse API and event for when it changes to allow for use in upcoming feature I am making * Removed unnecessary log statements and formatted files * Update src/main/java/de/hysky/skyblocker/utils/Utils.java Co-authored-by: Kevin <92656833+kevinthegreat1@users.noreply.github.com> * Update src/main/java/de/hysky/skyblocker/utils/purse/PurseChangeCause.java Co-authored-by: Kevin <92656833+kevinthegreat1@users.noreply.github.com> * Created Purse API and event for when it changes to allow for use in upcoming feature I am making * Refactor purse api * Update src/main/java/de/hysky/skyblocker/utils/purse/PurseChangeCause.java --------- Co-authored-by: Kevin <92656833+kevinthegreat1@users.noreply.github.com> --- .../skyblocker/events/SkyblockEvents.java | 14 ++++++ .../java/de/hysky/skyblocker/utils/Utils.java | 41 ++++++++++------- .../utils/purse/PurseChangeCause.java | 45 +++++++++++++++++++ 3 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 src/main/java/de/hysky/skyblocker/utils/purse/PurseChangeCause.java diff --git a/src/main/java/de/hysky/skyblocker/events/SkyblockEvents.java b/src/main/java/de/hysky/skyblocker/events/SkyblockEvents.java index 51cc13e3ab..93622d8265 100644 --- a/src/main/java/de/hysky/skyblocker/events/SkyblockEvents.java +++ b/src/main/java/de/hysky/skyblocker/events/SkyblockEvents.java @@ -1,6 +1,7 @@ package de.hysky.skyblocker.events; import de.hysky.skyblocker.utils.Location; +import de.hysky.skyblocker.utils.purse.PurseChangeCause; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.event.Event; @@ -28,6 +29,7 @@ public final class SkyblockEvents { /** * Called when the player's Skyblock profile changes. + * * @implNote This is called upon receiving the chat message for the profile change rather than the exact moment of profile change, so it may be delayed by a few seconds. */ public static final Event PROFILE_CHANGE = EventFactory.createArrayBacked(ProfileChange.class, callbacks -> (prev, profile) -> { @@ -36,6 +38,12 @@ public final class SkyblockEvents { } }); + public static final Event PURSE_CHANGE = EventFactory.createArrayBacked(PurseChange.class, callbacks -> (diff, cause) -> { + for (PurseChange callback : callbacks) { + callback.onPurseChange(diff, cause); + } + }); + @Environment(EnvType.CLIENT) @FunctionalInterface public interface SkyblockJoin { @@ -59,4 +67,10 @@ public interface SkyblockLocationChange { public interface ProfileChange { void onSkyblockProfileChange(String prevProfileId, String profileId); } + + @Environment(EnvType.CLIENT) + @FunctionalInterface + public interface PurseChange { + void onPurseChange(double diff, PurseChangeCause cause); + } } diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java index 5c5d7d3842..10bf4063c0 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Utils.java +++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java @@ -7,6 +7,7 @@ import de.hysky.skyblocker.events.SkyblockEvents; import de.hysky.skyblocker.mixins.accessors.MessageHandlerAccessor; import de.hysky.skyblocker.skyblock.item.MuseumItemCache; +import de.hysky.skyblocker.utils.purse.PurseChangeCause; import de.hysky.skyblocker.utils.scheduler.MessageScheduler; import de.hysky.skyblocker.utils.scheduler.Scheduler; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -37,6 +38,8 @@ import java.time.Instant; import java.util.Collections; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Utility variables and methods for retrieving Skyblock related information. @@ -48,6 +51,7 @@ public class Utils { private static final String PROFILE_PREFIX = "Profile: "; private static final String PROFILE_MESSAGE_PREFIX = "§aYou are playing on profile: §e"; public static final String PROFILE_ID_PREFIX = "Profile ID: "; + private static final Pattern PURSE = Pattern.compile("(Purse|Piggy): (?[0-9,.]+)( \\((?[+\\-][0-9,.]+)\\))?"); private static boolean isOnHypixel = false; private static boolean isOnSkyblock = false; /** @@ -89,6 +93,8 @@ public class Utils { private static String locationRaw = ""; @NotNull private static String map = ""; + @NotNull + public static double purse = 0; /** * @implNote The parent text will always be empty, the actual text content is inside the text's siblings. @@ -130,6 +136,7 @@ public static boolean isInTheEnd() { public static boolean isInKuudra() { return location == Location.KUUDRAS_HOLLOW; } + public static boolean isInCrimson() { return location == Location.CRIMSON_ISLE; } @@ -272,22 +279,9 @@ public static String getIslandArea() { return "Unknown"; } - public static double getPurse() { - String purseString = null; - double purse = 0; - - try { - for (String sidebarLine : STRING_SCOREBOARD) { - if (sidebarLine.contains("Piggy:") || sidebarLine.contains("Purse:")) purseString = sidebarLine; - } - if (purseString != null) purse = Double.parseDouble(purseString.replaceAll("[^0-9.]", "").strip()); - else purse = 0; - - } catch (IndexOutOfBoundsException e) { - LOGGER.error("[Skyblocker] Failed to get purse from sidebar", e); - } - return purse; - } + public static double getPurse() { + return purse; + } public static int getBits() { int bits = 0; @@ -347,11 +341,25 @@ private static void updateScoreboard(MinecraftClient client) { TEXT_SCOREBOARD.addAll(textLines); STRING_SCOREBOARD.addAll(stringLines); + Utils.updatePurse(); } catch (NullPointerException e) { //Do nothing } } + public static void updatePurse() { + STRING_SCOREBOARD.stream().filter(s -> s.contains("Piggy:") || s.contains("Purse:")).findFirst().ifPresent(purseString -> { + Matcher matcher = PURSE.matcher(purseString); + if (matcher.find()) { + double newPurse = Double.parseDouble(matcher.group("purse").replaceAll(",", "")); + double changeSinceLast = newPurse - Utils.purse; + if (changeSinceLast == 0) return; + SkyblockEvents.PURSE_CHANGE.invoker().onPurseChange(changeSinceLast, PurseChangeCause.getCause(changeSinceLast)); + Utils.purse = newPurse; + } + }); + } + private static void updateFromPlayerList(MinecraftClient client) { if (client.getNetworkHandler() == null) { return; @@ -454,7 +462,6 @@ public void run() { * and {@link #location} * * @param message json message from chat - * * @deprecated Retained just in case the mod api doesn't work or gets disabled. */ @Deprecated diff --git a/src/main/java/de/hysky/skyblocker/utils/purse/PurseChangeCause.java b/src/main/java/de/hysky/skyblocker/utils/purse/PurseChangeCause.java new file mode 100644 index 0000000000..dca764c085 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/purse/PurseChangeCause.java @@ -0,0 +1,45 @@ +package de.hysky.skyblocker.utils.purse; + +import de.hysky.skyblocker.utils.Utils; +import net.minecraft.client.MinecraftClient; + +public enum PurseChangeCause { + // Gain + MOB_KILL, + TALISMAN_OF_COINS, + DICE_SIX, + TAKE_BANK, + UNKNOWN_GAIN, + // Loss + SLAYER_QUEST, + DICE_ROLL, + DEPO_BANK, + UNKNOWN_LOSS; + + public static PurseChangeCause getCause(double diff) { + if (diff > 0) { + if (diff == 5 || diff == 25) { + return TALISMAN_OF_COINS; + } + + if (diff == 15000000 || diff == 100000000) { + return DICE_SIX; + } + + if (MinecraftClient.getInstance().currentScreen == null) { + // UI closed + // need to make this more specific, but atm might as well attrib to mob kill + return MOB_KILL; + } else if (Utils.getIslandArea().replaceAll("\\P{InBasic_Latin}", "").strip().equals("Bank")) { + return TAKE_BANK; + } + return UNKNOWN_GAIN; + } else { + // TODO: implement slayer quest loss + if (diff == -6666666 || diff == -666666) { + return DICE_ROLL; + } + return UNKNOWN_LOSS; + } + } +}