diff options
Diffstat (limited to 'src/main/java/de/hysky/skyblocker/utils/ItemUtils.java')
-rw-r--r-- | src/main/java/de/hysky/skyblocker/utils/ItemUtils.java | 168 |
1 files changed, 88 insertions, 80 deletions
diff --git a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java index 70a8c241..086686a7 100644 --- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java +++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java @@ -1,29 +1,41 @@ package de.hysky.skyblocker.utils; +import com.google.gson.Gson; +import com.google.gson.JsonParser; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.properties.PropertyMap; import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import de.hysky.skyblocker.mixin.accessor.ItemStackAccessor; +import com.mojang.serialization.Codec; +import com.mojang.serialization.JsonOps; +import com.mojang.serialization.codecs.RecordCodecBuilder; import it.unimi.dsi.fastutil.ints.IntIntPair; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.component.ComponentChanges; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.LoreComponent; +import net.minecraft.component.type.NbtComponent; +import net.minecraft.component.type.ProfileComponent; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.StringNbtReader; +import net.minecraft.registry.Registries; +import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.text.Text; -import net.minecraft.text.Texts; import net.minecraft.util.Formatting; +import net.minecraft.util.dynamic.Codecs; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.time.Instant; import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.*; +import java.time.temporal.TemporalAccessor; +import java.util.List; +import java.util.Locale; +import java.util.Optional; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -31,83 +43,72 @@ import java.util.regex.Pattern; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; public class ItemUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(ItemUtils.class); - public static final String EXTRA_ATTRIBUTES = "ExtraAttributes"; public static final String ID = "id"; public static final String UUID = "uuid"; private static final DateTimeFormatter OBTAINED_DATE_FORMATTER = DateTimeFormatter.ofPattern("MMMM d, yyyy").withZone(ZoneId.systemDefault()).localizedBy(Locale.ENGLISH); - private static final SimpleDateFormat OLD_OBTAINED_DATE_FORMAT = new SimpleDateFormat("MM/dd/yy"); + private static final DateTimeFormatter OLD_OBTAINED_DATE_FORMAT = DateTimeFormatter.ofPattern("M/d/yy h:m a").withZone(ZoneId.of("UTC")).localizedBy(Locale.ENGLISH); public static final Pattern NOT_DURABILITY = Pattern.compile("[^0-9 /]"); public static final Predicate<String> FUEL_PREDICATE = line -> line.contains("Fuel: "); - - public static LiteralArgumentBuilder<FabricClientCommandSource> dumpHeldItemNbtCommand() { - return literal("dumpHeldItemNbt").executes(context -> { - context.getSource().sendFeedback(Text.literal("[Skyblocker Debug] Held Item Nbt: " + context.getSource().getPlayer().getMainHandStack().writeNbt(new NbtCompound()))); + private static final Gson GSON = new Gson(); //GSON Instance with no config + private static final Codec<RegistryEntry<Item>> EMPTY_ALLOWING_ITEM_CODEC = Registries.ITEM.getEntryCodec(); + public static final Codec<ItemStack> EMPTY_ALLOWING_ITEMSTACK_CODEC = Codec.lazyInitialized(() -> RecordCodecBuilder.create(instance -> instance.group( + EMPTY_ALLOWING_ITEM_CODEC.fieldOf("id").forGetter(ItemStack::getRegistryEntry), + Codec.INT.orElse(1).fieldOf("count").forGetter(ItemStack::getCount), + ComponentChanges.CODEC.optionalFieldOf("components", ComponentChanges.EMPTY).forGetter(ItemStack::getComponentChanges) + ).apply(instance, ItemStack::new))); + + public static LiteralArgumentBuilder<FabricClientCommandSource> dumpHeldItemCommand() { + return literal("dumpHeldItem").executes(context -> { + context.getSource().sendFeedback(Text.literal("[Skyblocker Debug] Held Item: " + GSON.toJson(ItemStack.CODEC.encodeStart(JsonOps.INSTANCE, context.getSource().getPlayer().getMainHandStack()).getOrThrow()))); return Command.SINGLE_SUCCESS; }); } - /** - * Gets the {@code ExtraAttributes} NBT tag from the item stack. - * - * @param stack the item stack to get the {@code ExtraAttributes} NBT tag from - * @return an optional containing the {@code ExtraAttributes} NBT tag of the item stack - */ - public static Optional<NbtCompound> getExtraAttributesOptional(@NotNull ItemStack stack) { - return Optional.ofNullable(stack.getSubNbt(EXTRA_ATTRIBUTES)); - } - - /** - * Gets the {@code ExtraAttributes} NBT tag from the item stack. - * - * @param stack the item stack to get the {@code ExtraAttributes} NBT tag from - * @return the {@code ExtraAttributes} NBT tag of the item stack, or null if the item stack is null or does not have an {@code ExtraAttributes} NBT tag - */ - @Nullable - public static NbtCompound getExtraAttributes(@NotNull ItemStack stack) { - return stack.getSubNbt(EXTRA_ATTRIBUTES); + @SuppressWarnings("deprecation") + public static NbtCompound getCustomData(@NotNull ItemStack stack) { + return stack.getOrDefault(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT).getNbt(); } /** - * Gets the internal name of the item stack from the {@code ExtraAttributes} NBT tag. + * Gets the Skyblock item id of the item stack. * * @param stack the item stack to get the internal name from * @return an optional containing the internal name of the item stack */ - public static Optional<String> getItemIdOptional(@NotNull ItemStack stack) { - return getExtraAttributesOptional(stack).map(extraAttributes -> extraAttributes.getString(ID)); + public static Optional<String> getItemIdOptional(@NotNull ItemStack stack) { + NbtCompound customData = getCustomData(stack); + return customData.contains(ID) ? Optional.of(customData.getString(ID)) : Optional.empty(); } /** - * Gets the internal name of the item stack from the {@code ExtraAttributes} NBT tag. + * Gets the Skyblock item id of the item stack. * * @param stack the item stack to get the internal name from * @return the internal name of the item stack, or an empty string if the item stack is null or does not have an internal name */ - public static String getItemId(@NotNull ItemStack stack) { - NbtCompound extraAttributes = getExtraAttributes(stack); - return extraAttributes != null ? extraAttributes.getString(ID) : ""; + public static String getItemId(@NotNull ItemStack stack) { + return getCustomData(stack).getString(ID); } /** - * Gets the UUID of the item stack from the {@code ExtraAttributes} NBT tag. + * Gets the UUID of the item stack. * * @param stack the item stack to get the UUID from * @return an optional containing the UUID of the item stack */ - public static Optional<String> getItemUuidOptional(@NotNull ItemStack stack) { - return getExtraAttributesOptional(stack).map(extraAttributes -> extraAttributes.getString(UUID)); + public static Optional<String> getItemUuidOptional(@NotNull ItemStack stack) { + NbtCompound customData = getCustomData(stack); + return customData.contains(UUID) ? Optional.of(customData.getString(UUID)) : Optional.empty(); } /** - * Gets the UUID of the item stack from the {@code ExtraAttributes} NBT tag. + * Gets the UUID of the item stack. * * @param stack the item stack to get the UUID from * @return the UUID of the item stack, or an empty string if the item stack is null or does not have a UUID */ - public static String getItemUuid(@NotNull ItemStack stack) { - NbtCompound extraAttributes = getExtraAttributes(stack); - return extraAttributes != null ? extraAttributes.getString(UUID) : ""; + public static String getItemUuid(@NotNull ItemStack stack) { + return getCustomData(stack).getString(UUID); } /** @@ -126,47 +127,41 @@ public class ItemUtils { * @param stack the item under the pointer * @return if the item have a "Timestamp" it will be shown formated on the tooltip */ - public static String getTimestamp(ItemStack stack) { - NbtCompound ea = getExtraAttributes(stack); - - if (ea != null && ea.contains("timestamp", NbtElement.LONG_TYPE)) { - Instant date = Instant.ofEpochMilli(ea.getLong("timestamp")); + public static String getTimestamp(ItemStack stack) { + NbtCompound customData = getCustomData(stack); + if (customData != null && customData.contains("timestamp", NbtElement.LONG_TYPE)) { + Instant date = Instant.ofEpochMilli(customData.getLong("timestamp")); return OBTAINED_DATE_FORMATTER.format(date); } - if (ea != null && ea.contains("timestamp", NbtElement.STRING_TYPE)) { - try { - Instant date = OLD_OBTAINED_DATE_FORMAT.parse(ea.getString("timestamp")).toInstant(); - - return OBTAINED_DATE_FORMATTER.format(date); - } catch (ParseException e) { - LOGGER.warn("[Skyblocker Item Utils] Encountered an unknown exception while parsing time stamp of item {} with extra attributes {}", stack, ea, e); - } + if (customData != null && customData.contains("timestamp", NbtElement.STRING_TYPE)) { + TemporalAccessor date = OLD_OBTAINED_DATE_FORMAT.parse(customData.getString("timestamp")); + return OBTAINED_DATE_FORMATTER.format(date); } return ""; } public static boolean hasCustomDurability(@NotNull ItemStack stack) { - NbtCompound extraAttributes = getExtraAttributes(stack); - return extraAttributes != null && (extraAttributes.contains("drill_fuel") || extraAttributes.getString(ID).equals("PICKONIMBUS")); + NbtCompound customData = getCustomData(stack); + return customData != null && (customData.contains("drill_fuel") || customData.getString(ID).equals("PICKONIMBUS")); } @Nullable public static IntIntPair getDurability(@NotNull ItemStack stack) { - NbtCompound extraAttributes = getExtraAttributes(stack); - if (extraAttributes == null) return null; + NbtCompound customData = getCustomData(stack); + if (customData == null) return null; // TODO Calculate drill durability based on the drill_fuel flag, fuel_tank flag, and hotm level // TODO Cache the max durability and only update the current durability on inventory tick - int pickonimbusDurability = extraAttributes.getInt("pickonimbus_durability"); + int pickonimbusDurability = customData.getInt("pickonimbus_durability"); if (pickonimbusDurability > 0) { return IntIntPair.of(pickonimbusDurability, 5000); } - String drillFuel = Formatting.strip(getNbtTooltip(stack, FUEL_PREDICATE)); + String drillFuel = Formatting.strip(getLoreLineIf(stack, FUEL_PREDICATE)); if (drillFuel != null) { String[] drillFuelStrings = NOT_DURABILITY.matcher(drillFuel).replaceAll("").trim().split("/"); return IntIntPair.of(Integer.parseInt(drillFuelStrings[0]), Integer.parseInt(drillFuelStrings[1]) * 1000); @@ -176,8 +171,8 @@ public class ItemUtils { } @Nullable - public static String getNbtTooltip(ItemStack item, Predicate<String> predicate) { - for (Text line : getNbtTooltips(item)) { + public static String getLoreLineIf(ItemStack item, Predicate<String> predicate) { + for (Text line : getLore(item)) { String string = line.getString(); if (predicate.test(string)) { return string; @@ -188,8 +183,8 @@ public class ItemUtils { } @Nullable - public static Matcher getNbtTooltip(ItemStack item, Pattern pattern) { - for (Text line : getNbtTooltips(item)) { + public static Matcher getLoreLineIfMatch(ItemStack item, Pattern pattern) { + for (Text line : getLore(item)) { String string = line.getString(); Matcher matcher = pattern.matcher(string); if (matcher.matches()) { @@ -200,19 +195,32 @@ public class ItemUtils { return null; } - public static List<Text> getNbtTooltips(ItemStack item) { - NbtCompound displayNbt = item.getSubNbt("display"); - if (displayNbt == null || !displayNbt.contains("Lore", NbtElement.LIST_TYPE)) { - return Collections.emptyList(); - } + public static List<Text> getLore(ItemStack item) { + return item.getOrDefault(DataComponentTypes.LORE, LoreComponent.DEFAULT).styledLines(); + } + + public static PropertyMap propertyMapWithTexture(String textureValue) { + return Codecs.GAME_PROFILE_PROPERTY_MAP.parse(JsonOps.INSTANCE, JsonParser.parseString("[{\"name\":\"textures\",\"value\":\"" + textureValue + "\"}]")).getOrThrow(); + } + + public static String getHeadTexture(ItemStack stack) { + if (!stack.isOf(Items.PLAYER_HEAD) || !stack.contains(DataComponentTypes.PROFILE)) return ""; + + ProfileComponent profile = stack.get(DataComponentTypes.PROFILE); + String texture = profile.properties().get("textures").stream() + .map(Property::value) + .findFirst() + .orElse(""); - return displayNbt.getList("Lore", NbtElement.STRING_TYPE).stream().map(NbtElement::asString).map(Text.Serialization::fromJson).filter(Objects::nonNull).map(text -> Texts.setStyleIfAbsent(text, ItemStackAccessor.getLORE_STYLE())).map(Text.class::cast).toList(); + return texture; } public static ItemStack getSkyblockerStack() { try { - return ItemStack.fromNbt(StringNbtReader.parse("{id:\"minecraft:player_head\",Count:1,tag:{SkullOwner:{Id:[I;-300151517,-631415889,-1193921967,-1821784279],Properties:{textures:[{Value:\"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0=\"}]}}}}")); - } catch (CommandSyntaxException e) { + ItemStack stack = new ItemStack(Items.PLAYER_HEAD); + stack.set(DataComponentTypes.PROFILE, new ProfileComponent(Optional.of("SkyblockerStack"), Optional.of(java.util.UUID.randomUUID()), propertyMapWithTexture("e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOCJ9fX0="))); + return stack; + } catch (Exception e) { throw new RuntimeException(e); } } |