diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/util/CustomSkull.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/util/CustomSkull.java index 08f96b79..37ec05fd 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/util/CustomSkull.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/item/util/CustomSkull.java @@ -1,19 +1,14 @@ package net.Indyuce.mmoitems.api.item.util; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.item.ItemTag; import io.lumine.mythic.lib.util.AdventureUtils; import io.lumine.mythic.lib.version.VersionMaterial; -import net.Indyuce.mmoitems.MMOItems; import org.bukkit.ChatColor; import org.bukkit.inventory.ItemFlag; -import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; -import java.lang.reflect.Field; -import java.util.UUID; -import java.util.logging.Level; import java.util.stream.Collectors; public class CustomSkull extends ConfigItem { @@ -31,19 +26,11 @@ public class CustomSkull extends ConfigItem { public void updateItem() { setItem(VersionMaterial.PLAYER_HEAD.toItem()); - ItemMeta meta = getItem().getItemMeta(); + SkullMeta meta = (SkullMeta) getItem().getItemMeta(); AdventureUtils.setDisplayName(meta, getName()); meta.addItemFlags(ItemFlag.values()); - GameProfile gameProfile = new GameProfile(UUID.randomUUID(), "SkullTexture"); - gameProfile.getProperties().put("textures", new Property("textures", textureValue)); - try { - Field profileField = meta.getClass().getDeclaredField("profile"); - profileField.setAccessible(true); - profileField.set(meta, gameProfile); - } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException exception) { - MMOItems.plugin.getLogger().log(Level.WARNING, "Could not load skull texture"); - } + UtilityMethods.setTextureValue(meta, textureValue); if (hasLore()) AdventureUtils.setLore(meta, getLore() diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/util/NoClipItem.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/util/NoClipItem.java index 69cd68e9..d8bd1a13 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/util/NoClipItem.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/util/NoClipItem.java @@ -1,9 +1,9 @@ package net.Indyuce.mmoitems.api.util; -import java.lang.reflect.Field; -import java.util.Random; -import java.util.logging.Level; - +import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.api.item.ItemTag; +import io.lumine.mythic.lib.api.item.NBTItem; +import net.Indyuce.mmoitems.MMOItems; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.enchantments.Enchantment; @@ -20,12 +20,8 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.SkullMeta; -import com.mojang.authlib.GameProfile; - -import net.Indyuce.mmoitems.MMOItems; -import io.lumine.mythic.lib.MythicLib; -import io.lumine.mythic.lib.api.item.ItemTag; -import io.lumine.mythic.lib.api.item.NBTItem; +import java.util.Random; +import java.util.logging.Level; public class NoClipItem implements Listener { private final Item item; @@ -115,18 +111,11 @@ public class NoClipItem implements Listener { } // Copy Skull textures - if (oldItem.getItemMeta() instanceof SkullMeta) { - try { - final Field oldProfileField = oldItem.getItemMeta().getClass().getDeclaredField("profile"); - oldProfileField.setAccessible(true); - final GameProfile oldProfile = (GameProfile) oldProfileField.get(oldItem.getItemMeta()); - - final Field profileField = newItemMeta.getClass().getDeclaredField("profile"); - profileField.setAccessible(true); - profileField.set(newItemMeta, oldProfile); - } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException exception) { - MMOItems.plugin.getLogger().log(Level.WARNING, "Could not set skull texture on stripItemData method in the NoClipItem class. Please report this issue!"); - } + if (oldItem.getItemMeta() instanceof SkullMeta) try { + final Object oldProfile = MythicLib.plugin.getVersion().getWrapper().getProfile((SkullMeta) oldItem.getItemMeta()); + MythicLib.plugin.getVersion().getWrapper().setProfile((SkullMeta) newItemMeta, oldProfile); + } catch (RuntimeException exception) { + MMOItems.plugin.getLogger().log(Level.WARNING, "Could not set skull texture on stripItemData method in the NoClipItem class. Please report this issue!"); } // Copy Leather colors diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/SkullTextureStat.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/SkullTextureStat.java index 1c949ad3..aa6da37b 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/SkullTextureStat.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/SkullTextureStat.java @@ -1,7 +1,6 @@ package net.Indyuce.mmoitems.stat; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; +import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.item.ItemTag; import io.lumine.mythic.lib.api.util.AltChar; import io.lumine.mythic.lib.version.VersionMaterial; @@ -12,111 +11,110 @@ import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder; import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem; import net.Indyuce.mmoitems.gui.edition.EditionInventory; import net.Indyuce.mmoitems.stat.data.SkullTextureData; -import net.Indyuce.mmoitems.stat.data.random.RandomStatData; -import net.Indyuce.mmoitems.stat.data.type.StatData; import net.Indyuce.mmoitems.stat.type.ItemStat; import org.apache.commons.lang.Validate; import org.bukkit.ChatColor; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; public class SkullTextureStat extends ItemStat { - public SkullTextureStat() { - super("SKULL_TEXTURE", VersionMaterial.PLAYER_HEAD.toMaterial(), "Skull Texture", - new String[] { "The head texture &nvalue&7.", "Can be found on heads databases." }, new String[] { "all" }, - VersionMaterial.PLAYER_HEAD.toMaterial()); - } + public SkullTextureStat() { + super("SKULL_TEXTURE", VersionMaterial.PLAYER_HEAD.toMaterial(), "Skull Texture", new String[]{"The skull texture &nvalue&7.", "Can be found on head databases."}, new String[]{"all"}, VersionMaterial.PLAYER_HEAD.toMaterial()); + } - @Override - public SkullTextureData whenInitialized(Object object) { - Validate.isTrue(object instanceof ConfigurationSection, "Must specify a config section"); - ConfigurationSection config = (ConfigurationSection) object; + @Override + public SkullTextureData whenInitialized(Object object) { + Validate.isTrue(object instanceof ConfigurationSection, "Must specify a config section"); + ConfigurationSection config = (ConfigurationSection) object; - String value = config.getString("value"); - Validate.notNull(value, "Could not load skull texture value"); + final String value = config.getString("value"); + Validate.notNull(value, "Could not load skull texture value"); - String format = config.getString("uuid"); - Validate.notNull(format, "Could not find skull texture UUID: re-enter your skull texture value and one will be selected randomly."); + final String uuid = config.getString("uuid"); + Validate.notNull(uuid, "Could not find skull texture UUID: re-enter your skull texture value and one will be selected randomly."); - SkullTextureData skullTexture = new SkullTextureData(new GameProfile(UUID.fromString(format), "SkullTexture")); - skullTexture.getGameProfile().getProperties().put("textures", new Property("textures", value)); - return skullTexture; - } + final Object profile = MythicLib.plugin.getVersion().getWrapper().newProfile(UUID.fromString(uuid), value); + final SkullTextureData skullTexture = new SkullTextureData(profile); + return skullTexture; + } - @Override - public void whenDisplayed(List lore, Optional statData) { - lore.add(ChatColor.GRAY + "Current Value: " + (statData.isPresent() ? ChatColor.GREEN + "Texture value provided" : ChatColor.RED + "None")); - lore.add(""); - lore.add(ChatColor.YELLOW + AltChar.listDash + " Left click to change this value."); - lore.add(ChatColor.YELLOW + AltChar.listDash + " Right click to remove this value."); - } + @Override + public void whenDisplayed(List lore, Optional statData) { + lore.add(ChatColor.GRAY + "Current Value: " + (statData.isPresent() ? ChatColor.GREEN + "Texture value provided" : ChatColor.RED + "None")); + lore.add(""); + lore.add(ChatColor.YELLOW + AltChar.listDash + " Left click to change this value."); + lore.add(ChatColor.YELLOW + AltChar.listDash + " Right click to remove this value."); + } - @Override - public void whenInput(@NotNull EditionInventory inv, @NotNull String message, Object... info) { - inv.getEditedSection().set("skull-texture.value", message); - inv.getEditedSection().set("skull-texture.uuid", UUID.randomUUID().toString()); - inv.registerTemplateEdition(); - inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + getName() + " successfully changed to " + message + "."); - } + @Override + public void whenInput(@NotNull EditionInventory inv, @NotNull String message, Object... info) { + inv.getEditedSection().set("skull-texture.value", message); + inv.getEditedSection().set("skull-texture.uuid", UUID.randomUUID().toString()); + inv.registerTemplateEdition(); + inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + getName() + " successfully changed to " + message + "."); + } - @Override - public void whenApplied(@NotNull ItemStackBuilder item, @NotNull SkullTextureData data) { - if (item.getItemStack().getType() != VersionMaterial.PLAYER_HEAD.toMaterial()) - return; + @Override + public void whenApplied(@NotNull ItemStackBuilder item, @NotNull SkullTextureData data) { + if (item.getItemStack().getType() != VersionMaterial.PLAYER_HEAD.toMaterial()) return; - try { - Field profileField = item.getMeta().getClass().getDeclaredField("profile"); - profileField.setAccessible(true); - profileField.set(item.getMeta(), ((SkullTextureData) data).getGameProfile()); - } catch (NoSuchFieldException | IllegalAccessException exception) { - throw new IllegalArgumentException(exception.getMessage()); - } - } - /** - * This stat is saved not as a custom tag, but as the vanilla HideFlag itself. - * Alas this is an empty array - */ - @NotNull - @Override - public ArrayList getAppliedNBT(@NotNull SkullTextureData data) { return new ArrayList<>(); } + if (data.getGameProfile() != null) + MythicLib.plugin.getVersion().getWrapper().setProfile((SkullMeta) item.getMeta(), data.getGameProfile()); + } - @Override - public void whenClicked(@NotNull EditionInventory inv, @NotNull InventoryClickEvent event) { - if (event.getAction() == InventoryAction.PICKUP_HALF) { - inv.getEditedSection().set(getPath(), null); - inv.registerTemplateEdition(); - inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + "Successfully removed " + getName() + "."); - } else - new StatEdition(inv, this).enable("Write in the chat the text you want."); - } + /** + * This stat is saved not as a custom tag, but as the vanilla HideFlag itself. + * Alas this is an empty array + */ + @NotNull + @Override + public ArrayList getAppliedNBT(@NotNull SkullTextureData data) { + return new ArrayList<>(); + } - @Override - public void whenLoaded(@NotNull ReadMMOItem mmoitem) { - try { - Field profileField = mmoitem.getNBT().getItem().getItemMeta().getClass().getDeclaredField("profile"); - profileField.setAccessible(true); - mmoitem.setData(ItemStats.SKULL_TEXTURE, new SkullTextureData((GameProfile) profileField.get(mmoitem.getNBT().getItem().getItemMeta()))); - } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ignored) {} - } + @Override + public void whenClicked(@NotNull EditionInventory inv, @NotNull InventoryClickEvent event) { + if (event.getAction() == InventoryAction.PICKUP_HALF) { + inv.getEditedSection().set(getPath(), null); + inv.registerTemplateEdition(); + inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + "Successfully removed " + getName() + "."); + } else new StatEdition(inv, this).enable("Write in the chat the text you want."); + } - /** - * This stat is saved not as a custom tag, but as the vanilla Head Texture itself. - * Alas this method returns null. - */ - @Nullable - @Override - public SkullTextureData getLoadedNBT(@NotNull ArrayList storedTags) { return null; } + @Override + public void whenLoaded(@NotNull ReadMMOItem mmoitem) { + try { + final ItemMeta meta = mmoitem.getNBT().getItem().getItemMeta(); + Validate.isTrue(meta instanceof SkullMeta); + final Object profile = MythicLib.plugin.getVersion().getWrapper().getProfile((SkullMeta) meta); + mmoitem.setData(ItemStats.SKULL_TEXTURE, new SkullTextureData(profile)); + } catch (RuntimeException ignored) { + } + } - @NotNull - @Override - public SkullTextureData getClearStatData() { return new SkullTextureData(new GameProfile(UUID.fromString("df930b7b-a84d-4f76-90ac-33be6a5b6c88"), "gunging")); } + /** + * This stat is saved not as a custom tag, but as the vanilla Head Texture itself. + * Alas this method returns null. + */ + @Nullable + @Override + public SkullTextureData getLoadedNBT(@NotNull ArrayList storedTags) { + return null; + } + + @NotNull + @Override + public SkullTextureData getClearStatData() { + return new SkullTextureData(null); + } } diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/data/SkullTextureData.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/data/SkullTextureData.java index 90aeb8c4..032dc1c8 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/data/SkullTextureData.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/stat/data/SkullTextureData.java @@ -1,6 +1,5 @@ package net.Indyuce.mmoitems.stat.data; -import com.mojang.authlib.GameProfile; import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder; import net.Indyuce.mmoitems.stat.data.random.RandomStatData; import net.Indyuce.mmoitems.stat.data.type.StatData; @@ -8,18 +7,24 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class SkullTextureData implements StatData, RandomStatData { - private GameProfile profile; - public SkullTextureData(GameProfile profile) { + /** + * Spigot 1.20.2 introduced a PlayerProfile API which requires + * to both support PlayerProfile and GameProfile objects as + * reflection is no longer supported by >1.20.2 + */ + private Object profile; + + public SkullTextureData(Object profile) { this.profile = profile; } @Nullable - public GameProfile getGameProfile() { + public Object getGameProfile() { return profile; } - public void setGameProfile(@Nullable GameProfile profile) { + public void setGameProfile(@Nullable Object profile) { this.profile = profile; } diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/util/MMOUtils.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/util/MMOUtils.java index 089d4f80..70064b43 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/util/MMOUtils.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/util/MMOUtils.java @@ -1,8 +1,6 @@ package net.Indyuce.mmoitems.util; import com.google.common.collect.ImmutableMap; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.UtilityMethods; import io.lumine.mythic.lib.api.item.ItemTag; @@ -11,7 +9,6 @@ import io.lumine.mythic.lib.api.item.SupportedNBTTagValues; import io.lumine.mythic.lib.skill.trigger.TriggerType; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.Type; -import org.apache.commons.codec.binary.Base64; import org.bukkit.*; import org.bukkit.attribute.Attribute; import org.bukkit.entity.Entity; @@ -20,13 +17,11 @@ import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; -import java.lang.reflect.Field; import java.util.*; @SuppressWarnings("unused") @@ -68,23 +63,6 @@ public class MMOUtils { return isNonEmpty(str) ? str : Objects.requireNonNull(fallback); } - /** - * @return The skull texture URL from a given player head - */ - @Deprecated - public static String getSkullTextureURL(ItemStack item) { - try { - ItemMeta meta = item.getItemMeta(); - Field profileField = meta.getClass().getDeclaredField("profile"); - profileField.setAccessible(true); - Collection properties = ((GameProfile) profileField.get(item.getItemMeta())).getProperties().get("textures"); - Property property = properties.toArray(new Property[0])[0]; - return new String(Base64.decodeBase64(property.getValue())).replace("{textures:{SKIN:{url:\"", "").replace("\"}}}", ""); - } catch (Exception e) { - return ""; - } - } - private static final String UNIVERSAL_REFERENCE = "all"; /**