aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorRime <81419447+Emirlol@users.noreply.github.com>2025-02-27 23:50:44 +0300
committerGitHub <noreply@github.com>2025-02-28 04:50:44 +0800
commit9219939d0769b10f4ec504f57d98a60c24247185 (patch)
tree105a226def7d5d396843f88c3fcea7e04d5733c3 /src/main/java
parente2659c8ced1685fa0c231195db53df45500a6144 (diff)
downloadSkyblocker-9219939d0769b10f4ec504f57d98a60c24247185.tar.gz
Skyblocker-9219939d0769b10f4ec504f57d98a60c24247185.tar.bz2
Skyblocker-9219939d0769b10f4ec504f57d98a60c24247185.zip
Initial (and hopefully last) commit for npc price fix (#1176)
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/debug/Debug.java6
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/NpcPriceTooltip.java53
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/ItemUtils.java23
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/TextUtils.java112
4 files changed, 160 insertions, 34 deletions
diff --git a/src/main/java/de/hysky/skyblocker/debug/Debug.java b/src/main/java/de/hysky/skyblocker/debug/Debug.java
index cfd0b528..03b49532 100644
--- a/src/main/java/de/hysky/skyblocker/debug/Debug.java
+++ b/src/main/java/de/hysky/skyblocker/debug/Debug.java
@@ -145,16 +145,16 @@ public class Debug {
JSON {
@Override
public Text format(ItemStack stack) {
- return Text.literal(SkyblockerMod.GSON_COMPACT.toJson(ItemStack.CODEC.encodeStart(ItemStackComponentizationFixer.getRegistryLookup().getOps(JsonOps.INSTANCE), stack).getOrThrow()));
+ return Text.literal(SkyblockerMod.GSON_COMPACT.toJson(ItemUtils.EMPTY_ALLOWING_ITEMSTACK_CODEC.encodeStart(ItemStackComponentizationFixer.getRegistryLookup().getOps(JsonOps.INSTANCE), stack).getOrThrow()));
}
},
SNBT {
@Override
public Text format(ItemStack stack) {
- return NbtHelper.toPrettyPrintedText(ItemStack.CODEC.encodeStart(MinecraftClient.getInstance().player.getRegistryManager().getOps(NbtOps.INSTANCE), stack).getOrThrow());
+ return NbtHelper.toPrettyPrintedText(ItemUtils.EMPTY_ALLOWING_ITEMSTACK_CODEC.encodeStart(MinecraftClient.getInstance().player.getRegistryManager().getOps(NbtOps.INSTANCE), stack).getOrThrow());
}
};
- abstract Text format(ItemStack stack);
+ public abstract Text format(ItemStack stack);
}
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/NpcPriceTooltip.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/NpcPriceTooltip.java
index 6bb1bcdb..9b019531 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/NpcPriceTooltip.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/NpcPriceTooltip.java
@@ -1,18 +1,31 @@
package de.hysky.skyblocker.skyblock.item.tooltip.adders;
+import de.hysky.skyblocker.debug.Debug;
import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip;
import de.hysky.skyblocker.skyblock.item.tooltip.SimpleTooltipAdder;
import de.hysky.skyblocker.skyblock.item.tooltip.info.TooltipInfoType;
+import de.hysky.skyblocker.utils.RegexUtils;
+import de.hysky.skyblocker.utils.TextUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
-import org.apache.commons.lang3.math.NumberUtils;
+import net.minecraft.util.Util;
import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.List;
+import java.util.OptionalInt;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class NpcPriceTooltip extends SimpleTooltipAdder {
+ private static final Pattern STORED_PATTERN = Pattern.compile("Stored: ([\\d,]+)/\\S+");
+ private static final Logger LOGGER = LoggerFactory.getLogger(NpcPriceTooltip.class);
+ private static final short LOG_INTERVAL = 1000;
+ private static long lastLog = Util.getMeasuringTimeMs();
+
public NpcPriceTooltip(int priority) {
super(priority);
}
@@ -26,19 +39,35 @@ public class NpcPriceTooltip extends SimpleTooltipAdder {
public void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List<Text> lines) {
// NPC prices seem to use the Skyblock item id, not the Skyblock api id.
final String internalID = stack.getSkyblockId();
- if (TooltipInfoType.NPC.hasOrNullWarning(internalID)) {
- int amount;
- if (lines.get(1).getString().endsWith("Sack")) {
- //The amount is in the 2nd sibling of the 3rd line of the lore. here V
- //Example line: empty[style={color=dark_purple,!italic}, siblings=[literal{Stored: }[style={color=gray}], literal{0}[style={color=dark_gray}], literal{/20k}[style={color=gray}]]
- String line = lines.get(3).getSiblings().get(1).getString().replace(",", "");
- amount = NumberUtils.isParsable(line) && !line.equals("0") ? Integer.parseInt(line) : stack.getCount();
+ if (TooltipInfoType.NPC.getData() == null) {
+ ItemTooltip.nullWarning();
+ return;
+ }
+ double price = TooltipInfoType.NPC.getData().getOrDefault(internalID, -1); // The original default return value of 0 can be an actual price, so we use a value that can't be a price
+ if (price < 0) return;
+
+ int amount = parseAmount(stack, lines);
+ lines.add(Text.literal(String.format("%-21s", "NPC Sell Price:"))
+ .formatted(Formatting.YELLOW)
+ .append(ItemTooltip.getCoinsMessage(price, amount)));
+ }
+
+ private int parseAmount(ItemStack stack, List<Text> lines) {
+ if (lines.size() >= 2 && lines.get(1).getString().endsWith("Sack")) {
+ //Example line: empty[style={color=dark_purple,!italic}, siblings=[literal{Stored: }[style={color=gray}], literal{0}[style={color=dark_gray}], literal{/20k}[style={color=gray}]]
+ Matcher matcher = TextUtils.matchInList(lines, STORED_PATTERN);
+ if (matcher == null) {
+ // Log a warning every second if the amount couldn't be found, to prevent spamming the logs every frame (which can be hundreds of times per second)
+ if (Util.getMeasuringTimeMs() - lastLog > LOG_INTERVAL) {
+ LOGGER.warn("Failed to find stored amount in sack tooltip for item `{}`", Debug.DumpFormat.JSON.format(stack).getString()); // This is a very unintended way of serializing the item stack, but it's so much cleaner than actually using the codec
+ lastLog = Util.getMeasuringTimeMs();
+ }
+ return stack.getCount();
} else {
- amount = stack.getCount();
+ OptionalInt amount = RegexUtils.findIntFromMatcher(matcher);
+ return amount.isPresent() ? amount.getAsInt() : stack.getCount();
}
- lines.add(Text.literal(String.format("%-21s", "NPC Sell Price:"))
- .formatted(Formatting.YELLOW)
- .append(ItemTooltip.getCoinsMessage(TooltipInfoType.NPC.getData().getDouble(internalID), amount)));
}
+ return stack.getCount();
}
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
index b886f40f..385e1fd1 100644
--- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
@@ -39,10 +39,7 @@ import net.minecraft.util.dynamic.Codecs;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.List;
-import java.util.Locale;
-import java.util.Optional;
-import java.util.OptionalDouble;
+import java.util.*;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -259,7 +256,7 @@ public final class ItemUtils {
/**
* Parses the {@code petInfo} field from a pet item that has it into the {@link PetInfo} record.
- *
+ *
* @return the parsed {@link PetInfo} if successful, or {@link PetInfo#EMPTY}
*/
@NotNull
@@ -394,13 +391,7 @@ public final class ItemUtils {
*/
@Nullable
public static Matcher getLoreLineIfMatch(ItemStack stack, Pattern pattern) {
- Matcher matcher = pattern.matcher("");
- for (Text line : getLore(stack)) {
- if (matcher.reset(line.getString()).matches()) {
- return matcher;
- }
- }
- return null;
+ return TextUtils.matchInList(getLore(stack), pattern);
}
/**
@@ -411,13 +402,7 @@ public final class ItemUtils {
*/
@Nullable
public static Matcher getLoreLineIfContainsMatch(ItemStack stack, Pattern pattern) {
- Matcher matcher = pattern.matcher("");
- for (Text line : getLore(stack)) {
- if (matcher.reset(line.getString()).find()) {
- return matcher;
- }
- }
- return null;
+ return TextUtils.findInList(getLore(stack), pattern);
}
public static @NotNull List<Text> getLore(ItemStack stack) {
diff --git a/src/main/java/de/hysky/skyblocker/utils/TextUtils.java b/src/main/java/de/hysky/skyblocker/utils/TextUtils.java
new file mode 100644
index 00000000..4c641952
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/TextUtils.java
@@ -0,0 +1,112 @@
+package de.hysky.skyblocker.utils;
+
+import net.minecraft.text.Text;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility class for text operations.
+ */
+public final class TextUtils {
+ private TextUtils() {}
+
+ /**
+ * Finds the first occurrence of the pattern in the list of texts, using {@link Matcher#matches()} ()}.
+ *
+ * @param list the list of texts to search in
+ * @param pattern the pattern to search for
+ * @return the index of the first occurrence if found, -1 otherwise
+ */
+ public static int indexOfInList(List<Text> list, Pattern pattern) {
+ return indexOfInList(list, pattern, 0);
+ }
+
+ /**
+ * Finds the first occurrence of the pattern in the list of texts starting from the specified index, using {@link Matcher#matches()}}.
+ *
+ * @param list the list of texts to search in
+ * @param pattern the pattern to search for
+ * @param startIndex the index to start searching from (inclusive)
+ * @return the index of the first occurrence if found, -1 otherwise
+ */
+ public static int indexOfInList(List<Text> list, Pattern pattern, int startIndex) {
+ if (startIndex >= list.size()) return -1; // Start index is out of bounds, or the list is empty
+
+ Matcher matcher = pattern.matcher(""); // Empty matcher
+ for (int i = startIndex, listSize = list.size(); i < listSize; i++) {
+ Text text = list.get(i);
+ if (matcher.reset(text.getString()).matches()) return i;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Finds the first occurrence of the pattern in the list of texts using {@link Matcher#find()}.
+ *
+ * @param list the list of texts to search in
+ * @param pattern the pattern to search for
+ * @return the matcher if found, {@code null} otherwise
+ */
+ @Nullable
+ public static Matcher findInList(List<Text> list, Pattern pattern) {
+ return findInList(list, pattern, 0);
+ }
+
+ /**
+ * Finds the first occurrence of the pattern in the list of texts starting from the specified index using {@link Matcher#find()}.
+ *
+ * @param list the list of texts to search in
+ * @param pattern the pattern to search for
+ * @param startIndex the index to start searching from (inclusive)
+ * @return the matcher if found, {@code null} otherwise
+ */
+ @Nullable
+ public static Matcher findInList(List<Text> list, Pattern pattern, int startIndex) {
+ if (startIndex >= list.size()) return null; // Start index is out of bounds, or the list is empty
+
+ Matcher matcher = pattern.matcher(""); // Empty matcher
+ for (int i = startIndex, listSize = list.size(); i < listSize; i++) {
+ Text text = list.get(i);
+ if (matcher.reset(text.getString()).find()) return matcher;
+ }
+
+ return null;
+ }
+
+ /**
+ * Finds the first occurrence of the pattern in the list of texts using {@link Matcher#matches()}.
+ *
+ * @param list the list of texts to search in
+ * @param pattern the pattern to search for
+ * @return the matcher if found, {@code null} otherwise
+ */
+ @Nullable
+ public static Matcher matchInList(List<Text> list, Pattern pattern) {
+ return matchInList(list, pattern, 0);
+ }
+
+ /**
+ * Finds the first occurrence of the pattern in the list of texts starting from the specified index using {@link Matcher#matches()}.
+ *
+ * @param list the list of texts to search in
+ * @param pattern the pattern to search for
+ * @param startIndex the index to start searching from (inclusive)
+ * @return the matcher if found, {@code null} otherwise
+ */
+ @Nullable
+ public static Matcher matchInList(List<Text> list, Pattern pattern, int startIndex) {
+ if (startIndex >= list.size()) return null; // Start index is out of bounds, or the list is empty
+
+ Matcher matcher = pattern.matcher(""); // Empty matcher
+ for (int i = startIndex, listSize = list.size(); i < listSize; i++) {
+ Text text = list.get(i);
+ if (matcher.reset(text.getString()).matches()) return matcher;
+ }
+
+ return null;
+ }
+}