diff options
| author | Aaron <51387595+AzureAaron@users.noreply.github.com> | 2024-12-06 01:39:50 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-06 01:39:50 -0500 |
| commit | fa726da23c40146c78fbf5e3824616e91284f4b1 (patch) | |
| tree | 913ee83661bf4045c312f59bab44cf36350e3088 /src/main/java | |
| parent | af5ec9fe170bbb8c0b0f492db2715dd3b9e35b0a (diff) | |
| download | Skyblocker-fa726da23c40146c78fbf5e3824616e91284f4b1.tar.gz Skyblocker-fa726da23c40146c78fbf5e3824616e91284f4b1.tar.bz2 Skyblocker-fa726da23c40146c78fbf5e3824616e91284f4b1.zip | |
Item DFU Unification (#1054)
Diffstat (limited to 'src/main/java')
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; |
