aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2024-12-06 01:39:50 -0500
committerGitHub <noreply@github.com>2024-12-06 01:39:50 -0500
commitfa726da23c40146c78fbf5e3824616e91284f4b1 (patch)
tree913ee83661bf4045c312f59bab44cf36350e3088 /src/main/java
parentaf5ec9fe170bbb8c0b0f492db2715dd3b9e35b0a (diff)
downloadSkyblocker-fa726da23c40146c78fbf5e3824616e91284f4b1.tar.gz
Skyblocker-fa726da23c40146c78fbf5e3824616e91284f4b1.tar.bz2
Skyblocker-fa726da23c40146c78fbf5e3824616e91284f4b1.zip
Item DFU Unification (#1054)
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemFixerUpper.java347
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java246
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java62
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/datafixer/LegacyItemStackFixer.java7
-rw-r--r--src/main/java/de/hysky/skyblocker/utils/datafixer/LegacyStringNbtReader.java81
5 files changed, 225 insertions, 518 deletions
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemFixerUpper.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemFixerUpper.java
deleted file mode 100644
index e931c7e2..00000000
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemFixerUpper.java
+++ /dev/null
@@ -1,347 +0,0 @@
-package de.hysky.skyblocker.skyblock.itemlist;
-
-import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
-import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
-import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-
-import java.util.Map;
-
-public class ItemFixerUpper {
- private final static String[] ANVIL_VARIANTS = {
- "minecraft:anvil",
- "minecraft:chipped_anvil",
- "minecraft:damaged_anvil"
- };
-
- private final static String[] COAL_VARIANTS = {
- "minecraft:coal",
- "minecraft:charcoal"
- };
-
- private final static String[] COBBLESTONE_WALL_VARIANTS = {
- "minecraft:cobblestone_wall",
- "minecraft:mossy_cobblestone_wall"
- };
-
- private final static String[] COOKED_FISH_VARIANTS = {
- "minecraft:cooked_cod",
- "minecraft:cooked_salmon"
- };
-
- private final static String[] DIRT_VARIANTS = {
- "minecraft:dirt",
- "minecraft:coarse_dirt",
- "minecraft:podzol"
- };
-
- private final static String[] DOUBLE_PLANT_VARIANTS = {
- "minecraft:sunflower",
- "minecraft:lilac",
- "minecraft:tall_grass",
- "minecraft:large_fern",
- "minecraft:rose_bush",
- "minecraft:peony"
- };
-
- private final static String[] DYE_VARIANTS = {
- "minecraft:ink_sac",
- "minecraft:red_dye",
- "minecraft:green_dye",
- "minecraft:cocoa_beans",
- "minecraft:lapis_lazuli",
- "minecraft:purple_dye",
- "minecraft:cyan_dye",
- "minecraft:light_gray_dye",
- "minecraft:gray_dye",
- "minecraft:pink_dye",
- "minecraft:lime_dye",
- "minecraft:yellow_dye",
- "minecraft:light_blue_dye",
- "minecraft:magenta_dye",
- "minecraft:orange_dye",
- "minecraft:bone_meal"
- };
-
- private final static String[] FISH_VARIANTS = {
- "minecraft:cod",
- "minecraft:salmon",
- "minecraft:tropical_fish",
- "minecraft:pufferfish"
- };
-
- private final static String[] GOLDEN_APPLE_VARIANTS = {
- "minecraft:golden_apple",
- "minecraft:enchanted_golden_apple"
- };
-
- private final static String[] LOG_VARIANTS = {
- "minecraft:oak_log",
- "minecraft:spruce_log",
- "minecraft:birch_log",
- "minecraft:jungle_log",
- "minecraft:oak_wood",
- "minecraft:spruce_wood",
- "minecraft:birch_wood",
- "minecraft:jungle_wood",
- };
-
- private final static String[] LOG2_VARIANTS = {
- "minecraft:acacia_log",
- "minecraft:dark_oak_log",
- "minecraft:acacia_wood",
- "minecraft:dark_oak_wood"
- };
-
- private final static String[] MONSTER_EGG_VARIANTS = {
- "minecraft:infested_stone",
- "minecraft:infested_cobblestone",
- "minecraft:infested_stone_bricks",
- "minecraft:infested_mossy_stone_bricks",
- "minecraft:infested_cracked_stone_bricks",
- "minecraft:infested_chiseled_stone_bricks"
- };
-
- private final static String[] PRISMARINE_VARIANTS = {
- "minecraft:prismarine",
- "minecraft:prismarine_bricks",
- "minecraft:dark_prismarine"
- };
-
- private final static String[] QUARTZ_BLOCK_VARIANTS = {
- "minecraft:quartz_block",
- "minecraft:chiseled_quartz_block",
- "minecraft:quartz_pillar"
- };
-
- private final static String[] RED_FLOWER_VARIANTS = {
- "minecraft:poppy",
- "minecraft:blue_orchid",
- "minecraft:allium",
- "minecraft:azure_bluet",
- "minecraft:red_tulip",
- "minecraft:orange_tulip",
- "minecraft:white_tulip",
- "minecraft:pink_tulip",
- "minecraft:oxeye_daisy"
- };
-
- private final static String[] SAND_VARIANTS = {
- "minecraft:sand",
- "minecraft:red_sand"
- };
-
- private final static String[] SKULL_VARIANTS = {
- "minecraft:skeleton_skull",
- "minecraft:wither_skeleton_skull",
- "minecraft:zombie_head",
- "minecraft:player_head",
- "minecraft:creeper_head"
- };
-
- private final static String[] SPONGE_VARIANTS = {
- "minecraft:sponge",
- "minecraft:wet_sponge"
- };
-
- private final static String[] STONE_VARIANTS = {
- "minecraft:stone",
- "minecraft:granite",
- "minecraft:polished_granite",
- "minecraft:diorite",
- "minecraft:polished_diorite",
- "minecraft:andesite",
- "minecraft:polished_andesite"
- };
-
- private final static String[] STONE_SLAB_VARIANTS = {
- "minecraft:smooth_stone_slab",
- "minecraft:sandstone_slab",
- "minecraft:petrified_oak_slab",
- "minecraft:cobblestone_slab",
- "minecraft:brick_slab",
- "minecraft:stone_brick_slab",
- "minecraft:nether_brick_slab",
- "minecraft:quartz_slab"
- };
-
- private final static String[] STONEBRICK_VARIANTS = {
- "minecraft:stone_bricks",
- "minecraft:mossy_stone_bricks",
- "minecraft:cracked_stone_bricks",
- "minecraft:chiseled_stone_bricks"
- };
-
- private final static String[] TALLGRASS_VARIANTS = {
- "minecraft:dead_bush",
- "minecraft:short_grass",
- "minecraft:fern"
- };
-
- private final static Int2ObjectMap<String> SPAWN_EGG_VARIANTS = Int2ObjectMaps.unmodifiable(new Int2ObjectOpenHashMap<>(Map.ofEntries(
- //This entry 0 is technically not right but Hypixel decided to make it polar bear so well we use that
- Map.entry(0, "minecraft:polar_bear_spawn_egg"),
- //This entry 4 does not actually exist, Hypixel uses it as a placeholder for elder guardians
- Map.entry(4, "minecraft:elder_guardian_spawn_egg"),
- Map.entry(50, "minecraft:creeper_spawn_egg"),
- Map.entry(51, "minecraft:skeleton_spawn_egg"),
- Map.entry(52, "minecraft:spider_spawn_egg"),
- Map.entry(54, "minecraft:zombie_spawn_egg"),
- Map.entry(55, "minecraft:slime_spawn_egg"),
- Map.entry(56, "minecraft:ghast_spawn_egg"),
- Map.entry(57, "minecraft:zombified_piglin_spawn_egg"),
- Map.entry(58, "minecraft:enderman_spawn_egg"),
- Map.entry(59, "minecraft:cave_spider_spawn_egg"),
- Map.entry(60, "minecraft:silverfish_spawn_egg"),
- Map.entry(61, "minecraft:blaze_spawn_egg"),
- Map.entry(62, "minecraft:magma_cube_spawn_egg"),
- Map.entry(65, "minecraft:bat_spawn_egg"),
- Map.entry(66, "minecraft:witch_spawn_egg"),
- Map.entry(67, "minecraft:endermite_spawn_egg"),
- Map.entry(68, "minecraft:guardian_spawn_egg"),
- Map.entry(90, "minecraft:pig_spawn_egg"),
- Map.entry(91, "minecraft:sheep_spawn_egg"),
- Map.entry(92, "minecraft:cow_spawn_egg"),
- Map.entry(93, "minecraft:chicken_spawn_egg"),
- Map.entry(94, "minecraft:squid_spawn_egg"),
- Map.entry(95, "minecraft:wolf_spawn_egg"),
- Map.entry(96, "minecraft:mooshroom_spawn_egg"),
- Map.entry(98, "minecraft:ocelot_spawn_egg"),
- Map.entry(100, "minecraft:horse_spawn_egg"),
- Map.entry(101, "minecraft:rabbit_spawn_egg"),
- Map.entry(120, "minecraft:villager_spawn_egg")
- )));
-
- private final static String[] SANDSTONE_VARIANTS = {
- ":",
- ":chiseled_",
- ":cut_"
- };
-
- private final static String[] COLOR_VARIANTS = {
- ":white_",
- ":orange_",
- ":magenta_",
- ":light_blue_",
- ":yellow_",
- ":lime_",
- ":pink_",
- ":gray_",
- ":light_gray_",
- ":cyan_",
- ":purple_",
- ":blue_",
- ":brown_",
- ":green_",
- ":red_",
- ":black_"
- };
-
- private final static String[] WOOD_VARIANTS = {
- ":oak_",
- ":spruce_",
- ":birch_",
- ":jungle_",
- ":acacia_",
- ":dark_oak_"
- };
-
- //this is the map of all renames
- private final static Map<String, String> RENAMED = Map.ofEntries(
- Map.entry("minecraft:bed", "minecraft:red_bed"),
- Map.entry("minecraft:boat", "minecraft:oak_boat"),
- Map.entry("minecraft:brick_block", "minecraft:bricks"),
- Map.entry("minecraft:deadbush", "minecraft:dead_bush"),
- Map.entry("minecraft:fence_gate", "minecraft:oak_fence_gate"),
- Map.entry("minecraft:fence", "minecraft:oak_fence"),
- Map.entry("minecraft:firework_charge", "minecraft:firework_star"),
- Map.entry("minecraft:fireworks", "minecraft:firework_rocket"),
- Map.entry("minecraft:golden_rail", "minecraft:powered_rail"),
- Map.entry("minecraft:grass", "minecraft:grass_block"),
- Map.entry("minecraft:hardened_clay", "minecraft:terracotta"),
- Map.entry("minecraft:lit_pumpkin", "minecraft:jack_o_lantern"),
- Map.entry("minecraft:melon_block", "minecraft:melon"),
- Map.entry("minecraft:melon", "minecraft:melon_slice"),
- Map.entry("minecraft:mob_spawner", "minecraft:spawner"),
- Map.entry("minecraft:nether_brick", "minecraft:nether_bricks"),
- Map.entry("minecraft:netherbrick", "minecraft:nether_brick"),
- Map.entry("minecraft:noteblock", "minecraft:note_block"),
- Map.entry("minecraft:piston_extension", "minecraft:moving_piston"),
- Map.entry("minecraft:portal", "minecraft:nether_portal"),
- Map.entry("minecraft:pumpkin", "minecraft:carved_pumpkin"),
- Map.entry("minecraft:quartz_ore", "minecraft:nether_quartz_ore"),
- Map.entry("minecraft:record_11", "minecraft:music_disc_11"),
- Map.entry("minecraft:record_13", "minecraft:music_disc_13"),
- Map.entry("minecraft:record_blocks", "minecraft:music_disc_blocks"),
- Map.entry("minecraft:record_cat", "minecraft:music_disc_cat"),
- Map.entry("minecraft:record_chirp", "minecraft:music_disc_chirp"),
- Map.entry("minecraft:record_far", "minecraft:music_disc_far"),
- Map.entry("minecraft:record_mall", "minecraft:music_disc_mall"),
- Map.entry("minecraft:record_mellohi", "minecraft:music_disc_mellohi"),
- Map.entry("minecraft:record_stal", "minecraft:music_disc_stal"),
- Map.entry("minecraft:record_strad", "minecraft:music_disc_strad"),
- Map.entry("minecraft:record_wait", "minecraft:music_disc_wait"),
- Map.entry("minecraft:record_ward", "minecraft:music_disc_ward"),
- Map.entry("minecraft:red_nether_brick", "minecraft:red_nether_bricks"),
- Map.entry("minecraft:reeds", "minecraft:sugar_cane"),
- Map.entry("minecraft:sign", "minecraft:oak_sign"),
- Map.entry("minecraft:slime", "minecraft:slime_block"),
- Map.entry("minecraft:snow_layer", "minecraft:snow"),
- Map.entry("minecraft:snow", "minecraft:snow_block"),
- Map.entry("minecraft:speckled_melon", "minecraft:glistering_melon_slice"),
- Map.entry("minecraft:stone_slab2", "minecraft:red_sandstone_slab"),
- Map.entry("minecraft:stone_stairs", "minecraft:cobblestone_stairs"),
- Map.entry("minecraft:trapdoor", "minecraft:oak_trapdoor"),
- Map.entry("minecraft:waterlily", "minecraft:lily_pad"),
- Map.entry("minecraft:web", "minecraft:cobweb"),
- Map.entry("minecraft:wooden_button", "minecraft:oak_button"),
- Map.entry("minecraft:wooden_door", "minecraft:oak_door"),
- Map.entry("minecraft:wooden_pressure_plate", "minecraft:oak_pressure_plate"),
- Map.entry("minecraft:yellow_flower", "minecraft:dandelion")
- );
-
- //TODO : Add mushroom block variants
- //i'll do it later because it isn't used and unlike the other, it's not just a rename or a separate, it's a separate and a merge
-
- public static String convertItemId(String id, int damage) {
- return switch (id) {
- //all the case are simple separate
- case "minecraft:anvil" -> ANVIL_VARIANTS[damage];
- case "minecraft:coal" -> COAL_VARIANTS[damage];
- case "minecraft:cobblestone_wall" -> COBBLESTONE_WALL_VARIANTS[damage];
- case "minecraft:cooked_fish" -> COOKED_FISH_VARIANTS[damage];
- case "minecraft:dirt" -> DIRT_VARIANTS[damage];
- case "minecraft:double_plant" -> DOUBLE_PLANT_VARIANTS[damage];
- case "minecraft:dye" -> DYE_VARIANTS[damage];
- case "minecraft:fish" -> FISH_VARIANTS[damage];
- case "minecraft:golden_apple" -> GOLDEN_APPLE_VARIANTS[damage];
- case "minecraft:log" -> LOG_VARIANTS[damage];
- case "minecraft:log2" -> LOG2_VARIANTS[damage];
- case "minecraft:monster_egg" -> MONSTER_EGG_VARIANTS[damage];
- case "minecraft:prismarine" -> PRISMARINE_VARIANTS[damage];
- case "minecraft:quartz_block" -> QUARTZ_BLOCK_VARIANTS[damage];
- case "minecraft:red_flower" -> RED_FLOWER_VARIANTS[damage];
- case "minecraft:sand" -> SAND_VARIANTS[damage];
- case "minecraft:skull" -> SKULL_VARIANTS[damage];
- case "minecraft:sponge" -> SPONGE_VARIANTS[damage];
- case "minecraft:stone" -> STONE_VARIANTS[damage];
- case "minecraft:stone_slab" -> STONE_SLAB_VARIANTS[damage];
- case "minecraft:stonebrick" -> STONEBRICK_VARIANTS[damage];
- case "minecraft:tallgrass" -> TALLGRASS_VARIANTS[damage];
- //we use a Map from int to str instead of an array because numbers are not consecutive
- case "minecraft:spawn_egg" -> SPAWN_EGG_VARIANTS.get(damage);
- //when we use the generalized variant we need to replaceFirst
- case "minecraft:sandstone", "minecraft:red_sandstone" -> id.replaceFirst(":", SANDSTONE_VARIANTS[damage]);
- //to use the general color variants we need to reverse the order because Minecraft decided so for some reason
- case "minecraft:banner" -> id.replaceFirst(":", COLOR_VARIANTS[15 - damage]);
- case "minecraft:carpet", "minecraft:stained_glass", "minecraft:stained_glass_pane", "minecraft:wool" -> id.replaceFirst(":", COLOR_VARIANTS[damage]);
- //for the terracotta we replace the whole name by the color and append "terracotta" at the end
- case "minecraft:stained_hardened_clay" -> id.replaceFirst(":stained_hardened_clay", COLOR_VARIANTS[damage]) + "terracotta";
- //for the wooden slab we need to remove the "wooden_" prefix, but otherwise it's the same, so I just combined them anyway
- case "minecraft:leaves", "minecraft:planks", "minecraft:sapling", "minecraft:wooden_slab" -> id.replaceFirst(":(?:wooden_)?", WOOD_VARIANTS[damage]);
- //here we replace the 2 by nothing to remove it as it's not needed anymore
- case "minecraft:leaves2" -> id.replaceFirst(":", WOOD_VARIANTS[damage + 4]).replaceFirst("2", "");
- //the default case is just a rename or no change
- default -> RENAMED.getOrDefault(id, id);
- };
- }
-}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java
index ab1af83d..eccfe7a2 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java
@@ -1,151 +1,131 @@
package de.hysky.skyblocker.skyblock.itemlist;
-import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.NEURepoManager;
import de.hysky.skyblocker.utils.TextTransformer;
+import de.hysky.skyblocker.utils.datafixer.LegacyItemStackFixer;
+import de.hysky.skyblocker.utils.datafixer.LegacyStringNbtReader;
import io.github.moulberry.repo.constants.PetNumbers;
import io.github.moulberry.repo.data.NEUItem;
import io.github.moulberry.repo.data.Rarity;
-import it.unimi.dsi.fastutil.ints.IntList;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.*;
import net.minecraft.item.ItemStack;
+import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
-import net.minecraft.nbt.NbtString;
-import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
-import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+
+import com.mojang.logging.LogUtils;
public class ItemStackBuilder {
- public static final Pattern SKULL_UUID_PATTERN = Pattern.compile("(?<=SkullOwner:\\{)Id:\"(.{36})\"");
- public static final Pattern SKULL_TEXTURE_PATTERN = Pattern.compile("(?<=Properties:\\{textures:\\[0:\\{Value:)\"(.+?)\"");
- private static final Pattern COLOR_PATTERN = Pattern.compile("color:(\\d+)");
- private static final Pattern EXPLOSION_COLOR_PATTERN = Pattern.compile("\\{Explosion:\\{(?:Type:[0-9a-z]+,)?Colors:\\[(?<color>[0-9]+)]\\}");
- private static Map<String, Map<Rarity, PetNumbers>> petNums;
-
- public static void loadPetNums() {
- try {
- petNums = NEURepoManager.NEU_REPO.getConstants().getPetNumbers();
- } catch (Exception e) {
- ItemRepository.LOGGER.error("Failed to load petnums.json");
- }
- }
-
- public static ItemStack fromNEUItem(NEUItem item) {
- String internalName = item.getSkyblockItemId();
-
- List<Pair<String, String>> injectors = new ArrayList<>(petData(internalName));
-
- String legacyId = item.getMinecraftItemId();
- Identifier itemId = Identifier.of(ItemFixerUpper.convertItemId(legacyId, item.getDamage()));
-
- ItemStack stack = new ItemStack(Registries.ITEM.get(itemId));
-
- // Custom Data
- NbtCompound customData = new NbtCompound();
-
- // Add Skyblock Item Id
- customData.put(ItemUtils.ID, NbtString.of(internalName));
-
- // Item Name
- String name = injectData(item.getDisplayName(), injectors);
- stack.set(DataComponentTypes.CUSTOM_NAME, TextTransformer.fromLegacy(name));
-
- // Lore
- stack.set(DataComponentTypes.LORE, new LoreComponent(item.getLore().stream().map(line -> TextTransformer.fromLegacy(injectData(line, injectors))).map(Text.class::cast).toList()));
-
- String nbttag = item.getNbttag();
- // add skull texture
- Matcher skullUuid = SKULL_UUID_PATTERN.matcher(nbttag);
- Matcher skullTexture = SKULL_TEXTURE_PATTERN.matcher(nbttag);
- if (skullUuid.find() && skullTexture.find()) {
- UUID uuid = UUID.fromString(skullUuid.group(1));
- String textureValue = skullTexture.group(1);
-
- stack.set(DataComponentTypes.PROFILE, new ProfileComponent(Optional.of(internalName.substring(0, Math.min(internalName.length(), 15))), Optional.of(uuid), ItemUtils.propertyMapWithTexture(textureValue)));
- }
-
- // add leather armor dye color
- Matcher colorMatcher = COLOR_PATTERN.matcher(nbttag);
- if (colorMatcher.find()) {
- int color = Integer.parseInt(colorMatcher.group(1));
- stack.set(DataComponentTypes.DYED_COLOR, new DyedColorComponent(color, false));
- }
- // add enchantment glint
- if (nbttag.contains("ench:")) {
- stack.set(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true);
- }
-
- //Hide weapon damage and other useless info
- stack.set(DataComponentTypes.ATTRIBUTE_MODIFIERS, new AttributeModifiersComponent(List.of(), false));
-
- // Add firework star color
- Matcher explosionColorMatcher = EXPLOSION_COLOR_PATTERN.matcher(nbttag);
- if (explosionColorMatcher.find()) {
- //We used create an IntArrayList and took the color as the list's capacity and not add anything to the list which y'know casually leaked a lot of memory...
- IntList color = IntList.of(Integer.parseInt(explosionColorMatcher.group("color")));
-
- //Forget about the actual ball type because it probably doesn't matter
- stack.set(DataComponentTypes.FIREWORK_EXPLOSION, new FireworkExplosionComponent(FireworkExplosionComponent.Type.SMALL_BALL, color, IntList.of(), false, false));
- }
-
- // Attach custom nbt data
- stack.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(customData));
-
- return stack;
- }
-
- private static List<Pair<String, String>> petData(String internalName) {
- List<Pair<String, String>> list = new ArrayList<>();
-
- String petName = internalName.split(";")[0];
- if (!internalName.contains(";") || !petNums.containsKey(petName)) return list;
-
- final Rarity[] rarities = {
- Rarity.COMMON,
- Rarity.UNCOMMON,
- Rarity.RARE,
- Rarity.EPIC,
- Rarity.LEGENDARY,
- Rarity.MYTHIC,
- };
- Rarity rarity = rarities[Integer.parseInt(internalName.split(";")[1])];
- PetNumbers data = petNums.get(petName).get(rarity);
-
- int minLevel = data.getLowLevel();
- int maxLevel = data.getHighLevel();
- list.add(new Pair<>("\\{LVL\\}", minLevel + " ➡ " + maxLevel));
-
- Map<String, Double> statNumsMin = data.getStatsAtLowLevel().getStatNumbers();
- Map<String, Double> statNumsMax = data.getStatsAtHighLevel().getStatNumbers();
- Set<Map.Entry<String, Double>> entrySet = statNumsMin.entrySet();
- for (Map.Entry<String, Double> entry : entrySet) {
- String key = entry.getKey();
- String left = "\\{" + key + "\\}";
- String right = statNumsMin.get(key) + " ➡ " + statNumsMax.get(key);
- list.add(new Pair<>(left, right));
- }
-
- List<Double> otherNumsMin = data.getStatsAtLowLevel().getOtherNumbers();
- List<Double> otherNumsMax = data.getStatsAtHighLevel().getOtherNumbers();
- for (int i = 0; i < otherNumsMin.size(); ++i) {
- String left = "\\{" + i + "\\}";
- String right = otherNumsMin.get(i) + " ➡ " + otherNumsMax.get(i);
- list.add(new Pair<>(left, right));
- }
-
- return list;
- }
-
- public static String injectData(String string, List<Pair<String, String>> injectors) {
- for (Pair<String, String> injector : injectors) {
- string = string.replaceAll(injector.getLeft(), injector.getRight());
- }
- return string;
- }
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private static Map<String, Map<Rarity, PetNumbers>> petNums;
+
+ protected static void loadPetNums() {
+ try {
+ petNums = NEURepoManager.NEU_REPO.getConstants().getPetNumbers();
+ } catch (Exception e) {
+ ItemRepository.LOGGER.error("Failed to load petnums.json");
+ }
+ }
+
+ protected static ItemStack fromNEUItem(NEUItem item) {
+ try {
+ NbtCompound nbt = new NbtCompound();
+ NbtCompound tag = LegacyStringNbtReader.parse(item.getNbttag());
+
+ //Construct the nbt
+ nbt.put("tag", tag);
+ nbt.putString("id", item.getMinecraftItemId());
+ nbt.putShort("Damage", (short) item.getDamage());
+ nbt.putInt("Count", 1);
+
+ ItemStack stack = LegacyItemStackFixer.fixLegacyStack(nbt);
+
+ //The item couldn't be fixed up
+ if (stack.isEmpty()) {
+ LOGGER.error("[Skyblocker ItemStackBuilder] Failed to build item with skyblock id: {}!", item.getSkyblockItemId());
+
+ return createErrorStack(item.getSkyblockItemId());
+ }
+
+ List<Pair<String, String>> injectors = new ArrayList<>(petData(item.getSkyblockItemId()));
+
+ //Inject data into the item name
+ String name = injectData(item.getDisplayName(), injectors);
+ stack.set(DataComponentTypes.CUSTOM_NAME, TextTransformer.fromLegacy(name));
+
+ //Inject Data into the lore
+ stack.set(DataComponentTypes.LORE, new LoreComponent(item.getLore().stream()
+ .map(line -> TextTransformer.fromLegacy(injectData(line, injectors)))
+ .map(Text.class::cast)
+ .toList()));
+
+ return stack;
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker ItemStackBuilder] Failed to build item with skyblock id: {}!", item.getSkyblockItemId(), e);
+ }
+
+ return createErrorStack(item.getSkyblockItemId());
+ }
+
+ private static ItemStack createErrorStack(String skyblockItemId) {
+ ItemStack errorStack = new ItemStack(Items.BARRIER);
+ errorStack.set(DataComponentTypes.CUSTOM_NAME, Text.of(skyblockItemId));
+
+ return errorStack;
+ }
+
+ private static List<Pair<String, String>> petData(String internalName) {
+ List<Pair<String, String>> list = new ArrayList<>();
+
+ String petName = internalName.split(";")[0];
+ if (!internalName.contains(";") || !petNums.containsKey(petName)) return list;
+
+ final Rarity[] rarities = {
+ Rarity.COMMON,
+ Rarity.UNCOMMON,
+ Rarity.RARE,
+ Rarity.EPIC,
+ Rarity.LEGENDARY,
+ Rarity.MYTHIC,
+ };
+ Rarity rarity = rarities[Integer.parseInt(internalName.split(";")[1])];
+ PetNumbers data = petNums.get(petName).get(rarity);
+
+ int minLevel = data.getLowLevel();
+ int maxLevel = data.getHighLevel();
+ list.add(new Pair<>("\\{LVL\\}", minLevel + " ➡ " + maxLevel));
+
+ Map<String, Double> statNumsMin = data.getStatsAtLowLevel().getStatNumbers();
+ Map<String, Double> statNumsMax = data.getStatsAtHighLevel().getStatNumbers();
+ Set<Map.Entry<String, Double>> entrySet = statNumsMin.entrySet();
+ for (Map.Entry<String, Double> entry : entrySet) {
+ String key = entry.getKey();
+ String left = "\\{" + key + "\\}";
+ String right = statNumsMin.get(key) + " ➡ " + statNumsMax.get(key);
+ list.add(new Pair<>(left, right));
+ }
+
+ List<Double> otherNumsMin = data.getStatsAtLowLevel().getOtherNumbers();
+ List<Double> otherNumsMax = data.getStatsAtHighLevel().getOtherNumbers();
+ for (int i = 0; i < otherNumsMin.size(); ++i) {
+ String left = "\\{" + i + "\\}";
+ String right = otherNumsMin.get(i) + " ➡ " + otherNumsMax.get(i);
+ list.add(new Pair<>(left, right));
+ }
+
+ return list;
+ }
+
+ private static String injectData(String string, List<Pair<String, String>> injectors) {
+ for (Pair<String, String> injector : injectors) {
+ string = string.replaceAll(injector.getLeft(), injector.getRight());
+ }
+ return string;
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java
index db9b8240..9f9dbca0 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/profileviewer/inventory/Pet.java
@@ -1,12 +1,10 @@
package de.hysky.skyblocker.skyblock.profileviewer.inventory;
import de.hysky.skyblocker.skyblock.item.PetInfo;
-import de.hysky.skyblocker.skyblock.itemlist.ItemFixerUpper;
import de.hysky.skyblocker.skyblock.itemlist.ItemRepository;
import de.hysky.skyblocker.skyblock.profileviewer.utils.LevelFinder;
import de.hysky.skyblocker.skyblock.profileviewer.utils.ProfileViewerUtils;
import de.hysky.skyblocker.skyblock.tabhud.util.Ico;
-import de.hysky.skyblocker.utils.ItemUtils;
import de.hysky.skyblocker.utils.NEURepoManager;
import io.github.moulberry.repo.constants.PetNumbers;
import io.github.moulberry.repo.data.NEUItem;
@@ -21,39 +19,34 @@ import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.component.type.ProfileComponent;
import net.minecraft.item.ItemStack;
-import net.minecraft.registry.Registries;
+import net.minecraft.item.Items;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
-import net.minecraft.util.Identifier;
-
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static de.hysky.skyblocker.skyblock.itemlist.ItemStackBuilder.SKULL_TEXTURE_PATTERN;
import static de.hysky.skyblocker.skyblock.profileviewer.utils.ProfileViewerUtils.numLetterFormat;
public class Pet {
+ private static final Pattern statsMatcher = Pattern.compile("\\{[A-Za-z_]+}");
+ private static final Pattern numberMatcher = Pattern.compile("\\{\\d+}");
+
private final String name;
private final double xp;
private final String tier;
private final Optional<String> heldItem;
private final Optional<String> skin;
- private final Optional<String> skinTexture;
+ private final Optional<ProfileComponent> skinTexture;
private final int level;
private final double perecentageToLevel;
private final long levelXP;
private final long nextLevelXP;
private final ItemStack icon;
- private final Pattern statsMatcher = Pattern.compile("\\{[A-Za-z_]+}");
- private final Pattern numberMatcher = Pattern.compile("\\{\\d+}");
-
-
-
private static final Object2IntMap<String> TIER_MAP = Object2IntMaps.unmodifiable(new Object2IntOpenHashMap<>(Map.of(
"COMMON", 0, "UNCOMMON", 1, "RARE", 2, "EPIC", 3, "LEGENDARY", 4, "MYTHIC", 5
)));
@@ -99,15 +92,19 @@ public class Pet {
return tier;
}
- private Optional<String> calculateSkinTexture() {
+ private Optional<ProfileComponent> calculateSkinTexture() {
if (this.skin.isPresent()) {
- NEUItem item = NEURepoManager.NEU_REPO.getItems().getItemBySkyblockId("PET_SKIN_" + this.skin.get());
- if (item == null) return Optional.empty();
- Matcher skullTexture = SKULL_TEXTURE_PATTERN.matcher(item.getNbttag());
- if (skullTexture.find()) return Optional.of(skullTexture.group(1));
+ ItemStack item = ItemRepository.getItemStack("PET_SKIN_" + this.skin.get());
+
+ if (item == null || item.isEmpty()) return Optional.empty();
+
+ ProfileComponent profile = item.get(DataComponentTypes.PROFILE);
+
+ return profile != null ? Optional.of(profile) : Optional.empty();
}
return Optional.empty();
}
+
public int getLevel() { return level; }
public ItemStack getIcon() { return icon; }
@@ -139,14 +136,14 @@ public class Pet {
* @return The ItemStack representing the pet with all its properties set.
*/
private ItemStack fromNEUItem(NEUItem item, ItemStack heldItem) {
- if (item == null) {
- ItemStack errIcon = Ico.BARRIER.copy();
- errIcon.set(DataComponentTypes.CUSTOM_NAME, Text.of(this.getName()));
- return errIcon;
- }
+ if (item == null) return getErrorStack();
+
+ ItemStack petStack = ItemRepository.getItemStack(item.getSkyblockItemId());
+
+ if (petStack == null || petStack.isEmpty()) return getErrorStack();
- Identifier itemId = Identifier.of(ItemFixerUpper.convertItemId(item.getMinecraftItemId(), item.getDamage()));
- ItemStack petStack = new ItemStack(Registries.ITEM.get(itemId)).copy();
+ // Copy to avoid mutating the original stack
+ petStack = petStack.copy();
List<Text> formattedLore = !(name.equals("GOLDEN_DRAGON") && level < 101) ? processLore(item.getLore(), heldItem) : buildGoldenDragonEggLore(item.getLore());
@@ -167,16 +164,7 @@ public class Pet {
// Skin Head Texture
if (skinTexture.isPresent()) {
formattedLore.set(0, Text.of(formattedLore.getFirst().getString() + ", " + Formatting.strip(NEURepoManager.NEU_REPO.getItems().getItems().get("PET_SKIN_" + skin.get()).getDisplayName())));
- petStack.set(DataComponentTypes.PROFILE, new ProfileComponent(
- Optional.of(item.getSkyblockItemId()), Optional.of(UUID.randomUUID()),
- ItemUtils.propertyMapWithTexture(this.skinTexture.get())));
- } else {
- Matcher skullTexture = SKULL_TEXTURE_PATTERN.matcher(item.getNbttag());
- if (skullTexture.find()) {
- petStack.set(DataComponentTypes.PROFILE, new ProfileComponent(
- Optional.of(item.getSkyblockItemId()), Optional.of(UUID.randomUUID()),
- ItemUtils.propertyMapWithTexture(skullTexture.group(1))));
- }
+ petStack.set(DataComponentTypes.PROFILE, skinTexture.get());
}
if ((boosted())) formattedLore.set(formattedLore.size() - 1, Text.literal(Rarity.values()[getTier() + 1].toString()).setStyle(style).formatted(Formatting.BOLD, RARITY_COLOR_MAP.get(getTier() + 1)));
@@ -265,4 +253,10 @@ public class Pet {
private boolean boosted() {
return this.heldItem.isPresent() && this.heldItem.get().equals("PET_ITEM_TIER_BOOST");
}
+
+ private ItemStack getErrorStack() {
+ ItemStack errIcon = new ItemStack(Items.BARRIER);
+ errIcon.set(DataComponentTypes.CUSTOM_NAME, Text.of(this.getName()));
+ return errIcon;
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/utils/datafixer/LegacyItemStackFixer.java b/src/main/java/de/hysky/skyblocker/utils/datafixer/LegacyItemStackFixer.java
index 8a5c0430..c27e05dc 100644
--- a/src/main/java/de/hysky/skyblocker/utils/datafixer/LegacyItemStackFixer.java
+++ b/src/main/java/de/hysky/skyblocker/utils/datafixer/LegacyItemStackFixer.java
@@ -1,14 +1,13 @@
package de.hysky.skyblocker.utils.datafixer;
import static net.azureaaron.legacyitemdfu.LegacyItemStackFixer.getFixer;
+import static net.azureaaron.legacyitemdfu.LegacyItemStackFixer.getFirstVersion;
+import static net.azureaaron.legacyitemdfu.LegacyItemStackFixer.getLatestVersion;
import java.util.List;
import org.slf4j.Logger;
-import static net.azureaaron.legacyitemdfu.LegacyItemStackFixer.FIRST_VERSION;
-import static net.azureaaron.legacyitemdfu.LegacyItemStackFixer.LATEST_VERSION;
-
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Dynamic;
@@ -33,7 +32,7 @@ public class LegacyItemStackFixer {
@SuppressWarnings("deprecation")
public static ItemStack fixLegacyStack(NbtCompound nbt) {
RegistryOps<NbtElement> ops = ItemStackComponentizationFixer.getRegistryLookup().getOps(NbtOps.INSTANCE);
- Dynamic<NbtElement> fixed = getFixer().update(TypeReferences.LEGACY_ITEM_STACK, new Dynamic<>(ops, nbt), FIRST_VERSION, LATEST_VERSION);
+ Dynamic<NbtElement> fixed = getFixer().update(TypeReferences.LEGACY_ITEM_STACK, new Dynamic<>(ops, nbt), getFirstVersion(), getLatestVersion());
ItemStack stack = ItemStack.CODEC.parse(fixed)
.setPartial(ItemStack.EMPTY)
.resultOrPartial(LegacyItemStackFixer::log)
diff --git a/src/main/java/de/hysky/skyblocker/utils/datafixer/LegacyStringNbtReader.java b/src/main/java/de/hysky/skyblocker/utils/datafixer/LegacyStringNbtReader.java
new file mode 100644
index 00000000..eb7fb4e8
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/utils/datafixer/LegacyStringNbtReader.java
@@ -0,0 +1,81 @@
+package de.hysky.skyblocker.utils.datafixer;
+
+import com.mojang.brigadier.StringReader;
+import com.mojang.brigadier.exceptions.CommandSyntaxException;