From af6f67ff9cd501ba9033e3c80325811752bf27a8 Mon Sep 17 00:00:00 2001 From: Fernando Pettinelli Date: Mon, 14 Sep 2020 17:17:21 -0300 Subject: [PATCH] Changes the Anvil GUI for SongodaCore's ChatPrompt. Also moves the redeem logic from the interact listener to the voucher to avoid duplicate code. Adds support for custom player textures. You can get them from https://minecraft-heads.com. Copying the value or the Minecraft URL value works. Changes the checks for a voucher for a very simple NBT check. Should also fix the random lore issue not working. --- .../songoda/epicvouchers/EpicVouchers.java | 6 +- .../inventory/icons/ListEntryIcon.java | 15 ++--- .../libraries/inventory/icons/StringIcon.java | 14 ++--- .../listeners/PlayerInteractListener.java | 46 +++++----------- .../epicvouchers/menus/VoucherEditorMenu.java | 10 ++++ .../epicvouchers/menus/VoucherMenu.java | 1 + .../menus/sub/editor/StringListMenu.java | 15 ++--- .../epicvouchers/utils/SkullUtils.java | 47 ++++++++++++++++ .../epicvouchers/voucher/CoolDownManager.java | 3 +- .../songoda/epicvouchers/voucher/Voucher.java | 55 ++++++++++++++++++- .../epicvouchers/voucher/VoucherExecutor.java | 2 +- 11 files changed, 154 insertions(+), 60 deletions(-) create mode 100644 src/main/java/com/songoda/epicvouchers/utils/SkullUtils.java diff --git a/src/main/java/com/songoda/epicvouchers/EpicVouchers.java b/src/main/java/com/songoda/epicvouchers/EpicVouchers.java index a874598..9b1b50c 100644 --- a/src/main/java/com/songoda/epicvouchers/EpicVouchers.java +++ b/src/main/java/com/songoda/epicvouchers/EpicVouchers.java @@ -92,8 +92,10 @@ public class EpicVouchers extends SongodaPlugin { guiManager.init(); manager.registerEvents(new PlayerInteractListener(this), this); manager.registerEvents(new PlayerCommandListener(), this); + } - + @Override + public void onDataLoad() { if (!new File(this.getDataFolder(), "vouchers.yml").exists()) saveResource("vouchers.yml", false); vouchersConfig.load(); @@ -128,6 +130,7 @@ public class EpicVouchers extends SongodaPlugin { .setData((short) cs.getInt("data", 0)) .setName(cs.getString("name", "default")) .setLore(cs.getStringList("lore")) + .setTexture(cs.getString("texture", "")) .setGlow(cs.getBoolean("glow", false)) .setConfirm(cs.getBoolean("confirm", true)) .setUnbreakable(cs.getBoolean("unbreakable", false)) @@ -171,6 +174,7 @@ public class EpicVouchers extends SongodaPlugin { vouchersConfig.set(prefix + "data", voucher.getData()); vouchersConfig.set(prefix + "name", voucher.getName()); vouchersConfig.set(prefix + "lore", voucher.getLore()); + vouchersConfig.set(prefix + "texture", voucher.getTexture()); vouchersConfig.set(prefix + "glow", voucher.isGlow()); vouchersConfig.set(prefix + "confirm", voucher.isConfirm()); vouchersConfig.set(prefix + "unbreakable", voucher.isUnbreakable()); diff --git a/src/main/java/com/songoda/epicvouchers/libraries/inventory/icons/ListEntryIcon.java b/src/main/java/com/songoda/epicvouchers/libraries/inventory/icons/ListEntryIcon.java index 0c92b7e..2bf3c44 100644 --- a/src/main/java/com/songoda/epicvouchers/libraries/inventory/icons/ListEntryIcon.java +++ b/src/main/java/com/songoda/epicvouchers/libraries/inventory/icons/ListEntryIcon.java @@ -1,9 +1,10 @@ package com.songoda.epicvouchers.libraries.inventory.icons; -import com.songoda.core.gui.AnvilGui; +import com.songoda.core.input.ChatPrompt; import com.songoda.epicvouchers.EpicVouchers; import com.songoda.epicvouchers.libraries.ItemBuilder; import com.songoda.epicvouchers.utils.Pair; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; @@ -21,13 +22,9 @@ public class ListEntryIcon extends Icon { onRemove.accept(event.getPlayer(), entry); return; } - - AnvilGui gui = new AnvilGui(event.getPlayer()); - gui.setTitle("Current: " + entry); - gui.setAction(aevent -> onEdit.accept(event.getPlayer(), new Pair<>(entry, gui.getInputText().trim()))); - instance.getGuiManager().showGUI(event.getPlayer(), gui); + ChatPrompt.showPrompt(instance, event.getPlayer(), aevent -> { + Bukkit.getScheduler().runTaskLater(instance, () -> onEdit.accept(event.getPlayer(), new Pair<>(entry, aevent.getMessage().trim())), 1L); }); - - - } + }); } +} diff --git a/src/main/java/com/songoda/epicvouchers/libraries/inventory/icons/StringIcon.java b/src/main/java/com/songoda/epicvouchers/libraries/inventory/icons/StringIcon.java index a30f0e3..072d4f2 100644 --- a/src/main/java/com/songoda/epicvouchers/libraries/inventory/icons/StringIcon.java +++ b/src/main/java/com/songoda/epicvouchers/libraries/inventory/icons/StringIcon.java @@ -1,10 +1,11 @@ package com.songoda.epicvouchers.libraries.inventory.icons; import com.songoda.core.compatibility.ServerVersion; -import com.songoda.core.gui.AnvilGui; +import com.songoda.core.input.ChatPrompt; import com.songoda.core.utils.TextUtils; import com.songoda.epicvouchers.EpicVouchers; import com.songoda.epicvouchers.libraries.ItemBuilder; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -48,18 +49,15 @@ public class StringIcon extends Icon { consumer.accept(event.getPlayer(), ""); event.getPlayer().sendMessage(TextUtils.formatText("&7Successfully cleared&7.")); } else { - AnvilGui gui = new AnvilGui(event.getPlayer()); - gui.setTitle("current:" + current); - gui.setAction(aevent -> { - final String msg = gui.getInputText().trim(); + ChatPrompt.showPrompt(instance, event.getPlayer(), TextUtils.formatText("&7Enter a new value. Current: &r" + current), aevent -> { + final String msg = aevent.getMessage().trim(); if (!predicate.test(msg)) { event.getPlayer().sendMessage(TextUtils.formatText("&cFailed to set value to: " + msg)); return; } - consumer.accept(event.getPlayer(), msg); event.getPlayer().sendMessage(TextUtils.formatText("&7Successfully set to &r" + msg + "&7.")); - }); - instance.getGuiManager().showGUI(event.getPlayer(), gui); + Bukkit.getScheduler().runTaskLater(instance, () -> consumer.accept(event.getPlayer(), msg), 1L); + }); } }); diff --git a/src/main/java/com/songoda/epicvouchers/listeners/PlayerInteractListener.java b/src/main/java/com/songoda/epicvouchers/listeners/PlayerInteractListener.java index 9479001..a025972 100644 --- a/src/main/java/com/songoda/epicvouchers/listeners/PlayerInteractListener.java +++ b/src/main/java/com/songoda/epicvouchers/listeners/PlayerInteractListener.java @@ -1,11 +1,10 @@ package com.songoda.epicvouchers.listeners; +import com.songoda.core.nms.NmsManager; +import com.songoda.core.nms.nbt.NBTItem; import com.songoda.epicvouchers.EpicVouchers; -import com.songoda.epicvouchers.menus.ConfirmMenu; import com.songoda.epicvouchers.voucher.Voucher; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; @@ -13,8 +12,6 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import java.util.UUID; - public class PlayerInteractListener implements Listener { private final EpicVouchers instance; @@ -28,10 +25,20 @@ public class PlayerInteractListener implements Listener { final ItemStack item = event.getItem(); if (item == null || (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK)) return; - final Player player = event.getPlayer(); + + final NBTItem itemNbt = NmsManager.getNbt().of(item); for (Voucher voucher : instance.getVoucherManager().getVouchers()) { final ItemStack voucherItem = voucher.toItemStack(); + + // Check voucher NBT. + if (itemNbt.has("epicvouchers:voucher") && itemNbt.getNBTObject("epicvouchers:voucher").asString().equals(voucher.getKey())) { + event.setCancelled(true); + voucher.redeemVoucher(event); + continue; + } + + // Legacy crap. // does the item they're holding match this voucher? if (voucherItem != null && !voucherItem.isSimilar(item)) continue; @@ -46,32 +53,7 @@ public class PlayerInteractListener implements Listener { } event.setCancelled(true); - - // does the player have permission to redeem this voucher? - if (!voucher.getPermission().isEmpty() && !player.hasPermission(voucher.getPermission())) { - // todo: probably should send a message to the player... - return; - } - - UUID uuid = player.getUniqueId(); - - if (instance.getCoolDowns().isOnCoolDown(uuid)) { - instance.getLocale().getMessage("event.general.cooldown") - .processPlaceholder("time", instance.getCoolDowns().getTime(uuid)) - .processPlaceholder("voucher", voucher.getName(true)) - .sendPrefixedMessage(player); - return; - } - - if (voucher.isConfirm()) { - new ConfirmMenu(instance, - () -> instance.getVoucherExecutor().redeemVoucher(player, voucher, item, true, event), - () -> { - }) - .open(player); - } else { - instance.getVoucherExecutor().redeemVoucher(player, voucher, item, true, event); - } + voucher.redeemVoucher(event); } } } \ No newline at end of file diff --git a/src/main/java/com/songoda/epicvouchers/menus/VoucherEditorMenu.java b/src/main/java/com/songoda/epicvouchers/menus/VoucherEditorMenu.java index 0406690..9345033 100644 --- a/src/main/java/com/songoda/epicvouchers/menus/VoucherEditorMenu.java +++ b/src/main/java/com/songoda/epicvouchers/menus/VoucherEditorMenu.java @@ -1,5 +1,7 @@ package com.songoda.epicvouchers.menus; +import com.songoda.core.compatibility.CompatibleMaterial; +import com.songoda.core.utils.ItemUtils; import com.songoda.epicvouchers.EpicVouchers; import com.songoda.epicvouchers.libraries.ItemBuilder; import com.songoda.epicvouchers.libraries.inventory.IconInv; @@ -13,6 +15,7 @@ import com.songoda.epicvouchers.menus.sub.editor.SoundsMenu; import com.songoda.epicvouchers.menus.sub.editor.TitlesMenu; import com.songoda.epicvouchers.voucher.Voucher; import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; @@ -87,6 +90,13 @@ public class VoucherEditorMenu extends IconInv { reopen(player); })); + addIcon(13, new StringIcon(instance, new ItemBuilder(voucher.getTexture() == null ? CompatibleMaterial.PLAYER_HEAD.getItem() : ItemUtils.getCustomHead(voucher.getTexture())) + .name(ChatColor.YELLOW + "Skull Texture") + .lore(GRAY + "Right click to edit", GRAY + "Left click to clear").build(), voucher.getTexture(), (player, editString) -> { + voucher.setTexture(editString); + reopen(player); + })); + // Sections addIcon(18, new StringListIcon(instance, voucher.getCommands(), "Commands", voucher)); diff --git a/src/main/java/com/songoda/epicvouchers/menus/VoucherMenu.java b/src/main/java/com/songoda/epicvouchers/menus/VoucherMenu.java index a93445d..4f794d8 100644 --- a/src/main/java/com/songoda/epicvouchers/menus/VoucherMenu.java +++ b/src/main/java/com/songoda/epicvouchers/menus/VoucherMenu.java @@ -41,6 +41,7 @@ public class VoucherMenu extends IconInv { Voucher voucher = new Voucher(msg, instance); voucher.setMaterial(PAPER); voucher.setName("&f" + msg); + voucher.setTexture(""); instance.getVoucherManager().addVoucher(voucher); event.getPlayer().sendMessage(TextUtils.formatText("&7Successfully created voucher with id &r" + msg + "&7.")); diff --git a/src/main/java/com/songoda/epicvouchers/menus/sub/editor/StringListMenu.java b/src/main/java/com/songoda/epicvouchers/menus/sub/editor/StringListMenu.java index 95e035f..923162b 100644 --- a/src/main/java/com/songoda/epicvouchers/menus/sub/editor/StringListMenu.java +++ b/src/main/java/com/songoda/epicvouchers/menus/sub/editor/StringListMenu.java @@ -1,12 +1,14 @@ package com.songoda.epicvouchers.menus.sub.editor; -import com.songoda.core.gui.AnvilGui; +import com.songoda.core.input.ChatPrompt; +import com.songoda.core.utils.TextUtils; import com.songoda.epicvouchers.EpicVouchers; import com.songoda.epicvouchers.libraries.ItemBuilder; import com.songoda.epicvouchers.libraries.inventory.IconInv; import com.songoda.epicvouchers.libraries.inventory.icons.ListEntryIcon; import com.songoda.epicvouchers.menus.VoucherEditorMenu; import com.songoda.epicvouchers.voucher.Voucher; +import org.bukkit.Bukkit; import org.bukkit.Material; import java.util.List; @@ -32,13 +34,12 @@ public class StringListMenu extends IconInv { .build()); addIcon(size - 1, new ItemBuilder(PAPER).name(GREEN + "Add to list").build(), event -> { - AnvilGui gui = new AnvilGui(event.getPlayer()); - gui.setAction(aevent -> { - list.add(gui.getInputText().trim()); - voucher.saveSetting(key.toLowerCase(), list); - new StringListMenu(instance, key, list, toEdit, voucher).open(event.getPlayer()); + ChatPrompt.showPrompt(instance, event.getPlayer(), TextUtils.formatText("Enter a new value."), aevent -> { + list.add(aevent.getMessage().trim()); + voucher.saveSetting(key.toLowerCase(), list); + Bukkit.getScheduler().runTaskLater(instance, () -> new StringListMenu(instance, key, list, toEdit, voucher).open(event.getPlayer()), 1L); + }); - instance.getGuiManager().showGUI(event.getPlayer(), gui); }); for (int i = 0; i < list.size(); i++) { diff --git a/src/main/java/com/songoda/epicvouchers/utils/SkullUtils.java b/src/main/java/com/songoda/epicvouchers/utils/SkullUtils.java new file mode 100644 index 0000000..56db989 --- /dev/null +++ b/src/main/java/com/songoda/epicvouchers/utils/SkullUtils.java @@ -0,0 +1,47 @@ +package com.songoda.epicvouchers.utils; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import com.songoda.core.compatibility.ServerVersion; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; + +import java.lang.reflect.Field; +import java.util.Base64; +import java.util.UUID; + +public class SkullUtils { + + + /* + * Custom skull texture. Should probably be moved to SongodaCore. + */ + public static ItemStack customTexture(ItemStack itemStack, String texture) { + if (ServerVersion.isServerVersionBelow(ServerVersion.V1_8)) { + return itemStack; + } + + if (texture == null || texture.isEmpty()) { + return itemStack; + } + + SkullMeta skullMeta = (SkullMeta)itemStack.getItemMeta(); + GameProfile gameProfile = new GameProfile(UUID.nameUUIDFromBytes(texture.getBytes()), "CustomHead"); + if (texture.endsWith("=")) { + gameProfile.getProperties().put("textures", new Property("texture", texture.replaceAll("=", ""))); + } else { + byte[] encodedData = Base64.getEncoder().encode(String.format("{textures:{SKIN:{url:\"http://textures.minecraft.net/texture/%s\"}}}", texture).getBytes()); + gameProfile.getProperties().put("textures", new Property("textures", new String(encodedData))); + } + + try { + Field profileField = skullMeta.getClass().getDeclaredField("profile"); + profileField.setAccessible(true); + profileField.set(skullMeta, gameProfile); + itemStack.setItemMeta(skullMeta); + return itemStack; + } catch (IllegalAccessException | NoSuchFieldException ex) { + throw new RuntimeException("Reflection error while setting head texture", ex); + } + } +} diff --git a/src/main/java/com/songoda/epicvouchers/voucher/CoolDownManager.java b/src/main/java/com/songoda/epicvouchers/voucher/CoolDownManager.java index c8cf06a..a8facbe 100644 --- a/src/main/java/com/songoda/epicvouchers/voucher/CoolDownManager.java +++ b/src/main/java/com/songoda/epicvouchers/voucher/CoolDownManager.java @@ -4,11 +4,12 @@ import com.songoda.epicvouchers.EpicVouchers; import org.bukkit.Bukkit; import java.util.HashMap; +import java.util.Map; import java.util.UUID; public class CoolDownManager { - private final HashMap entries = new HashMap<>(); + private final Map entries = new HashMap<>(); private final EpicVouchers instance; public CoolDownManager(EpicVouchers instance) { diff --git a/src/main/java/com/songoda/epicvouchers/voucher/Voucher.java b/src/main/java/com/songoda/epicvouchers/voucher/Voucher.java index d860908..f2b3a2e 100644 --- a/src/main/java/com/songoda/epicvouchers/voucher/Voucher.java +++ b/src/main/java/com/songoda/epicvouchers/voucher/Voucher.java @@ -1,5 +1,6 @@ package com.songoda.epicvouchers.voucher; +import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.core.compatibility.ServerVersion; import com.songoda.core.nms.NmsManager; import com.songoda.core.nms.nbt.NBTItem; @@ -7,18 +8,22 @@ import com.songoda.core.utils.TextUtils; import com.songoda.epicvouchers.EpicVouchers; import com.songoda.epicvouchers.events.ForceRedeemEvent; import com.songoda.epicvouchers.events.VoucherReceiveEvent; +import com.songoda.epicvouchers.menus.ConfirmMenu; +import com.songoda.epicvouchers.utils.SkullUtils; import lombok.experimental.Accessors; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import java.util.stream.Collectors; import static org.bukkit.Material.PAPER; @@ -34,6 +39,7 @@ public class Voucher { private int coolDown = 0; private String name; private List lore = new ArrayList<>(); + private String texture; private boolean glow = true; private boolean confirm = true; private boolean unbreakable = false; @@ -113,7 +119,15 @@ public class Voucher { item = nbtItem.finish(); } } - return item; + + if (texture != null && !texture.isEmpty() && CompatibleMaterial.PLAYER_HEAD.getMaterial() == material) { + item = SkullUtils.customTexture(itemStack, texture); + } + + NBTItem nbtItem = NmsManager.getNbt().of(item); + nbtItem.set("epicvouchers:voucher", key); + + return nbtItem.finish(); } public String getName(boolean applyFormatting) { @@ -200,6 +214,40 @@ public class Voucher { } } + public void redeemVoucher(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + // does the player have permission to redeem this voucher? + if (!permission.isEmpty() && !player.hasPermission(permission)) { + player.sendMessage(instance.getLocale().getMessage("event.general.nopermission").getPrefixedMessage()); + return; + } + + UUID uuid = player.getUniqueId(); + + if (instance.getCoolDowns().isOnCoolDown(uuid)) { + instance.getLocale().getMessage("event.general.cooldown") + .processPlaceholder("time", instance.getCoolDowns().getTime(uuid)) + .processPlaceholder("voucher", getName(true)) + .sendPrefixedMessage(player); + return; + } + + if (confirm) { + new ConfirmMenu(instance, + () -> instance.getVoucherExecutor().redeemVoucher(player, this, event.getItem(), true, event), + () -> { + }) + .open(player); + } else { + instance.getVoucherExecutor().redeemVoucher(player, this, event.getItem(), true, event); + } + } + + public String getTexture() { + return texture; + } + public String getActionBar() { return TextUtils.formatText(actionBar); } @@ -417,6 +465,11 @@ public class Voucher { return this; } + public Voucher setTexture(String texture) { + this.texture = texture; + return this; + } + public Voucher setActionBar(String actionBar) { this.actionBar = actionBar; return this; diff --git a/src/main/java/com/songoda/epicvouchers/voucher/VoucherExecutor.java b/src/main/java/com/songoda/epicvouchers/voucher/VoucherExecutor.java index 6cd0b57..1f5ad75 100644 --- a/src/main/java/com/songoda/epicvouchers/voucher/VoucherExecutor.java +++ b/src/main/java/com/songoda/epicvouchers/voucher/VoucherExecutor.java @@ -5,10 +5,10 @@ import com.songoda.epicvouchers.EpicVouchers; import com.songoda.epicvouchers.events.VoucherRedeemEvent; import com.songoda.epicvouchers.libraries.BountifulAPI; import com.songoda.epicvouchers.listeners.PlayerCommandListener; +import org.apache.commons.lang.StringUtils; import org.bukkit.Bukkit; import org.bukkit.Effect; import org.bukkit.Sound; -import org.bukkit.craftbukkit.libs.org.apache.commons.lang3.StringUtils; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot;