diff --git a/build.gradle.kts b/build.gradle.kts index 696f347..fea4ebf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { compileOnly(libs.headdb) compileOnly(libs.itemsadder) compileOnly(libs.oraxen) + compileOnly(libs.mythiclib) compileOnly(libs.mmoitems) compileOnly(libs.score) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 68878e4..ef10912 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,8 @@ authlib = "1.5.25" headdb = "1.3.1" itemsadder = "3.2.5" oraxen = "1.159.0" -mmoitems = "6.9.4-SNAPSHOT" +mythiclib = "1.6.2-SNAPSHOT" +mmoitems = "6.9.5-SNAPSHOT" papi = "2.11.6" score = "4.23.10.8" @@ -23,6 +24,7 @@ authlib = { module = "com.mojang:authlib", version.ref = "authlib" } headdb = { module = "com.arcaniax:HeadDatabase-API", version.ref = "headdb" } itemsadder = { module = "com.github.LoneDev6:api-itemsadder", version.ref = "itemsadder" } oraxen = { module = "com.github.oraxen:oraxen", version.ref = "oraxen" } +mythiclib = { module = "io.lumine:MythicLib-dist", version.ref = "mythiclib"} mmoitems = { module = "net.Indyuce:MMOItems-API", version.ref = "mmoitems" } papi = { module = "me.clip:placeholderapi", version.ref = "papi" } score = { module = "com.github.Ssomar-Developement:SCore", version.ref = "score" } diff --git a/src/main/java/com/extendedclip/deluxemenus/config/DeluxeMenusConfig.java b/src/main/java/com/extendedclip/deluxemenus/config/DeluxeMenusConfig.java index 8ef1b78..c6ddc80 100644 --- a/src/main/java/com/extendedclip/deluxemenus/config/DeluxeMenusConfig.java +++ b/src/main/java/com/extendedclip/deluxemenus/config/DeluxeMenusConfig.java @@ -1056,9 +1056,14 @@ private RequirementList getRequirements(FileConfiguration c, String path) { case DOES_NOT_HAVE_ITEM: ItemWrapper wrapper = new ItemWrapper(); if (c.contains(rPath + ".material")) { + String materialName = c.getString(rPath + ".material"); try { - if (!containsPlaceholders(c.getString(rPath + ".material"))) - Material.valueOf(c.getString(rPath + ".material").toUpperCase()); + if (!containsPlaceholders(materialName) && plugin.getItemHooks().values() + .stream() + .filter(x -> materialName.toLowerCase().startsWith(x.getPrefix())) + .findFirst() + .orElse(null) == null) + Material.valueOf(materialName.toUpperCase()); } catch (Exception ex) { DeluxeMenus.debug( DebugLevel.HIGHEST, @@ -1067,7 +1072,7 @@ private RequirementList getRequirements(FileConfiguration c, String path) { ); break; } - wrapper.setMaterial(c.getString(rPath + ".material")); + wrapper.setMaterial(materialName); } else { DeluxeMenus.debug( DebugLevel.HIGHEST, diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/BaseHeadHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/BaseHeadHook.java index 778f0e7..2fc1992 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/BaseHeadHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/BaseHeadHook.java @@ -31,6 +31,19 @@ public ItemStack getItem(@NotNull final String... arguments) { return DeluxeMenus.getInstance().getHead().clone(); } + @Override + public boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull String... arguments) { + if (arguments.length == 0) { + return false; + } + String itemTexture = SkullUtils.getTextureFromSkull(item); + String texture = SkullUtils.decodeSkinUrl(arguments[0]); + if (itemTexture == null || texture == null) return false; + + texture = texture.substring("https://textures.minecraft.net/texture/".length()-1); + return texture.equals(itemTexture); + } + @Override public String getPrefix() { return "basehead-"; diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/ExecutableBlocksHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/ExecutableBlocksHook.java index d0942d6..22184d7 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/ExecutableBlocksHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/ExecutableBlocksHook.java @@ -28,6 +28,11 @@ public ItemStack getItem(@NotNull String... arguments) { return (item == null) ? new ItemStack(Material.STONE) : item.clone(); } + @Override + public boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull String... arguments) { + return false; + } + @Override public String getPrefix() { return "executableblocks-"; diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/ExecutableItemsHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/ExecutableItemsHook.java index 553b61d..9bdf126 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/ExecutableItemsHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/ExecutableItemsHook.java @@ -5,6 +5,8 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; + +import com.ssomar.score.api.executableitems.config.ExecutableItemInterface; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; @@ -31,6 +33,16 @@ public ItemStack getItem(@NotNull String... arguments) { return (item == null) ? new ItemStack(Material.STONE) : item.clone(); } + @Override + public boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull String... arguments) { + if (arguments.length == 0) { + return false; + } + ExecutableItemInterface fromId = ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(arguments[0]).orElse(null); + ExecutableItemInterface fromItem = ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(item).orElse(null); + return fromItem != null && fromItem.equals(fromId); + } + @Override public String getPrefix() { return "executableitems-"; diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/HeadDatabaseHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/HeadDatabaseHook.java index 32e8c88..b3e5c02 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/HeadDatabaseHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/HeadDatabaseHook.java @@ -32,6 +32,14 @@ public ItemStack getItem(@NotNull final String... arguments) { return DeluxeMenus.getInstance().getHead().clone(); } + @Override + public boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull String... arguments) { + if (arguments.length == 0) { + return false; + } + return arguments[0].equalsIgnoreCase(api.getItemID(item)); + } + @Override public String getPrefix() { return "hdb-"; diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/ItemHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/ItemHook.java index b0c49fa..d88d8f1 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/ItemHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/ItemHook.java @@ -7,6 +7,8 @@ public interface ItemHook { ItemStack getItem(@NotNull final String... arguments); + boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull final String... arguments); + String getPrefix(); } diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/ItemsAdderHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/ItemsAdderHook.java index 9882323..ac3760b 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/ItemsAdderHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/ItemsAdderHook.java @@ -36,6 +36,15 @@ public ItemStack getItem(@NotNull final String... arguments) { return item.clone(); } + @Override + public boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull String... arguments) { + if (arguments.length == 0) { + return false; + } + CustomStack stack = CustomStack.byItemStack(item); + return stack != null && stack.getId().equalsIgnoreCase(arguments[0]); + } + @Override public String getPrefix() { return "itemsadder-"; diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/MMOItemsHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/MMOItemsHook.java index 588a9ec..282e870 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/MMOItemsHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/MMOItemsHook.java @@ -60,6 +60,16 @@ public ItemStack getItem(@NotNull final String... arguments) { return mmoItem == null ? new ItemStack(Material.STONE, 1) : mmoItem; } + @Override + public boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull String... arguments) { + if (arguments.length == 0) { + return false; + } + String[] splitArgs = arguments[0].split(":"); + if (splitArgs.length != 2) return false; + return splitArgs[0].equalsIgnoreCase(MMOItems.getTypeName(item)) && splitArgs[1].equalsIgnoreCase(MMOItems.getID(item)); + } + @Override public String getPrefix() { return "mmoitems-"; diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/NamedHeadHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/NamedHeadHook.java index 0d02f9c..26768da 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/NamedHeadHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/NamedHeadHook.java @@ -1,56 +1,68 @@ -package com.extendedclip.deluxemenus.hooks; - -import com.extendedclip.deluxemenus.DeluxeMenus; -import com.extendedclip.deluxemenus.cache.SimpleCache; -import com.extendedclip.deluxemenus.utils.SkullUtils; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; - -public class NamedHeadHook implements ItemHook, Listener, SimpleCache { - - private final Map cache = new ConcurrentHashMap<>(); - - public NamedHeadHook(@NotNull final DeluxeMenus plugin) { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - @Override - public ItemStack getItem(@NotNull final String... arguments) { - if (arguments.length == 0) { - return DeluxeMenus.getInstance().getHead().clone(); - } - - try { - return cache.computeIfAbsent(arguments[0], SkullUtils::getSkullByName).clone(); - } catch (Exception exception) { - DeluxeMenus.printStacktrace( - "Something went wrong while trying to get a head by name" + - ": " + arguments[0], - exception - ); - } - - return DeluxeMenus.getInstance().getHead().clone(); - } - - @EventHandler(ignoreCancelled = true) - public void onPlayerQuit(final PlayerQuitEvent event) { - cache.remove(event.getPlayer().getName()); - } - - @Override - public String getPrefix() { - return "head-"; - } - - @Override - public void clearCache() { - cache.clear(); - } -} +package com.extendedclip.deluxemenus.hooks; + +import com.extendedclip.deluxemenus.DeluxeMenus; +import com.extendedclip.deluxemenus.cache.SimpleCache; +import com.extendedclip.deluxemenus.utils.SkullUtils; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.extendedclip.deluxemenus.utils.VersionHelper; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; +import org.jetbrains.annotations.NotNull; + +public class NamedHeadHook implements ItemHook, Listener, SimpleCache { + + private final Map cache = new ConcurrentHashMap<>(); + + public NamedHeadHook(@NotNull final DeluxeMenus plugin) { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @Override + public ItemStack getItem(@NotNull final String... arguments) { + if (arguments.length == 0) { + return DeluxeMenus.getInstance().getHead().clone(); + } + + try { + return cache.computeIfAbsent(arguments[0], SkullUtils::getSkullByName).clone(); + } catch (Exception exception) { + DeluxeMenus.printStacktrace( + "Something went wrong while trying to get a head by name" + + ": " + arguments[0], + exception + ); + } + + return DeluxeMenus.getInstance().getHead().clone(); + } + + @Override + public boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull String... arguments) { + if (arguments.length == 0) { + return false; + } + return arguments[0].equalsIgnoreCase(SkullUtils.getSkullOwner(item)); + } + + @EventHandler(ignoreCancelled = true) + public void onPlayerQuit(final PlayerQuitEvent event) { + cache.remove(event.getPlayer().getName()); + } + + @Override + public String getPrefix() { + return "head-"; + } + + @Override + public void clearCache() { + cache.clear(); + } +} diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/OraxenHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/OraxenHook.java index 98a56aa..166fd23 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/OraxenHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/OraxenHook.java @@ -28,6 +28,14 @@ public ItemStack getItem(@NotNull String... arguments) { return (item == null) ? new ItemStack(Material.STONE) : item.clone(); } + @Override + public boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull String... arguments) { + if (arguments.length == 0) { + return false; + } + return arguments[0].equalsIgnoreCase(OraxenItems.getIdByItem(item)); + } + @Override public String getPrefix() { return "oraxen-"; diff --git a/src/main/java/com/extendedclip/deluxemenus/hooks/TextureHeadHook.java b/src/main/java/com/extendedclip/deluxemenus/hooks/TextureHeadHook.java index c3c1917..147d655 100644 --- a/src/main/java/com/extendedclip/deluxemenus/hooks/TextureHeadHook.java +++ b/src/main/java/com/extendedclip/deluxemenus/hooks/TextureHeadHook.java @@ -31,6 +31,14 @@ public ItemStack getItem(@NotNull final String... arguments) { return DeluxeMenus.getInstance().getHead().clone(); } + @Override + public boolean itemMatchesIdentifiers(@NotNull ItemStack item, @NotNull String... arguments) { + if (arguments.length == 0) { + return false; + } + return arguments[0].equals(SkullUtils.getTextureFromSkull(item)); + } + @Override public String getPrefix() { return "texture-"; diff --git a/src/main/java/com/extendedclip/deluxemenus/requirement/HasItemRequirement.java b/src/main/java/com/extendedclip/deluxemenus/requirement/HasItemRequirement.java index d296719..8fa9f37 100644 --- a/src/main/java/com/extendedclip/deluxemenus/requirement/HasItemRequirement.java +++ b/src/main/java/com/extendedclip/deluxemenus/requirement/HasItemRequirement.java @@ -1,149 +1,160 @@ -package com.extendedclip.deluxemenus.requirement; - -import com.extendedclip.deluxemenus.DeluxeMenus; -import com.extendedclip.deluxemenus.menu.MenuHolder; -import com.extendedclip.deluxemenus.requirement.wrappers.ItemWrapper; -import com.extendedclip.deluxemenus.utils.StringUtils; -import com.extendedclip.deluxemenus.utils.VersionHelper; -import java.util.List; -import java.util.stream.Collectors; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -public class HasItemRequirement extends Requirement { - - private final ItemWrapper wrapper; - private final boolean invert; - - public HasItemRequirement(ItemWrapper wrapper, boolean invert) { - this.wrapper = wrapper; - this.invert = invert; - } - - @Override - public boolean evaluate(MenuHolder holder) { - String materialName = holder.setPlaceholdersAndArguments(wrapper.getMaterial()).toUpperCase(); - Material material = DeluxeMenus.MATERIALS.get(materialName); - if (material == null) { - return invert; - } - - if (material == Material.AIR) return invert == (holder.getViewer().getInventory().firstEmpty() == -1); - - ItemStack[] armor = wrapper.checkArmor() ? holder.getViewer().getInventory().getArmorContents() : null; - ItemStack[] offHand = wrapper.checkOffhand() ? holder.getViewer().getInventory().getExtraContents() : null; - ItemStack[] inventory = holder.getViewer().getInventory().getStorageContents(); - - int total = 0; - for (ItemStack itemToCheck: inventory) { - if (!isRequiredItem(itemToCheck, holder, material)) continue; - total += itemToCheck.getAmount(); - } - - if (offHand != null) { - for (ItemStack itemToCheck: offHand) { - if (!isRequiredItem(itemToCheck, holder, material)) continue; - total += itemToCheck.getAmount(); - } - } - - if (armor != null) { - for (ItemStack itemToCheck: armor) { - if (!isRequiredItem(itemToCheck, holder, material)) continue; - total += itemToCheck.getAmount(); - } - } - - return invert == (total < wrapper.getAmount()); - } - - private boolean isRequiredItem(ItemStack itemToCheck, MenuHolder holder, Material material) { - if (itemToCheck == null || itemToCheck.getType() == Material.AIR) return false; - if (wrapper.getMaterial() != null && itemToCheck.getType() != material) return false; - if (wrapper.hasData() && itemToCheck.getDurability() != wrapper.getData()) return false; - - ItemMeta metaToCheck = itemToCheck.getItemMeta(); - if (wrapper.isStrict()) { - if (metaToCheck != null) { - if (VersionHelper.IS_CUSTOM_MODEL_DATA) { - if (metaToCheck.hasCustomModelData()) return false; - } - if (metaToCheck.hasLore()) return false; - return !metaToCheck.hasDisplayName(); - } - - } else { - if ((wrapper.getCustomData() != 0 || wrapper.getName() != null || wrapper.getLore() != null) && metaToCheck == null) - return false; - - if (wrapper.getCustomData() != 0) { - if (VersionHelper.IS_CUSTOM_MODEL_DATA) { - if (!metaToCheck.hasCustomModelData()) return false; - if (metaToCheck.getCustomModelData() != wrapper.getCustomData()) return false; - } - } - - if (wrapper.getName() != null) { - if (!metaToCheck.hasDisplayName()) return false; - - String name = StringUtils.color(holder.setPlaceholdersAndArguments(wrapper.getName())); - String nameToCheck = StringUtils.color(holder.setPlaceholdersAndArguments(metaToCheck.getDisplayName())); - - if (wrapper.checkNameContains() && wrapper.checkNameIgnoreCase()) { - if (!org.apache.commons.lang3.StringUtils.containsIgnoreCase(nameToCheck, name)) return false; - } - else if (wrapper.checkNameContains()) { - if (!nameToCheck.contains(name)) return false; - } - else if (wrapper.checkNameIgnoreCase()) { - if (!nameToCheck.equalsIgnoreCase(name)) return false; - } - else if (!nameToCheck.equals(name)) { - return false; - } - } - - if (wrapper.getLoreList() != null) { - List loreX = metaToCheck.getLore(); - if (loreX == null) return false; - - String lore = wrapper.getLoreList().stream().map(holder::setPlaceholdersAndArguments).map(StringUtils::color).collect(Collectors.joining("&&")); - String loreToCheck = loreX.stream().map(holder::setPlaceholdersAndArguments).map(StringUtils::color).collect(Collectors.joining("&&")); - - if (wrapper.checkLoreContains() && wrapper.checkLoreIgnoreCase()) { - if (!org.apache.commons.lang3.StringUtils.containsIgnoreCase(loreToCheck, lore)) return false; - } - else if (wrapper.checkLoreContains()) { - if (!loreToCheck.contains(lore)) return false; - } - else if (wrapper.checkLoreIgnoreCase()) { - if (!loreToCheck.equalsIgnoreCase(lore)) return false; - } - else if (!loreToCheck.equals(lore)) { - return false; - } - } - - if (wrapper.getLore() != null) { - List loreX = metaToCheck.getLore(); - if (loreX == null) return false; - - String lore = StringUtils.color(holder.setPlaceholdersAndArguments(wrapper.getLore())); - String loreToCheck = loreX.stream().map(holder::setPlaceholdersAndArguments).map(StringUtils::color).collect(Collectors.joining("&&")); - - if (wrapper.checkLoreContains() && wrapper.checkLoreIgnoreCase()) { - return org.apache.commons.lang3.StringUtils.containsIgnoreCase(loreToCheck, lore); - } - else if (wrapper.checkLoreContains()) { - return loreToCheck.contains(lore); - } - else if (wrapper.checkLoreIgnoreCase()) { - return loreToCheck.equalsIgnoreCase(lore); - } - else return loreToCheck.equals(lore); - } - } - return true; - } -} +package com.extendedclip.deluxemenus.requirement; + +import com.extendedclip.deluxemenus.DeluxeMenus; +import com.extendedclip.deluxemenus.hooks.ItemHook; +import com.extendedclip.deluxemenus.menu.MenuHolder; +import com.extendedclip.deluxemenus.requirement.wrappers.ItemWrapper; +import com.extendedclip.deluxemenus.utils.StringUtils; +import com.extendedclip.deluxemenus.utils.VersionHelper; +import java.util.List; +import java.util.stream.Collectors; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class HasItemRequirement extends Requirement { + + private final ItemWrapper wrapper; + private final boolean invert; + + public HasItemRequirement(ItemWrapper wrapper, boolean invert) { + this.wrapper = wrapper; + this.invert = invert; + } + + @Override + public boolean evaluate(MenuHolder holder) { + String materialName = holder.setPlaceholdersAndArguments(wrapper.getMaterial()); + Material material = DeluxeMenus.MATERIALS.get(materialName.toUpperCase()); + ItemHook pluginHook = null; + if (material == null) { + pluginHook = DeluxeMenus.getInstance().getItemHooks().values() + .stream() + .filter(x -> materialName.toLowerCase().startsWith(x.getPrefix())) + .findFirst() + .orElse(null); + if (pluginHook == null) return invert; + } + + if (material == Material.AIR) return invert == (holder.getViewer().getInventory().firstEmpty() == -1); + + ItemStack[] armor = wrapper.checkArmor() ? holder.getViewer().getInventory().getArmorContents() : null; + ItemStack[] offHand = wrapper.checkOffhand() ? holder.getViewer().getInventory().getExtraContents() : null; + ItemStack[] inventory = holder.getViewer().getInventory().getStorageContents(); + + int total = 0; + for (ItemStack itemToCheck: inventory) { + if (!isRequiredItem(itemToCheck, holder, material, pluginHook)) continue; + total += itemToCheck.getAmount(); + } + + if (offHand != null) { + for (ItemStack itemToCheck: offHand) { + if (!isRequiredItem(itemToCheck, holder, material, pluginHook)) continue; + total += itemToCheck.getAmount(); + } + } + + if (armor != null) { + for (ItemStack itemToCheck: armor) { + if (!isRequiredItem(itemToCheck, holder, material, pluginHook)) continue; + total += itemToCheck.getAmount(); + } + } + + return invert == (total < wrapper.getAmount()); + } + + private boolean isRequiredItem(ItemStack itemToCheck, MenuHolder holder, Material material, ItemHook pluginHook) { + if (itemToCheck == null || itemToCheck.getType() == Material.AIR) return false; + + if (pluginHook != null) { + if (!pluginHook.itemMatchesIdentifiers(itemToCheck, holder.setPlaceholdersAndArguments(wrapper.getMaterial().substring(pluginHook.getPrefix().length())))) return false; + } + else if (wrapper.getMaterial() != null && itemToCheck.getType() != material) return false; + if (wrapper.hasData() && itemToCheck.getDurability() != wrapper.getData()) return false; + + ItemMeta metaToCheck = itemToCheck.getItemMeta(); + if (wrapper.isStrict()) { + if (metaToCheck != null) { + if (VersionHelper.IS_CUSTOM_MODEL_DATA) { + if (metaToCheck.hasCustomModelData()) return false; + } + if (metaToCheck.hasLore()) return false; + return !metaToCheck.hasDisplayName(); + } + + } else { + if ((wrapper.getCustomData() != 0 || wrapper.getName() != null || wrapper.getLore() != null) && metaToCheck == null) + return false; + + if (wrapper.getCustomData() != 0) { + if (VersionHelper.IS_CUSTOM_MODEL_DATA) { + if (!metaToCheck.hasCustomModelData()) return false; + if (metaToCheck.getCustomModelData() != wrapper.getCustomData()) return false; + } + } + + if (wrapper.getName() != null) { + if (!metaToCheck.hasDisplayName()) return false; + + String name = StringUtils.color(holder.setPlaceholdersAndArguments(wrapper.getName())); + String nameToCheck = StringUtils.color(holder.setPlaceholdersAndArguments(metaToCheck.getDisplayName())); + + if (wrapper.checkNameContains() && wrapper.checkNameIgnoreCase()) { + if (!org.apache.commons.lang3.StringUtils.containsIgnoreCase(nameToCheck, name)) return false; + } + else if (wrapper.checkNameContains()) { + if (!nameToCheck.contains(name)) return false; + } + else if (wrapper.checkNameIgnoreCase()) { + if (!nameToCheck.equalsIgnoreCase(name)) return false; + } + else if (!nameToCheck.equals(name)) { + return false; + } + } + + if (wrapper.getLoreList() != null) { + List loreX = metaToCheck.getLore(); + if (loreX == null) return false; + + String lore = wrapper.getLoreList().stream().map(holder::setPlaceholdersAndArguments).map(StringUtils::color).collect(Collectors.joining("&&")); + String loreToCheck = loreX.stream().map(holder::setPlaceholdersAndArguments).map(StringUtils::color).collect(Collectors.joining("&&")); + + if (wrapper.checkLoreContains() && wrapper.checkLoreIgnoreCase()) { + if (!org.apache.commons.lang3.StringUtils.containsIgnoreCase(loreToCheck, lore)) return false; + } + else if (wrapper.checkLoreContains()) { + if (!loreToCheck.contains(lore)) return false; + } + else if (wrapper.checkLoreIgnoreCase()) { + if (!loreToCheck.equalsIgnoreCase(lore)) return false; + } + else if (!loreToCheck.equals(lore)) { + return false; + } + } + + if (wrapper.getLore() != null) { + List loreX = metaToCheck.getLore(); + if (loreX == null) return false; + + String lore = StringUtils.color(holder.setPlaceholdersAndArguments(wrapper.getLore())); + String loreToCheck = loreX.stream().map(holder::setPlaceholdersAndArguments).map(StringUtils::color).collect(Collectors.joining("&&")); + + if (wrapper.checkLoreContains() && wrapper.checkLoreIgnoreCase()) { + return org.apache.commons.lang3.StringUtils.containsIgnoreCase(loreToCheck, lore); + } + else if (wrapper.checkLoreContains()) { + return loreToCheck.contains(lore); + } + else if (wrapper.checkLoreIgnoreCase()) { + return loreToCheck.equalsIgnoreCase(lore); + } + else return loreToCheck.equals(lore); + } + } + return true; + } +} diff --git a/src/main/java/com/extendedclip/deluxemenus/utils/SkullUtils.java b/src/main/java/com/extendedclip/deluxemenus/utils/SkullUtils.java index de1167f..428e5cf 100644 --- a/src/main/java/com/extendedclip/deluxemenus/utils/SkullUtils.java +++ b/src/main/java/com/extendedclip/deluxemenus/utils/SkullUtils.java @@ -80,6 +80,41 @@ public static ItemStack getSkullByBase64EncodedTextureUrl(@NotNull final String return head; } + public static String getTextureFromSkull(ItemStack item) { + if (!(item.getItemMeta() instanceof SkullMeta)) return null; + SkullMeta meta = (SkullMeta) item.getItemMeta(); + + if (VersionHelper.HAS_PLAYER_PROFILES) { + PlayerProfile profile = meta.getOwnerProfile(); + if (profile == null) return null; + + URL url = profile.getTextures().getSkin(); + if (url == null) return null; + + return url.toString().substring("https://textures.minecraft.net/texture/".length()-1); + } + + GameProfile profile; + try { + final Field profileField = meta.getClass().getDeclaredField("profile"); + profileField.setAccessible(true); + profile = (GameProfile) profileField.get(meta); + } catch (final NoSuchFieldException | IllegalArgumentException | IllegalAccessException exception) { + DeluxeMenus.printStacktrace( + "Failed to get base64 texture url from head item", + exception + ); + return null; + } + + for (Property property : profile.getProperties().get("textures")) { + if (property.getName().equals("textures")) { + return decodeSkinUrl(property.getValue()); + } + } + return null; + } + /** * Get the skull from a player name @@ -110,6 +145,18 @@ public static ItemStack getSkullByName(@NotNull final String playerName) { return head; } + public static String getSkullOwner(ItemStack skull) { + if (skull == null || !(skull.getItemMeta() instanceof SkullMeta)) return null; + SkullMeta meta = (SkullMeta) skull.getItemMeta(); + + if (!VersionHelper.IS_SKULL_OWNER_LEGACY) { + if (meta.getOwningPlayer() == null) return null; + return meta.getOwningPlayer().getName(); + } + + return meta.getOwner(); + } + /** * Create a game profile object * @@ -164,7 +211,7 @@ private static PlayerProfile getPlayerProfile(@NotNull final String base64Url) { * @return the url of the texture if found, otherwise {@code null} */ @Nullable - private static String decodeSkinUrl(@NotNull final String base64Texture) { + public static String decodeSkinUrl(@NotNull final String base64Texture) { final String decoded = new String(Base64.getDecoder().decode(base64Texture)); final JsonObject object = GSON.fromJson(decoded, JsonObject.class);