Fixes code style and some warnings

This commit is contained in:
Kristian Knarvik 2023-03-10 16:24:12 +01:00
parent 3db0627cc7
commit 80ed7838d9
35 changed files with 1205 additions and 1551 deletions

View File

@ -34,10 +34,9 @@ import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
public class ArmoredElytra extends JavaPlugin implements Listener
{
public class ArmoredElytra extends JavaPlugin implements Listener {
private static final MinecraftVersion minecraftVersion = MinecraftVersion
.get(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]);
.get(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]);
private static ArmoredElytra INSTANCE;
private Messages messages;
@ -49,11 +48,9 @@ public class ArmoredElytra extends JavaPlugin implements Listener
private NBTEditor nbtEditor;
@Override
public void onEnable()
{
public void onEnable() {
INSTANCE = this;
if (minecraftVersion.isOlderThan(MinecraftVersion.v1_17))
{
if (minecraftVersion.isOlderThan(MinecraftVersion.v1_17)) {
myLogger(Level.SEVERE, "Trying to run this plugin on an unsupported version... ABORT!");
setEnabled(false);
return;
@ -73,185 +70,167 @@ public class ArmoredElytra extends JavaPlugin implements Listener
// Check if the user allows checking for updates.
updateManager.setEnabled(config.checkForUpdates());
if (config.allowStats())
{
if (config.allowStats()) {
myLogger(Level.INFO, "Enabling stats! Thanks, it really helps!");
@SuppressWarnings("unused") final Metrics metrics = new Metrics(this, 1656);
}
else
// Y u do dis? :(
} else
// Y u do dis? :(
{
myLogger(Level.INFO,
"Stats disabled, not loading stats :(... Please consider enabling it! I am a simple man, " +
"seeing higher user numbers helps me stay motivated!");
"Stats disabled, not loading stats :(... Please consider enabling it! I am a simple man, " +
"seeing higher user numbers helps me stay motivated!");
}
Bukkit.getPluginManager().registerEvents(new EventHandlers(this, nbtEditor, durabilityManager), this);
Objects.requireNonNull(getCommand("ArmoredElytra"), "ArmoredElytra base command not found!")
.setExecutor(new CommandHandler(this, nbtEditor, durabilityManager));
.setExecutor(new CommandHandler(this, nbtEditor, durabilityManager));
// Load the plugin normally if not in uninstall mode.
if (!config.uninstallMode())
{
if (!config.uninstallMode()) {
Bukkit.getPluginManager().registerEvents(new FlyDurabilityHandler(config.noFlightDurability(),
nbtEditor, durabilityManager), this);
nbtEditor, durabilityManager), this);
final Listener creationListener =
config.craftingInSmithingTable() ?
new SmithingTableCraftHandler(this, nbtEditor, durabilityManager, config) :
new AnvilHandler(this, nbtEditor, durabilityManager, config);
config.craftingInSmithingTable() ?
new SmithingTableCraftHandler(this, nbtEditor, durabilityManager, config) :
new AnvilHandler(this, nbtEditor, durabilityManager, config);
Bukkit.getPluginManager().registerEvents(creationListener, this);
if (config.allowUpgradeToNetherite())
if (config.allowUpgradeToNetherite()) {
Bukkit.getPluginManager()
.registerEvents(new NetheriteUpgradeListener(this, nbtEditor, durabilityManager, config), this);
.registerEvents(new NetheriteUpgradeListener(this, nbtEditor, durabilityManager, config), this);
}
if (config.dropNetheriteAsChestplate())
if (config.dropNetheriteAsChestplate()) {
Bukkit.getPluginManager().registerEvents(new ItemDropListener(nbtEditor), this);
}
// Log all allowed enchantments.
myLogger(Level.INFO, ("Allowed enchantments:"));
for (final Enchantment enchantment : config.allowedEnchantments())
myLogger(Level.INFO, " - " + enchantment.toString());
}
else
{
} else {
myLogger(Level.WARNING, "Plugin in uninstall mode!");
Bukkit.getPluginManager().registerEvents(new Uninstaller(this, nbtEditor), this);
}
}
public MinecraftVersion getMinecraftVersion()
{
public MinecraftVersion getMinecraftVersion() {
return minecraftVersion;
}
public Messages getMyMessages()
{
public Messages getMyMessages() {
return messages;
}
public NBTEditor getNbtEditor()
{
public NBTEditor getNbtEditor() {
return nbtEditor;
}
private void readMessages()
{
private void readMessages() {
// Shouldn't be used.
armorTierNames.put(ArmorTier.NONE, new ArmorTierName("NONE", "NONE"));
armorTierNames.put(ArmorTier.LEATHER, new ArmorTierName(messages.getString(Message.TIER_LEATHER),
messages.getString(Message.TIER_SHORT_LEATHER)));
messages.getString(Message.TIER_SHORT_LEATHER)));
armorTierNames.put(ArmorTier.GOLD, new ArmorTierName(messages.getString(Message.TIER_GOLD),
messages.getString(Message.TIER_SHORT_GOLD)));
messages.getString(Message.TIER_SHORT_GOLD)));
armorTierNames.put(ArmorTier.CHAIN, new ArmorTierName(messages.getString(Message.TIER_CHAIN),
messages.getString(Message.TIER_SHORT_CHAIN)));
messages.getString(Message.TIER_SHORT_CHAIN)));
armorTierNames.put(ArmorTier.IRON, new ArmorTierName(messages.getString(Message.TIER_IRON),
messages.getString(Message.TIER_SHORT_IRON)));
messages.getString(Message.TIER_SHORT_IRON)));
armorTierNames.put(ArmorTier.DIAMOND, new ArmorTierName(messages.getString(Message.TIER_DIAMOND),
messages.getString(Message.TIER_SHORT_DIAMOND)));
messages.getString(Message.TIER_SHORT_DIAMOND)));
armorTierNames.put(ArmorTier.NETHERITE, new ArmorTierName(messages.getString(Message.TIER_NETHERITE),
messages.getString(Message.TIER_SHORT_NETHERITE)));
messages.getString(Message.TIER_SHORT_NETHERITE)));
}
public boolean playerHasCraftPerm(HumanEntity player, ArmorTier armorTier)
{
public boolean playerHasCraftPerm(HumanEntity player, ArmorTier armorTier) {
return getConfigLoader().bypassCraftPerm() ||
player.hasPermission("armoredelytra.craft." + ArmorTier.getName(armorTier));
player.hasPermission("armoredelytra.craft." + ArmorTier.getName(armorTier));
}
public boolean playerHasWearPerm(HumanEntity player, ArmorTier armorTier)
{
public boolean playerHasWearPerm(HumanEntity player, ArmorTier armorTier) {
return getConfigLoader().bypassWearPerm() ||
player.hasPermission("armoredelytra.wear." + ArmorTier.getName(armorTier));
player.hasPermission("armoredelytra.wear." + ArmorTier.getName(armorTier));
}
// Returns the config handler.
public ConfigLoader getConfigLoader()
{
public ConfigLoader getConfigLoader() {
return config;
}
// Send a message to a player in a specific color.
public void messagePlayer(HumanEntity player, ChatColor color, String str)
{
public void messagePlayer(HumanEntity player, ChatColor color, String str) {
player.sendMessage(color + str);
}
// Send a message to a player.
public void messagePlayer(HumanEntity player, String str)
{
public void messagePlayer(HumanEntity player, String str) {
messagePlayer(player, ChatColor.WHITE, str);
}
private String getMessageWithTierNames(final Message message, final ArmorTier armorTier)
{
private String getMessageWithTierNames(final Message message, final ArmorTier armorTier) {
ArmorTierName tierName = armorTierNames.get(armorTier);
return getMyMessages().getString(message,
tierName.getLongName(),
tierName.getShortName());
tierName.getLongName(),
tierName.getShortName());
}
// Send the usageDeniedMessage message to the player.
public void usageDeniedMessage(HumanEntity player, ArmorTier armorTier)
{
public void usageDeniedMessage(HumanEntity player, ArmorTier armorTier) {
final String message = getMessageWithTierNames(Message.MESSAGES_USAGEDENIED, armorTier);
if (!message.equals("NONE"))
if (!message.equals("NONE")) {
messagePlayer(player, ChatColor.RED, message);
}
}
// Send the elytraReceivedMessage message to the player.
public void elytraReceivedMessage(HumanEntity player, ArmorTier armorTier)
{
public void elytraReceivedMessage(HumanEntity player, ArmorTier armorTier) {
final String message = getMessageWithTierNames(Message.MESSAGES_ELYTRARECEIVED, armorTier);
if (!message.equals("NONE"))
if (!message.equals("NONE")) {
messagePlayer(player, ChatColor.GREEN, message);
}
}
public void sendNoGivePermissionMessage(HumanEntity player, ArmorTier armorTier)
{
public void sendNoGivePermissionMessage(HumanEntity player, ArmorTier armorTier) {
final String message = getMessageWithTierNames(Message.MESSAGES_NOGIVEPERMISSION, armorTier);
messagePlayer(player, ChatColor.RED, message);
}
public @Nullable List<String> getElytraLore(ArmorTier armorTier)
{
public @Nullable List<String> getElytraLore(ArmorTier armorTier) {
final String message = ChatColor.stripColor(getMessageWithTierNames(Message.MESSAGES_LORE, armorTier));
return message.equals("NONE") ? null : Collections.singletonList(message);
}
// Print a string to the log.
public void myLogger(Level level, String str)
{
public void myLogger(Level level, String str) {
Bukkit.getLogger().log(level, "[" + getName() + "] " + str);
}
// Log message that only gets printed when debugging is enabled in the config file.
public void debugMsg(Level level, String str)
{
if (config.enableDebug())
public void debugMsg(Level level, String str) {
if (config.enableDebug()) {
myLogger(level, str);
}
}
// Give the provided player the provided item.
public void giveArmoredElytraToPlayer(HumanEntity player, ItemStack item)
{
if (item != null)
public void giveArmoredElytraToPlayer(HumanEntity player, ItemStack item) {
if (item != null) {
player.getInventory().addItem(item);
}
}
public UpdateManager getUpdateManager()
{
public UpdateManager getUpdateManager() {
return updateManager;
}
public static ArmoredElytra getInstance()
{
public static ArmoredElytra getInstance() {
return INSTANCE;
}
public String getArmoredElytraName(ArmorTier tier)
{
if (tier == null)
{
public String getArmoredElytraName(ArmorTier tier) {
if (tier == null) {
getLogger().log(Level.INFO, "ArmorTier was null! Failed to obtain proper string!");
return "NULL";
}

View File

@ -24,17 +24,14 @@ import org.bukkit.inventory.meta.ItemMeta;
import javax.annotation.Nullable;
import java.util.logging.Level;
public class AnvilHandler extends ArmoredElytraHandler implements Listener
{
public class AnvilHandler extends ArmoredElytraHandler implements Listener {
protected AnvilHandler(ArmoredElytra plugin, boolean creationEnabled,
NBTEditor nbtEditor, DurabilityManager durabilityManager, ConfigLoader config)
{
NBTEditor nbtEditor, DurabilityManager durabilityManager, ConfigLoader config) {
super(plugin, creationEnabled, nbtEditor, durabilityManager, config);
}
public AnvilHandler(ArmoredElytra plugin, NBTEditor nbtEditor,
DurabilityManager durabilityManager, ConfigLoader config)
{
DurabilityManager durabilityManager, ConfigLoader config) {
super(plugin, true, nbtEditor, durabilityManager, config);
}
@ -48,100 +45,109 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
// Ignoring:
// - Elytra (not armored) + !chestplate -> None
// - * + * -> None
private Action isValidInput(ArmorTier itemOneTier, ItemStack itemOne, ItemStack itemTwo)
{
if (itemOne == null || itemTwo == null)
private Action isValidInput(ArmorTier itemOneTier, ItemStack itemOne, ItemStack itemTwo) {
if (itemOne == null || itemTwo == null) {
return Action.NONE;
}
if (itemOne.getType() != Material.ELYTRA)
if (itemOne.getType() != Material.ELYTRA) {
return Action.NONE;
}
final Material matTwo = itemTwo.getType();
// If the elytra is to be combined with chest armor...
if (Util.isChestPlate(matTwo))
if (Util.isChestPlate(matTwo)) {
return creationEnabled ? Action.CREATE : Action.NONE;
}
if (itemOneTier != ArmorTier.NONE)
{
if (itemOneTier != ArmorTier.NONE) {
// If the armored elytra is to be enchanted using an enchanted book...
if (matTwo == Material.ENCHANTED_BOOK)
if (matTwo == Material.ENCHANTED_BOOK) {
return config.allowAddingEnchantments() ? Action.ENCHANT : Action.BLOCK;
}
// If the armored elytra is to be repaired using its repair item...
if (ArmorTier.getRepairItem(itemOneTier) == matTwo)
if (ArmorTier.getRepairItem(itemOneTier) == matTwo) {
return durabilityManager.getRealDurability(itemOne, itemOneTier) == 0 ? Action.BLOCK : Action.REPAIR;
}
// If the armored elytra is to be combined with another armored elytra of the same tier...
if (nbtEditor.getArmorTier(itemTwo) == itemOneTier)
if (nbtEditor.getArmorTier(itemTwo) == itemOneTier) {
return creationEnabled ? Action.COMBINE : Action.NONE;
}
// If the armored elytra is not of the leather tier, but itemTwo is leather,
// Pick the block action, as that would repair the elytra by default (vanilla).
// Also block Armored Elytra + Elytra and Elytra + Membrane
if (itemOneTier != ArmorTier.LEATHER && matTwo == Material.LEATHER || matTwo == Material.ELYTRA ||
matTwo.equals(XMaterial.PHANTOM_MEMBRANE.parseMaterial()))
matTwo.equals(XMaterial.PHANTOM_MEMBRANE.parseMaterial())) {
return Action.BLOCK;
}
}
return Action.NONE;
}
// Handle all anvil related stuff for this plugin.
@EventHandler(priority = EventPriority.LOWEST)
private void onAnvilInventoryOpen(PrepareAnvilEvent event)
{
if (!(event.getView().getPlayer() instanceof Player player))
private void onAnvilInventoryOpen(PrepareAnvilEvent event) {
if (!(event.getView().getPlayer() instanceof Player player)) {
return;
}
ItemStack itemA = event.getInventory().getItem(0);
ItemStack itemB = event.getInventory().getItem(1);
if (itemA != null && itemB != null)
// If itemB is the (armored) elytra, while itemA isn't, switch itemA and itemB.
if (itemB.getType() == Material.ELYTRA && itemA.getType() != Material.ELYTRA)
{
// If itemB is the (armored) elytra, while itemA isn't, switch itemA and itemB.
{
if (itemB.getType() == Material.ELYTRA && itemA.getType() != Material.ELYTRA) {
ItemStack tmp = itemA;
itemA = itemB;
itemB = tmp;
}
}
// If one of the input items is null and the other an armored elytra, remove the result.
// This prevents some naming issues.
if ((itemA == null ^ itemB == null) &&
nbtEditor.getArmorTier(itemA == null ? itemB : itemA) != ArmorTier.NONE)
nbtEditor.getArmorTier(itemA == null ? itemB : itemA) != ArmorTier.NONE) {
event.setResult(null);
}
if (itemA == null || itemB == null)
if (itemA == null || itemB == null) {
return;
}
final ArmorTier currentArmorTier = nbtEditor.getArmorTier(itemA);
final Action action = isValidInput(currentArmorTier, itemA, itemB);
if (action == Action.NONE)
if (action == Action.NONE) {
return;
}
final ArmorTier newArmorTier;
if (action == Action.CREATE)
if (action == Action.CREATE) {
newArmorTier = Util.armorToTier(itemB);
else if (action == Action.COMBINE)
} else if (action == Action.COMBINE) {
newArmorTier = nbtEditor.getArmorTier(itemB);
else
} else {
newArmorTier = currentArmorTier;
}
final @Nullable String name = getElytraResultName(itemA, action, currentArmorTier, newArmorTier,
event.getInventory().getRenameText());
event.getInventory().getRenameText());
final @Nullable ItemStack result =
!plugin.playerHasCraftPerm(player, newArmorTier) ? null :
switch (action)
{
case REPAIR -> armoredElytraBuilder.repair(itemA, itemB, name);
case ENCHANT -> armoredElytraBuilder.enchant(itemA, itemB, name);
case COMBINE, CREATE -> armoredElytraBuilder.combine(itemA, itemB, newArmorTier, name);
case BLOCK -> null;
//noinspection ConstantConditions
case NONE -> itemA;
};
!plugin.playerHasCraftPerm(player, newArmorTier) ? null :
switch (action) {
case REPAIR -> armoredElytraBuilder.repair(itemA, itemB, name);
case ENCHANT -> armoredElytraBuilder.enchant(itemA, itemB, name);
case COMBINE, CREATE -> armoredElytraBuilder.combine(itemA, itemB, newArmorTier, name);
case BLOCK -> null;
//noinspection ConstantConditions
case NONE -> itemA;
};
event.setResult(result);
player.updateInventory();
@ -149,14 +155,14 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
private @Nullable String getElytraResultName(final ItemStack baseItem, final Action action,
final ArmorTier currentArmorTier, final ArmorTier newArmorTier,
final String renameText)
{
final String renameText) {
final String currentTierName = plugin.getArmoredElytraName(currentArmorTier);
final String tierName = plugin.getArmoredElytraName(newArmorTier);
if (renameText == null || !config.allowRenaming() ||
ChatColor.stripColor(currentTierName).equals(ChatColor.stripColor(renameText)))
ChatColor.stripColor(currentTierName).equals(ChatColor.stripColor(renameText))) {
return tierName;
}
final ItemMeta meta = baseItem.getItemMeta();
final String currentName = meta == null ? null : meta.getDisplayName();
@ -165,36 +171,35 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
// (so it's named properly) or when the current name is already the tier name (just returning the current
// name would strip the tier's color in this case).
if ((action == Action.CREATE && renameText.equals("")) ||
ChatColor.stripColor(tierName).equals(ChatColor.stripColor(renameText)))
ChatColor.stripColor(tierName).equals(ChatColor.stripColor(renameText))) {
return tierName;
}
return renameText.equals("") ? currentName : renameText;
}
// Let the player take items out of the anvil.
@EventHandler
public void onInventoryClick(InventoryClickEvent e)
{
if (e.getRawSlot() != 2 || !(e.getWhoClicked() instanceof Player player))
public void onInventoryClick(InventoryClickEvent e) {
if (e.getRawSlot() != 2 || !(e.getWhoClicked() instanceof Player player)) {
return;
}
// Check if the event was a player who interacted with an anvil.
if (e.getView().getType() != InventoryType.ANVIL)
if (e.getView().getType() != InventoryType.ANVIL) {
return;
}
AnvilInventory anvilInventory;
// Try to cast inventory being used in the event to an anvil inventory.
// This will throw a ClassCastException when a CraftInventoryCustom is used.
try
{
try {
anvilInventory = (AnvilInventory) e.getInventory();
}
catch (ClassCastException exception)
{
} catch (ClassCastException exception) {
// Print warning to console and exit onInventoryClick event (no support for
// custom inventories as they are usually used for GUI's).
plugin.debugMsg(Level.WARNING, "Could not cast inventory to anvilInventory for player " + player.getName()
+ "! Armored Elytras cannot be crafted!");
+ "! Armored Elytras cannot be crafted!");
exception.printStackTrace();
return;
}
@ -203,15 +208,14 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
final @Nullable ItemStack item1 = anvilInventory.getItem(1);
final @Nullable ItemStack item2 = anvilInventory.getItem(2);
if (item0 != null && item1 != null && item2 != null && item2.getType() == Material.ELYTRA)
{
if (item0 != null && item1 != null && item2 != null && item2.getType() == Material.ELYTRA) {
final ArmorTier armortier = nbtEditor.getArmorTier(anvilInventory.getItem(2));
// If there's an armored elytra in the final slot...
if (armortier != ArmorTier.NONE && plugin.playerHasCraftPerm(player, armortier))
{
if (!giveItemToPlayer(player, item2, e.isShiftClick()))
if (armortier != ArmorTier.NONE && plugin.playerHasCraftPerm(player, armortier)) {
if (!giveItemToPlayer(player, item2, e.isShiftClick())) {
return;
}
// Clean the anvil's inventory after transferring the items.
anvilInventory.clear();

View File

@ -15,8 +15,7 @@ import javax.annotation.CheckReturnValue;
*
* @author Pim
*/
abstract class ArmoredElytraHandler
{
abstract class ArmoredElytraHandler {
protected final ArmoredElytra plugin;
protected final boolean creationEnabled;
protected final ConfigLoader config;
@ -26,8 +25,7 @@ abstract class ArmoredElytraHandler
protected ArmoredElytraHandler(ArmoredElytra plugin, boolean creationEnabled, NBTEditor nbtEditor,
DurabilityManager durabilityManager, ConfigLoader config,
ArmoredElytraBuilder armoredElytraBuilder)
{
ArmoredElytraBuilder armoredElytraBuilder) {
this.plugin = plugin;
this.creationEnabled = creationEnabled;
this.nbtEditor = nbtEditor;
@ -37,10 +35,9 @@ abstract class ArmoredElytraHandler
}
protected ArmoredElytraHandler(ArmoredElytra plugin, boolean creationEnabled, NBTEditor nbtEditor,
DurabilityManager durabilityManager, ConfigLoader config)
{
DurabilityManager durabilityManager, ConfigLoader config) {
this(plugin, creationEnabled, nbtEditor, durabilityManager, config,
new ArmoredElytraBuilder(nbtEditor, durabilityManager, config, plugin));
new ArmoredElytraBuilder(nbtEditor, durabilityManager, config, plugin));
}
/**
@ -53,17 +50,16 @@ abstract class ArmoredElytraHandler
* @return True if the item could be given to the player, otherwise false (e.g. when their inventory is full).
*/
@CheckReturnValue
protected boolean giveItemToPlayer(final Player player, final ItemStack item, final boolean direct)
{
if (direct)
{
protected boolean giveItemToPlayer(final Player player, final ItemStack item, final boolean direct) {
if (direct) {
// If the player's inventory is full, don't do anything.
if (player.getInventory().firstEmpty() == -1)
if (player.getInventory().firstEmpty() == -1) {
return false;
}
player.getInventory().addItem(item);
}
else
} else {
player.setItemOnCursor(item);
}
return true;
}
}

View File

@ -20,51 +20,41 @@ import java.lang.reflect.Field;
import java.util.Map;
import java.util.logging.Level;
public class CommandHandler implements CommandExecutor
{
public class CommandHandler implements CommandExecutor {
private final ArmoredElytra plugin;
private static Field BY_KEY_FIELD;
private final ArmoredElytraBuilder armoredElytraBuilder;
public CommandHandler(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager)
{
public CommandHandler(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager) {
this.plugin = plugin;
armoredElytraBuilder = new ArmoredElytraBuilder(nbtEditor, durabilityManager, plugin.getConfigLoader(), plugin);
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
{
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
Player player;
if (sender instanceof Player)
{
if (sender instanceof Player) {
player = (Player) sender;
if (plugin.getConfigLoader().uninstallMode())
{
if (plugin.getConfigLoader().uninstallMode()) {
plugin.messagePlayer(player, plugin.getMyMessages().getString(Message.MESSAGES_UNINSTALLMODE));
return true;
}
if (cmd.getName().equalsIgnoreCase("ArmoredElytra"))
if (args.length == 1 || args.length == 2)
{
if (cmd.getName().equalsIgnoreCase("ArmoredElytra")) {
if (args.length == 1 || args.length == 2) {
ItemStack newElytra = null;
String tier = null;
Player receiver;
boolean allowed = false;
if (args.length == 1)
{
if (args.length == 1) {
receiver = player;
tier = args[0];
}
else
{
} else {
receiver = Bukkit.getPlayer(args[0]);
if (receiver == null)
{
if (receiver == null) {
plugin.messagePlayer(player, ChatColor.RED, "Player \"" + args[0] + "\" not found!");
return true;
}
@ -72,56 +62,50 @@ public class CommandHandler implements CommandExecutor
}
ArmorTier armorTier = ArmorTier.valueOfName(tier.toLowerCase());
if (armorTier != null)
if (armorTier != null) {
allowed = player.hasPermission("armoredelytra.give." + ArmorTier.getName(armorTier));
else
{
} else {
plugin.messagePlayer(player, plugin.getMyMessages()
.getString(Message.MESSAGES_UNSUPPORTEDTIER));
.getString(Message.MESSAGES_UNSUPPORTEDTIER));
return false;
}
if (allowed)
{
if (allowed) {
plugin.elytraReceivedMessage(receiver, armorTier);
plugin.giveArmoredElytraToPlayer(receiver, armoredElytraBuilder.newArmoredElytra(armorTier));
}
else
} else {
plugin.sendNoGivePermissionMessage(player, armorTier);
}
return true;
}
}
else
{
if (plugin.getConfigLoader().uninstallMode())
{
}
} else {
if (plugin.getConfigLoader().uninstallMode()) {
plugin.myLogger(Level.INFO, "Plugin in uninstall mode! New Armored Elytras are not allowed!");
return true;
}
if (args.length == 1 &&
(args[0].equalsIgnoreCase("listAvailableEnchantments") ||
args[0].equalsIgnoreCase("listEnchantments") ||
args[0].equalsIgnoreCase("enchantments")))
{
(args[0].equalsIgnoreCase("listAvailableEnchantments") ||
args[0].equalsIgnoreCase("listEnchantments") ||
args[0].equalsIgnoreCase("enchantments"))) {
listAvailableEnchantments();
return true;
}
if (args.length == 2)
{
if (args.length == 2) {
final String tier = args[1];
player = Bukkit.getPlayer(args[0]);
if (player != null)
{
if (player != null) {
ArmorTier armorTier = ArmorTier.valueOfName(tier.toLowerCase());
if (armorTier == null)
if (armorTier == null) {
return false;
}
plugin.elytraReceivedMessage(player, armorTier);
plugin.giveArmoredElytraToPlayer(player, armoredElytraBuilder.newArmoredElytra(armorTier));
plugin.myLogger(Level.INFO, ("Giving an armored elytra of the " + ArmorTier.getArmor(armorTier) +
" armor tier to player " + player.getName()));
" armor tier to player " + player.getName()));
return true;
}
plugin.myLogger(Level.INFO, ("Player " + args[1] + " not found!"));
@ -131,28 +115,22 @@ public class CommandHandler implements CommandExecutor
return false;
}
private void listAvailableEnchantments()
{
try
{
if (BY_KEY_FIELD == null)
{
private void listAvailableEnchantments() {
try {
if (BY_KEY_FIELD == null) {
BY_KEY_FIELD = Enchantment.class.getDeclaredField("byKey");
BY_KEY_FIELD.setAccessible(true);
}
@SuppressWarnings("unchecked")
final Map<NamespacedKey, Enchantment> byKey = (Map<NamespacedKey, Enchantment>) BY_KEY_FIELD.get(null);
@SuppressWarnings("unchecked") final Map<NamespacedKey, Enchantment> byKey = (Map<NamespacedKey, Enchantment>) BY_KEY_FIELD.get(null);
final StringBuilder sb = new StringBuilder("\nAvailable enchantments: \n");
byKey.keySet().stream()
.map(NamespacedKey::toString).sorted()
.forEach(name -> sb.append(" - ").append(name).append("\n"));
.map(NamespacedKey::toString).sorted()
.forEach(name -> sb.append(" - ").append(name).append("\n"));
Bukkit.getLogger().info(sb.toString());
}
catch (NoSuchFieldException | IllegalAccessException e)
{
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException("Failed to get registered enchantments!", e);
}
}

View File

@ -26,122 +26,122 @@ import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Random;
public class EventHandlers implements Listener
{
public class EventHandlers implements Listener {
private final Random random = new Random();
private final ArmoredElytra plugin;
private final NBTEditor nbtEditor;
private final DurabilityManager durabilityManager;
public EventHandlers(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager)
{
public EventHandlers(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager) {
this.plugin = plugin;
this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager;
initializeArmorEquipEvent();
}
private void initializeArmorEquipEvent()
{
private void initializeArmorEquipEvent() {
Bukkit.getPluginManager().registerEvents(new ArmorListener(new ArrayList<>()), plugin);
Bukkit.getPluginManager().registerEvents(new DispenserArmorListener(), plugin);
}
// Make sure the player has the correct permission and that the item is not
// broken.
private AllowedToWearEnum isAllowedToWear(ItemStack elytra, Player player, ArmorTier armorTier)
{
if (armorTier.equals(ArmorTier.NONE))
private AllowedToWearEnum isAllowedToWear(ItemStack elytra, Player player, ArmorTier armorTier) {
if (armorTier.equals(ArmorTier.NONE)) {
return AllowedToWearEnum.ALLOWED;
if (Util.isBroken(elytra))
}
if (Util.isBroken(elytra)) {
return AllowedToWearEnum.BROKEN;
if (!plugin.playerHasWearPerm(player, armorTier))
}
if (!plugin.playerHasWearPerm(player, armorTier)) {
return AllowedToWearEnum.NOPERMISSION;
}
return AllowedToWearEnum.ALLOWED;
}
// Handle armored elytra durability loss.
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerDamage(EntityDamageEvent e)
{
if (!(e.getEntity() instanceof final Player p))
public void onPlayerDamage(EntityDamageEvent e) {
if (!(e.getEntity() instanceof final Player p)) {
return;
}
final ItemStack elytra = p.getInventory().getChestplate();
if (elytra == null)
if (elytra == null) {
return;
}
final ArmorTier armorTier = nbtEditor.getArmorTier(elytra);
if (armorTier == ArmorTier.NONE)
if (armorTier == ArmorTier.NONE) {
return;
}
final DamageCause cause = e.getCause();
// The elytra doesn't receive any damage for these causes:
if (cause == DamageCause.DROWNING || cause == DamageCause.STARVATION || cause == DamageCause.SUFFOCATION ||
cause == DamageCause.SUICIDE || cause == DamageCause.FLY_INTO_WALL || cause == DamageCause.POISON)
cause == DamageCause.SUICIDE || cause == DamageCause.FLY_INTO_WALL || cause == DamageCause.POISON) {
return;
}
final boolean removeDurability;
if (elytra.containsEnchantment(Enchantment.DURABILITY))
{
if (elytra.containsEnchantment(Enchantment.DURABILITY)) {
final int randomInt = random.nextInt(101);
final int enchantLevel = elytra.getEnchantmentLevel(Enchantment.DURABILITY);
// Formula taken from: https://minecraft.fandom.com/wiki/Unbreaking#Usage
final float removeDurabilityChance = 60 + 40f / (enchantLevel + 1);
removeDurability = randomInt <= removeDurabilityChance;
}
else
} else {
removeDurability = true;
}
// Even when we don't subtract durability, we still want to update the durability, so just subtract 0.
final int durabilityLoss = removeDurability ? (int) Math.max(1, e.getDamage() / 4) : 0;
final int newDurability = durabilityManager.removeDurability(elytra, durabilityLoss, armorTier);
if (durabilityManager.isBroken(newDurability, armorTier))
if (durabilityManager.isBroken(newDurability, armorTier)) {
Util.moveChestplateToInventory(p);
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onMending(PlayerItemMendEvent e)
{
public void onMending(PlayerItemMendEvent e) {
final ArmorTier armorTier = nbtEditor.getArmorTier(e.getItem());
if (armorTier == ArmorTier.NONE)
if (armorTier == ArmorTier.NONE) {
return;
}
final int newDurability = durabilityManager.removeDurability(e.getItem(), -e.getRepairAmount(), armorTier);
// Apply it again a tick later, so we can override the durability of the armored elytra without
// interfering with the player XP change event that depends on the success of this one.
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () ->
durabilityManager.setDurability(e.getItem(), newDurability, armorTier), 1);
durabilityManager.setDurability(e.getItem(), newDurability, armorTier), 1);
}
@EventHandler
public void onEquip(ArmorEquipEvent e)
{
public void onEquip(ArmorEquipEvent e) {
if (e.getMethod().equals(ArmorEquipEvent.EquipMethod.DEATH) ||
e.getMethod().equals(ArmorEquipEvent.EquipMethod.BROKE))
e.getMethod().equals(ArmorEquipEvent.EquipMethod.BROKE)) {
return;
}
if (!e.getType().equals(ArmorType.CHESTPLATE) ||
e.getNewArmorPiece() == null ||
!e.getNewArmorPiece().getType().equals(Material.ELYTRA))
e.getNewArmorPiece() == null ||
!e.getNewArmorPiece().getType().equals(Material.ELYTRA)) {
return;
}
final ArmorTier armorTier = nbtEditor.getArmorTier(e.getNewArmorPiece());
final AllowedToWearEnum allowed = isAllowedToWear(e.getNewArmorPiece(), e.getPlayer(), armorTier);
switch (allowed)
{
case ALLOWED:
break;
case BROKEN:
switch (allowed) {
case BROKEN -> {
plugin.messagePlayer(e.getPlayer(), plugin.getMyMessages().getString(Message.MESSAGES_REPAIRNEEDED));
e.setCancelled(true);
break;
case NOPERMISSION:
}
case NOPERMISSION -> {
plugin.usageDeniedMessage(e.getPlayer(), armorTier);
e.setCancelled(true);
break;
default:
break;
}
case ALLOWED, default -> {
}
}
}
}

View File

@ -10,14 +10,12 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerItemDamageEvent;
public class FlyDurabilityHandler implements Listener
{
public class FlyDurabilityHandler implements Listener {
private final boolean disableDurability;
private final NBTEditor nbtEditor;
private final DurabilityManager durabilityManager;
public FlyDurabilityHandler(boolean disableDurability, NBTEditor nbtEditor, DurabilityManager durabilityManager)
{
public FlyDurabilityHandler(boolean disableDurability, NBTEditor nbtEditor, DurabilityManager durabilityManager) {
this.disableDurability = disableDurability;
this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager;
@ -25,26 +23,30 @@ public class FlyDurabilityHandler implements Listener
// Do not decrease elytra durability while flying.
@EventHandler(priority = EventPriority.LOWEST)
public void onItemDamage(PlayerItemDamageEvent e)
{
if (e.getItem().getType() != Material.ELYTRA)
public void onItemDamage(PlayerItemDamageEvent e) {
if (e.getItem().getType() != Material.ELYTRA) {
return;
}
if (!e.getPlayer().isGliding())
if (!e.getPlayer().isGliding()) {
return;
}
final ArmorTier armorTier = nbtEditor.getArmorTier(e.getItem());
if (armorTier == ArmorTier.NONE)
if (armorTier == ArmorTier.NONE) {
return;
}
// This also cancels durability decrease when it should (i.e. getting hit) while flying,
// but that is likely to be rare enough for it to not matter.
e.setCancelled(true);
if (disableDurability)
if (disableDurability) {
return;
}
final int newDurability = durabilityManager.removeDurability(e.getItem(), e.getDamage(), armorTier);
if (durabilityManager.isBroken(newDurability, armorTier))
if (durabilityManager.isBroken(newDurability, armorTier)) {
Util.moveChestplateToInventory(e.getPlayer());
}
}
}

View File

@ -11,12 +11,10 @@ import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.inventory.InventoryPickupItemEvent;
import org.bukkit.inventory.ItemStack;
public class ItemDropListener implements Listener
{
public class ItemDropListener implements Listener {
private final NBTEditor nbtEditor;
public ItemDropListener(NBTEditor nbtEditor)
{
public ItemDropListener(NBTEditor nbtEditor) {
this.nbtEditor = nbtEditor;
}
@ -29,11 +27,11 @@ public class ItemDropListener implements Listener
* @param itemStack The dropped item to analyze.
* @return The new item to drop if it should be changed. If no change is required, null is returned.
*/
private ItemStack getNewDrop(final ItemStack itemStack)
{
private ItemStack getNewDrop(final ItemStack itemStack) {
if (itemStack == null || itemStack.getType() != Material.ELYTRA ||
nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE)
nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE) {
return null;
}
final ItemStack newDrop = new ItemStack(Material.NETHERITE_CHESTPLATE, 1);
newDrop.setItemMeta(itemStack.getItemMeta());
@ -50,11 +48,11 @@ public class ItemDropListener implements Listener
* @param itemStack The picked-up item to analyze.
* @return The new item to pick up if it should be changed. If no change is required, null is returned.
*/
private ItemStack getNewPickup(final ItemStack itemStack)
{
private ItemStack getNewPickup(final ItemStack itemStack) {
if (itemStack == null || itemStack.getType() != Material.NETHERITE_CHESTPLATE ||
nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE)
nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE) {
return null;
}
final ItemStack newDrop = new ItemStack(Material.ELYTRA, 1);
newDrop.setItemMeta(itemStack.getItemMeta());
@ -63,26 +61,26 @@ public class ItemDropListener implements Listener
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onDrop(final ItemSpawnEvent event)
{
public void onDrop(final ItemSpawnEvent event) {
final ItemStack newDrop = getNewDrop(event.getEntity().getItemStack());
if (newDrop != null)
if (newDrop != null) {
event.getEntity().setItemStack(newDrop);
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onEntityPickup(EntityPickupItemEvent event)
{
public void onEntityPickup(EntityPickupItemEvent event) {
final ItemStack newPickup = getNewPickup(event.getItem().getItemStack());
if (newPickup != null)
if (newPickup != null) {
event.getItem().setItemStack(newPickup);
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onInventoryPickup(InventoryPickupItemEvent event)
{
public void onInventoryPickup(InventoryPickupItemEvent event) {
final ItemStack newPickup = getNewPickup(event.getItem().getItemStack());
if (newPickup != null)
if (newPickup != null) {
event.getItem().setItemStack(newPickup);
}
}
}

View File

@ -8,30 +8,27 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.scheduler.BukkitRunnable;
public class LoginHandler implements Listener
{
public class LoginHandler implements Listener {
private final ArmoredElytra plugin;
private final String message;
public LoginHandler(ArmoredElytra plugin, String message)
{
public LoginHandler(ArmoredElytra plugin, String message) {
this.plugin = plugin;
this.message = message;
}
@EventHandler
public void onLogin(PlayerLoginEvent event)
{
public void onLogin(PlayerLoginEvent event) {
Player player = event.getPlayer();
if (player.hasPermission("armoredElytra.admin"))
// Slight delay so the player actually receives the message;
new BukkitRunnable()
{
// Slight delay so the player actually receives the message;
{
new BukkitRunnable() {
@Override
public void run()
{
public void run() {
plugin.messagePlayer(player, ChatColor.AQUA, message);
}
}.runTaskLater(plugin, 10);
}
}
}

View File

@ -14,43 +14,42 @@ import org.bukkit.inventory.SmithingInventory;
import javax.annotation.Nullable;
public class NetheriteUpgradeListener extends SmithingTableListener
{
public class NetheriteUpgradeListener extends SmithingTableListener {
public NetheriteUpgradeListener(final ArmoredElytra plugin, NBTEditor nbtEditor,
DurabilityManager durabilityManager, ConfigLoader config)
{
DurabilityManager durabilityManager, ConfigLoader config) {
super(plugin, false, nbtEditor, durabilityManager, config);
}
@EventHandler(ignoreCancelled = true)
public void onSmithingTableUsage(final PrepareSmithingEvent event)
{
public void onSmithingTableUsage(final PrepareSmithingEvent event) {
final SmithingInventory inventory = event.getInventory();
final ItemStack[] contents = inventory.getContents();
final ItemStack itemStackA = contents[0];
final ItemStack itemStackB = contents[1];
if (!validInput(itemStackA, itemStackB))
if (!validInput(itemStackA, itemStackB)) {
return;
}
if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), ArmorTier.NETHERITE))
if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), ArmorTier.NETHERITE)) {
return;
}
event.setResult(armoredElytraBuilder
.newBuilder()
.ofElytra(itemStackA)
.upgradeToTier(ArmorTier.NETHERITE)
.build());
.newBuilder()
.ofElytra(itemStackA)
.upgradeToTier(ArmorTier.NETHERITE)
.build());
}
private boolean validInput(@Nullable ItemStack itemStackA, @Nullable ItemStack itemStackB)
{
private boolean validInput(@Nullable ItemStack itemStackA, @Nullable ItemStack itemStackB) {
if (itemStackA == null || itemStackB == null ||
itemStackA.getType() != Material.ELYTRA ||
plugin.getNbtEditor().getArmorTier(itemStackA) != ArmorTier.DIAMOND ||
itemStackB.getType() != Material.NETHERITE_INGOT)
itemStackA.getType() != Material.ELYTRA ||
plugin.getNbtEditor().getArmorTier(itemStackA) != ArmorTier.DIAMOND ||
itemStackB.getType() != Material.NETHERITE_INGOT) {
return false;
}
// For some reason, adding multiple netherite ingots causes the view to not update properly.
// The resulting armored elytra is hidden and the red cross indicates the combination is impossible.
@ -61,8 +60,7 @@ public class NetheriteUpgradeListener extends SmithingTableListener
@Override
@EventHandler(ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event)
{
public void onInventoryClick(InventoryClickEvent event) {
super.onInventoryClick(event);
}
}

View File

@ -14,20 +14,17 @@ import org.bukkit.event.inventory.PrepareSmithingEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.SmithingInventory;
public class SmithingTableCraftHandler extends SmithingTableListener
{
public class SmithingTableCraftHandler extends SmithingTableListener {
public SmithingTableCraftHandler(final ArmoredElytra plugin, NBTEditor nbtEditor,
DurabilityManager durabilityManager, ConfigLoader config)
{
DurabilityManager durabilityManager, ConfigLoader config) {
super(plugin, true, nbtEditor, durabilityManager, config);
// Register the anvil handler with creation disabled so AEs can still be repaired and stuff.
Bukkit.getPluginManager()
.registerEvents(new AnvilHandler(plugin, false, nbtEditor, durabilityManager, config), plugin);
.registerEvents(new AnvilHandler(plugin, false, nbtEditor, durabilityManager, config), plugin);
}
@EventHandler(ignoreCancelled = true)
public void onSmithingTableUsage(final PrepareSmithingEvent event)
{
public void onSmithingTableUsage(final PrepareSmithingEvent event) {
final SmithingInventory inventory = event.getInventory();
final ItemStack[] contents = inventory.getContents();
@ -35,28 +32,29 @@ public class SmithingTableCraftHandler extends SmithingTableListener
final ItemStack itemStackB = contents[1];
final ArmorTier newArmorTier = getNewArmorTier(itemStackA, itemStackB);
if (newArmorTier == ArmorTier.NONE)
if (newArmorTier == ArmorTier.NONE) {
return;
}
if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), newArmorTier))
if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), newArmorTier)) {
return;
}
event.setResult(armoredElytraBuilder.combine(itemStackA, itemStackB, newArmorTier, null));
}
protected ArmorTier getNewArmorTier(ItemStack itemStackA, ItemStack itemStackB)
{
protected ArmorTier getNewArmorTier(ItemStack itemStackA, ItemStack itemStackB) {
if (itemStackA == null || itemStackB == null ||
itemStackA.getType() != Material.ELYTRA || !Util.isChestPlate(itemStackB))
itemStackA.getType() != Material.ELYTRA || !Util.isChestPlate(itemStackB)) {
return ArmorTier.NONE;
}
return Util.armorToTier(itemStackB.getType());
}
@Override
@EventHandler(ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event)
{
public void onInventoryClick(InventoryClickEvent event) {
super.onInventoryClick(event);
}
}

View File

@ -15,24 +15,23 @@ import org.bukkit.inventory.SmithingInventory;
import java.util.logging.Level;
abstract class SmithingTableListener extends ArmoredElytraHandler implements Listener
{
abstract class SmithingTableListener extends ArmoredElytraHandler implements Listener {
protected SmithingTableListener(ArmoredElytra plugin, boolean creationEnabled,
NBTEditor nbtEditor, DurabilityManager durabilityManager, ConfigLoader config)
{
NBTEditor nbtEditor, DurabilityManager durabilityManager, ConfigLoader config) {
super(plugin, creationEnabled, nbtEditor, durabilityManager, config);
}
protected void onInventoryClick(InventoryClickEvent event)
{
if (!isAESmithingTableEvent(event))
protected void onInventoryClick(InventoryClickEvent event) {
if (!isAESmithingTableEvent(event)) {
return;
}
final SmithingInventory smithingInventory = (SmithingInventory) event.getInventory();
final ItemStack result = smithingInventory.getItem(2);
// This cast may look unchecked, but it was checked by isSmithingTableEvent already.
if (!giveItemToPlayer((Player) event.getWhoClicked(), result, event.isShiftClick()))
if (!giveItemToPlayer((Player) event.getWhoClicked(), result, event.isShiftClick())) {
return;
}
smithingInventory.clear();
}
@ -43,42 +42,39 @@ abstract class SmithingTableListener extends ArmoredElytraHandler implements Lis
* @param event The {@link InventoryClickEvent} which may be of use to us.
* @return True if this plugin can process this event further.
*/
protected boolean isAESmithingTableEvent(final InventoryClickEvent event)
{
if (event.getRawSlot() != 2)
protected boolean isAESmithingTableEvent(final InventoryClickEvent event) {
if (event.getRawSlot() != 2) {
return false;
}
// Check if the event was a player who interacted with a smithing table.
final Player player = (Player) event.getWhoClicked();
if (event.getView().getType() != InventoryType.SMITHING)
if (event.getView().getType() != InventoryType.SMITHING) {
return false;
}
SmithingInventory smithingInventory;
// Try to cast inventory being used in the event to a smithing inventory.
// This will throw a ClassCastException when a CraftInventoryCustom is used.
try
{
try {
smithingInventory = (SmithingInventory) event.getInventory();
}
catch (ClassCastException exception)
{
} catch (ClassCastException exception) {
// Print warning to console and exit onInventoryClick event (no support for
// custom inventories as they are usually used for GUI's).
plugin.debugMsg(Level.WARNING, "Could not cast inventory to SmithingInventory for player " +
player.getName() + "! Armored Elytras cannot be crafted!");
player.getName() + "! Armored Elytras cannot be crafted!");
exception.printStackTrace();
return false;
}
if (smithingInventory.getItem(0) == null ||
smithingInventory.getItem(1) == null ||
smithingInventory.getItem(2) == null)
smithingInventory.getItem(1) == null ||
smithingInventory.getItem(2) == null) {
return false;
}
final ItemStack result = smithingInventory.getItem(2);
if (result == null || result.getType() != Material.ELYTRA ||
nbtEditor.getArmorTier(result) == ArmorTier.NONE)
return false;
return true;
return result != null && result.getType() == Material.ELYTRA &&
nbtEditor.getArmorTier(result) != ArmorTier.NONE;
}
}

View File

@ -5,7 +5,6 @@ import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryOpenEvent;
@ -15,24 +14,20 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
public class Uninstaller implements Listener
{
public class Uninstaller implements Listener {
private final ArmoredElytra plugin;
private final NBTEditor nbtEditor;
public Uninstaller(ArmoredElytra plugin, NBTEditor nbtEditor)
{
public Uninstaller(ArmoredElytra plugin, NBTEditor nbtEditor) {
this.plugin = plugin;
this.nbtEditor = nbtEditor;
}
public int removeArmoredElytras(Inventory inv)
{
public int removeArmoredElytras(Inventory inv) {
int count = 0;
for (ItemStack is : inv)
if (is != null && is.getType() == Material.ELYTRA &&
nbtEditor.getArmorTier(is) != ArmorTier.NONE)
{
nbtEditor.getArmorTier(is) != ArmorTier.NONE) {
inv.remove(is);
++count;
}
@ -40,38 +35,36 @@ public class Uninstaller implements Listener
}
@EventHandler
public void onChestOpen(InventoryOpenEvent event)
{
public void onChestOpen(InventoryOpenEvent event) {
if (event.getInventory().getType().equals(InventoryType.CHEST))
// Slight delay so the inventory has time to get loaded.
new BukkitRunnable()
{
// Slight delay so the inventory has time to get loaded.
{
new BukkitRunnable() {
@Override
public void run()
{
public void run() {
Inventory inv = event.getInventory();
int removed = removeArmoredElytras(inv);
if (removed != 0)
plugin.messagePlayer((Player) (event.getPlayer()), ChatColor.RED,
"Removed " + removed + " armored elytras from your chest!");
if (removed != 0) {
plugin.messagePlayer(event.getPlayer(), ChatColor.RED,
"Removed " + removed + " armored elytras from your chest!");
}
}
}.runTaskLater(plugin, 20);
}
}
@EventHandler
public void onPlayerLogin(PlayerLoginEvent event)
{
public void onPlayerLogin(PlayerLoginEvent event) {
// Slight delay so the inventory has time to get loaded.
new BukkitRunnable()
{
new BukkitRunnable() {
@Override
public void run()
{
public void run() {
Inventory inv = event.getPlayer().getInventory();
int removed = removeArmoredElytras(inv);
if (removed != 0)
if (removed != 0) {
plugin.messagePlayer(event.getPlayer(), ChatColor.RED,
"Removed " + removed + " armored elytras from your inventory!");
"Removed " + removed + " armored elytras from your inventory!");
}
}
}.runTaskLater(plugin, 20);
}

View File

@ -11,8 +11,7 @@ import org.bukkit.inventory.ItemStack;
* @author Arnah
* @since Jul 30, 2015
*/
public final class ArmorEquipEvent extends PlayerEvent implements Cancellable
{
public final class ArmorEquipEvent extends PlayerEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancel = false;
private final EquipMethod equipType;
@ -28,8 +27,7 @@ public final class ArmorEquipEvent extends PlayerEvent implements Cancellable
* @param newArmorPiece The ItemStack of the armor added.
*/
public ArmorEquipEvent(final Player player, final EquipMethod equipType, final ArmorType type,
final ItemStack oldArmorPiece, final ItemStack newArmorPiece)
{
final ItemStack oldArmorPiece, final ItemStack newArmorPiece) {
super(player);
this.equipType = equipType;
this.type = type;
@ -42,8 +40,7 @@ public final class ArmorEquipEvent extends PlayerEvent implements Cancellable
*
* @return A list of handlers handling this event.
*/
public static HandlerList getHandlerList()
{
public static HandlerList getHandlerList() {
return handlers;
}
@ -53,8 +50,7 @@ public final class ArmorEquipEvent extends PlayerEvent implements Cancellable
* @return A list of handlers handling this event.
*/
@Override
public final HandlerList getHandlers()
{
public HandlerList getHandlers() {
return handlers;
}
@ -64,8 +60,7 @@ public final class ArmorEquipEvent extends PlayerEvent implements Cancellable
* @param cancel If this event should be cancelled.
*/
@Override
public final void setCancelled(final boolean cancel)
{
public void setCancelled(final boolean cancel) {
this.cancel = cancel;
}
@ -75,52 +70,44 @@ public final class ArmorEquipEvent extends PlayerEvent implements Cancellable
* @return If this event is cancelled
*/
@Override
public final boolean isCancelled()
{
public boolean isCancelled() {
return cancel;
}
public final ArmorType getType()
{
public ArmorType getType() {
return type;
}
/**
* Returns the last equipped armor piece, could be a piece of armor, {@link Material#Air}, or null.
*/
public final ItemStack getOldArmorPiece()
{
public ItemStack getOldArmorPiece() {
return oldArmorPiece;
}
public final void setOldArmorPiece(final ItemStack oldArmorPiece)
{
public void setOldArmorPiece(final ItemStack oldArmorPiece) {
this.oldArmorPiece = oldArmorPiece;
}
/**
* Returns the newly equipped armor, could be a piece of armor, {@link Material#Air}, or null.
*/
public final ItemStack getNewArmorPiece()
{
public ItemStack getNewArmorPiece() {
return newArmorPiece;
}
public final void setNewArmorPiece(final ItemStack newArmorPiece)
{
public void setNewArmorPiece(final ItemStack newArmorPiece) {
this.newArmorPiece = newArmorPiece;
}
/**
* Gets the method used to either equip or unequip an armor piece.
*/
public EquipMethod getMethod()
{
public EquipMethod getMethod() {
return equipType;
}
public enum EquipMethod
{
public enum EquipMethod {
/**
* When you shift click an armor piece to equip or unequip
*/
@ -154,6 +141,5 @@ public final class ArmorEquipEvent extends PlayerEvent implements Cancellable
* When you die causing all armor to unequip
*/
DEATH,
;
}
}

View File

@ -25,85 +25,77 @@ import java.util.List;
* @author Arnah
* @since Jul 30, 2015
*/
public class ArmorListener implements Listener
{
public class ArmorListener implements Listener {
private final List<String> blockedMaterials;
public ArmorListener(List<String> blockedMaterials)
{
public ArmorListener(List<String> blockedMaterials) {
this.blockedMaterials = blockedMaterials;
}
@EventHandler
public final void inventoryClick(final InventoryClickEvent e)
{
public final void inventoryClick(final InventoryClickEvent e) {
boolean shift = false, numberkey = false;
if (e.isCancelled())
if (e.isCancelled()) {
return;
}
if (e.getAction() == InventoryAction.NOTHING)
// Why does this get called if nothing happens??
// Why does this get called if nothing happens??
{
return;
if (e.getClick().equals(ClickType.SHIFT_LEFT) || e.getClick().equals(ClickType.SHIFT_RIGHT))
}
if (e.getClick().equals(ClickType.SHIFT_LEFT) || e.getClick().equals(ClickType.SHIFT_RIGHT)) {
shift = true;
if (e.getClick().equals(ClickType.NUMBER_KEY))
}
if (e.getClick().equals(ClickType.NUMBER_KEY)) {
numberkey = true;
}
if (e.getSlotType() != SlotType.ARMOR && e.getSlotType() != SlotType.QUICKBAR &&
e.getSlotType() != SlotType.CONTAINER)
e.getSlotType() != SlotType.CONTAINER) {
return;
if (e.getClickedInventory() != null && !e.getClickedInventory().getType().equals(InventoryType.PLAYER))
}
if (e.getClickedInventory() != null && !e.getClickedInventory().getType().equals(InventoryType.PLAYER)) {
return;
}
if (!e.getInventory().getType().equals(InventoryType.CRAFTING) &&
!e.getInventory().getType().equals(InventoryType.PLAYER))
!e.getInventory().getType().equals(InventoryType.PLAYER)) {
return;
if (!(e.getWhoClicked() instanceof Player))
}
if (!(e.getWhoClicked() instanceof Player)) {
return;
}
ArmorType newArmorType = ArmorType.matchType(shift ? e.getCurrentItem() : e.getCursor());
if (!shift && newArmorType != null && e.getRawSlot() != newArmorType.getSlot())
// Used for drag and drop checking to make sure you aren't trying to place a
// helmet in the boots slot.
return;
if (shift)
// Used for drag and drop checking to make sure you aren't trying to place a
// helmet in the boots slot.
{
return;
}
if (shift) {
newArmorType = ArmorType.matchType(e.getCurrentItem());
if (newArmorType != null)
{
boolean equipping = true;
if (e.getRawSlot() == newArmorType.getSlot())
equipping = false;
if (newArmorType != null) {
boolean equipping = e.getRawSlot() != newArmorType.getSlot();
if (newArmorType.equals(ArmorType.HELMET) &&
(equipping ? isAirOrNull(e.getWhoClicked().getInventory().getHelmet()) :
!isAirOrNull(e.getWhoClicked().getInventory().getHelmet())) ||
newArmorType.equals(ArmorType.CHESTPLATE) && (equipping ?
isAirOrNull(e.getWhoClicked().getInventory()
.getChestplate()) :
!isAirOrNull(e.getWhoClicked().getInventory()
.getChestplate())) ||
newArmorType.equals(ArmorType.LEGGINGS) && (equipping ?
isAirOrNull(
e.getWhoClicked().getInventory().getLeggings()) :
!isAirOrNull(
e.getWhoClicked().getInventory().getLeggings())) ||
newArmorType.equals(ArmorType.BOOTS) && (equipping ?
isAirOrNull(e.getWhoClicked().getInventory().getBoots()) :
!isAirOrNull(e.getWhoClicked().getInventory().getBoots())))
{
(equipping == isAirOrNull(e.getWhoClicked().getInventory().getHelmet())) ||
newArmorType.equals(ArmorType.CHESTPLATE) && (equipping == isAirOrNull(e.getWhoClicked().getInventory()
.getChestplate())) ||
newArmorType.equals(ArmorType.LEGGINGS) && (equipping == isAirOrNull(
e.getWhoClicked().getInventory().getLeggings())) ||
newArmorType.equals(ArmorType.BOOTS) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getBoots()))) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(),
EquipMethod.SHIFT_CLICK, newArmorType,
equipping ? null : e.getCurrentItem(),
equipping ? e.getCurrentItem() : null);
EquipMethod.SHIFT_CLICK, newArmorType,
equipping ? null : e.getCurrentItem(),
equipping ? e.getCurrentItem() : null);
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled())
if (armorEquipEvent.isCancelled()) {
e.setCancelled(true);
}
}
}
}
else
{
} else {
ItemStack newArmorPiece = e.getCursor();
ItemStack oldArmorPiece = e.getCurrentItem();
if (numberkey)
if (e.getClickedInventory().getType().equals(InventoryType.PLAYER))
{
if (numberkey) {
if (e.getClickedInventory().getType().equals(InventoryType.PLAYER)) {
// Prevents shit in the 2by2 crafting
// e.getClickedInventory() == The players inventory
// e.getHotBarButton() == key people are pressing to equip or unequip the item
@ -112,72 +104,70 @@ public class ArmorListener implements Listener
// e.getSlot() == Armor slot, can't use e.getRawSlot() as that gives a hotbar
// slot ;-;
ItemStack hotbarItem = e.getClickedInventory().getItem(e.getHotbarButton());
if (!isAirOrNull(hotbarItem))
{
if (!isAirOrNull(hotbarItem)) {
// Equipping
newArmorType = ArmorType.matchType(hotbarItem);
newArmorPiece = hotbarItem;
oldArmorPiece = e.getClickedInventory().getItem(e.getSlot());
}
else
// Unequipping
} else
// Unequipping
{
newArmorType = ArmorType
.matchType(!isAirOrNull(e.getCurrentItem()) ? e.getCurrentItem() : e.getCursor());
}
else
{
.matchType(!isAirOrNull(e.getCurrentItem()) ? e.getCurrentItem() : e.getCursor());
}
} else {
if (isAirOrNull(e.getCursor()) && !isAirOrNull(e.getCurrentItem()))
// unequip with no new item going into the slot.
// unequip with no new item going into the slot.
{
newArmorType = ArmorType.matchType(e.getCurrentItem());
}
}
if (newArmorType != null && e.getRawSlot() == newArmorType.getSlot())
{
}
if (newArmorType != null && e.getRawSlot() == newArmorType.getSlot()) {
EquipMethod method = EquipMethod.PICK_DROP;
if (e.getAction().equals(InventoryAction.HOTBAR_SWAP) || numberkey)
if (e.getAction().equals(InventoryAction.HOTBAR_SWAP) || numberkey) {
method = EquipMethod.HOTBAR_SWAP;
}
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), method, newArmorType,
oldArmorPiece, newArmorPiece);
oldArmorPiece, newArmorPiece);
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled())
if (armorEquipEvent.isCancelled()) {
e.setCancelled(true);
}
}
}
}
@EventHandler
public void playerInteractEvent(PlayerInteractEvent e)
{
if (e.getAction() == Action.PHYSICAL)
public void playerInteractEvent(PlayerInteractEvent e) {
if (e.getAction() == Action.PHYSICAL) {
return;
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)
{
}
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
final Player player = e.getPlayer();
if (e.getClickedBlock() != null && e.getAction() == Action.RIGHT_CLICK_BLOCK)
{
if (e.getClickedBlock() != null && e.getAction() == Action.RIGHT_CLICK_BLOCK) {
// Having both of these checks is useless, might as well do it though.
// Some blocks have actions when you right click them which stops the client
// from equipping the armor in hand.
Material mat = e.getClickedBlock().getType();
for (String s : blockedMaterials)
if (mat.name().equalsIgnoreCase(s))
if (mat.name().equalsIgnoreCase(s)) {
return;
}
}
ArmorType newArmorType = ArmorType.matchType(e.getItem());
if (newArmorType != null)
{
if (newArmorType != null) {
if (newArmorType.equals(ArmorType.HELMET) && isAirOrNull(e.getPlayer().getInventory().getHelmet()) ||
newArmorType
.equals(ArmorType.CHESTPLATE) && isAirOrNull(e.getPlayer().getInventory().getChestplate()) ||
newArmorType
.equals(ArmorType.LEGGINGS) && isAirOrNull(e.getPlayer().getInventory().getLeggings()) ||
newArmorType.equals(ArmorType.BOOTS) && isAirOrNull(e.getPlayer().getInventory().getBoots()))
{
newArmorType
.equals(ArmorType.CHESTPLATE) && isAirOrNull(e.getPlayer().getInventory().getChestplate()) ||
newArmorType
.equals(ArmorType.LEGGINGS) && isAirOrNull(e.getPlayer().getInventory().getLeggings()) ||
newArmorType.equals(ArmorType.BOOTS) && isAirOrNull(e.getPlayer().getInventory().getBoots())) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(e.getPlayer(), EquipMethod.HOTBAR,
ArmorType.matchType(e.getItem()), null,
e.getItem());
ArmorType.matchType(e.getItem()), null,
e.getItem());
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled())
{
if (armorEquipEvent.isCancelled()) {
e.setCancelled(true);
player.updateInventory();
}
@ -187,23 +177,22 @@ public class ArmorListener implements Listener
}
@EventHandler
public void inventoryDrag(InventoryDragEvent event)
{
public void inventoryDrag(InventoryDragEvent event) {
// getType() seems to always be even.
// Old Cursor gives the item you are equipping
// Raw slot is the ArmorType slot
// Can't replace armor using this method making getCursor() useless.
ArmorType type = ArmorType.matchType(event.getOldCursor());
if (event.getRawSlots().isEmpty())
// Idk if this will ever happen
return;
if (type != null && type.getSlot() == event.getRawSlots().stream().findFirst().orElse(0))
// Idk if this will ever happen
{
return;
}
if (type != null && type.getSlot() == event.getRawSlots().stream().findFirst().orElse(0)) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) event.getWhoClicked(), EquipMethod.DRAG,
type, null, event.getOldCursor());
type, null, event.getOldCursor());
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled())
{
if (armorEquipEvent.isCancelled()) {
event.setResult(Result.DENY);
event.setCancelled(true);
}
@ -211,41 +200,37 @@ public class ArmorListener implements Listener
}
@EventHandler
public void itemBreakEvent(PlayerItemBreakEvent e)
{
public void itemBreakEvent(PlayerItemBreakEvent e) {
ArmorType type = ArmorType.matchType(e.getBrokenItem());
if (type != null)
{
if (type != null) {
Player p = e.getPlayer();
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, EquipMethod.BROKE, type, e.getBrokenItem(), null);
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled())
{
if (armorEquipEvent.isCancelled()) {
ItemStack i = e.getBrokenItem().clone();
i.setAmount(1);
i.setDurability((short) (i.getDurability() - 1));
if (type.equals(ArmorType.HELMET))
if (type.equals(ArmorType.HELMET)) {
p.getInventory().setHelmet(i);
else if (type.equals(ArmorType.CHESTPLATE))
} else if (type.equals(ArmorType.CHESTPLATE)) {
p.getInventory().setChestplate(i);
else if (type.equals(ArmorType.LEGGINGS))
} else if (type.equals(ArmorType.LEGGINGS)) {
p.getInventory().setLeggings(i);
else if (type.equals(ArmorType.BOOTS))
} else if (type.equals(ArmorType.BOOTS)) {
p.getInventory().setBoots(i);
}
}
}
}
@EventHandler
public void playerDeathEvent(PlayerDeathEvent e)
{
public void playerDeathEvent(PlayerDeathEvent e) {
Player p = e.getEntity();
for (ItemStack oldArmor : p.getInventory().getArmorContents())
if (!isAirOrNull(oldArmor))
{
if (!isAirOrNull(oldArmor)) {
ArmorType type = ArmorType.matchType(oldArmor);
Bukkit.getServer().getPluginManager().callEvent(new ArmorEquipEvent(p, EquipMethod.DEATH,
type, oldArmor, null));
type, oldArmor, null));
// No way to cancel a death event.
}
}
@ -253,8 +238,7 @@ public class ArmorListener implements Listener
/**
* A utility method to support versions that use null or air ItemStacks.
*/
private boolean isAirOrNull(ItemStack item)
{
private boolean isAirOrNull(ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
}

View File

@ -7,8 +7,7 @@ import org.bukkit.inventory.ItemStack;
* @author Arnah
* @since Jul 30, 2015
*/
public enum ArmorType
{
public enum ArmorType {
HELMET(5),
CHESTPLATE(6),
LEGGINGS(7),
@ -16,8 +15,7 @@ public enum ArmorType
private final int slot;
ArmorType(int slot)
{
ArmorType(int slot) {
this.slot = slot;
}
@ -27,27 +25,28 @@ public enum ArmorType
* @param itemStack The ItemStack to parse the type of.
* @return The parsed ArmorType. (null if none were found.)
*/
public static final ArmorType matchType(final ItemStack itemStack)
{
if (itemStack == null || itemStack.getType().equals(Material.AIR))
public static ArmorType matchType(final ItemStack itemStack) {
if (itemStack == null || itemStack.getType().equals(Material.AIR)) {
return null;
if (itemStack.getType().equals(Material.ELYTRA))
}
if (itemStack.getType().equals(Material.ELYTRA)) {
return CHESTPLATE;
}
String type = itemStack.getType().name();
if (type.endsWith("_HELMET") || type.endsWith("_SKULL"))
if (type.endsWith("_HELMET") || type.endsWith("_SKULL")) {
return HELMET;
else if (type.endsWith("_CHESTPLATE"))
} else if (type.endsWith("_CHESTPLATE")) {
return CHESTPLATE;
else if (type.endsWith("_LEGGINGS"))
} else if (type.endsWith("_LEGGINGS")) {
return LEGGINGS;
else if (type.endsWith("_BOOTS"))
} else if (type.endsWith("_BOOTS")) {
return BOOTS;
else
} else {
return null;
}
}
public int getSlot()
{
public int getSlot() {
return slot;
}
}

View File

@ -10,21 +10,19 @@ import org.bukkit.event.block.BlockDispenseArmorEvent;
* @author Arnah
* @since Feb 08, 2019
*/
public class DispenserArmorListener implements Listener
{
public class DispenserArmorListener implements Listener {
@EventHandler
public void dispenseArmorEvent(BlockDispenseArmorEvent event)
{
public void dispenseArmorEvent(BlockDispenseArmorEvent event) {
ArmorType type = ArmorType.matchType(event.getItem());
if (type != null)
if (event.getTargetEntity() instanceof Player)
{
Player p = (Player) event.getTargetEntity();
if (type != null) {
if (event.getTargetEntity() instanceof Player p) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, ArmorEquipEvent.EquipMethod.DISPENSER, type,
null, event.getItem());
null, event.getItem());
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled())
if (armorEquipEvent.isCancelled()) {
event.setCancelled(true);
}
}
}
}
}

View File

@ -14,17 +14,15 @@ import org.bukkit.inventory.meta.LeatherArmorMeta;
import javax.annotation.Nullable;
import java.util.List;
@SuppressWarnings({"unused", "UnusedReturnValue", "ClassCanBeRecord"})
public class ArmoredElytraBuilder
{
@SuppressWarnings({"unused", "UnusedReturnValue"})
public class ArmoredElytraBuilder {
private final NBTEditor nbtEditor;
private final DurabilityManager durabilityManager;
private final ConfigLoader config;
private final ArmoredElytra plugin;
public ArmoredElytraBuilder(NBTEditor nbtEditor, DurabilityManager durabilityManager,
ConfigLoader config, ArmoredElytra plugin)
{
ConfigLoader config, ArmoredElytra plugin) {
this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager;
@ -37,8 +35,7 @@ public class ArmoredElytraBuilder
*
* @return The first step of the new builder.
*/
public IStep0 newBuilder()
{
public IStep0 newBuilder() {
return new Builder(nbtEditor, durabilityManager, config, plugin);
}
@ -52,8 +49,7 @@ public class ArmoredElytraBuilder
* ArmoredElytra#getArmoredElytraName(ArmorTier)} is used to set the name.
* @return The new armored elytra.
*/
public @Nullable ItemStack repair(ItemStack armoredElytra, ItemStack repairItems, @Nullable String name)
{
public @Nullable ItemStack repair(ItemStack armoredElytra, ItemStack repairItems, @Nullable String name) {
return newBuilder().ofElytra(armoredElytra).repair(repairItems.getAmount()).withName(name).build();
}
@ -66,11 +62,11 @@ public class ArmoredElytraBuilder
* ArmoredElytra#getArmoredElytraName(ArmorTier)} is used to set the name.
* @return The new armored elytra.
*/
public @Nullable ItemStack enchant(ItemStack armoredElytra, ItemStack sourceItem, @Nullable String name)
{
public @Nullable ItemStack enchant(ItemStack armoredElytra, ItemStack sourceItem, @Nullable String name) {
final EnchantmentContainer enchantments = EnchantmentContainer.getEnchantmentsOf(sourceItem, plugin);
if (enchantments.isEmpty())
if (enchantments.isEmpty()) {
return null;
}
return newBuilder().ofElytra(armoredElytra).addEnchantments(enchantments).withName(name).build();
}
@ -86,16 +82,14 @@ public class ArmoredElytraBuilder
* ArmoredElytra#getArmoredElytraName(ArmorTier)} is used to set the name.
* @return The new armored elytra.
*/
public ItemStack combine(ItemStack elytra, ItemStack combiner, ArmorTier armorTier, @Nullable String name)
{
public ItemStack combine(ItemStack elytra, ItemStack combiner, ArmorTier armorTier, @Nullable String name) {
return newBuilder().ofElytra(elytra).combineWith(combiner, armorTier).withName(name).build();
}
/**
* See {@link #combine(ItemStack, ItemStack, ArmorTier, String)} for unknown armor tiers.
*/
public ItemStack combine(ItemStack elytra, ItemStack combiner, @Nullable String name)
{
public ItemStack combine(ItemStack elytra, ItemStack combiner, @Nullable String name) {
return newBuilder().ofElytra(elytra).combineWith(combiner).withName(name).build();
}
@ -105,16 +99,14 @@ public class ArmoredElytraBuilder
* @param armorTier The tier of the new armored elytra.
* @return The new armored elytra.
*/
public ItemStack newArmoredElytra(ArmorTier armorTier)
{
public ItemStack newArmoredElytra(ArmorTier armorTier) {
return newBuilder().newItem(armorTier).build();
}
/**
* Represents the third and last step of the armored elytra build process.
*/
public interface IStep2
{
public interface IStep2 {
/**
* Specifies the new name of the armored elytra.
*
@ -163,8 +155,7 @@ public class ArmoredElytraBuilder
/**
* Represents the second and last step of the armored elytra build process.
*/
public interface IStep1
{
public interface IStep1 {
/**
* Repairs the armored elytra provided as input.
*
@ -219,8 +210,7 @@ public class ArmoredElytraBuilder
/**
* Represents the first and last step of the armored elytra build process.
*/
public interface IStep0
{
public interface IStep0 {
/**
* Use an elytra as base item to create the new armored elytra from.
*
@ -239,8 +229,7 @@ public class ArmoredElytraBuilder
IStep2 newItem(ArmorTier armorTier);
}
private static final class Builder implements IStep0, IStep1, IStep2
{
private static final class Builder implements IStep0, IStep1, IStep2 {
private static final Color DEFAULT_LEATHER_COLOR = Bukkit.getServer().getItemFactory().getDefaultLeatherColor();
private final NBTEditor nbtEditor;
@ -293,8 +282,7 @@ public class ArmoredElytraBuilder
private @Nullable Boolean isUnbreakable = null;
private Builder(NBTEditor nbtEditor, DurabilityManager durabilityManager,
ConfigLoader config, ArmoredElytra plugin)
{
ConfigLoader config, ArmoredElytra plugin) {
this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager;
this.config = config;
@ -302,8 +290,7 @@ public class ArmoredElytraBuilder
}
@Override
public ItemStack build()
{
public ItemStack build() {
// Get default values if unset.
newArmorTier = newArmorTier == null ? currentArmorTier : newArmorTier;
name = name == null ? plugin.getArmoredElytraName(newArmorTier) : name;
@ -312,7 +299,7 @@ public class ArmoredElytraBuilder
isUnbreakable = isUnbreakable == null ? config.unbreakable() : isUnbreakable;
final ItemStack output = nbtEditor.addArmorNBTTags(newArmoredElytra, newArmorTier,
isUnbreakable, name, lore, color);
isUnbreakable, name, lore, color);
durabilityManager.setDurability(output, durability, newArmorTier);
combinedEnchantments.applyEnchantments(output);
@ -320,100 +307,94 @@ public class ArmoredElytraBuilder
}
@Override
public IStep2 withName(@Nullable String name)
{
public IStep2 withName(@Nullable String name) {
this.name = name;
return this;
}
@Override
public IStep2 withColor(@Nullable Color color)
{
public IStep2 withColor(@Nullable Color color) {
this.color = color;
return this;
}
@Override
public IStep2 withLore(@Nullable List<String> lore)
{
public IStep2 withLore(@Nullable List<String> lore) {
this.lore = lore;
return this;
}
@Override
public IStep2 unbreakable(boolean isUnbreakable)
{
public IStep2 unbreakable(boolean isUnbreakable) {
this.isUnbreakable = isUnbreakable;
return this;
}
@Override
public IStep2 repair(int count)
{
if (currentArmorTier == ArmorTier.NONE)
public IStep2 repair(int count) {
if (currentArmorTier == ArmorTier.NONE) {
throw new IllegalArgumentException("Non-armored elytras cannot be repaired!");
}
durability = durabilityManager.getRepairedDurability(newArmoredElytra, count, currentArmorTier);
return this;
}
@Override
public IStep2 addEnchantments(EnchantmentContainer enchantmentContainer)
{
public IStep2 addEnchantments(EnchantmentContainer enchantmentContainer) {
combinedEnchantments.merge(enchantmentContainer);
return this;
}
@Override
public IStep2 addEnchantments(ItemStack sourceItem)
{
public IStep2 addEnchantments(ItemStack sourceItem) {
return addEnchantments(EnchantmentContainer.getEnchantmentsOf(sourceItem, plugin));
}
@Override
public IStep2 combineWith(ItemStack item, ArmorTier armorTier)
{
if (armorTier == ArmorTier.NONE && !Util.isChestPlate(item))
public IStep2 combineWith(ItemStack item, ArmorTier armorTier) {
if (armorTier == ArmorTier.NONE && !Util.isChestPlate(item)) {
throw new IllegalArgumentException("Non-armored elytras can only be combined with chest plates!");
}
newArmorTier = armorTier;
if (currentArmorTier == ArmorTier.NONE &&
item.getType().equals(Material.ELYTRA) && newArmorTier != ArmorTier.NONE)
item.getType().equals(Material.ELYTRA) && newArmorTier != ArmorTier.NONE) {
throw new IllegalArgumentException("A regular elytra cannot be combined with an armored one!");
}
withColor(getItemColor(newArmoredElytra, item));
addEnchantments(item);
durability = durabilityManager.getCombinedDurability(newArmoredElytra, item,
currentArmorTier, newArmorTier);
currentArmorTier, newArmorTier);
return this;
}
@Override
public IStep2 combineWith(ItemStack item)
{
public IStep2 combineWith(ItemStack item) {
final ArmorTier armorTier = item.getType().equals(Material.ELYTRA) ?
nbtEditor.getArmorTier(item) : Util.armorToTier(item.getType());
nbtEditor.getArmorTier(item) : Util.armorToTier(item.getType());
return combineWith(item, armorTier);
}
@Override
public IStep2 upgradeToTier(ArmorTier armorTier)
{
public IStep2 upgradeToTier(ArmorTier armorTier) {
newArmorTier = armorTier;
return this;
}
@Override
public IStep1 ofElytra(ItemStack elytra)
{
if (!elytra.getType().equals(Material.ELYTRA))
public IStep1 ofElytra(ItemStack elytra) {
if (!elytra.getType().equals(Material.ELYTRA)) {
throw new IllegalArgumentException("Expected elytra as input, but got: " + elytra);
}
newArmoredElytra = new ItemStack(elytra);
if (currentArmorTier == null)
if (currentArmorTier == null) {
currentArmorTier = nbtEditor.getArmorTier(elytra);
}
combinedEnchantments = EnchantmentContainer.getEnchantmentsOf(newArmoredElytra, plugin);
@ -422,8 +403,7 @@ public class ArmoredElytraBuilder
}
@Override
public IStep2 newItem(ArmorTier armorTier)
{
public IStep2 newItem(ArmorTier armorTier) {
currentArmorTier = newArmorTier = armorTier;
ofElytra(new ItemStack(Material.ELYTRA));
return this;
@ -438,11 +418,11 @@ public class ArmoredElytraBuilder
* @param itemB The second {@link ItemStack} to check.
* @return The color of the item, if it has a color, otherwise null.
*/
private @Nullable Color getItemColor(final ItemStack itemA, final ItemStack itemB)
{
private @Nullable Color getItemColor(final ItemStack itemA, final ItemStack itemB) {
final @Nullable Color colorA = getItemColor(itemA);
if (colorA != null && !colorA.equals(DEFAULT_LEATHER_COLOR))
if (colorA != null && !colorA.equals(DEFAULT_LEATHER_COLOR)) {
return colorA;
}
final @Nullable Color colorB = getItemColor(itemB);
return colorB != null ? colorB : colorA;
@ -456,13 +436,14 @@ public class ArmoredElytraBuilder
* @param itemStack The item to analyze.
* @return The color of the item, if available, otherwise null.
*/
private @Nullable Color getItemColor(final ItemStack itemStack)
{
if (itemStack.getType() == Material.ELYTRA)
private @Nullable Color getItemColor(final ItemStack itemStack) {
if (itemStack.getType() == Material.ELYTRA) {
return nbtEditor.getColorOfArmoredElytra(itemStack);
}
if (!itemStack.hasItemMeta() || !(itemStack.getItemMeta() instanceof LeatherArmorMeta))
if (!itemStack.hasItemMeta() || !(itemStack.getItemMeta() instanceof LeatherArmorMeta)) {
return null;
}
return ((LeatherArmorMeta) itemStack.getItemMeta()).getColor();
}

View File

@ -8,8 +8,7 @@ import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable;
public class DurabilityManager
{
public class DurabilityManager {
private static final int ELYTRA_MAX_DURABILITY = Material.ELYTRA.getMaxDurability();
private final int[] repairAmounts = new int[ArmorTier.values().length];
@ -18,8 +17,7 @@ public class DurabilityManager
private final NBTEditor nbtEditor;
private final ConfigLoader config;
public DurabilityManager(NBTEditor nbtEditor, ConfigLoader config)
{
public DurabilityManager(NBTEditor nbtEditor, ConfigLoader config) {
this.nbtEditor = nbtEditor;
this.config = config;
init();
@ -40,10 +38,10 @@ public class DurabilityManager
* @param targetTier The target tier of the armored elytra.
*/
public int setCombinedDurability(ItemStack armoredElytraOut, ItemStack armoredElytraIn, ItemStack other,
ArmorTier currentTier, ArmorTier targetTier)
{
if (nbtEditor.isUnbreakable(armoredElytraIn))
ArmorTier currentTier, ArmorTier targetTier) {
if (nbtEditor.isUnbreakable(armoredElytraIn)) {
return 0;
}
final int combinedDurability = getCombinedDurability(armoredElytraIn, other, currentTier, targetTier);
setDurability(armoredElytraOut, combinedDurability, targetTier);
@ -61,24 +59,24 @@ public class DurabilityManager
* @return The new real durability value of the armored elytra if it were to be combined with the other item.
*/
public int getCombinedDurability(ItemStack armoredElytra, ItemStack other,
ArmorTier currentTier, ArmorTier targetTier)
{
if (nbtEditor.isUnbreakable(armoredElytra))
ArmorTier currentTier, ArmorTier targetTier) {
if (nbtEditor.isUnbreakable(armoredElytra)) {
return 0;
}
final ArmorTier otherTier = nbtEditor.getArmorTier(other);
final int currentMaxDurability = getMaxDurability(currentTier);
final int targetMaxDurability = getMaxDurability(targetTier);
final int otherMaxDurability = otherTier != ArmorTier.NONE ?
getMaxDurability(otherTier) : other.getType().getMaxDurability();
getMaxDurability(otherTier) : other.getType().getMaxDurability();
final int otherDurability = other.getType().equals(Material.ELYTRA) ?
getRealDurability(other, null) : getItemDurability(other);
getRealDurability(other, null) : getItemDurability(other);
final int currentDurability = getRealDurability(armoredElytra, currentTier);
final int combinedDurability = targetMaxDurability -
(otherMaxDurability - otherDurability) -
(currentMaxDurability - currentDurability);
(otherMaxDurability - otherDurability) -
(currentMaxDurability - currentDurability);
return Util.between(combinedDurability, 0, targetMaxDurability);
}
@ -92,10 +90,10 @@ public class DurabilityManager
* retrieved from the item itself.
* @return The new durability after removing the provided amount.
*/
public int removeDurability(ItemStack armoredElytra, int durabilityLoss, @Nullable ArmorTier providedTier)
{
if (nbtEditor.isUnbreakable(armoredElytra))
public int removeDurability(ItemStack armoredElytra, int durabilityLoss, @Nullable ArmorTier providedTier) {
if (nbtEditor.isUnbreakable(armoredElytra)) {
return 0;
}
final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(armoredElytra) : providedTier;
final int currentDurability = getRealDurability(armoredElytra, currentTier);
@ -115,10 +113,10 @@ public class DurabilityManager
* from the item itself.
* @return The required number of repair items required to fully repair the armored elytra.
*/
public int getFullRepairItemCount(ItemStack armoredElytra, @Nullable ArmorTier providedTier)
{
if (nbtEditor.isUnbreakable(armoredElytra))
public int getFullRepairItemCount(ItemStack armoredElytra, @Nullable ArmorTier providedTier) {
if (nbtEditor.isUnbreakable(armoredElytra)) {
return 0;
}
final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(armoredElytra) : providedTier;
final int repairableDurability = getMaxDurability(currentTier) - getRealDurability(armoredElytra, currentTier);
@ -135,10 +133,10 @@ public class DurabilityManager
* from the item itself.
* @return The real durability value of the armored elytra if it were to be repaired.
*/
public int getRepairedDurability(ItemStack armoredElytra, int repairCount, @Nullable ArmorTier providedTier)
{
if (nbtEditor.isUnbreakable(armoredElytra))
public int getRepairedDurability(ItemStack armoredElytra, int repairCount, @Nullable ArmorTier providedTier) {
if (nbtEditor.isUnbreakable(armoredElytra)) {
return 0;
}
final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(armoredElytra) : providedTier;
final int restoredDurability = repairCount * getRepairAmount(currentTier);
@ -156,15 +154,16 @@ public class DurabilityManager
* from the item itself.
* @return The real durability of the item.
*/
public int getRealDurability(ItemStack item, @Nullable ArmorTier providedTier)
{
public int getRealDurability(ItemStack item, @Nullable ArmorTier providedTier) {
final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(item) : providedTier;
if (currentTier == ArmorTier.NONE)
if (currentTier == ArmorTier.NONE) {
return getItemDurability(item);
}
if (nbtEditor.isUnbreakable(item))
if (nbtEditor.isUnbreakable(item)) {
return 0;
}
final int realDurability = nbtEditor.getRealDurability(item, currentTier);
return realDurability == -1 ? upgradeArmoredElytraToDurability(item, currentTier) : realDurability;
@ -178,10 +177,10 @@ public class DurabilityManager
* @param providedTier The tier of the armored elytra (if this is available). If this is null, it will be retrieved
* from the item itself.
*/
public void setDurability(ItemStack item, int durability, @Nullable ArmorTier providedTier)
{
if (nbtEditor.isUnbreakable(item))
public void setDurability(ItemStack item, int durability, @Nullable ArmorTier providedTier) {
if (nbtEditor.isUnbreakable(item)) {
return;
}
final ArmorTier currentTier = providedTier == null ? nbtEditor.getArmorTier(item) : providedTier;
final int oldMaxDurability = getMaxDurability(currentTier);
@ -199,14 +198,13 @@ public class DurabilityManager
* @param currentTier The current tier of the armored elytra.
* @return The real durability of the armored elytra.
*/
private int upgradeArmoredElytraToDurability(ItemStack armoredElytra, ArmorTier currentTier)
{
private int upgradeArmoredElytraToDurability(ItemStack armoredElytra, ArmorTier currentTier) {
final int maxDurability = getMaxDurability(currentTier);
final int rawDurability = getItemDurability(armoredElytra);
final int realDurability = maxDurability == ELYTRA_MAX_DURABILITY ?
rawDurability :
getRemappedDurability(rawDurability, ELYTRA_MAX_DURABILITY, maxDurability);
rawDurability :
getRemappedDurability(rawDurability, ELYTRA_MAX_DURABILITY, maxDurability);
nbtEditor.updateDurability(armoredElytra, realDurability, rawDurability);
return realDurability;
@ -219,10 +217,10 @@ public class DurabilityManager
* @param armorTier The armor tier for which to figure out the maximum durability.
* @return The maximum durability of the armor tier.
*/
private int calculateMaxDurability(ArmorTier armorTier)
{
if (armorTier == ArmorTier.NONE || !config.useTierDurability())
private int calculateMaxDurability(ArmorTier armorTier) {
if (armorTier == ArmorTier.NONE || !config.useTierDurability()) {
return ELYTRA_MAX_DURABILITY;
}
return ArmorTier.getMaxDurability(armorTier);
}
@ -233,8 +231,7 @@ public class DurabilityManager
* @param armorTier The armor tier for which to check.
* @return True if the provided durability should be considered 'broken' for the provided armor tier.
*/
public boolean isBroken(int durability, ArmorTier armorTier)
{
public boolean isBroken(int durability, ArmorTier armorTier) {
return durability >= getMaxDurability(armorTier);
}
@ -245,11 +242,11 @@ public class DurabilityManager
* @param armorTier The armor tier for which to check.
* @return True if the provided armored elytra should be considered 'broken'.
*/
public boolean isBroken(ItemStack armoredElytra, @Nullable ArmorTier armorTier)
{
public boolean isBroken(ItemStack armoredElytra, @Nullable ArmorTier armorTier) {
final int realDurability = getRealDurability(armoredElytra, armorTier);
if (realDurability == 0)
if (realDurability == 0) {
return false;
}
return isBroken(realDurability, armorTier == null ? nbtEditor.getArmorTier(armoredElytra) : armorTier);
}
@ -259,8 +256,7 @@ public class DurabilityManager
* @param armorTier The armor tier for which to get the maximum durability.
* @return The maximum durability of the given armor tier.
*/
private int getMaxDurability(ArmorTier armorTier)
{
private int getMaxDurability(ArmorTier armorTier) {
return maxDurabilities[armorTier.ordinal()];
}
@ -270,8 +266,7 @@ public class DurabilityManager
* @param armorTier The armor tier.
* @return The amount of durability restored per repair step for the given armor tier.
*/
private int getRepairAmount(ArmorTier armorTier)
{
private int getRepairAmount(ArmorTier armorTier) {
return repairAmounts[armorTier.ordinal()];
}
@ -285,8 +280,7 @@ public class DurabilityManager
* @return The new durability value after remapping it to the new maximum. The value cannot be less than 0 or more
* than newMax.
*/
private int getRemappedDurability(int durability, int oldMax, int newMax)
{
private int getRemappedDurability(int durability, int oldMax, int newMax) {
final float relativeDurability = (float) durability / oldMax;
return Util.between((int) Math.ceil(relativeDurability * newMax), 0, newMax);
}
@ -294,14 +288,12 @@ public class DurabilityManager
/**
* Initializes the {@link #maxDurabilities} and {@link #repairAmounts} arrays.
*/
private void init()
{
private void init() {
repairAmounts[0] = 0;
maxDurabilities[0] = ELYTRA_MAX_DURABILITY;
final ArmorTier[] armorTiers = ArmorTier.values();
for (int idx = 1; idx < armorTiers.length; ++idx)
{
for (int idx = 1; idx < armorTiers.length; ++idx) {
final ArmorTier armorTier = armorTiers[idx];
final int maxDurability = calculateMaxDurability(armorTier);
@ -319,8 +311,7 @@ public class DurabilityManager
* @return The durability of the item.
*/
@SuppressWarnings("deprecation")
private int getItemDurability(ItemStack item)
{
private int getItemDurability(ItemStack item) {
return item.getDurability();
}
}

View File

@ -21,14 +21,13 @@ import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class NBTEditor
{
public class NBTEditor {
private static final NamespacedKey ARMOR_TIER_KEY = new NamespacedKey(ArmoredElytra.getInstance(),
"ARMOR_TIER_LEVEL");
"ARMOR_TIER_LEVEL");
private static final NamespacedKey ARMOR_COLOR_KEY = new NamespacedKey(ArmoredElytra.getInstance(),
"ARMORED_ELYTRA_COLOR");
"ARMORED_ELYTRA_COLOR");
private static final NamespacedKey DURABILITY_KEY = new NamespacedKey(ArmoredElytra.getInstance(),
"ARMORED_ELYTRA_DURABILITY");
"ARMORED_ELYTRA_DURABILITY");
/**
* Gets the real durability value as stored in the NBT of an armored elytra.
@ -37,20 +36,21 @@ public class NBTEditor
* @param providedTier The armor tier of the armored elytra. If this is null, it will be retrieved from NBT.
* @return The real durability of the itemstack if the itemstack has the AE durability attribute, or -1 otherwise.
*/
public int getRealDurability(ItemStack itemStack, @Nullable ArmorTier providedTier)
{
public int getRealDurability(ItemStack itemStack, @Nullable ArmorTier providedTier) {
final @Nullable ItemMeta meta = itemStack.getItemMeta();
final ArmorTier armorTier = providedTier == null ? getArmorTier(meta) : providedTier;
if (armorTier == ArmorTier.NONE)
if (armorTier == ArmorTier.NONE) {
return -1;
}
if (!(meta instanceof Damageable))
if (!(meta instanceof Damageable)) {
throw new IllegalStateException("Item \"" + itemStack + "\" with meta \"" + meta + "\" is not Damageable!");
}
final @Nullable Integer realDurability =
Objects.requireNonNull(meta, "Meta cannot be null for armored elytras!")
.getPersistentDataContainer().get(DURABILITY_KEY, PersistentDataType.INTEGER);
Objects.requireNonNull(meta, "Meta cannot be null for armored elytras!")
.getPersistentDataContainer().get(DURABILITY_KEY, PersistentDataType.INTEGER);
return realDurability == null ? -1 : realDurability;
}
@ -63,13 +63,13 @@ public class NBTEditor
* @param displayDurability The durability value to display on the item. This is the durability value the client can
* actually see.This only works if the item's meta is an instance of {@link Damageable}.
*/
public void updateDurability(ItemStack itemStack, int realDurability, int displayDurability)
{
public void updateDurability(ItemStack itemStack, int realDurability, int displayDurability) {
final ItemMeta meta = getOrCreateItemMeta(itemStack);
meta.getPersistentDataContainer().set(DURABILITY_KEY, PersistentDataType.INTEGER, realDurability);
if (meta instanceof Damageable)
if (meta instanceof Damageable) {
((Damageable) meta).setDamage(displayDurability);
}
itemStack.setItemMeta(meta);
}
@ -87,67 +87,73 @@ public class NBTEditor
* @return The NEW item.
*/
public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, String name,
@Nullable List<String> lore, @Nullable Color color)
{
if (armorTier == null || armorTier == ArmorTier.NONE)
@Nullable List<String> lore, @Nullable Color color) {
if (armorTier == null || armorTier == ArmorTier.NONE) {
return new ItemStack(item);
}
final ItemStack ret = new ItemStack(item);
final ItemMeta meta = getOrCreateItemMeta(ret);
meta.getPersistentDataContainer().set(ARMOR_TIER_KEY, PersistentDataType.INTEGER,
ArmorTier.getTierID(armorTier));
ArmorTier.getTierID(armorTier));
if (color != null && armorTier == ArmorTier.LEATHER)
if (color != null && armorTier == ArmorTier.LEATHER) {
meta.getPersistentDataContainer().set(ARMOR_COLOR_KEY, PersistentDataType.INTEGER, color.asRGB());
}
overwriteNBTValue(meta, Attribute.GENERIC_ARMOR, ArmorTier.getArmor(armorTier), "generic.armor");
if (ArmorTier.getToughness(armorTier) > 0)
if (ArmorTier.getToughness(armorTier) > 0) {
overwriteNBTValue(meta, Attribute.GENERIC_ARMOR_TOUGHNESS, ArmorTier.getToughness(armorTier),
"generic.armor_toughness");
"generic.armor_toughness");
}
if (ArmorTier.getKnockbackResistance(armorTier) > 0)
if (ArmorTier.getKnockbackResistance(armorTier) > 0) {
overwriteNBTValue(meta, Attribute.GENERIC_KNOCKBACK_RESISTANCE, ArmorTier.getKnockbackResistance(armorTier),
"generic.knockback_resistance");
"generic.knockback_resistance");
}
meta.setUnbreakable(unbreakable);
meta.setDisplayName(name);
if (lore != null)
if (lore != null) {
meta.setLore(lore);
}
ret.setItemMeta(meta);
return ret;
}
void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName)
{
if (meta.hasAttributeModifiers())
void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName) {
if (meta.hasAttributeModifiers()) {
meta.removeAttributeModifier(attribute);
}
final AttributeModifier attributeModifier = new AttributeModifier(UUID.randomUUID(), modifierName, value,
AttributeModifier.Operation.ADD_NUMBER,
EquipmentSlot.CHEST);
AttributeModifier.Operation.ADD_NUMBER,
EquipmentSlot.CHEST);
meta.addAttributeModifier(attribute, attributeModifier);
}
ArmorTier getArmorTier(@Nullable ItemMeta meta)
{
if (meta == null || !meta.hasAttributeModifiers())
ArmorTier getArmorTier(@Nullable ItemMeta meta) {
if (meta == null || !meta.hasAttributeModifiers()) {
return ArmorTier.NONE;
}
final @Nullable Integer tierID = meta.getPersistentDataContainer()
.get(ARMOR_TIER_KEY, PersistentDataType.INTEGER);
if (tierID != null)
.get(ARMOR_TIER_KEY, PersistentDataType.INTEGER);
if (tierID != null) {
return ArmorTier.getArmorTierFromID(tierID);
}
final Collection<AttributeModifier> attributeModifiers = meta.getAttributeModifiers(Attribute.GENERIC_ARMOR);
if (attributeModifiers == null)
if (attributeModifiers == null) {
return ArmorTier.NONE;
}
for (final AttributeModifier attributeModifier : attributeModifiers)
{
for (final AttributeModifier attributeModifier : attributeModifiers) {
final ArmorTier armorTier = ArmorTier.getArmorTierFromArmor((int) attributeModifier.getAmount());
if (armorTier != ArmorTier.NONE)
if (armorTier != ArmorTier.NONE) {
return armorTier;
}
}
return ArmorTier.NONE;
@ -159,10 +165,10 @@ public class NBTEditor
* @param item The item to check.
* @return The {@link ArmorTier} that is on the item. If none is found, {@link ArmorTier#NONE} is returned.
*/
public ArmorTier getArmorTier(@Nullable ItemStack item)
{
if (item == null)
public ArmorTier getArmorTier(@Nullable ItemStack item) {
if (item == null) {
return ArmorTier.NONE;
}
return getArmorTier(item.getItemMeta());
}
@ -172,8 +178,7 @@ public class NBTEditor
* @param item The item to check. This may or may not be an armored elytra.
* @return True if the item exists and is unbreakable. Otherwise, false.
*/
public boolean isUnbreakable(@Nullable ItemStack item)
{
public boolean isUnbreakable(@Nullable ItemStack item) {
final @Nullable ItemMeta meta = item == null ? null : item.getItemMeta();
return meta != null && meta.isUnbreakable();
}
@ -186,30 +191,32 @@ public class NBTEditor
* @param item The armored elytra to check.
* @return The color of the armored elytra, if the input is a colored armored elytra, otherwise null.
*/
public Color getColorOfArmoredElytra(@Nullable ItemStack item)
{
if (item == null || item.getType() != Material.ELYTRA || !item.hasItemMeta())
public Color getColorOfArmoredElytra(@Nullable ItemStack item) {
if (item == null || item.getType() != Material.ELYTRA || !item.hasItemMeta()) {
return null;
}
final ItemMeta meta = item.getItemMeta();
if (meta == null)
if (meta == null) {
return null;
}
final PersistentDataContainer container = meta.getPersistentDataContainer();
if (!container.has(ARMOR_COLOR_KEY, PersistentDataType.INTEGER))
if (!container.has(ARMOR_COLOR_KEY, PersistentDataType.INTEGER)) {
return null;
}
final Integer rgb = container.get(ARMOR_COLOR_KEY, PersistentDataType.INTEGER);
return rgb == null ? null : Color.fromRGB(rgb);
}
static ItemMeta getOrCreateItemMeta(ItemStack item)
{
static ItemMeta getOrCreateItemMeta(ItemStack item) {
final ItemMeta meta = item.hasItemMeta() ?
item.getItemMeta() :
Bukkit.getItemFactory().getItemMeta(item.getType());
if (meta == null)
item.getItemMeta() :
Bukkit.getItemFactory().getItemMeta(item.getType());
if (meta == null) {
throw new IllegalArgumentException("Tried to add armor to invalid item: " + item);
}
return meta;
}
}

View File

@ -1,7 +1,6 @@
package nl.pim16aap2.armoredElytra.util;
public enum Action
{
public enum Action {
/**
* Take no action at all and let vanilla (or some other plugin) handle the process.
*/

View File

@ -1,6 +1,5 @@
package nl.pim16aap2.armoredElytra.util;
public enum AllowedToWearEnum
{
public enum AllowedToWearEnum {
BROKEN, NOPERMISSION, ALLOWED
}

View File

@ -5,8 +5,7 @@ import org.bukkit.Material;
import java.util.HashMap;
import java.util.Map;
public enum ArmorTier
{
public enum ArmorTier {
// Tier: TierID, armor-value, armor-toughness, knockbackResistance, repair, defaultRepairCount, name, durability
NONE(0, 0, 0, 0, null, 0, "", 0),
LEATHER(1, 3, 0, 0, Material.LEATHER, 6, "leather", 80),
@ -30,8 +29,7 @@ public enum ArmorTier
private static final Map<Integer, ArmorTier> armorIDMap = new HashMap<>();
ArmorTier(int tierID, int armor, int toughness, double knockbackResistance, Material repair,
int defaultRepairCount, String name, int durability)
{
int defaultRepairCount, String name, int durability) {
this.tierID = tierID;
this.armor = armor;
this.toughness = toughness;
@ -42,64 +40,52 @@ public enum ArmorTier
this.durability = durability;
}
public static int getArmor(ArmorTier tier)
{
public static int getArmor(ArmorTier tier) {
return tier.armor;
}
public static int getMaxDurability(ArmorTier tier)
{
public static int getMaxDurability(ArmorTier tier) {
return tier.durability;
}
public static int getTierID(ArmorTier tier)
{
public static int getTierID(ArmorTier tier) {
return tier.tierID;
}
public static int getToughness(ArmorTier tier)
{
public static int getToughness(ArmorTier tier) {
return tier.toughness;
}
// return the armor toughness of a tier.
public static double getKnockbackResistance(ArmorTier tier)
{
public static double getKnockbackResistance(ArmorTier tier) {
return tier.knockbackResistance;
}
// return the repair item of a tier
public static Material getRepairItem(ArmorTier tier)
{
public static Material getRepairItem(ArmorTier tier) {
return tier.repair;
}
public static String getName(ArmorTier tier)
{
public static String getName(ArmorTier tier) {
return tier.name;
}
public static ArmorTier valueOfName(String name)
{
public static ArmorTier valueOfName(String name) {
return map.get(name);
}
public static ArmorTier getArmorTierFromArmor(int armor)
{
public static ArmorTier getArmorTierFromArmor(int armor) {
ArmorTier tier = armorValueMap.get(armor);
return tier == null ? ArmorTier.NONE : tier;
}
public static ArmorTier getArmorTierFromID(int tierID)
{
public static ArmorTier getArmorTierFromID(int tierID) {
ArmorTier tier = armorIDMap.get(tierID);
return tier == null ? ArmorTier.NONE : tier;
}
static
{
for (ArmorTier tier : ArmorTier.values())
{
static {
for (ArmorTier tier : ArmorTier.values()) {
map.put(tier.name, tier);
armorValueMap.put(tier.armor, tier);
armorIDMap.put(tier.tierID, tier);
@ -113,8 +99,7 @@ public enum ArmorTier
armorValueMap.put(ArmorTier.DIAMOND.armor, ArmorTier.DIAMOND);
}
public static int getDefaultRepairCount(ArmorTier armorTier)
{
public static int getDefaultRepairCount(ArmorTier armorTier) {
return armorTier.defaultRepairCount;
}
}

View File

@ -3,33 +3,27 @@ package nl.pim16aap2.armoredElytra.util;
/**
* @author Pim
*/
public class ArmorTierName
{
public class ArmorTierName {
private String longName, shortName;
public ArmorTierName(final String longName, final String shortName)
{
public ArmorTierName(final String longName, final String shortName) {
this.longName = longName;
this.shortName = shortName;
}
public String getLongName()
{
public String getLongName() {
return longName;
}
public String getShortName()
{
public String getShortName() {
return shortName;
}
public void setLongName(final String longName)
{
public void setLongName(final String longName) {
this.longName = longName;
}
public void setShortName(final String shortName)
{
public void setShortName(final String shortName) {
this.shortName = shortName;
}
}

View File

@ -18,10 +18,9 @@ import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
public class ConfigLoader
{
public class ConfigLoader {
private static final String HEADER =
"Config file for ArmoredElytra. Don't forget to make a backup before making changes!";
"Config file for ArmoredElytra. Don't forget to make a backup before making changes!";
private final ArmoredElytra plugin;
@ -46,137 +45,135 @@ public class ConfigLoader
private boolean allowRenaming;
private boolean allowAddingEnchantments;
public ConfigLoader(ArmoredElytra plugin)
{
public ConfigLoader(ArmoredElytra plugin) {
this.plugin = plugin;
makeConfig();
}
// Read the current config, the make a new one based on the old one or default values, whichever is applicable.
private void makeConfig()
{
private void makeConfig() {
// All the comments for the various config options.
String[] unbreakableComment =
{
"Setting this to true will cause armored elytras to be unbreakable.",
"Changing this to false will NOT make unbreakable elytras breakable again!"
};
{
"Setting this to true will cause armored elytras to be unbreakable.",
"Changing this to false will NOT make unbreakable elytras breakable again!"
};
String[] flyDurabilityComment =
{
"Setting this to true will cause armored elytras to not lose any durability while flying.",
"This is not a permanent option and will affect ALL elytras."
};
{
"Setting this to true will cause armored elytras to not lose any durability while flying.",
"This is not a permanent option and will affect ALL elytras."
};
String[] useTierDurabilityComment =
{
"Use the maximum durability of the armor tier of armored elytras.",
"For example, when this is true, a diamond armored elytra would have a durability of 528.",
"When this is false, all armored elytras have the maximum durability of a regular elytra."
};
{
"Use the maximum durability of the armor tier of armored elytras.",
"For example, when this is true, a diamond armored elytra would have a durability of 528.",
"When this is false, all armored elytras have the maximum durability of a regular elytra."
};
String[] repairComment =
{
"Amount of items it takes to fully repair an armored elytra",
"Repair cost for every tier of armored elytra in number of items to repair 100%.",
"Note that this value cannot be less than 1."
};
{
"Amount of items it takes to fully repair an armored elytra",
"Repair cost for every tier of armored elytra in number of items to repair 100%.",
"Note that this value cannot be less than 1."
};
String[] enchantmentsComment =
{
"List of enchantments that are allowed to be put on an armored elytra.",
"If you do not want to allow any enchantments at all, remove them all and add \"NONE\"",
"You can find supported enchantments by running the command:",
"\"armoredelytra listAvailableEnchantments\" in console",
"If you install additional enchantment plugins, you can add their enchantments as well.",
"Just add their 'NamespacedKey'. Ask the enchantment plugin dev for more info if you need it."
};
{
"List of enchantments that are allowed to be put on an armored elytra.",
"If you do not want to allow any enchantments at all, remove them all and add \"NONE\"",
"You can find supported enchantments by running the command:",
"\"armoredelytra listAvailableEnchantments\" in console",
"If you install additional enchantment plugins, you can add their enchantments as well.",
"Just add their 'NamespacedKey'. Ask the enchantment plugin dev for more info if you need it."
};
String[] mutuallyExclusiveEnchantmentsComment =
{
"The lists of enchantments that are mutually exclusive.",
"Each group [] on this list is treated as mutually exclusive, " +
"so only one of them can be on an ArmoredElytra.",
"The default follows modern vanilla rules by making the different " +
"types of protection mutually exclusive.",
"If you do not want any enchantments to be mutually exclusive, " +
"replace all the entries in this list with \"[]\"",
"You can find supported enchantments by running the command:",
"\"armoredelytra listAvailableEnchantments\" in console",
"If you install additional enchant plugins, " +
"you can make their enchantments mutually exclusive as well.",
"Just add their 'NamespacedKey'. Ask the enchantment plugin dev for more info if you need it."
};
{
"The lists of enchantments that are mutually exclusive.",
"Each group [] on this list is treated as mutually exclusive, " +
"so only one of them can be on an ArmoredElytra.",
"The default follows modern vanilla rules by making the different " +
"types of protection mutually exclusive.",
"If you do not want any enchantments to be mutually exclusive, " +
"replace all the entries in this list with \"[]\"",
"You can find supported enchantments by running the command:",
"\"armoredelytra listAvailableEnchantments\" in console",
"If you install additional enchant plugins, " +
"you can make their enchantments mutually exclusive as well.",
"Just add their 'NamespacedKey'. Ask the enchantment plugin dev for more info if you need it."
};
String[] dropNetheriteAsChestplateComment =
{
"Whether to drop Netherite Armored Elytras as netherite chestplates when they are dropped",
"This means that they won't burn in lava etc.",
"When you pick them up, they will turn into Netherite Armored Elytras again."
};
{
"Whether to drop Netherite Armored Elytras as netherite chestplates when they are dropped",
"This means that they won't burn in lava etc.",
"When you pick them up, they will turn into Netherite Armored Elytras again."
};
String[] updateComment =
{
"Allow this plugin to check for updates on startup. It will not download new versions on its own!"
};
{
"Allow this plugin to check for updates on startup. It will not download new versions on its own!"
};
String[] bStatsComment =
{
"Allow this plugin to send (anonymous) stats using bStats. Please consider keeping it enabled.",
"It has a negligible impact on performance and more users on stats keeps me more motivated " +
"to support this plugin!"
};
{
"Allow this plugin to send (anonymous) stats using bStats. Please consider keeping it enabled.",
"It has a negligible impact on performance and more users on stats keeps me more motivated " +
"to support this plugin!"
};
String[] debugComment =
{
"Print debug messages to console. You will most likely never need this."
};
{
"Print debug messages to console. You will most likely never need this."
};
String[] uninstallComment =
{
"Setting this to true will disable this plugin and remove any armored elytras it can find.",
"It will check player's inventories and their end chest upon login and any regular" +
" chest when it is opened.",
"This means it will take a while for all armored elytras to be removed from your server, " +
"but it doesn't take up ",
"a lot of resources, so you can just leave the plugin enabled and ignore it.",
"Please do not forget to MAKE A BACKUP before enabling this option!"
};
{
"Setting this to true will disable this plugin and remove any armored elytras it can find.",
"It will check player's inventories and their end chest upon login and any regular" +
" chest when it is opened.",
"This means it will take a while for all armored elytras to be removed from your server, " +
"but it doesn't take up ",
"a lot of resources, so you can just leave the plugin enabled and ignore it.",
"Please do not forget to MAKE A BACKUP before enabling this option!"
};
String[] languageFileComment =
{
"Specify a language file to be used."
};
{
"Specify a language file to be used."
};
String[] permissionsComment =
{
"Globally bypass permissions for wearing and/or crafting armored elytras.",
"Useful if permissions are unavailable."
};
{
"Globally bypass permissions for wearing and/or crafting armored elytras.",
"Useful if permissions are unavailable."
};
String[] craftingInSmithingTableComment =
{
"When enabled, armored elytra creation in anvils is disabled. ",
"Instead, you will have to craft them in a smithy. Enchanting/repairing them still works via the anvil."
};
{
"When enabled, armored elytra creation in anvils is disabled. ",
"Instead, you will have to craft them in a smithy. Enchanting/repairing them still works via the anvil."
};
String[] allowUpgradeToNetheriteComment =
{
"Whether or not to allow upgrading diamond armored elytras to netherite ones is possible.",
"When allowed, you can combine a diamond one with a netherite ingot in a smithing table",
"and you'll receive a netherite one."
};
{
"Whether or not to allow upgrading diamond armored elytras to netherite ones is possible.",
"When allowed, you can combine a diamond one with a netherite ingot in a smithing table",
"and you'll receive a netherite one."
};
String[] allowRenamingComment =
{
"Whether or not to allow renaming of armored elytras in anvils."
};
{
"Whether or not to allow renaming of armored elytras in anvils."
};
String[] allowAddingEnchantmentsComment =
{
"Allow new enchantments to be added to armored elytras.",
"When false, no enchantments can be added to armored elytras, even those on the allowed list.",
"When true, only enchantments from the allowed list can be added."
};
{
"Allow new enchantments to be added to armored elytras.",
"When false, no enchantments can be added to armored elytras, even those on the allowed list.",
"When true, only enchantments from the allowed list can be added."
};
// Set default list of allowed enchantments.
List<String> defaultAllowedEnchantments = new ArrayList<>(
Arrays.asList("minecraft:unbreaking", "minecraft:fire_protection", "minecraft:blast_protection",
"minecraft:projectile_protection", "minecraft:protection",
"minecraft:thorns", "minecraft:binding_curse", "minecraft:vanishing_curse",
"minecraft:mending"));
Arrays.asList("minecraft:unbreaking", "minecraft:fire_protection", "minecraft:blast_protection",
"minecraft:projectile_protection", "minecraft:protection",
"minecraft:thorns", "minecraft:binding_curse", "minecraft:vanishing_curse",
"minecraft:mending"));
// Set a default list of lists of mutually exclusive enchantments
// Default only has a list for the protection enchantments
List<List<String>> defaultMutuallyExclusiveEnchantments = new ArrayList<>();
defaultMutuallyExclusiveEnchantments.add(List.of("minecraft:protection",
"minecraft:projectile_protection",
"minecraft:blast_protection",
"minecraft:fire_protection"));
"minecraft:projectile_protection",
"minecraft:blast_protection",
"minecraft:fire_protection"));
FileConfiguration config = plugin.getConfig();
@ -186,8 +183,7 @@ public class ConfigLoader
useTierDurability = addNewConfigOption(config, "useTierDurability", true, useTierDurabilityComment);
final ArmorTier[] armorTiers = ArmorTier.values();
for (int idx = 1; idx < armorTiers.length; ++idx)
{
for (int idx = 1; idx < armorTiers.length; ++idx) {
final ArmorTier armorTier = armorTiers[idx];
// Only the first one should have the comment.
@ -199,31 +195,32 @@ public class ConfigLoader
}
final int armorTierCount = ArmorTier.values().length;
if (repairCounts.length != armorTierCount)
if (repairCounts.length != armorTierCount) {
throw new IllegalStateException("Incorrect repair counts array size! Expected size " +
armorTierCount + " but got size " + repairCounts.length);
armorTierCount + " but got size " + repairCounts.length);
}
craftingInSmithingTable = addNewConfigOption(config, "craftingInSmithingTable", true,
craftingInSmithingTableComment);
craftingInSmithingTableComment);
allowUpgradeToNetherite = addNewConfigOption(config, "allowUpgradeToNetherite", true,
allowUpgradeToNetheriteComment);
allowUpgradeToNetheriteComment);
defaultAllowedEnchantments = addNewConfigOption(config, "allowedEnchantments", defaultAllowedEnchantments,
enchantmentsComment);
enchantmentsComment);
allowedEnchantments = new LinkedHashSet<>();
defaultAllowedEnchantments.forEach(this::addNameSpacedKey);
defaultMutuallyExclusiveEnchantments =
addNewConfigOption(config, "mutuallyExclusiveEnchantments",
defaultMutuallyExclusiveEnchantments, mutuallyExclusiveEnchantmentsComment);
addNewConfigOption(config, "mutuallyExclusiveEnchantments",
defaultMutuallyExclusiveEnchantments, mutuallyExclusiveEnchantmentsComment);
mutuallyExclusiveEnchantments = new LinkedList<>();
defaultMutuallyExclusiveEnchantments.forEach(this::addMutuallyExclusiveEnchantments);
allowAddingEnchantments = addNewConfigOption(config, "allowAddingEnchantments", true,
allowAddingEnchantmentsComment);
allowAddingEnchantmentsComment);
allowRenaming = addNewConfigOption(config, "allowRenaming", true, allowRenamingComment);
dropNetheriteAsChestplate = addNewConfigOption(config, "dropNetheriteAsChestplate", true,
dropNetheriteAsChestplateComment);
dropNetheriteAsChestplateComment);
checkForUpdates = addNewConfigOption(config, "checkForUpdates", true, updateComment);
allowStats = addNewConfigOption(config, "allowStats", true, bStatsComment);
@ -236,178 +233,149 @@ public class ConfigLoader
writeConfig();
}
private @Nullable Enchantment enchantmentFromNameSpacedKey(String fullKey)
{
try
{
private @Nullable Enchantment enchantmentFromNameSpacedKey(String fullKey) {
try {
final String[] keyParts = fullKey.strip().split(":", 2);
if (keyParts.length < 2)
{
if (keyParts.length < 2) {
Bukkit.getLogger().warning("\"" + fullKey + "\" is not a valid NamespacedKey!");
return null;
}
//noinspection deprecation
final NamespacedKey key = new NamespacedKey(keyParts[0], keyParts[1]);
final Enchantment enchantment = Enchantment.getByKey(key);
if (enchantment == null)
{
if (enchantment == null) {
Bukkit.getLogger().warning("The enchantment \"" + fullKey + "\" could not be found!");
return null;
}
return enchantment;
}
catch (Exception e)
{
} catch (Exception e) {
plugin.getLogger().log(Level.WARNING, e, () -> "Failed to register NamespacedKey key: '" + fullKey + "'");
}
return null;
}
private void addNameSpacedKey(String fullKey)
{
private void addNameSpacedKey(String fullKey) {
final @Nullable Enchantment enchantment = enchantmentFromNameSpacedKey(fullKey);
if (enchantment != null)
if (enchantment != null) {
allowedEnchantments.add(enchantment);
}
}
private void addMutuallyExclusiveEnchantments(List<String> fullKeys)
{
private void addMutuallyExclusiveEnchantments(List<String> fullKeys) {
final List<Enchantment> enchantments = new LinkedList<>();
for (String fullKey : fullKeys)
{
for (String fullKey : fullKeys) {
final @Nullable Enchantment enchantment = enchantmentFromNameSpacedKey(fullKey);
if (enchantment != null)
if (enchantment != null) {
enchantments.add(enchantment);
}
}
mutuallyExclusiveEnchantments.add(enchantments);
}
private <T> T addNewConfigOption(FileConfiguration config, String optionName, T defaultValue, String[] comment)
{
private <T> T addNewConfigOption(FileConfiguration config, String optionName, T defaultValue, String[] comment) {
ConfigOption<T> option = new ConfigOption<>(plugin, config, optionName, defaultValue, comment);
configOptionsList.add(option);
return option.getValue();
}
// Write new config file.
private void writeConfig()
{
private void writeConfig() {
// Write all the config options to the config.yml.
try
{
try {
final Path dataDir = plugin.getDataFolder().toPath();
if (!Files.exists(dataDir))
if (!Files.exists(dataDir)) {
Files.createDirectory(dataDir);
}
final Path configFile = dataDir.resolve("config.yml");
final StringBuilder sb = new StringBuilder(6000);
sb.append("# ").append(HEADER).append('\n');
for (final ConfigOption<?> configOption : configOptionsList)
{
if (configOption.hasComment())
for (final ConfigOption<?> configOption : configOptionsList) {
if (configOption.hasComment()) {
sb.append('\n');
}
sb.append(configOption).append('\n');
}
Files.write(configFile, sb.toString().getBytes(),
StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
}
catch (IOException e)
{
StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
} catch (IOException e) {
Bukkit.getLogger().log(Level.SEVERE, "Could not save config.yml! " +
"Please contact pim16aap2 and show him the following code:");
"Please contact pim16aap2 and show him the following code:");
e.printStackTrace();
}
}
public boolean allowStats()
{
public boolean allowStats() {
return allowStats;
}
public boolean craftingInSmithingTable()
{
public boolean craftingInSmithingTable() {
return craftingInSmithingTable;
}
public boolean allowUpgradeToNetherite()
{
public boolean allowUpgradeToNetherite() {
return allowUpgradeToNetherite;
}
public boolean unbreakable()
{
public boolean unbreakable() {
return unbreakable;
}
public boolean enableDebug()
{
public boolean enableDebug() {
return enableDebug;
}
public String languageFile()
{
public String languageFile() {
return languageFile;
}
public int getFullRepairItemCount(ArmorTier armorTier)
{
public int getFullRepairItemCount(ArmorTier armorTier) {
return repairCounts[armorTier.ordinal()];
}
public boolean allowRenaming()
{
public boolean allowRenaming() {
return allowRenaming;
}
public boolean allowAddingEnchantments()
{
public boolean allowAddingEnchantments() {
return allowAddingEnchantments;
}
public boolean uninstallMode()
{
public boolean uninstallMode() {
return uninstallMode;
}
public boolean checkForUpdates()
{
public boolean checkForUpdates() {
return checkForUpdates;
}
public boolean noFlightDurability()
{
public boolean noFlightDurability() {
return noFlightDurability;
}
public boolean dropNetheriteAsChestplate()
{
public boolean dropNetheriteAsChestplate() {
return dropNetheriteAsChestplate;
}
public LinkedHashSet<Enchantment> allowedEnchantments()
{
public LinkedHashSet<Enchantment> allowedEnchantments() {
return allowedEnchantments;
}
public List<List<Enchantment>> getMutuallyExclusiveEnchantments()
{
public List<List<Enchantment>> getMutuallyExclusiveEnchantments() {
return mutuallyExclusiveEnchantments;
}
public boolean bypassWearPerm()
{
public boolean bypassWearPerm() {
return bypassWearPerm;
}
public boolean bypassCraftPerm()
{
public boolean bypassCraftPerm() {
return bypassCraftPerm;
}
public boolean useTierDurability()
{
public boolean useTierDurability() {
return useTierDurability;
}
}

View File

@ -12,8 +12,7 @@ import java.util.List;
* For Lists, every option appears on a new line after a '-'.
*/
public class ConfigOption<V>
{
public class ConfigOption<V> {
private final ArmoredElytra plugin;
private final FileConfiguration config;
private final String optionName;
@ -22,8 +21,7 @@ public class ConfigOption<V>
private final String[] comment;
public ConfigOption(ArmoredElytra plugin, FileConfiguration config, String optionName, V defaultValue,
String[] comment)
{
String[] comment) {
this.plugin = plugin;
this.config = config;
this.optionName = optionName;
@ -33,63 +31,55 @@ public class ConfigOption<V>
}
@SuppressWarnings("unchecked")
private void setValue()
{
try
{
private void setValue() {
try {
value = (V) config.get(optionName, defaultValue);
}
catch (Exception e)
{
} catch (Exception e) {
plugin.myLogger(java.util.logging.Level.WARNING, "Failed to read config value of: \"" + optionName +
"\"! Using default value instead!");
"\"! Using default value instead!");
plugin.myLogger(java.util.logging.Level.WARNING, Util.exceptionToString(e));
value = defaultValue;
}
}
public V getValue()
{
public V getValue() {
return value;
}
public @Nullable String[] getComment()
{
public @Nullable String[] getComment() {
return comment;
}
public boolean hasComment()
{
public boolean hasComment() {
return comment != null;
}
@Override
public String toString()
{
String string = "";
public String toString() {
StringBuilder string = new StringBuilder();
// Print the comments, if there are any.
if (comment != null)
if (comment != null) {
for (String comLine : comment)
// Prefix every line by a comment-sign (#).
string += "# " + comLine + "\n";
string.append("# ").append(comLine).append("\n");
}
string += optionName + ": ";
if (value.getClass().isAssignableFrom(String.class))
string += "\'" + value.toString() + "\'";
else if (value instanceof List<?>)
{
string.append(optionName).append(": ");
if (value.getClass().isAssignableFrom(String.class)) {
string.append("\'").append(value).append("\'");
} else if (value instanceof List<?>) {
StringBuilder builder = new StringBuilder();
builder.append("\n");
int listSize = ((List<?>) value).size();
for (int index = 0; index < listSize; ++index)
// Don't print newline at the end
builder.append(" - " + ((List<?>) value).get(index) + (index == listSize - 1 ? "" : "\n"));
string += builder.toString();
builder.append(" - ").append(((List<?>) value).get(index)).append(index == listSize - 1 ? "" : "\n");
string.append(builder);
} else {
string.append(value);
}
else
string += value.toString();
return string;
return string.toString();
}
}

View File

@ -14,8 +14,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Integer>>
{
public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Integer>> {
private Map<Enchantment, Integer> enchantments;
/**
@ -25,8 +24,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
* @param plugin The {@link ArmoredElytra} instance to use for obtaining the list of allowed enchantments. See
* {@link ConfigLoader#allowedEnchantments()}.
*/
public EnchantmentContainer(final Map<Enchantment, Integer> enchantments, final ArmoredElytra plugin)
{
public EnchantmentContainer(final Map<Enchantment, Integer> enchantments, final ArmoredElytra plugin) {
this(enchantments);
filter(plugin.getConfigLoader().allowedEnchantments());
filterMutuallyExclusive();
@ -35,18 +33,15 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
/**
* Copy constructor.
*/
public EnchantmentContainer(EnchantmentContainer other)
{
public EnchantmentContainer(EnchantmentContainer other) {
this(other.enchantments);
}
public EnchantmentContainer()
{
public EnchantmentContainer() {
enchantments = new HashMap<>();
}
private EnchantmentContainer(final Map<Enchantment, Integer> enchantments)
{
private EnchantmentContainer(final Map<Enchantment, Integer> enchantments) {
this.enchantments = new HashMap<>(enchantments);
}
@ -57,14 +52,14 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
* @param plugin The {@link ArmoredElytra} instance to use.
* @return A new {@link EnchantmentContainer} with the enchantments from the item.
*/
public static EnchantmentContainer getEnchantmentsOf(final ItemStack is, final ArmoredElytra plugin)
{
if (is == null)
public static EnchantmentContainer getEnchantmentsOf(final ItemStack is, final ArmoredElytra plugin) {
if (is == null) {
return new EnchantmentContainer(Collections.emptyMap(), plugin);
}
return is.getType() == Material.ENCHANTED_BOOK ?
getEnchantmentsFromBook(is, plugin) :
getEnchantmentsFromItem(is, plugin);
getEnchantmentsFromBook(is, plugin) :
getEnchantmentsFromItem(is, plugin);
}
/**
@ -74,8 +69,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
* @param plugin The {@link ArmoredElytra} instance to use.
* @return A new {@link EnchantmentContainer} with the enchantments from the item.
*/
private static EnchantmentContainer getEnchantmentsFromItem(final ItemStack is, final ArmoredElytra plugin)
{
private static EnchantmentContainer getEnchantmentsFromItem(final ItemStack is, final ArmoredElytra plugin) {
return new EnchantmentContainer(is.getEnchantments(), plugin);
}
@ -86,14 +80,15 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
* @param plugin The {@link ArmoredElytra} instance to use.
* @return A new enchantment container with the enchantments from the book.
*/
private static EnchantmentContainer getEnchantmentsFromBook(final ItemStack is, final ArmoredElytra plugin)
{
if (!is.hasItemMeta())
private static EnchantmentContainer getEnchantmentsFromBook(final ItemStack is, final ArmoredElytra plugin) {
if (!is.hasItemMeta()) {
return new EnchantmentContainer(new HashMap<>(0), plugin);
}
final EnchantmentStorageMeta meta = (EnchantmentStorageMeta) is.getItemMeta();
if (meta == null || !meta.hasStoredEnchants())
if (meta == null || !meta.hasStoredEnchants()) {
return new EnchantmentContainer(new HashMap<>(0), plugin);
}
return new EnchantmentContainer(meta.getStoredEnchants(), plugin);
}
@ -105,18 +100,14 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
* @param enchantment The enchantment to get the mutually exclusives of
* @return A linked list containing all the mutually exclusive enchantments
*/
private static List<Enchantment> getMutuallyExclusiveEnchantments(Enchantment enchantment)
{
private static List<Enchantment> getMutuallyExclusiveEnchantments(Enchantment enchantment) {
final List<Enchantment> enchantments = new LinkedList<>();
for (final List<Enchantment> mutuallyExclusiveEnchantments :
ArmoredElytra.getInstance().getConfigLoader().getMutuallyExclusiveEnchantments())
{
for (Enchantment mutuallyExclusiveEnchantment : mutuallyExclusiveEnchantments)
{
if (mutuallyExclusiveEnchantment.equals(enchantment))
{
ArmoredElytra.getInstance().getConfigLoader().getMutuallyExclusiveEnchantments()) {
for (Enchantment mutuallyExclusiveEnchantment : mutuallyExclusiveEnchantments) {
if (mutuallyExclusiveEnchantment.equals(enchantment)) {
enchantments.addAll(
mutuallyExclusiveEnchantments.stream().filter(i -> !i.equals(enchantment)).toList());
mutuallyExclusiveEnchantments.stream().filter(i -> !i.equals(enchantment)).toList());
break;
}
}
@ -129,8 +120,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
*
* @return The total number of enchantments in this container.
*/
public int getEnchantmentCount()
{
public int getEnchantmentCount() {
return enchantments.size();
}
@ -139,22 +129,22 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
*
* @param allowed The names of enchantments (upper case) that are allowed. Any names not in this list are removed.
*/
public void filter(final Collection<Enchantment> allowed)
{
if (!enchantments.isEmpty())
public void filter(final Collection<Enchantment> allowed) {
if (!enchantments.isEmpty()) {
enchantments.keySet().retainAll(allowed);
}
}
/**
* Remove any entries from the list of enchantments that are mutually exclusive to each other.
* <br>First instance of a mutually exclusive enchantment gets priority
*/
private void filterMutuallyExclusive()
{
private void filterMutuallyExclusive() {
final List<Enchantment> disallowedEnchantments = new LinkedList<>();
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet())
{
if (disallowedEnchantments.contains(entry.getKey())) continue;
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
if (disallowedEnchantments.contains(entry.getKey())) {
continue;
}
disallowedEnchantments.addAll(getMutuallyExclusiveEnchantments(entry.getKey()));
}
disallowedEnchantments.forEach(enchantments.keySet()::remove);
@ -165,8 +155,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
*
* @param is The itemstack to apply the enchantments to.
*/
public void applyEnchantments(final ItemStack is)
{
public void applyEnchantments(final ItemStack is) {
// Clear enchantments before applying new ones
for (Enchantment enchantment : is.getEnchantments().keySet())
is.removeEnchantment(enchantment);
@ -177,18 +166,17 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
/**
* Merges this container with another one.
*/
public void merge(EnchantmentContainer other)
{
if (this == other)
public void merge(EnchantmentContainer other) {
if (this == other) {
throw new IllegalArgumentException("EnchantmentContainers cannot be combined with themselves!");
}
enchantments = merge(enchantments, other.enchantments);
}
/**
* Gets the number of enchantments in this container.
*/
public int size()
{
public int size() {
return enchantments.size();
}
@ -197,8 +185,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
*
* @return True if there are exactly 0 enchantments in this container.
*/
public boolean isEmpty()
{
public boolean isEmpty() {
return enchantments.isEmpty();
}
@ -209,8 +196,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
* @param second The second enchantment container. In case of conflicts, this will take precedence.
* @return The new map of enchantments.
*/
public static EnchantmentContainer merge(final EnchantmentContainer first, final EnchantmentContainer second)
{
public static EnchantmentContainer merge(final EnchantmentContainer first, final EnchantmentContainer second) {
return new EnchantmentContainer(merge(first.enchantments, second.enchantments));
}
@ -222,46 +208,46 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
* @return The new map of enchantments.
*/
private static Map<Enchantment, Integer> merge(final Map<Enchantment, Integer> first,
final Map<Enchantment, Integer> second)
{
if (second == null || second.isEmpty())
final Map<Enchantment, Integer> second) {
if (second == null || second.isEmpty()) {
return first;
}
if (first == null || first.isEmpty())
if (first == null || first.isEmpty()) {
return second;
}
final List<Enchantment> blackList =
second.keySet().stream()
.flatMap(ench -> getMutuallyExclusiveEnchantments(ench).stream())
.toList();
second.keySet().stream()
.flatMap(ench -> getMutuallyExclusiveEnchantments(ench).stream())
.toList();
blackList.forEach(first.keySet()::remove);
final Map<Enchantment, Integer> combined = new HashMap<>(first);
for (Map.Entry<Enchantment, Integer> entry : second.entrySet())
{
for (Map.Entry<Enchantment, Integer> entry : second.entrySet()) {
// Check for enchants with higher level
Integer enchantLevel = combined.get(entry.getKey());
if (enchantLevel != null)
{
if (enchantLevel != null) {
final int oldLevel = enchantLevel;
if (entry.getValue().equals(enchantLevel) && entry.getValue() < entry.getKey().getMaxLevel())
if (entry.getValue().equals(enchantLevel) && entry.getValue() < entry.getKey().getMaxLevel()) {
enchantLevel = entry.getValue() + 1;
else if (entry.getValue() > enchantLevel)
} else if (entry.getValue() > enchantLevel) {
enchantLevel = entry.getValue();
}
if (enchantLevel != oldLevel)
if (enchantLevel != oldLevel) {
combined.put(entry.getKey(), enchantLevel);
}
else
}
} else {
combined.put(entry.getKey(), entry.getValue());
}
}
return combined;
}
@Override
public String toString()
{
public String toString() {
StringBuilder sb = new StringBuilder("[");
enchantments.forEach((k, v) -> sb.append("\"").append(k).append("\" (").append(v).append("), "));
String ret = sb.toString();
@ -270,8 +256,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
}
@Override
public Iterator<Map.Entry<Enchantment, Integer>> iterator()
{
public Iterator<Map.Entry<Enchantment, Integer>> iterator() {
return enchantments.entrySet().iterator();
}
}

View File

@ -1,7 +1,6 @@
package nl.pim16aap2.armoredElytra.util;
public enum MinecraftVersion
{
public enum MinecraftVersion {
v1_6,
v1_7,
v1_8,
@ -27,8 +26,7 @@ public enum MinecraftVersion
private final String versionName;
MinecraftVersion()
{
MinecraftVersion() {
versionName = name().substring(1);
}
@ -38,8 +36,7 @@ public enum MinecraftVersion
* @param other The other version to check against.
* @return True if this version is newer than the other version.
*/
public boolean isNewerThan(final MinecraftVersion other)
{
public boolean isNewerThan(final MinecraftVersion other) {
return ordinal() > other.ordinal();
}
@ -49,18 +46,18 @@ public enum MinecraftVersion
* @param other The other version to check against.
* @return True if this version is older than the other version.
*/
public boolean isOlderThan(final MinecraftVersion other)
{
public boolean isOlderThan(final MinecraftVersion other) {
return ordinal() < other.ordinal();
}
public static MinecraftVersion get(final String versionName)
{
if (versionName == null)
public static MinecraftVersion get(final String versionName) {
if (versionName == null) {
return null;
}
for (final MinecraftVersion mcVersion : MinecraftVersion.values())
if (versionName.contains(mcVersion.versionName))
if (versionName.contains(mcVersion.versionName)) {
return mcVersion;
}
return MinecraftVersion.UNKNOWN;
}
}

View File

@ -34,22 +34,22 @@ import java.util.regex.Pattern;
*
* @author Parker Hawke - 2008Choco
*/
public final class UpdateChecker
{
public final class UpdateChecker {
public static final IVersionScheme VERSION_SCHEME_DECIMAL = (first, second) ->
{
String[] firstSplit = splitVersionInfo(first), secondSplit = splitVersionInfo(second);
if (firstSplit == null || secondSplit == null)
if (firstSplit == null || secondSplit == null) {
return null;
}
for (int i = 0; i < Math.min(firstSplit.length, secondSplit.length); i++)
{
for (int i = 0; i < Math.min(firstSplit.length, secondSplit.length); i++) {
int currentValue = NumberUtils.toInt(firstSplit[i]), newestValue = NumberUtils.toInt(secondSplit[i]);
if (newestValue > currentValue)
if (newestValue > currentValue) {
return second;
else if (newestValue < currentValue)
} else if (newestValue < currentValue) {
return first;
}
}
return (secondSplit.length > firstSplit.length) ? second : first;
@ -67,8 +67,7 @@ public final class UpdateChecker
private final int pluginID;
private final IVersionScheme versionScheme;
private UpdateChecker(final ArmoredElytra plugin, final int pluginID, final IVersionScheme versionScheme)
{
private UpdateChecker(final ArmoredElytra plugin, final int pluginID, final IVersionScheme versionScheme) {
this.plugin = plugin;
this.pluginID = pluginID;
this.versionScheme = versionScheme;
@ -80,66 +79,59 @@ public final class UpdateChecker
*
* @return a future update result
*/
public CompletableFuture<UpdateResult> requestUpdateCheck()
{
public CompletableFuture<UpdateResult> requestUpdateCheck() {
return CompletableFuture.supplyAsync(
() ->
{
int responseCode;
try
() ->
{
URL url = new URL(String.format(UPDATE_URL, pluginID));
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("User-Agent", USER_AGENT);
int responseCode;
try {
URL url = new URL(String.format(UPDATE_URL, pluginID));
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("User-Agent", USER_AGENT);
InputStreamReader reader = new InputStreamReader(connection.getInputStream());
responseCode = connection.getResponseCode();
InputStreamReader reader = new InputStreamReader(connection.getInputStream());
responseCode = connection.getResponseCode();
JsonElement element = new JsonParser().parse(reader);
if (!element.isJsonArray())
JsonElement element = new JsonParser().parse(reader);
if (!element.isJsonArray()) {
return new UpdateResult(UpdateReason.INVALID_JSON);
}
reader.close();
JsonObject versionObject = element.getAsJsonArray().get(0).getAsJsonObject();
long age = -1;
String ageString = versionObject.get("releaseDate").getAsString();
try {
age = getAge(Long.parseLong(ageString));
} catch (NumberFormatException e) {
plugin.myLogger(Level.WARNING,
"Failed to obtain age of update from ageString: \"" + ageString + "\"");
}
String current = plugin.getDescription().getVersion(), newest = versionObject.get("name")
.getAsString();
String latest = versionScheme.compareVersions(current, newest);
if (latest == null) {
return new UpdateResult(UpdateReason.UNSUPPORTED_VERSION_SCHEME);
} else if (latest.equals(current)) {
return new UpdateResult(current.equals(newest) ?
UpdateReason.UP_TO_DATE :
UpdateReason.UNRELEASED_VERSION, current, age);
} else if (latest.equals(newest)) {
return new UpdateResult(UpdateReason.NEW_UPDATE, latest, age);
}
} catch (IOException e) {
return new UpdateResult(UpdateReason.COULD_NOT_CONNECT);
} catch (JsonSyntaxException e) {
return new UpdateResult(UpdateReason.INVALID_JSON);
reader.close();
JsonObject versionObject = element.getAsJsonArray().get(0).getAsJsonObject();
long age = -1;
String ageString = versionObject.get("releaseDate").getAsString();
try
{
age = getAge(Long.parseLong(ageString));
}
catch (NumberFormatException e)
{
plugin.myLogger(Level.WARNING,
"Failed to obtain age of update from ageString: \"" + ageString + "\"");
}
String current = plugin.getDescription().getVersion(), newest = versionObject.get("name")
.getAsString();
String latest = versionScheme.compareVersions(current, newest);
if (latest == null)
return new UpdateResult(UpdateReason.UNSUPPORTED_VERSION_SCHEME);
else if (latest.equals(current))
return new UpdateResult(current.equals(newest) ?
UpdateReason.UP_TO_DATE :
UpdateReason.UNRELEASED_VERSION, current, age);
else if (latest.equals(newest))
return new UpdateResult(UpdateReason.NEW_UPDATE, latest, age);
}
catch (IOException e)
{
return new UpdateResult(UpdateReason.COULD_NOT_CONNECT);
}
catch (JsonSyntaxException e)
{
return new UpdateResult(UpdateReason.INVALID_JSON);
}
return new UpdateResult(responseCode == 401 ?
UpdateReason.UNAUTHORIZED_QUERY : UpdateReason.UNKNOWN_ERROR);
});
return new UpdateResult(responseCode == 401 ?
UpdateReason.UNAUTHORIZED_QUERY : UpdateReason.UNKNOWN_ERROR);
});
}
/**
@ -148,8 +140,7 @@ public final class UpdateChecker
* @param updateTime A moment in time to compare the current time to.
* @return The difference in seconds between a given time and the current time.
*/
private long getAge(final long updateTime)
{
private long getAge(final long updateTime) {
long currentTime = Instant.now().getEpochSecond();
return currentTime - updateTime;
}
@ -160,16 +151,15 @@ public final class UpdateChecker
*
* @return the last update check result. null if none.
*/
public UpdateResult getLastResult()
{
public UpdateResult getLastResult() {
return lastResult;
}
private static String[] splitVersionInfo(String version)
{
private static String[] splitVersionInfo(String version) {
Matcher matcher = DECIMAL_SCHEME_PATTERN.matcher(version);
if (!matcher.find())
if (!matcher.find()) {
return null;
}
return matcher.group().split("\\.");
}
@ -186,8 +176,7 @@ public final class UpdateChecker
* @param versionScheme a custom version scheme parser. Cannot be null
* @return the UpdateChecker instance
*/
public static UpdateChecker init(final ArmoredElytra plugin, final int pluginID, final IVersionScheme versionScheme)
{
public static UpdateChecker init(final ArmoredElytra plugin, final int pluginID, final IVersionScheme versionScheme) {
Preconditions.checkArgument(pluginID > 0, "Plugin ID must be greater than 0");
return (instance == null) ? instance = new UpdateChecker(plugin, pluginID, versionScheme) : instance;
@ -204,8 +193,7 @@ public final class UpdateChecker
* value must be greater than 0
* @return the UpdateChecker instance
*/
public static UpdateChecker init(final ArmoredElytra plugin, final int pluginID)
{
public static UpdateChecker init(final ArmoredElytra plugin, final int pluginID) {
return init(plugin, pluginID, VERSION_SCHEME_DECIMAL);
}
@ -215,10 +203,9 @@ public final class UpdateChecker
*
* @return the UpdateChecker instance
*/
public static UpdateChecker get()
{
public static UpdateChecker get() {
Preconditions.checkState(instance != null,
"Instance has not yet been initialized. Be sure #init() has been invoked");
"Instance has not yet been initialized. Be sure #init() has been invoked");
return instance;
}
@ -228,8 +215,7 @@ public final class UpdateChecker
*
* @return true if initialized, false otherwise
*/
public static boolean isInitialized()
{
public static boolean isInitialized() {
return instance != null;
}
@ -237,8 +223,7 @@ public final class UpdateChecker
* A functional interface to compare two version Strings with similar version schemes.
*/
@FunctionalInterface
public interface IVersionScheme
{
public interface IVersionScheme {
/**
* Compare two versions and return the higher of the two. If null is returned, it is assumed that at least one
@ -255,8 +240,7 @@ public final class UpdateChecker
/**
* A constant reason for the result of {@link UpdateResult}.
*/
public enum UpdateReason
{
public enum UpdateReason {
/**
* A new update is available for download.
@ -307,8 +291,7 @@ public final class UpdateChecker
/**
* Represents a result for an update query performed by {@link UpdateChecker#requestUpdateCheck()}.
*/
public final class UpdateResult
{
public final class UpdateResult {
private final UpdateReason reason;
private final String newestVersion;
private final long age;
@ -317,18 +300,16 @@ public final class UpdateChecker
lastResult = this;
}
private UpdateResult(final UpdateReason reason, final String newestVersion, final long age)
{
private UpdateResult(final UpdateReason reason, final String newestVersion, final long age) {
this.reason = reason;
this.newestVersion = newestVersion;
this.age = age;
}
private UpdateResult(final UpdateReason reason)
{
private UpdateResult(final UpdateReason reason) {
Preconditions
.checkArgument(reason != UpdateReason.NEW_UPDATE && reason != UpdateReason.UP_TO_DATE,
"Reasons that might require updates must also provide the latest version String");
.checkArgument(reason != UpdateReason.NEW_UPDATE && reason != UpdateReason.UP_TO_DATE,
"Reasons that might require updates must also provide the latest version String");
this.reason = reason;
newestVersion = plugin.getDescription().getVersion();
age = -1;
@ -339,8 +320,7 @@ public final class UpdateChecker
*
* @return the reason
*/
public UpdateReason getReason()
{
public UpdateReason getReason() {
return reason;
}
@ -349,8 +329,7 @@ public final class UpdateChecker
*
* @return true if requires update, false otherwise
*/
public boolean requiresUpdate()
{
public boolean requiresUpdate() {
return reason == UpdateReason.NEW_UPDATE;
}
@ -360,8 +339,7 @@ public final class UpdateChecker
*
* @return the newest version of the plugin
*/
public String getNewestVersion()
{
public String getNewestVersion() {
return newestVersion;
}
@ -370,8 +348,7 @@ public final class UpdateChecker
*
* @return The number of seconds since the last update was released or -1 if unavailable.
*/
public long getAge()
{
public long getAge() {
return age;
}
}

View File

@ -9,77 +9,68 @@ import java.util.logging.Level;
/**
* @author Pim
*/
public final class UpdateManager
{
public final class UpdateManager {
private final ArmoredElytra plugin;
private boolean checkForUpdates = false;
private final UpdateChecker updater;
private BukkitTask updateRunner = null;
public UpdateManager(final ArmoredElytra plugin, final int pluginID)
{
public UpdateManager(final ArmoredElytra plugin, final int pluginID) {
this.plugin = plugin;
updater = UpdateChecker.init(plugin, pluginID);
}
public void setEnabled(final boolean newCheckForUpdates)
{
public void setEnabled(final boolean newCheckForUpdates) {
checkForUpdates = newCheckForUpdates;
initUpdater();
}
public String getNewestVersion()
{
if (!checkForUpdates || updater.getLastResult() == null)
public String getNewestVersion() {
if (!checkForUpdates || updater.getLastResult() == null) {
return null;
}
return updater.getLastResult().getNewestVersion();
}
public boolean updateAvailable()
{
public boolean updateAvailable() {
// Updates disabled, so no new updates available by definition.
if (!checkForUpdates || updater.getLastResult() == null)
if (!checkForUpdates || updater.getLastResult() == null) {
return false;
}
return updater.getLastResult().requiresUpdate();
}
public void checkForUpdates()
{
public void checkForUpdates() {
updater.requestUpdateCheck().whenComplete(
(result, throwable) ->
{
boolean updateAvailable = updateAvailable();
if (updateAvailable)
plugin.myLogger(Level.INFO,
"A new update is available: " + plugin.getUpdateManager().getNewestVersion());
});
(result, throwable) ->
{
boolean updateAvailable = updateAvailable();
if (updateAvailable) {
plugin.myLogger(Level.INFO,
"A new update is available: " + plugin.getUpdateManager().getNewestVersion());
}
});
}
private void initUpdater()
{
if (checkForUpdates)
{
private void initUpdater() {
if (checkForUpdates) {
// Run the UpdateChecker regularly.
if (updateRunner == null)
updateRunner = new BukkitRunnable()
{
if (updateRunner == null) {
updateRunner = new BukkitRunnable() {
@Override
public void run()
{
public void run() {
checkForUpdates();
}
// Run immediately, then every 12 hours.
}.runTaskTimer(plugin, 0L, 864000L);
}
else
{
}
} else {
plugin.myLogger(Level.INFO,
"Plugin update checking not enabled! You will not receive any messages about new updates " +
"for this plugin. Please consider turning this on in the config.");
if (updateRunner != null)
{
"Plugin update checking not enabled! You will not receive any messages about new updates " +
"for this plugin. Please consider turning this on in the config.");
if (updateRunner != null) {
updateRunner.cancel();
updateRunner = null;
}

View File

@ -12,102 +12,75 @@ import java.io.StringWriter;
import java.util.Locale;
import java.util.Map;
public class Util
{
public static String errorToString(Error e)
{
public class Util {
public static String errorToString(Error e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
public static String exceptionToString(Exception e)
{
public static String exceptionToString(Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
// Check if an item is broken or not.
public static boolean isBroken(ItemStack item)
{
public static boolean isBroken(ItemStack item) {
return item.getDurability() >= item.getType().getMaxDurability();
}
// Get the armor tier from a chest plate.
public static ArmorTier armorToTier(ItemStack itemStack)
{
public static ArmorTier armorToTier(ItemStack itemStack) {
return armorToTier(itemStack.getType());
}
// Get the armor tier from a chest plate.
public static ArmorTier armorToTier(Material mat)
{
public static ArmorTier armorToTier(Material mat) {
ArmorTier ret = ArmorTier.NONE;
XMaterial xmat = XMaterial.matchXMaterial(mat);
switch (xmat)
{
case LEATHER_CHESTPLATE:
ret = ArmorTier.LEATHER;
break;
case GOLDEN_CHESTPLATE:
ret = ArmorTier.GOLD;
break;
case CHAINMAIL_CHESTPLATE:
ret = ArmorTier.CHAIN;
break;
case IRON_CHESTPLATE:
ret = ArmorTier.IRON;
break;
case DIAMOND_CHESTPLATE:
ret = ArmorTier.DIAMOND;
break;
case NETHERITE_CHESTPLATE:
ret = ArmorTier.NETHERITE;
break;
default:
break;
switch (xmat) {
case LEATHER_CHESTPLATE -> ret = ArmorTier.LEATHER;
case GOLDEN_CHESTPLATE -> ret = ArmorTier.GOLD;
case CHAINMAIL_CHESTPLATE -> ret = ArmorTier.CHAIN;
case IRON_CHESTPLATE -> ret = ArmorTier.IRON;
case DIAMOND_CHESTPLATE -> ret = ArmorTier.DIAMOND;
case NETHERITE_CHESTPLATE -> ret = ArmorTier.NETHERITE;
default -> {
}
}
return ret;
}
public static boolean isChestPlate(ItemStack itemStack)
{
public static boolean isChestPlate(ItemStack itemStack) {
return isChestPlate(itemStack.getType());
}
// Check if mat is a chest plate.
public static boolean isChestPlate(Material mat)
{
try
{
public static boolean isChestPlate(Material mat) {
try {
XMaterial xmat = XMaterial.matchXMaterial(mat);
return xmat == XMaterial.LEATHER_CHESTPLATE || xmat == XMaterial.GOLDEN_CHESTPLATE ||
xmat == XMaterial.CHAINMAIL_CHESTPLATE || xmat == XMaterial.IRON_CHESTPLATE ||
xmat == XMaterial.DIAMOND_CHESTPLATE || xmat == XMaterial.NETHERITE_CHESTPLATE;
}
catch (IllegalArgumentException e)
{
xmat == XMaterial.CHAINMAIL_CHESTPLATE || xmat == XMaterial.IRON_CHESTPLATE ||
xmat == XMaterial.DIAMOND_CHESTPLATE || xmat == XMaterial.NETHERITE_CHESTPLATE;
} catch (IllegalArgumentException e) {
// No need to handle this, this is just XMaterial complaining the material doesn't exist.
return false;
}
}
public static String snakeToCamelCase(String input)
{
public static String snakeToCamelCase(String input) {
final char[] arr = input.toLowerCase(Locale.US).toCharArray();
int skipped = 0;
boolean capitalize = false;
for (int idx = 0; idx < arr.length; ++idx)
{
for (int idx = 0; idx < arr.length; ++idx) {
char current = arr[idx];
if (current == '_')
{
if (current == '_') {
++skipped;
capitalize = true;
continue;
@ -115,10 +88,10 @@ public class Util
final int targetIdx = idx - skipped;
if (capitalize)
{
if (targetIdx > 0)
if (capitalize) {
if (targetIdx > 0) {
current = Character.toUpperCase(current);
}
capitalize = false;
}
@ -131,30 +104,34 @@ public class Util
}
// Function that returns which/how many protection enchantments there are.
public static int getProtectionEnchantmentsVal(Map<Enchantment, Integer> enchantments)
{
public static int getProtectionEnchantmentsVal(Map<Enchantment, Integer> enchantments) {
int ret = 0;
if (enchantments.containsKey(Enchantment.PROTECTION_ENVIRONMENTAL))
if (enchantments.containsKey(Enchantment.PROTECTION_ENVIRONMENTAL)) {
ret += 1;
if (enchantments.containsKey(Enchantment.PROTECTION_EXPLOSIONS))
}
if (enchantments.containsKey(Enchantment.PROTECTION_EXPLOSIONS)) {
ret += 2;
if (enchantments.containsKey(Enchantment.PROTECTION_FALL))
}
if (enchantments.containsKey(Enchantment.PROTECTION_FALL)) {
ret += 4;
if (enchantments.containsKey(Enchantment.PROTECTION_FIRE))
}
if (enchantments.containsKey(Enchantment.PROTECTION_FIRE)) {
ret += 8;
if (enchantments.containsKey(Enchantment.PROTECTION_PROJECTILE))
}
if (enchantments.containsKey(Enchantment.PROTECTION_PROJECTILE)) {
ret += 16;
}
return ret;
}
public static void moveChestplateToInventory(Player player)
{
public static void moveChestplateToInventory(Player player) {
final PlayerInventory inventory = player.getInventory();
inventory.addItem(inventory.getChestplate());
final @Nullable ItemStack chestplate = inventory.getChestplate();
if (chestplate != null)
if (chestplate != null) {
chestplate.setAmount(0);
}
player.updateInventory();
}
@ -167,8 +144,7 @@ public class Util
* @param max The upper bound limit.
* @return The value if it is bigger than min and larger than max, otherwise either min or max.
*/
public static int between(int val, int min, int max)
{
public static int between(int val, int min, int max) {
return Math.max(min, Math.min(max, val));
}
}

View File

@ -65,8 +65,7 @@ import java.util.regex.Pattern;
* @see Material
* @see ItemStack
*/
public enum XMaterial
{
public enum XMaterial {
CHAINMAIL_CHESTPLATE,
DIAMOND_CHESTPLATE,
GOLDEN_CHESTPLATE("GOLD_CHESTPLATE"),
@ -95,11 +94,11 @@ public enum XMaterial
* @since 1.0.0
*/
private static final ImmutableSet<String> DAMAGEABLE = ImmutableSet.of(
"HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS",
"SWORD", "AXE", "PICKAXE", "SHOVEL", "HOE",
"ELYTRA", "TRIDENT", "HORSE_ARMOR", "BARDING",
"SHEARS", "FLINT_AND_STEEL", "BOW", "FISHING_ROD",
"CARROT_ON_A_STICK", "CARROT_STICK", "SPADE", "SHIELD"
"HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS",
"SWORD", "AXE", "PICKAXE", "SHOVEL", "HOE",
"ELYTRA", "TRIDENT", "HORSE_ARMOR", "BARDING",
"SHEARS", "FLINT_AND_STEEL", "BOW", "FISHING_ROD",
"CARROT_ON_A_STICK", "CARROT_STICK", "SPADE", "SHIELD"
);
/*
@ -124,10 +123,10 @@ public enum XMaterial
* @since 1.0.0
*/
private static final Cache<String, XMaterial> NAME_CACHE
= CacheBuilder.newBuilder()
.softValues()
.expireAfterAccess(15, TimeUnit.MINUTES)
.build();
= CacheBuilder.newBuilder()
.softValues()
.expireAfterAccess(15, TimeUnit.MINUTES)
.build();
/**
* Guava (Google Core Libraries for Java)'s cache for performance and timed caches. For XMaterials that are already
* parsed once.
@ -135,11 +134,11 @@ public enum XMaterial
* @since 3.0.0
*/
private static final Cache<XMaterial, Optional<Material>> PARSED_CACHE
= CacheBuilder.newBuilder()
.softValues()
.expireAfterAccess(10, TimeUnit.MINUTES)
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
.build();
= CacheBuilder.newBuilder()
.softValues()
.expireAfterAccess(10, TimeUnit.MINUTES)
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
.build();
/**
* Pre-compiled RegEx pattern. Include both replacements to avoid recreating string multiple times with multiple
@ -174,19 +173,16 @@ public enum XMaterial
*/
private final String[] legacy;
XMaterial(int data, String... legacy)
{
XMaterial(int data, String... legacy) {
this.data = (byte) data;
this.legacy = legacy;
}
XMaterial()
{
XMaterial() {
this(0);
}
XMaterial(String... legacy)
{
XMaterial(String... legacy) {
this(0, legacy);
}
@ -199,13 +195,11 @@ public enum XMaterial
* </blockquote>
*
* @return true if 1.13 or higher.
*
* @see #getVersion()
* @see #supports(int)
* @since 1.0.0
*/
public static boolean isNewVersion()
{
public static boolean isNewVersion() {
return ISFLAT;
}
@ -222,8 +216,7 @@ public enum XMaterial
*
* @since 2.0.0
*/
public static boolean isOneEight()
{
public static boolean isOneEight() {
return !supports(9);
}
@ -231,12 +224,10 @@ public enum XMaterial
* The current version of the server.
*
* @return the current server version or 0.0 if unknown.
*
* @see #isNewVersion()
* @since 2.0.0
*/
public static double getVersion()
{
public static double getVersion() {
return VERSION;
}
@ -248,18 +239,16 @@ public enum XMaterial
* @since 1.0.0
*/
@Nullable
private static XMaterial requestOldXMaterial(@Nonnull String name, byte data)
{
private static XMaterial requestOldXMaterial(@Nonnull String name, byte data) {
String holder = name + data;
XMaterial cache = NAME_CACHE.getIfPresent(holder);
if (cache != null)
if (cache != null) {
return cache;
}
for (XMaterial material : VALUES)
{
for (XMaterial material : VALUES) {
// Not using material.name().equals(name) check is intended.
if ((data == -1 || data == material.data) && material.anyMatchLegacy(name))
{
if ((data == -1 || data == material.data) && material.anyMatchLegacy(name)) {
NAME_CACHE.put(holder, material);
return material;
}
@ -277,17 +266,16 @@ public enum XMaterial
*
* @param name name of the material.
* @return true if XMaterial enum has this material.
*
* @since 1.0.0
*/
public static boolean contains(@Nonnull String name)
{
public static boolean contains(@Nonnull String name) {
Validate.notEmpty(name, "Cannot check for null or empty material name");
name = format(name);
for (XMaterial materials : VALUES)
if (materials.name().equals(name))
if (materials.name().equals(name)) {
return true;
}
return false;
}
@ -298,12 +286,12 @@ public enum XMaterial
* @since 2.0.0
*/
@Nonnull
public static Optional<XMaterial> matchXMaterial(@Nonnull String name)
{
public static Optional<XMaterial> matchXMaterial(@Nonnull String name) {
Validate.notEmpty(name, "Cannot match a material with null or empty material name");
Optional<XMaterial> oldMatch = matchXMaterialWithData(name);
if (oldMatch.isPresent())
if (oldMatch.isPresent()) {
return oldMatch;
}
return matchDefinedXMaterial(format(name), (byte) -1);
}
@ -319,17 +307,15 @@ public enum XMaterial
*
* @param name the material string that consists of the material name, data and separator character.
* @return the parsed XMaterial.
*
* @see #matchXMaterial(String)
* @since 3.0.0
*/
private static Optional<XMaterial> matchXMaterialWithData(String name)
{
for (char separator : new char[]{',', ':'})
{
private static Optional<XMaterial> matchXMaterialWithData(String name) {
for (char separator : new char[]{',', ':'}) {
int index = name.indexOf(separator);
if (index == -1)
if (index == -1) {
continue;
}
String mat = format(name.substring(0, index));
byte data = Byte.parseByte(StringUtils.deleteWhitespace(name.substring(index + 1)));
@ -348,11 +334,10 @@ public enum XMaterial
* @since 2.0.0
*/
@Nonnull
public static XMaterial matchXMaterial(@Nonnull Material material)
{
public static XMaterial matchXMaterial(@Nonnull Material material) {
Objects.requireNonNull(material, "Cannot match null material");
return matchDefinedXMaterial(material.name(), (byte) -1)
.orElseThrow(() -> new IllegalArgumentException("Unsupported Material With No Bytes: " + material.name()));
.orElseThrow(() -> new IllegalArgumentException("Unsupported Material With No Bytes: " + material.name()));
}
/**
@ -360,21 +345,19 @@ public enum XMaterial
*
* @param item the ItemStack to match.
* @return an XMaterial if matched any.
*
* @throws IllegalArgumentException may be thrown as an unexpected exception.
* @see #matchDefinedXMaterial(String, byte)
* @since 2.0.0
*/
@Nonnull
@SuppressWarnings("deprecation")
public static XMaterial matchXMaterial(@Nonnull ItemStack item)
{
public static XMaterial matchXMaterial(@Nonnull ItemStack item) {
Objects.requireNonNull(item, "Cannot match null ItemStack");
String material = item.getType().name();
byte data = (byte) (ISFLAT || isDamageable(material) ? 0 : item.getDurability());
return matchDefinedXMaterial(material, data)
.orElseThrow(() -> new IllegalArgumentException("Unsupported Material: " + material + " (" + data + ')'));
.orElseThrow(() -> new IllegalArgumentException("Unsupported Material: " + material + " (" + data + ')'));
}
/**
@ -384,31 +367,27 @@ public enum XMaterial
* @param name the formatted name of the material.
* @param data the data value of the material.
* @return an XMaterial (with the same data value if specified)
*
* @see #matchXMaterial(Material)
* @see #matchXMaterial(int, byte)
* @see #matchXMaterial(ItemStack)
* @since 3.0.0
*/
@Nonnull
private static Optional<XMaterial> matchDefinedXMaterial(@Nonnull String name, byte data)
{
private static Optional<XMaterial> matchDefinedXMaterial(@Nonnull String name, byte data) {
boolean duplicated = isDuplicated(name);
// Do basic number and boolean checks before accessing more complex enum stuff.
// Maybe we can simplify (ISFLAT || !duplicated) with the (!ISFLAT && duplicated)
// under it to save a few nanoseconds?
// if (!Boolean.valueOf(Boolean.getBoolean(Boolean.TRUE.toString())).equals(Boolean.FALSE.booleanValue()))
// return null;
if (data <= 0 && !duplicated)
{
if (data <= 0 && !duplicated) {
// Apparently the transform method is more efficient than toJavaUtil()
// toJavaUtil isn't even supported in older versions.
Optional<XMaterial> xMat =
Enums.getIfPresent(XMaterial.class, name).transform(Optional::of).or(Optional.empty());
Enums.getIfPresent(XMaterial.class, name).transform(Optional::of).or(Optional.empty());
if (xMat.isPresent())
if (xMat.isPresent()) {
return xMat;
}
}
// XMaterial Paradox (Duplication Check)
@ -416,11 +395,11 @@ public enum XMaterial
// going around the Singular Form and the Plural Form materials. A waste of brain cells and a waste of time.
// This solution works just fine anyway.
XMaterial xMat = requestOldXMaterial(name, data);
if (xMat == null)
if (xMat == null) {
return Optional.empty();
}
if (!ISFLAT && duplicated && xMat.name().charAt(xMat.name().length() - 1) == 'S')
{
if (!ISFLAT && duplicated && xMat.name().charAt(xMat.name().length() - 1) == 'S') {
// A solution for XMaterial Paradox.
// Manually parses the duplicated materials to find the exact material based on the server version.
// If ends with "S" -> Plural Form Material
@ -438,12 +417,10 @@ public enum XMaterial
*
* @param name the name of the material to check.
* @return true if there's a duplicated material for this material, otherwise false.
*
* @see #isDuplicated()
* @since 2.0.0
*/
private static boolean isDuplicated(@Nonnull String name)
{
private static boolean isDuplicated(@Nonnull String name) {
return false;
}
@ -454,18 +431,20 @@ public enum XMaterial
* @param id the ID (Magic value) of the material.
* @param data the data value of the material.
* @return a parsed XMaterial with the same ID and data value.
*
* @see #matchXMaterial(ItemStack)
* @since 2.0.0
*/
@Nonnull
public static Optional<XMaterial> matchXMaterial(int id, byte data)
{
if (id < 0 || data < 0) return Optional.empty();
public static Optional<XMaterial> matchXMaterial(int id, byte data) {
if (id < 0 || data < 0) {
return Optional.empty();
}
// Looping through Material.values() will take longer.
for (XMaterial materials : VALUES)
if (materials.data == data && materials.getId() == id) return Optional.of(materials);
if (materials.data == data && materials.getId() == id) {
return Optional.of(materials);
}
return Optional.empty();
}
@ -475,14 +454,12 @@ public enum XMaterial
*
* @param name the material name to modify.
* @return a Material enum name.
*
* @since 2.0.0
*/
@Nonnull
private static String format(@Nonnull String name)
{
private static String format(@Nonnull String name) {
return FORMAT_PATTERN.matcher(
name.trim().replace('-', '_').replace(' ', '_')).replaceAll("").toUpperCase(Locale.ENGLISH);
name.trim().replace('-', '_').replace(' ', '_')).replaceAll("").toUpperCase(Locale.ENGLISH);
}
/**
@ -490,11 +467,9 @@ public enum XMaterial
*
* @param version the major version to be checked. "1." is ignored. E.g. 1.12 = 12 | 1.9 = 9
* @return true of the version is equal or higher than the current version.
*
* @since 2.0.0
*/
public static boolean supports(int version)
{
public static boolean supports(int version) {
return VERSION >= version;
}
@ -502,13 +477,11 @@ public enum XMaterial
* Converts the enum names to a more friendly and readable string.
*
* @return a formatted string.
*
* @see #toWord(String)
* @since 2.1.0
*/
@Nonnull
public static String toWord(@Nonnull Material material)
{
public static String toWord(@Nonnull Material material) {
Objects.requireNonNull(material, "Cannot translate a null material to a word");
return toWord(material.name());
}
@ -525,12 +498,10 @@ public enum XMaterial
*
* @param name the name of the enum.
* @return a cleaned more readable enum name.
*
* @since 2.1.0
*/
@Nonnull
private static String toWord(@Nonnull String name)
{
private static String toWord(@Nonnull String name) {
return WordUtils.capitalize(name.replace('_', ' ').toLowerCase(Locale.ENGLISH));
}
@ -540,20 +511,17 @@ public enum XMaterial
* @param version Supports {@link Bukkit#getVersion()}, {@link Bukkit#getBukkitVersion()} and normal formats such as
* "1.14"
* @return the exact major version.
*
* @since 2.0.0
*/
@Nonnull
public static String getMajorVersion(@Nonnull String version)
{
public static String getMajorVersion(@Nonnull String version) {
Validate.notEmpty(version, "Cannot get major Minecraft version from null or empty string");
// getVersion()
int index = version.lastIndexOf("MC:");
if (index != -1)
if (index != -1) {
version = version.substring(index + 4, version.length() - 1);
else if (version.endsWith("SNAPSHOT"))
{
} else if (version.endsWith("SNAPSHOT")) {
// getBukkitVersion()
index = version.indexOf('-');
version = version.substring(0, index);
@ -561,8 +529,9 @@ public enum XMaterial
// 1.13.2, 1.14.4, etc...
int lastDot = version.lastIndexOf('.');
if (version.indexOf('.') != lastDot)
if (version.indexOf('.') != lastDot) {
version = version.substring(0, lastDot);
}
return version;
}
@ -572,16 +541,15 @@ public enum XMaterial
*
* @param name the name of the material.
* @return true of the material can be damaged.
*
* @see #isDamageable()
* @since 1.0.0
*/
public static boolean isDamageable(@Nonnull String name)
{
public static boolean isDamageable(@Nonnull String name) {
Objects.requireNonNull(name, "Material name cannot be null");
for (String damageable : DAMAGEABLE)
if (name.contains(damageable))
if (name.contains(damageable)) {
return true;
}
return false;
}
@ -622,38 +590,37 @@ public enum XMaterial
* @param material the base material to match other materials with.
* @param materials the material names to check base material on.
* @return true if one of the given material names is similar to the base material.
*
* @since 3.1.1
*/
public static boolean isOneOf(@Nonnull Material material, @Nullable List<String> materials)
{
if (materials == null || materials.isEmpty())
public static boolean isOneOf(@Nonnull Material material, @Nullable List<String> materials) {
if (materials == null || materials.isEmpty()) {
return false;
}
Objects.requireNonNull(material, "Cannot match materials with a null material");
String name = material.name();
for (String comp : materials)
{
for (String comp : materials) {
comp = comp.toUpperCase();
if (comp.startsWith("CONTAINS:"))
{
if (comp.startsWith("CONTAINS:")) {
comp = format(comp.substring(9));
if (name.contains(comp))
if (name.contains(comp)) {
return true;
}
continue;
}
if (comp.startsWith("REGEX:"))
{
if (comp.startsWith("REGEX:")) {
comp = comp.substring(6);
if (name.matches(comp))
if (name.matches(comp)) {
return true;
}
continue;
}
// Direct Object Equals
Optional<XMaterial> mat = matchXMaterial(comp);
if (mat.isPresent() && mat.get().parseMaterial() == material)
if (mat.isPresent() && mat.get().parseMaterial() == material) {
return true;
}
}
return false;
}
@ -662,16 +629,16 @@ public enum XMaterial
* Gets the version which this material was added in. If the material doesn't have a version it'll return 0;
*
* @return the Minecraft version which tihs material was added in.
*
* @since 3.0.0
*/
public int getMaterialVersion()
{
if (this.legacy.length == 0)
public int getMaterialVersion() {
if (this.legacy.length == 0) {
return 0;
}
String version = this.legacy[0];
if (version.charAt(1) != '.')
if (version.charAt(1) != '.') {
return 0;
}
return Integer.parseInt(version.substring(2));
}
@ -688,13 +655,13 @@ public enum XMaterial
*/
@Nonnull
@SuppressWarnings("deprecation")
public ItemStack setType(@Nonnull ItemStack item)
{
public ItemStack setType(@Nonnull ItemStack item) {
Objects.requireNonNull(item, "Cannot set material for null ItemStack");
item.setType(this.parseMaterial());
if (!ISFLAT && !this.isDamageable())
if (!ISFLAT && !this.isDamageable()) {
item.setDurability(this.data);
}
return item;
}
@ -703,15 +670,14 @@ public enum XMaterial
*
* @param materials the material names to check base material on.
* @return true if one of the given material names is similar to the base material.
*
* @see #isOneOf(Material, List)
* @since 3.0.0
*/
public boolean isOneOf(@Nullable List<String> materials)
{
public boolean isOneOf(@Nullable List<String> materials) {
Material material = this.parseMaterial();
if (material == null)
if (material == null) {
return false;
}
return isOneOf(material, materials);
}
@ -721,18 +687,18 @@ public enum XMaterial
*
* @param name the name to check
* @return true if it's one of the legacy names.
*
* @since 2.0.0
*/
private boolean anyMatchLegacy(@Nonnull String name)
{
for (String legacy : this.legacy)
{
private boolean anyMatchLegacy(@Nonnull String name) {
for (String legacy : this.legacy) {
if (legacy.isEmpty())
// Left-side suggestion list
// Left-side suggestion list
{
break;
if (name.equals(legacy))
}
if (name.equals(legacy)) {
return true;
}
}
return false;
}
@ -741,13 +707,11 @@ public enum XMaterial
* User-friendly readable name for this material In most cases you should be using {@link #name()} instead.
*
* @return string of this object.
*
* @see #toWord(String)
* @since 3.0.0
*/
@Override
public String toString()
{
public String toString() {
return toWord(this.name());
}
@ -755,15 +719,14 @@ public enum XMaterial
* Gets the ID (Magic value) of the material.
*
* @return the ID of the material or <b>-1</b> if it's a new block or the material is not supported.
*
* @see #matchXMaterial(int, byte)
* @since 2.2.0
*/
@SuppressWarnings("deprecation")
public int getId()
{
if (this.data != 0 || (this.legacy.length != 0 && Integer.parseInt(this.legacy[0].substring(2)) >= 13))
public int getId() {
if (this.data != 0 || (this.legacy.length != 0 && Integer.parseInt(this.legacy[0].substring(2)) >= 13)) {
return -1;
}
Material material = this.parseMaterial();
return material == null ? -1 : material.getId();
}
@ -772,12 +735,10 @@ public enum XMaterial
* Checks if the material has any duplicates.
*
* @return true if there is a duplicated name for this material, otherwise false.
*
* @see #isDuplicated(String)
* @since 2.0.0
*/
public boolean isDuplicated()
{
public boolean isDuplicated() {
return false;
}
@ -785,12 +746,10 @@ public enum XMaterial
* Checks if the material can be damaged by using it. Names going through this method are not formatted.
*
* @return true if the item can be damaged (have its durability changed), otherwise false.
*
* @see #isDamageable(String)
* @since 1.0.0
*/
public boolean isDamageable()
{
public boolean isDamageable() {
return isDamageable(this.name());
}
@ -802,12 +761,10 @@ public enum XMaterial
* ItemStack#getDurability()} if not damageable.
*
* @return data of this material, or 0 if none.
*
* @since 1.0.0
*/
@SuppressWarnings("deprecation")
public byte getData()
{
public byte getData() {
return data;
}
@ -816,12 +773,10 @@ public enum XMaterial
* version {@link #isNewVersion()}, then the first element will indicate which version the material was added in.
*
* @return a list of legacy material names and the first element as the version the material was added in if new.
*
* @since 1.0.0
*/
@Nonnull
public String[] getLegacy()
{
public String[] getLegacy() {
return legacy;
}
@ -829,14 +784,12 @@ public enum XMaterial
* Parses an item from this XMaterial. Uses data values on older versions.
*
* @return an ItemStack with the same material (and data value if in older versions.)
*
* @see #parseItem(boolean)
* @see #setType(ItemStack)
* @since 1.0.0
*/
@Nullable
public ItemStack parseItem()
{
public ItemStack parseItem() {
return parseItem(false);
}
@ -845,17 +798,16 @@ public enum XMaterial
*
* @param suggest if true {@link #parseMaterial(boolean)} true will be used.
* @return an ItemStack with the same material (and data value if in older versions.)
*
* @see #setType(ItemStack)
* @since 2.0.0
*/
@Nullable
@SuppressWarnings("deprecation")
public ItemStack parseItem(boolean suggest)
{
public ItemStack parseItem(boolean suggest) {
Material material = this.parseMaterial(suggest);
if (material == null)
if (material == null) {
return null;
}
return ISFLAT ? new ItemStack(material) : new ItemStack(material, 1, this.data);
}
@ -863,13 +815,11 @@ public enum XMaterial
* Parses the material of this XMaterial.
*
* @return the material related to this XMaterial based on the server version.
*
* @see #parseMaterial(boolean)
* @since 1.0.0
*/
@Nullable
public Material parseMaterial()
{
public Material parseMaterial() {
return parseMaterial(false);
}
@ -879,29 +829,29 @@ public enum XMaterial
* @param suggest use a suggested material (from older materials) if the material is added in a later version of
* Minecraft.
* @return the material related to this XMaterial based on the server version.
*
* @since 2.0.0
*/
@SuppressWarnings("OptionalAssignedToNull")
@Nullable
public Material parseMaterial(boolean suggest)
{
public Material parseMaterial(boolean suggest) {
Optional<Material> cache = PARSED_CACHE.getIfPresent(this);
if (cache != null)
if (cache != null) {
return cache.orElse(null);
}
Material mat;
if (!ISFLAT && this.isDuplicated())
if (!ISFLAT && this.isDuplicated()) {
mat = requestOldMaterial(suggest);
else
{
} else {
mat = Material.getMaterial(this.name());
if (mat == null)
if (mat == null) {
mat = requestOldMaterial(suggest);
}
}
if (mat != null)
if (mat != null) {
PARSED_CACHE.put(this, Optional.ofNullable(mat));
}
return mat;
}
@ -910,34 +860,34 @@ public enum XMaterial
*
* @param suggest if true suggested materials will be considered for old versions.
* @return a parsed material suitable for the current Minecraft version.
*
* @see #parseMaterial(boolean)
* @since 2.0.0
*/
@Nullable
private Material requestOldMaterial(boolean suggest)
{
for (int i = this.legacy.length - 1; i >= 0; i--)
{
private Material requestOldMaterial(boolean suggest) {
for (int i = this.legacy.length - 1; i >= 0; i--) {
String legacy = this.legacy[i];
// Check if we've reached the end and the last string is our
// material version.
if (i == 0 && legacy.charAt(1) == '.')
if (i == 0 && legacy.charAt(1) == '.') {
return null;
}
// According to the suggestion list format, all the other names continuing
// from here are considered as a "suggestion"
// The empty string is an indicator for suggestion list on the left side.
if (legacy.isEmpty())
{
if (suggest) continue;
if (legacy.isEmpty()) {
if (suggest) {
continue;
}
break;
}
Material material = Material.getMaterial(legacy);
if (material != null)
if (material != null) {
return material;
}
}
return null;
}
@ -948,15 +898,14 @@ public enum XMaterial
* @param item item to check.
* @return true if the material is the same as the item's material (and data value if on older versions), otherwise
* false.
*
* @since 1.0.0
*/
@SuppressWarnings("deprecation")
public boolean isSimilar(@Nonnull ItemStack item)
{
public boolean isSimilar(@Nonnull ItemStack item) {
Objects.requireNonNull(item, "Cannot compare with null ItemStack");
if (item.getType() != this.parseMaterial())
if (item.getType() != this.parseMaterial()) {
return false;
}
return ISFLAT || this.isDamageable() || item.getDurability() == this.data;
}
@ -964,20 +913,19 @@ public enum XMaterial
* Gets the suggested material names that can be used if the material is not supported in the current version.
*
* @return a list of suggested material names.
*
* @see #parseMaterial(boolean)
* @since 2.0.0
*/
@Nonnull
public List<String> getSuggestions()
{
if (this.legacy.length == 0 || this.legacy[0].charAt(1) != '.')
public List<String> getSuggestions() {
if (this.legacy.length == 0 || this.legacy[0].charAt(1) != '.') {
return new ArrayList<>();
}
List<String> suggestions = new ArrayList<>();
for (String legacy : this.legacy)
{
if (legacy.isEmpty())
for (String legacy : this.legacy) {
if (legacy.isEmpty()) {
break;
}
suggestions.add(legacy);
}
return suggestions;
@ -990,18 +938,18 @@ public enum XMaterial
* material later.
*
* @return true if the material exists in {@link Material} list.
*
* @since 2.0.0
*/
public boolean isSupported()
{
public boolean isSupported() {
int version = this.getMaterialVersion();
if (version != 0)
if (version != 0) {
return supports(version);
}
Material material = Material.getMaterial(this.name());
if (material != null)
if (material != null) {
return true;
}
return requestOldMaterial(false) != null;
}
@ -1009,12 +957,10 @@ public enum XMaterial
* Checks if the material is newly added after the 1.13 Aquatic Update.
*
* @return true if the material was newly added, otherwise false.
*
* @see #getMaterialVersion()
* @since 2.0.0
*/
public boolean isFromNewSystem()
{
public boolean isFromNewSystem() {
return this.legacy.length != 0 && Integer.parseInt(this.legacy[0].substring(2)) > 13;
}
}

View File

@ -5,8 +5,7 @@ package nl.pim16aap2.armoredElytra.util.messages;
*
* @author Pim
*/
public interface IMessageVariable
{
public interface IMessageVariable {
String VAR_TIER_NAME = "%ARMOR_TIER%";
String VAR_TIER_NAME_SHORT = "%ARMOR_TIER_SHORT%";
}

View File

@ -5,8 +5,7 @@ package nl.pim16aap2.armoredElytra.util.messages;
*
* @author Pim
*/
public enum Message implements IMessageVariable
{
public enum Message implements IMessageVariable {
EMPTY(),
TIER_LEATHER(),
@ -46,8 +45,7 @@ public enum Message implements IMessageVariable
*
* @param variableNames The names of the variables in the value that can be replaced.
*/
Message(final String... variableNames)
{
Message(final String... variableNames) {
this.variableNames = variableNames;
}
@ -58,8 +56,7 @@ public enum Message implements IMessageVariable
* @param idx The index of the variable name.
* @return The name of the variable at the given position of this message.
*/
public static String getVariableName(final Message msg, final int idx)
{
public static String getVariableName(final Message msg, final int idx) {
return msg.variableNames[idx];
}
@ -69,8 +66,7 @@ public enum Message implements IMessageVariable
* @param msg The message for which to retrieve the variable names.
* @return The names of the variables of this message.
*/
public static String[] getVariableNames(final Message msg)
{
public static String[] getVariableNames(final Message msg) {
return msg.variableNames;
}
@ -80,8 +76,7 @@ public enum Message implements IMessageVariable
* @param msg The message to retrieve the variable count for.
* @return The number of variables in this message that can be substituted.
*/
public static int getVariableCount(final Message msg)
{
public static int getVariableCount(final Message msg) {
return msg.variableNames.length;
}
}

View File

@ -23,8 +23,7 @@ import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.regex.Pattern;
public class Messages
{
public class Messages {
private static final String DEFAULT_FILENAME = "en_US.txt";
/**
@ -43,8 +42,7 @@ public class Messages
private static final Pattern matchNewLines = Pattern.compile("\\\\n");
private static final Pattern matchColorCodes = Pattern.compile("&((?i)[0-9a-fk-or])");
public Messages(final ArmoredElytra plugin)
{
public Messages(final ArmoredElytra plugin) {
this.plugin = plugin;
writeDefaultFiles(plugin);
@ -53,10 +51,9 @@ public class Messages
textFile = Path.of(plugin.getDataFolder().toURI()).resolve(fileName);
if (!Files.exists(textFile))
{
if (!Files.exists(textFile)) {
plugin.myLogger(Level.WARNING, "Failed to load language file: \"" + textFile +
"\": File not found! Using default file (\"" + DEFAULT_FILENAME + "\") instead!");
"\": File not found! Using default file (\"" + DEFAULT_FILENAME + "\") instead!");
textFile = Path.of(plugin.getDataFolder().toURI()).resolve(DEFAULT_FILENAME);
}
populateMessageMap();
@ -71,31 +68,27 @@ public class Messages
* @throws IOException
*/
private void processFile(final BufferedReader br, final BiConsumer<Message, String> action)
throws IOException
{
throws IOException {
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null)
{
while ((sCurrentLine = br.readLine()) != null) {
// Ignore comments.
if (sCurrentLine.startsWith("#") || sCurrentLine.isEmpty())
if (sCurrentLine.startsWith("#") || sCurrentLine.isEmpty()) {
continue;
}
String[] parts = sCurrentLine.split("=", 2);
try
{
try {
final Message msg = Message.valueOf(matchDots.matcher(parts[0]).replaceAll("_").toUpperCase());
final String value = matchNewLines.matcher(matchColorCodes.matcher(parts[1]).replaceAll("\u00A7$1"))
.replaceAll("\n");
.replaceAll("\n");
action.accept(msg, value);
}
catch (IllegalArgumentException e)
{
} catch (IllegalArgumentException e) {
plugin.myLogger(Level.WARNING, "Failed to identify Message corresponding to key: \"" + parts[0] +
"\". Its value will be ignored!");
"\". Its value will be ignored!");
System.out.println(
"Trying to find enum value of: " + matchDots.matcher(parts[0]).replaceAll("_").toUpperCase());
"Trying to find enum value of: " + matchDots.matcher(parts[0]).replaceAll("_").toUpperCase());
}
}
}
@ -106,8 +99,7 @@ public class Messages
* @param message The {@link Message}.
* @param value The value of the message.
*/
private void addMessage(final Message message, final String value)
{
private void addMessage(final Message message, final String value) {
messageMap.put(message, value);
}
@ -117,13 +109,13 @@ public class Messages
* @param message The {@link Message}.
* @param value The value of the message.
*/
private void addBackupMessage(final Message message, final String value)
{
if (messageMap.containsKey(message))
private void addBackupMessage(final Message message, final String value) {
if (messageMap.containsKey(message)) {
return;
}
plugin.myLogger(Level.WARNING,
"Could not find translation of key: \"" + message.name() + "\". Using default value instead!");
"Could not find translation of key: \"" + message.name() + "\". Using default value instead!");
addMessage(message, value);
}
@ -132,43 +124,31 @@ public class Messages
* <p>
* Missing translations will use their default value.
*/
private void populateMessageMap()
{
try (BufferedReader br = Files.newBufferedReader(textFile, StandardCharsets.UTF_8))
{
private void populateMessageMap() {
try (BufferedReader br = Files.newBufferedReader(textFile, StandardCharsets.UTF_8)) {
processFile(br, this::addMessage);
}
catch (FileNotFoundException e)
{
} catch (FileNotFoundException e) {
plugin.myLogger(Level.SEVERE, "Locale file \"" + textFile + "\" does not exist!");
e.printStackTrace();
}
catch (IOException e)
{
} catch (IOException e) {
plugin.myLogger(Level.SEVERE, "Could not read locale file! \"" + textFile + "\"");
e.printStackTrace();
}
final URL defaultFileUrl = Objects.requireNonNull(getClass().getClassLoader().getResource(DEFAULT_FILENAME));
try (BufferedReader br = new BufferedReader(
new InputStreamReader(defaultFileUrl.openStream(), StandardCharsets.UTF_8)))
{
new InputStreamReader(defaultFileUrl.openStream(), StandardCharsets.UTF_8))) {
processFile(br, this::addBackupMessage);
}
catch (FileNotFoundException e)
{
} catch (FileNotFoundException e) {
plugin.myLogger(Level.SEVERE, "Failed to load internal locale file!");
e.printStackTrace();
}
catch (IOException e)
{
} catch (IOException e) {
plugin.myLogger(Level.SEVERE, "Could not read internal locale file!");
e.printStackTrace();
}
for (final Message msg : Message.values())
if (!msg.equals(Message.EMPTY) && !messageMap.containsKey(msg))
{
if (!msg.equals(Message.EMPTY) && !messageMap.containsKey(msg)) {
plugin.myLogger(Level.WARNING, "Could not find translation of key: " + msg.name());
messageMap.put(msg, getFailureString(msg.name()));
}
@ -180,8 +160,7 @@ public class Messages
* @param key The key that could not be resolved.
* @return The default String to return in case a value could not be found for a given String.
*/
private String getFailureString(final String key)
{
private String getFailureString(final String key) {
return "Translation for key \"" + key + "\" not found! Contact server admin!";
}
@ -194,22 +173,20 @@ public class Messages
* @return The translated message of the provided {@link Message} and substitutes its variables for the provided
* values.
*/
public String getString(final Message msg, final String... values)
{
if (msg.equals(Message.EMPTY))
public String getString(final Message msg, final String... values) {
if (msg.equals(Message.EMPTY)) {
return "";
}
if (values.length != Message.getVariableCount(msg))
{
if (values.length != Message.getVariableCount(msg)) {
plugin.myLogger(Level.SEVERE,
"Expected " + Message.getVariableCount(msg) + " variables for key " + msg.name() +
" but only got " + values.length + ". This is a bug. Please contact pim16aap2!");
"Expected " + Message.getVariableCount(msg) + " variables for key " + msg.name() +
" but only got " + values.length + ". This is a bug. Please contact pim16aap2!");
return getFailureString(msg.name());
}
String value = messageMap.get(msg);
if (value != null)
{
if (value != null) {
for (int idx = 0; idx != values.length; ++idx)
value = value.replaceAll(Message.getVariableName(msg, idx), values[idx]);
return value;
@ -219,37 +196,30 @@ public class Messages
return getFailureString(msg.name());
}
private static void writeDefaultFiles(ArmoredElytra plugin)
{
try
{
private static void writeDefaultFiles(ArmoredElytra plugin) {
try {
getPackagedLocalizations(plugin).forEach(file -> plugin.saveResource(file, false));
}
catch (IOException e)
{
} catch (IOException e) {
plugin.myLogger(Level.SEVERE, "Failed to write default localization files!");
e.printStackTrace();
}
}
private static List<String> getPackagedLocalizations(ArmoredElytra plugin)
throws IOException
{
throws IOException {
final List<String> files = new ArrayList<>();
final Enumeration<URL> enumeration = plugin.getClass().getClassLoader().getResources("META-INF");
while (enumeration.hasMoreElements())
{
while (enumeration.hasMoreElements()) {
final URL url = enumeration.nextElement();
final JarURLConnection connection = (JarURLConnection) url.openConnection();
try (JarFile jarFile = connection.getJarFile())
{
try (JarFile jarFile = connection.getJarFile()) {
final Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements())
{
while (jarEntries.hasMoreElements()) {
final String name = jarEntries.nextElement().getName();
if (!name.contains("/") && (name.endsWith(".txt")))
if (!name.contains("/") && (name.endsWith(".txt"))) {
files.add(name);
}
}
}
}

View File

@ -3,11 +3,9 @@ package nl.pim16aap2.armoredElytra.util;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class UtilTest
{
class UtilTest {
@Test
void testSnakeToCamelCase()
{
void testSnakeToCamelCase() {
Assertions.assertEquals("testCase", Util.snakeToCamelCase("TeSt_Case"));
Assertions.assertEquals("testCase", Util.snakeToCamelCase("____test_case"));
Assertions.assertEquals("", Util.snakeToCamelCase("________"));