aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-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);