Merge branch 'development'

This commit is contained in:
Brianna 2020-11-13 15:58:02 -06:00
commit 9ef1317157
13 changed files with 199 additions and 74 deletions

View File

@ -1,12 +1,37 @@
## EpicVouchers
EpicVouchers is the best solution for vouchers on any server with amazing features updated everyday by me (Songoda).</br>
Quality, performance, and support are my priorities for this resource. Purchase it for $2.99 (sometimes cheaper with sales).
> **Note:** Please consider purchasing this resource on Spigot if you want to really support me.
</br>
## Developers
Here is an example with built-in methods for developers that want to use the EpicVouchers API for their own resources.</br>
This is a kinda long example so think about that too but I am sure that you will understand the usage of it quick and easy.
<p align="center">
<img src="https://proxy.songoda.com/200/https://cdn2.songoda.com/products/epicvouchers/5EJsLZfmeHcwy9rIY0dAgnzqR4rL4iCKAEyjgjIk.png" alt="EpicVouchers" />
</p>
<h1 align="center">EpicVouchers</h1>
<p align="center">
<b>Create vouchers that players can claim for rewards with seemingly infinite possibilities. Customize your servers vouchers through an intuitive in-game editor.</b>
<p align="center">
<img alt="Discord" src="https://img.shields.io/discord/293212540723396608?color=7289DA&label=Discord&logo=discord&logoColor=7289DA&link=https://discord.gg/songoda"> <img alt="Patreon" src="https://img.shields.io/badge/-Support_on_Patreon-F96854.svg?logo=patreon&style=flat&logoColor=white&link=https://wwww.patreon.com/join/songoda"> <br/> <img alt="Latest" src="https://img.shields.io/badge/-ver_2.1.18-4078C0.svg?logo=github&style=flat&logoColor-white&color=blue&label=Latest&labelColor=black"> <img alt="quality" src="https://img.shields.io/codacy/grade/4123a753597e43c89a93df5bbfb353ee"> <img alt="Last Updated" src="https://img.shields.io/github/last-commit/songoda/EpicVouchers"> <br/> <img alt="Servers" src="https://img.shields.io/bstats/servers/4209"> <img alt="Maintained" src="https://img.shields.io/maintenance/yes/2020">
<br />
## Table of Contents
* [Introduction](#introduction)
* [Marketplace](#marketplace)
* [Documentation](#documentation)
* [Developers API](#developers-api)
* [Support](#support)
* [Suggestions](#suggestions)
## Introduction
EpicVouchers is simple to use voucher plugin, that gives you the ability to reward players automatically without needing to give them permission to a command or manually run a command on a player yourself. This plugin is perfect for cosmetic rewards, selling in-game ranks, crate and kit rewards, unique shop designs, etc. The plugin also features an in-game GUI that allows you to create, edit and delete vouchers without needing to configurate the files, or restart/reload the server to apply the changes. It's a perfect plugin for production servers, and gives you unlimited ways to reward your loyal players easily.
## Marketplace
You can visit [our marketplace](https://songoda.com/marketplace/product/epicvouchers-advanced-vouchers-by-gui.25) to download EpicVouchers as well as take a look at many other fantastic plugins which are sure to catch your eye.
## Documentation
You can find all the information about the plugin, including dependencies, commands, permissions, incompatible plugins on [our wiki](https://wiki.songoda.com/Epic_Vouchers). Feel free to also contribute to the wiki as a way to help others in the community with using the plugin.
## Developers API
Here is an example with built-in methods for developers that want to use the EpicVouchers API for their own resources. This is a pretty long example, so take that into consideration when looking at the example, but I am sure that you will understand the usage of it quickly.
```ruby
@EventHandler
public void redeemListener(VoucherRedeemEvent event) {
@ -63,4 +88,10 @@ HandlerList handlers = event.getHandlers();
# Cancel the event with a boolean.
event.isCancelled(true);
}
```
```
## Support
If you encounter any issues while using the plugin, feel free to create a ticket on [our support desk](https://support.songoda.com).
## Suggestions
For suggestions about features you think should be added to the plugin to increase its functionality, feel free to create a thread over on [our feedback site](https://feedback.songoda.com).

View File

@ -2,7 +2,7 @@
<groupId>com.songoda</groupId>
<artifactId>EpicVouchers</artifactId>
<modelVersion>4.0.0</modelVersion>
<version>2.1.18</version>
<version>2.1.19</version>
<build>
<defaultGoal>clean install</defaultGoal>
<finalName>EpicVouchers-${project.version}</finalName>
@ -89,11 +89,11 @@
<repositories>
<repository>
<id>private</id>
<url>https://repo.songoda.com/artifactory/private/</url>
<url>https://repo.songoda.com/repository/private/</url>
</repository>
<repository>
<id>public</id>
<url>https://repo.songoda.com/artifactory/public/</url>
<url>https://repo.songoda.com/repository/public/</url>
</repository>
</repositories>
@ -101,7 +101,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.15</version>
<version>1.16.2</version>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -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());

View File

@ -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);
});
}
});
}
}

View File

@ -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);
});
}
});

View File

@ -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);
}
}
}

View File

@ -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;
@ -87,6 +89,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(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));

View File

@ -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."));

View File

@ -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++) {

View File

@ -0,0 +1,48 @@
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);
} catch (IllegalAccessException | NoSuchFieldException ex) {
ex.printStackTrace();
}
return itemStack;
}
}

View File

@ -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<UUID, Long> entries = new HashMap<>();
private final Map<UUID, Long> entries = new HashMap<>();
private final EpicVouchers instance;
public CoolDownManager(EpicVouchers instance) {

View File

@ -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<String> 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;

View File

@ -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;