aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2025-06-26 12:07:10 -0400
committerAaron <51387595+AzureAaron@users.noreply.github.com>2025-06-26 12:07:10 -0400
commit71ca871f2a2441813b26e24467b8e75b166f747a (patch)
tree68df274445975ad1fc1c13fe667c59b2df486a52 /src/main/java/de
parent3bd588279171d1f59b0433d2b94da29f5db4a740 (diff)
downloadSkyblocker-71ca871f2a2441813b26e24467b8e75b166f747a.tar.gz
Skyblocker-71ca871f2a2441813b26e24467b8e75b166f747a.tar.bz2
Skyblocker-71ca871f2a2441813b26e24467b8e75b166f747a.zip
Add attribute list for bazaar price support
The code for generating the list has been left in so that it can easily be regenerated if necessary.
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/hunting/Attribute.java16
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/hunting/Attributes.java53
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/hunting/AttributesDebug.java103
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/ItemUtils.java10
4 files changed, 177 insertions, 5 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/hunting/Attribute.java b/src/main/java/de/hysky/skyblocker/skyblock/hunting/Attribute.java
new file mode 100644
index 00000000..4090a571
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/hunting/Attribute.java
@@ -0,0 +1,16 @@
+package de.hysky.skyblocker.skyblock.hunting;
+
+import java.util.List;
+
+import com.mojang.serialization.Codec;
+import com.mojang.serialization.codecs.RecordCodecBuilder;
+
+public record Attribute(String name, String shardName, String id, String apiId) {
+ private static final Codec<Attribute> CODEC = RecordCodecBuilder.create(instance -> instance.group(
+ Codec.STRING.fieldOf("name").forGetter(Attribute::name),
+ Codec.STRING.fieldOf("shardName").forGetter(Attribute::shardName),
+ Codec.STRING.fieldOf("id").forGetter(Attribute::id),
+ Codec.STRING.fieldOf("apiId").forGetter(Attribute::apiId)
+ ).apply(instance, Attribute::new));
+ public static final Codec<List<Attribute>> LIST_CODEC = CODEC.listOf();
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/hunting/Attributes.java b/src/main/java/de/hysky/skyblocker/skyblock/hunting/Attributes.java
new file mode 100644
index 00000000..e24f11bd
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/hunting/Attributes.java
@@ -0,0 +1,53 @@
+package de.hysky.skyblocker.skyblock.hunting;
+
+import java.io.BufferedReader;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+
+import com.google.gson.JsonParser;
+import com.mojang.logging.LogUtils;
+import com.mojang.serialization.JsonOps;
+
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.annotations.Init;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.component.ComponentHolder;
+import net.minecraft.component.DataComponentTypes;
+import net.minecraft.util.Identifier;
+
+public class Attributes {
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private static final Identifier ATTRIBUTES_FILE = Identifier.of(SkyblockerMod.NAMESPACE, "hunting/attributes.json");
+ private static List<Attribute> attributes = List.of();
+
+ @Init
+ public static void init() {
+ ClientLifecycleEvents.CLIENT_STARTED.register(Attributes::loadShards);
+ }
+
+ private static void loadShards(MinecraftClient client) {
+ CompletableFuture.runAsync(() -> {
+ try (BufferedReader reader = client.getResourceManager().openAsReader(ATTRIBUTES_FILE)) {
+ attributes = Attribute.LIST_CODEC.parse(JsonOps.INSTANCE, JsonParser.parseReader(reader)).getOrThrow();
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker Attributes] Failed to load attributes.", e);
+ }
+ });
+ }
+
+ @Nullable
+ public static Attribute getAttributeFromItemName(ComponentHolder stack) {
+ if (!stack.contains(DataComponentTypes.CUSTOM_NAME)) return null;
+ String name = stack.get(DataComponentTypes.CUSTOM_NAME).getString();
+
+ for (Attribute attribute : attributes) {
+ if (attribute.shardName().equals(name)) return attribute;
+ }
+
+ return null;
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/hunting/AttributesDebug.java b/src/main/java/de/hysky/skyblocker/skyblock/hunting/AttributesDebug.java
new file mode 100644
index 00000000..1ba4bd72
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/hunting/AttributesDebug.java
@@ -0,0 +1,103 @@
+package de.hysky.skyblocker.skyblock.hunting;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.CompletableFuture;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.lwjgl.glfw.GLFW;
+import org.slf4j.Logger;
+
+import com.mojang.logging.LogUtils;
+import com.mojang.serialization.JsonOps;
+
+import de.hysky.skyblocker.SkyblockerMod;
+import de.hysky.skyblocker.skyblock.item.tooltip.info.TooltipInfoType;
+import de.hysky.skyblocker.utils.ItemUtils;
+import de.hysky.skyblocker.utils.RomanNumerals;
+import de.hysky.skyblocker.utils.container.ContainerSolver;
+import de.hysky.skyblocker.utils.container.ContainerSolverManager;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
+import net.fabricmc.fabric.api.client.screen.v1.ScreenKeyboardEvents;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.gui.screen.ingame.HandledScreen;
+import net.minecraft.item.ItemStack;
+import net.minecraft.screen.GenericContainerScreenHandler;
+
+public class AttributesDebug {
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private static final MinecraftClient CLIENT = MinecraftClient.getInstance();
+ private static final List<Attribute> DUMPED_ATTRIBUTES = new ArrayList<>();
+ private static final Pattern SOURCE_PATTERN = Pattern.compile("Source: (?<shardName>[A-za-z ]+) Shard \\((?<id>[CUREL]\\d+)\\)");
+ private static final Path ATTRIBUTE_EXPORT_DEST = SkyblockerMod.CONFIG_DIR.resolve("attribute_export.json");
+
+ //@Init
+ public static void init() {
+ ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
+ ScreenKeyboardEvents.afterKeyPress(screen).register((screen1, key, scancode, modifiers) -> {
+ if (key == GLFW.GLFW_KEY_G) {
+ dumpAttributes();
+ } else if (key == GLFW.GLFW_KEY_J) {
+ exportAttributes();
+ }
+ });
+ });
+ }
+
+ private static void dumpAttributes() {
+ if (CLIENT.currentScreen instanceof HandledScreen<?> screen && screen.getTitle().getString().equals("Attribute Menu")) {
+ @SuppressWarnings("unchecked")
+ Int2ObjectMap<ItemStack> slots = ContainerSolverManager.slotMap(screen.getScreenHandler().slots.subList(0, ((HandledScreen<GenericContainerScreenHandler>) screen).getScreenHandler().getRows() * 9));
+ ContainerSolver.trimEdges(slots, 6);
+
+ for (ItemStack stack : slots.values()) {
+ if (stack.isEmpty()) continue;
+
+ String name = stack.getName().getString();
+ Matcher sourceMatcher = ItemUtils.getLoreLineIfMatch(stack, SOURCE_PATTERN);
+
+ //Remove roman numeral from name
+ List<String> words = new ArrayList<>(Arrays.asList(name.split(" ")));
+ if (RomanNumerals.isValidRomanNumeral(words.getLast().strip())) {
+ words.removeLast();
+ name = String.join(" ", words);
+ }
+
+ if (sourceMatcher != null) {
+ String shardName = sourceMatcher.group("shardName");
+ String id = sourceMatcher.group("id");
+ String apiIdGuess = "SHARD_" + shardName.replace(' ', '_').toUpperCase(Locale.ENGLISH);
+ boolean hasDataForId = TooltipInfoType.BAZAAR.getData().containsKey(apiIdGuess);
+
+ //Most attributes follow the format above but some have different ids so this is to catch those ones
+ if (!hasDataForId) LOGGER.warn("[Skyblocker Attributes Debug] No data found for shard. Shard Name: {}", shardName);
+
+ Attribute attribute = new Attribute(name, shardName, id, apiIdGuess);
+ DUMPED_ATTRIBUTES.add(attribute);
+ } else {
+ LOGGER.warn("[Skyblocker Attributes Debug] Failed to match shard! Name: {}", name);
+ }
+ }
+ }
+ }
+
+ private static void exportAttributes() {
+ if (CLIENT.currentScreen instanceof HandledScreen screen && screen.getTitle().getString().equals("Attribute Menu")) {
+ List<Attribute> copy = DUMPED_ATTRIBUTES.stream().distinct().toList();
+
+ CompletableFuture.runAsync(() -> {
+ try {
+ Files.writeString(ATTRIBUTE_EXPORT_DEST, Attribute.LIST_CODEC.encodeStart(JsonOps.INSTANCE, copy).getOrThrow().toString());
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker Attributes Debug] Failed to export attributes!", e);
+ }
+ });
+ }
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
index a27ed97a..dc3f3c5a 100644
--- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
+++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
@@ -11,6 +11,8 @@ import com.mojang.serialization.JsonOps;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import de.hysky.skyblocker.SkyblockerMod;
import de.hysky.skyblocker.debug.Debug;
+import de.hysky.skyblocker.skyblock.hunting.Attribute;
+import de.hysky.skyblocker.skyblock.hunting.Attributes;
import de.hysky.skyblocker.skyblock.item.PetInfo;
import de.hysky.skyblocker.skyblock.item.tooltip.adders.ObtainedDateTooltip;
import de.hysky.skyblocker.skyblock.item.tooltip.info.TooltipInfoType;
@@ -185,11 +187,9 @@ public final class ItemUtils {
}
}
case "ATTRIBUTE_SHARD" -> {
- if (customData.contains("attributes")) {
- NbtCompound shards = customData.getCompoundOrEmpty("attributes");
- String shard = shards.getKeys().stream().findFirst().orElse("");
- return id + "-" + shard.toUpperCase(Locale.ENGLISH) + "_" + shards.getInt(shard, 0);
- }
+ Attribute attribute = Attributes.getAttributeFromItemName(itemStack);
+
+ if (attribute != null) return attribute.apiId();
}
case "NEW_YEAR_CAKE" -> {
return id + "_" + customData.getInt("new_years_cake", 0);