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

View File

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

View File

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

View File

@ -20,51 +20,41 @@ import java.lang.reflect.Field;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
public class CommandHandler implements CommandExecutor public class CommandHandler implements CommandExecutor {
{
private final ArmoredElytra plugin; private final ArmoredElytra plugin;
private static Field BY_KEY_FIELD; private static Field BY_KEY_FIELD;
private final ArmoredElytraBuilder armoredElytraBuilder; private final ArmoredElytraBuilder armoredElytraBuilder;
public CommandHandler(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager) public CommandHandler(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager) {
{
this.plugin = plugin; this.plugin = plugin;
armoredElytraBuilder = new ArmoredElytraBuilder(nbtEditor, durabilityManager, plugin.getConfigLoader(), plugin); armoredElytraBuilder = new ArmoredElytraBuilder(nbtEditor, durabilityManager, plugin.getConfigLoader(), plugin);
} }
@Override @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; Player player;
if (sender instanceof Player) if (sender instanceof Player) {
{
player = (Player) sender; player = (Player) sender;
if (plugin.getConfigLoader().uninstallMode()) if (plugin.getConfigLoader().uninstallMode()) {
{
plugin.messagePlayer(player, plugin.getMyMessages().getString(Message.MESSAGES_UNINSTALLMODE)); plugin.messagePlayer(player, plugin.getMyMessages().getString(Message.MESSAGES_UNINSTALLMODE));
return true; return true;
} }
if (cmd.getName().equalsIgnoreCase("ArmoredElytra")) if (cmd.getName().equalsIgnoreCase("ArmoredElytra")) {
if (args.length == 1 || args.length == 2) if (args.length == 1 || args.length == 2) {
{
ItemStack newElytra = null; ItemStack newElytra = null;
String tier = null; String tier = null;
Player receiver; Player receiver;
boolean allowed = false; boolean allowed = false;
if (args.length == 1) if (args.length == 1) {
{
receiver = player; receiver = player;
tier = args[0]; tier = args[0];
} } else {
else
{
receiver = Bukkit.getPlayer(args[0]); receiver = Bukkit.getPlayer(args[0]);
if (receiver == null) if (receiver == null) {
{
plugin.messagePlayer(player, ChatColor.RED, "Player \"" + args[0] + "\" not found!"); plugin.messagePlayer(player, ChatColor.RED, "Player \"" + args[0] + "\" not found!");
return true; return true;
} }
@ -72,56 +62,50 @@ public class CommandHandler implements CommandExecutor
} }
ArmorTier armorTier = ArmorTier.valueOfName(tier.toLowerCase()); ArmorTier armorTier = ArmorTier.valueOfName(tier.toLowerCase());
if (armorTier != null) if (armorTier != null) {
allowed = player.hasPermission("armoredelytra.give." + ArmorTier.getName(armorTier)); allowed = player.hasPermission("armoredelytra.give." + ArmorTier.getName(armorTier));
else } else {
{
plugin.messagePlayer(player, plugin.getMyMessages() plugin.messagePlayer(player, plugin.getMyMessages()
.getString(Message.MESSAGES_UNSUPPORTEDTIER)); .getString(Message.MESSAGES_UNSUPPORTEDTIER));
return false; return false;
} }
if (allowed) if (allowed) {
{
plugin.elytraReceivedMessage(receiver, armorTier); plugin.elytraReceivedMessage(receiver, armorTier);
plugin.giveArmoredElytraToPlayer(receiver, armoredElytraBuilder.newArmoredElytra(armorTier)); plugin.giveArmoredElytraToPlayer(receiver, armoredElytraBuilder.newArmoredElytra(armorTier));
} } else {
else
plugin.sendNoGivePermissionMessage(player, armorTier); plugin.sendNoGivePermissionMessage(player, armorTier);
}
return true; return true;
} }
} }
else } else {
{ if (plugin.getConfigLoader().uninstallMode()) {
if (plugin.getConfigLoader().uninstallMode())
{
plugin.myLogger(Level.INFO, "Plugin in uninstall mode! New Armored Elytras are not allowed!"); plugin.myLogger(Level.INFO, "Plugin in uninstall mode! New Armored Elytras are not allowed!");
return true; return true;
} }
if (args.length == 1 && if (args.length == 1 &&
(args[0].equalsIgnoreCase("listAvailableEnchantments") || (args[0].equalsIgnoreCase("listAvailableEnchantments") ||
args[0].equalsIgnoreCase("listEnchantments") || args[0].equalsIgnoreCase("listEnchantments") ||
args[0].equalsIgnoreCase("enchantments"))) args[0].equalsIgnoreCase("enchantments"))) {
{
listAvailableEnchantments(); listAvailableEnchantments();
return true; return true;
} }
if (args.length == 2) if (args.length == 2) {
{
final String tier = args[1]; final String tier = args[1];
player = Bukkit.getPlayer(args[0]); player = Bukkit.getPlayer(args[0]);
if (player != null) if (player != null) {
{
ArmorTier armorTier = ArmorTier.valueOfName(tier.toLowerCase()); ArmorTier armorTier = ArmorTier.valueOfName(tier.toLowerCase());
if (armorTier == null) if (armorTier == null) {
return false; return false;
}
plugin.elytraReceivedMessage(player, armorTier); plugin.elytraReceivedMessage(player, armorTier);
plugin.giveArmoredElytraToPlayer(player, armoredElytraBuilder.newArmoredElytra(armorTier)); plugin.giveArmoredElytraToPlayer(player, armoredElytraBuilder.newArmoredElytra(armorTier));
plugin.myLogger(Level.INFO, ("Giving an armored elytra of the " + ArmorTier.getArmor(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; return true;
} }
plugin.myLogger(Level.INFO, ("Player " + args[1] + " not found!")); plugin.myLogger(Level.INFO, ("Player " + args[1] + " not found!"));
@ -131,28 +115,22 @@ public class CommandHandler implements CommandExecutor
return false; return false;
} }
private void listAvailableEnchantments() private void listAvailableEnchantments() {
{ try {
try if (BY_KEY_FIELD == null) {
{
if (BY_KEY_FIELD == null)
{
BY_KEY_FIELD = Enchantment.class.getDeclaredField("byKey"); BY_KEY_FIELD = Enchantment.class.getDeclaredField("byKey");
BY_KEY_FIELD.setAccessible(true); BY_KEY_FIELD.setAccessible(true);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked") final Map<NamespacedKey, Enchantment> byKey = (Map<NamespacedKey, Enchantment>) BY_KEY_FIELD.get(null);
final Map<NamespacedKey, Enchantment> byKey = (Map<NamespacedKey, Enchantment>) BY_KEY_FIELD.get(null);
final StringBuilder sb = new StringBuilder("\nAvailable enchantments: \n"); final StringBuilder sb = new StringBuilder("\nAvailable enchantments: \n");
byKey.keySet().stream() byKey.keySet().stream()
.map(NamespacedKey::toString).sorted() .map(NamespacedKey::toString).sorted()
.forEach(name -> sb.append(" - ").append(name).append("\n")); .forEach(name -> sb.append(" - ").append(name).append("\n"));
Bukkit.getLogger().info(sb.toString()); Bukkit.getLogger().info(sb.toString());
} } catch (NoSuchFieldException | IllegalAccessException e) {
catch (NoSuchFieldException | IllegalAccessException e)
{
throw new RuntimeException("Failed to get registered enchantments!", 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.ArrayList;
import java.util.Random; import java.util.Random;
public class EventHandlers implements Listener public class EventHandlers implements Listener {
{
private final Random random = new Random(); private final Random random = new Random();
private final ArmoredElytra plugin; private final ArmoredElytra plugin;
private final NBTEditor nbtEditor; private final NBTEditor nbtEditor;
private final DurabilityManager durabilityManager; private final DurabilityManager durabilityManager;
public EventHandlers(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager) public EventHandlers(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager) {
{
this.plugin = plugin; this.plugin = plugin;
this.nbtEditor = nbtEditor; this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager; this.durabilityManager = durabilityManager;
initializeArmorEquipEvent(); initializeArmorEquipEvent();
} }
private void initializeArmorEquipEvent() private void initializeArmorEquipEvent() {
{
Bukkit.getPluginManager().registerEvents(new ArmorListener(new ArrayList<>()), plugin); Bukkit.getPluginManager().registerEvents(new ArmorListener(new ArrayList<>()), plugin);
Bukkit.getPluginManager().registerEvents(new DispenserArmorListener(), plugin); Bukkit.getPluginManager().registerEvents(new DispenserArmorListener(), plugin);
} }
// Make sure the player has the correct permission and that the item is not // Make sure the player has the correct permission and that the item is not
// broken. // broken.
private AllowedToWearEnum isAllowedToWear(ItemStack elytra, Player player, ArmorTier armorTier) private AllowedToWearEnum isAllowedToWear(ItemStack elytra, Player player, ArmorTier armorTier) {
{ if (armorTier.equals(ArmorTier.NONE)) {
if (armorTier.equals(ArmorTier.NONE))
return AllowedToWearEnum.ALLOWED; return AllowedToWearEnum.ALLOWED;
if (Util.isBroken(elytra)) }
if (Util.isBroken(elytra)) {
return AllowedToWearEnum.BROKEN; return AllowedToWearEnum.BROKEN;
if (!plugin.playerHasWearPerm(player, armorTier)) }
if (!plugin.playerHasWearPerm(player, armorTier)) {
return AllowedToWearEnum.NOPERMISSION; return AllowedToWearEnum.NOPERMISSION;
}
return AllowedToWearEnum.ALLOWED; return AllowedToWearEnum.ALLOWED;
} }
// Handle armored elytra durability loss. // Handle armored elytra durability loss.
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerDamage(EntityDamageEvent e) public void onPlayerDamage(EntityDamageEvent e) {
{ if (!(e.getEntity() instanceof final Player p)) {
if (!(e.getEntity() instanceof final Player p))
return; return;
}
final ItemStack elytra = p.getInventory().getChestplate(); final ItemStack elytra = p.getInventory().getChestplate();
if (elytra == null) if (elytra == null) {
return; return;
}
final ArmorTier armorTier = nbtEditor.getArmorTier(elytra); final ArmorTier armorTier = nbtEditor.getArmorTier(elytra);
if (armorTier == ArmorTier.NONE) if (armorTier == ArmorTier.NONE) {
return; return;
}
final DamageCause cause = e.getCause(); final DamageCause cause = e.getCause();
// The elytra doesn't receive any damage for these causes: // The elytra doesn't receive any damage for these causes:
if (cause == DamageCause.DROWNING || cause == DamageCause.STARVATION || cause == DamageCause.SUFFOCATION || 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; return;
}
final boolean removeDurability; final boolean removeDurability;
if (elytra.containsEnchantment(Enchantment.DURABILITY)) if (elytra.containsEnchantment(Enchantment.DURABILITY)) {
{
final int randomInt = random.nextInt(101); final int randomInt = random.nextInt(101);
final int enchantLevel = elytra.getEnchantmentLevel(Enchantment.DURABILITY); final int enchantLevel = elytra.getEnchantmentLevel(Enchantment.DURABILITY);
// Formula taken from: https://minecraft.fandom.com/wiki/Unbreaking#Usage // Formula taken from: https://minecraft.fandom.com/wiki/Unbreaking#Usage
final float removeDurabilityChance = 60 + 40f / (enchantLevel + 1); final float removeDurabilityChance = 60 + 40f / (enchantLevel + 1);
removeDurability = randomInt <= removeDurabilityChance; removeDurability = randomInt <= removeDurabilityChance;
} } else {
else
removeDurability = true; removeDurability = true;
}
// Even when we don't subtract durability, we still want to update the durability, so just subtract 0. // 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 durabilityLoss = removeDurability ? (int) Math.max(1, e.getDamage() / 4) : 0;
final int newDurability = durabilityManager.removeDurability(elytra, durabilityLoss, armorTier); final int newDurability = durabilityManager.removeDurability(elytra, durabilityLoss, armorTier);
if (durabilityManager.isBroken(newDurability, armorTier)) if (durabilityManager.isBroken(newDurability, armorTier)) {
Util.moveChestplateToInventory(p); Util.moveChestplateToInventory(p);
}
} }
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onMending(PlayerItemMendEvent e) public void onMending(PlayerItemMendEvent e) {
{
final ArmorTier armorTier = nbtEditor.getArmorTier(e.getItem()); final ArmorTier armorTier = nbtEditor.getArmorTier(e.getItem());
if (armorTier == ArmorTier.NONE) if (armorTier == ArmorTier.NONE) {
return; return;
}
final int newDurability = durabilityManager.removeDurability(e.getItem(), -e.getRepairAmount(), armorTier); 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 // 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. // interfering with the player XP change event that depends on the success of this one.
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () ->
durabilityManager.setDurability(e.getItem(), newDurability, armorTier), 1); durabilityManager.setDurability(e.getItem(), newDurability, armorTier), 1);
} }
@EventHandler @EventHandler
public void onEquip(ArmorEquipEvent e) public void onEquip(ArmorEquipEvent e) {
{
if (e.getMethod().equals(ArmorEquipEvent.EquipMethod.DEATH) || if (e.getMethod().equals(ArmorEquipEvent.EquipMethod.DEATH) ||
e.getMethod().equals(ArmorEquipEvent.EquipMethod.BROKE)) e.getMethod().equals(ArmorEquipEvent.EquipMethod.BROKE)) {
return; return;
}
if (!e.getType().equals(ArmorType.CHESTPLATE) || if (!e.getType().equals(ArmorType.CHESTPLATE) ||
e.getNewArmorPiece() == null || e.getNewArmorPiece() == null ||
!e.getNewArmorPiece().getType().equals(Material.ELYTRA)) !e.getNewArmorPiece().getType().equals(Material.ELYTRA)) {
return; return;
}
final ArmorTier armorTier = nbtEditor.getArmorTier(e.getNewArmorPiece()); final ArmorTier armorTier = nbtEditor.getArmorTier(e.getNewArmorPiece());
final AllowedToWearEnum allowed = isAllowedToWear(e.getNewArmorPiece(), e.getPlayer(), armorTier); final AllowedToWearEnum allowed = isAllowedToWear(e.getNewArmorPiece(), e.getPlayer(), armorTier);
switch (allowed) switch (allowed) {
{ case BROKEN -> {
case ALLOWED:
break;
case BROKEN:
plugin.messagePlayer(e.getPlayer(), plugin.getMyMessages().getString(Message.MESSAGES_REPAIRNEEDED)); plugin.messagePlayer(e.getPlayer(), plugin.getMyMessages().getString(Message.MESSAGES_REPAIRNEEDED));
e.setCancelled(true); e.setCancelled(true);
break; }
case NOPERMISSION: case NOPERMISSION -> {
plugin.usageDeniedMessage(e.getPlayer(), armorTier); plugin.usageDeniedMessage(e.getPlayer(), armorTier);
e.setCancelled(true); e.setCancelled(true);
break; }
default: case ALLOWED, default -> {
break; }
} }
} }
} }

View File

@ -10,14 +10,12 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.event.player.PlayerItemDamageEvent;
public class FlyDurabilityHandler implements Listener public class FlyDurabilityHandler implements Listener {
{
private final boolean disableDurability; private final boolean disableDurability;
private final NBTEditor nbtEditor; private final NBTEditor nbtEditor;
private final DurabilityManager durabilityManager; private final DurabilityManager durabilityManager;
public FlyDurabilityHandler(boolean disableDurability, NBTEditor nbtEditor, DurabilityManager durabilityManager) public FlyDurabilityHandler(boolean disableDurability, NBTEditor nbtEditor, DurabilityManager durabilityManager) {
{
this.disableDurability = disableDurability; this.disableDurability = disableDurability;
this.nbtEditor = nbtEditor; this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager; this.durabilityManager = durabilityManager;
@ -25,26 +23,30 @@ public class FlyDurabilityHandler implements Listener
// Do not decrease elytra durability while flying. // Do not decrease elytra durability while flying.
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onItemDamage(PlayerItemDamageEvent e) public void onItemDamage(PlayerItemDamageEvent e) {
{ if (e.getItem().getType() != Material.ELYTRA) {
if (e.getItem().getType() != Material.ELYTRA)
return; return;
}
if (!e.getPlayer().isGliding()) if (!e.getPlayer().isGliding()) {
return; return;
}
final ArmorTier armorTier = nbtEditor.getArmorTier(e.getItem()); final ArmorTier armorTier = nbtEditor.getArmorTier(e.getItem());
if (armorTier == ArmorTier.NONE) if (armorTier == ArmorTier.NONE) {
return; return;
}
// This also cancels durability decrease when it should (i.e. getting hit) while flying, // 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. // but that is likely to be rare enough for it to not matter.
e.setCancelled(true); e.setCancelled(true);
if (disableDurability) if (disableDurability) {
return; return;
}
final int newDurability = durabilityManager.removeDurability(e.getItem(), e.getDamage(), armorTier); final int newDurability = durabilityManager.removeDurability(e.getItem(), e.getDamage(), armorTier);
if (durabilityManager.isBroken(newDurability, armorTier)) if (durabilityManager.isBroken(newDurability, armorTier)) {
Util.moveChestplateToInventory(e.getPlayer()); 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.event.inventory.InventoryPickupItemEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
public class ItemDropListener implements Listener public class ItemDropListener implements Listener {
{
private final NBTEditor nbtEditor; private final NBTEditor nbtEditor;
public ItemDropListener(NBTEditor nbtEditor) public ItemDropListener(NBTEditor nbtEditor) {
{
this.nbtEditor = nbtEditor; this.nbtEditor = nbtEditor;
} }
@ -29,11 +27,11 @@ public class ItemDropListener implements Listener
* @param itemStack The dropped item to analyze. * @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. * @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 || if (itemStack == null || itemStack.getType() != Material.ELYTRA ||
nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE) nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE) {
return null; return null;
}
final ItemStack newDrop = new ItemStack(Material.NETHERITE_CHESTPLATE, 1); final ItemStack newDrop = new ItemStack(Material.NETHERITE_CHESTPLATE, 1);
newDrop.setItemMeta(itemStack.getItemMeta()); newDrop.setItemMeta(itemStack.getItemMeta());
@ -50,11 +48,11 @@ public class ItemDropListener implements Listener
* @param itemStack The picked-up item to analyze. * @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. * @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 || if (itemStack == null || itemStack.getType() != Material.NETHERITE_CHESTPLATE ||
nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE) nbtEditor.getArmorTier(itemStack) != ArmorTier.NETHERITE) {
return null; return null;
}
final ItemStack newDrop = new ItemStack(Material.ELYTRA, 1); final ItemStack newDrop = new ItemStack(Material.ELYTRA, 1);
newDrop.setItemMeta(itemStack.getItemMeta()); newDrop.setItemMeta(itemStack.getItemMeta());
@ -63,26 +61,26 @@ public class ItemDropListener implements Listener
} }
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) @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()); final ItemStack newDrop = getNewDrop(event.getEntity().getItemStack());
if (newDrop != null) if (newDrop != null) {
event.getEntity().setItemStack(newDrop); event.getEntity().setItemStack(newDrop);
}
} }
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onEntityPickup(EntityPickupItemEvent event) public void onEntityPickup(EntityPickupItemEvent event) {
{
final ItemStack newPickup = getNewPickup(event.getItem().getItemStack()); final ItemStack newPickup = getNewPickup(event.getItem().getItemStack());
if (newPickup != null) if (newPickup != null) {
event.getItem().setItemStack(newPickup); event.getItem().setItemStack(newPickup);
}
} }
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onInventoryPickup(InventoryPickupItemEvent event) public void onInventoryPickup(InventoryPickupItemEvent event) {
{
final ItemStack newPickup = getNewPickup(event.getItem().getItemStack()); final ItemStack newPickup = getNewPickup(event.getItem().getItemStack());
if (newPickup != null) if (newPickup != null) {
event.getItem().setItemStack(newPickup); event.getItem().setItemStack(newPickup);
}
} }
} }

View File

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

View File

@ -14,43 +14,42 @@ import org.bukkit.inventory.SmithingInventory;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class NetheriteUpgradeListener extends SmithingTableListener public class NetheriteUpgradeListener extends SmithingTableListener {
{
public NetheriteUpgradeListener(final ArmoredElytra plugin, NBTEditor nbtEditor, public NetheriteUpgradeListener(final ArmoredElytra plugin, NBTEditor nbtEditor,
DurabilityManager durabilityManager, ConfigLoader config) DurabilityManager durabilityManager, ConfigLoader config) {
{
super(plugin, false, nbtEditor, durabilityManager, config); super(plugin, false, nbtEditor, durabilityManager, config);
} }
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onSmithingTableUsage(final PrepareSmithingEvent event) public void onSmithingTableUsage(final PrepareSmithingEvent event) {
{
final SmithingInventory inventory = event.getInventory(); final SmithingInventory inventory = event.getInventory();
final ItemStack[] contents = inventory.getContents(); final ItemStack[] contents = inventory.getContents();
final ItemStack itemStackA = contents[0]; final ItemStack itemStackA = contents[0];
final ItemStack itemStackB = contents[1]; final ItemStack itemStackB = contents[1];
if (!validInput(itemStackA, itemStackB)) if (!validInput(itemStackA, itemStackB)) {
return; return;
}
if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), ArmorTier.NETHERITE)) if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), ArmorTier.NETHERITE)) {
return; return;
}
event.setResult(armoredElytraBuilder event.setResult(armoredElytraBuilder
.newBuilder() .newBuilder()
.ofElytra(itemStackA) .ofElytra(itemStackA)
.upgradeToTier(ArmorTier.NETHERITE) .upgradeToTier(ArmorTier.NETHERITE)
.build()); .build());
} }
private boolean validInput(@Nullable ItemStack itemStackA, @Nullable ItemStack itemStackB) private boolean validInput(@Nullable ItemStack itemStackA, @Nullable ItemStack itemStackB) {
{
if (itemStackA == null || itemStackB == null || if (itemStackA == null || itemStackB == null ||
itemStackA.getType() != Material.ELYTRA || itemStackA.getType() != Material.ELYTRA ||
plugin.getNbtEditor().getArmorTier(itemStackA) != ArmorTier.DIAMOND || plugin.getNbtEditor().getArmorTier(itemStackA) != ArmorTier.DIAMOND ||
itemStackB.getType() != Material.NETHERITE_INGOT) itemStackB.getType() != Material.NETHERITE_INGOT) {
return false; return false;
}
// For some reason, adding multiple netherite ingots causes the view to not update properly. // 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. // 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 @Override
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event) public void onInventoryClick(InventoryClickEvent event) {
{
super.onInventoryClick(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.ItemStack;
import org.bukkit.inventory.SmithingInventory; import org.bukkit.inventory.SmithingInventory;
public class SmithingTableCraftHandler extends SmithingTableListener public class SmithingTableCraftHandler extends SmithingTableListener {
{
public SmithingTableCraftHandler(final ArmoredElytra plugin, NBTEditor nbtEditor, public SmithingTableCraftHandler(final ArmoredElytra plugin, NBTEditor nbtEditor,
DurabilityManager durabilityManager, ConfigLoader config) DurabilityManager durabilityManager, ConfigLoader config) {
{
super(plugin, true, nbtEditor, durabilityManager, config); super(plugin, true, nbtEditor, durabilityManager, config);
// Register the anvil handler with creation disabled so AEs can still be repaired and stuff. // Register the anvil handler with creation disabled so AEs can still be repaired and stuff.
Bukkit.getPluginManager() Bukkit.getPluginManager()
.registerEvents(new AnvilHandler(plugin, false, nbtEditor, durabilityManager, config), plugin); .registerEvents(new AnvilHandler(plugin, false, nbtEditor, durabilityManager, config), plugin);
} }
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onSmithingTableUsage(final PrepareSmithingEvent event) public void onSmithingTableUsage(final PrepareSmithingEvent event) {
{
final SmithingInventory inventory = event.getInventory(); final SmithingInventory inventory = event.getInventory();
final ItemStack[] contents = inventory.getContents(); final ItemStack[] contents = inventory.getContents();
@ -35,28 +32,29 @@ public class SmithingTableCraftHandler extends SmithingTableListener
final ItemStack itemStackB = contents[1]; final ItemStack itemStackB = contents[1];
final ArmorTier newArmorTier = getNewArmorTier(itemStackA, itemStackB); final ArmorTier newArmorTier = getNewArmorTier(itemStackA, itemStackB);
if (newArmorTier == ArmorTier.NONE) if (newArmorTier == ArmorTier.NONE) {
return; return;
}
if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), newArmorTier)) if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), newArmorTier)) {
return; return;
}
event.setResult(armoredElytraBuilder.combine(itemStackA, itemStackB, newArmorTier, null)); 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 || if (itemStackA == null || itemStackB == null ||
itemStackA.getType() != Material.ELYTRA || !Util.isChestPlate(itemStackB)) itemStackA.getType() != Material.ELYTRA || !Util.isChestPlate(itemStackB)) {
return ArmorTier.NONE; return ArmorTier.NONE;
}
return Util.armorToTier(itemStackB.getType()); return Util.armorToTier(itemStackB.getType());
} }
@Override @Override
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event) public void onInventoryClick(InventoryClickEvent event) {
{
super.onInventoryClick(event); super.onInventoryClick(event);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,14 +21,13 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
public class NBTEditor public class NBTEditor {
{
private static final NamespacedKey ARMOR_TIER_KEY = new NamespacedKey(ArmoredElytra.getInstance(), 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(), 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(), 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. * 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. * @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. * @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 @Nullable ItemMeta meta = itemStack.getItemMeta();
final ArmorTier armorTier = providedTier == null ? getArmorTier(meta) : providedTier; final ArmorTier armorTier = providedTier == null ? getArmorTier(meta) : providedTier;
if (armorTier == ArmorTier.NONE) if (armorTier == ArmorTier.NONE) {
return -1; return -1;
}
if (!(meta instanceof Damageable)) if (!(meta instanceof Damageable)) {
throw new IllegalStateException("Item \"" + itemStack + "\" with meta \"" + meta + "\" is not Damageable!"); throw new IllegalStateException("Item \"" + itemStack + "\" with meta \"" + meta + "\" is not Damageable!");
}
final @Nullable Integer realDurability = final @Nullable Integer realDurability =
Objects.requireNonNull(meta, "Meta cannot be null for armored elytras!") Objects.requireNonNull(meta, "Meta cannot be null for armored elytras!")
.getPersistentDataContainer().get(DURABILITY_KEY, PersistentDataType.INTEGER); .getPersistentDataContainer().get(DURABILITY_KEY, PersistentDataType.INTEGER);
return realDurability == null ? -1 : realDurability; 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 * @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}. * 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); final ItemMeta meta = getOrCreateItemMeta(itemStack);
meta.getPersistentDataContainer().set(DURABILITY_KEY, PersistentDataType.INTEGER, realDurability); meta.getPersistentDataContainer().set(DURABILITY_KEY, PersistentDataType.INTEGER, realDurability);
if (meta instanceof Damageable) if (meta instanceof Damageable) {
((Damageable) meta).setDamage(displayDurability); ((Damageable) meta).setDamage(displayDurability);
}
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);
} }
@ -87,67 +87,73 @@ public class NBTEditor
* @return The NEW item. * @return The NEW item.
*/ */
public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, String name, public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, String name,
@Nullable List<String> lore, @Nullable Color color) @Nullable List<String> lore, @Nullable Color color) {
{ if (armorTier == null || armorTier == ArmorTier.NONE) {
if (armorTier == null || armorTier == ArmorTier.NONE)
return new ItemStack(item); return new ItemStack(item);
}
final ItemStack ret = new ItemStack(item); final ItemStack ret = new ItemStack(item);
final ItemMeta meta = getOrCreateItemMeta(ret); final ItemMeta meta = getOrCreateItemMeta(ret);
meta.getPersistentDataContainer().set(ARMOR_TIER_KEY, PersistentDataType.INTEGER, 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()); meta.getPersistentDataContainer().set(ARMOR_COLOR_KEY, PersistentDataType.INTEGER, color.asRGB());
}
overwriteNBTValue(meta, Attribute.GENERIC_ARMOR, ArmorTier.getArmor(armorTier), "generic.armor"); 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), 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), overwriteNBTValue(meta, Attribute.GENERIC_KNOCKBACK_RESISTANCE, ArmorTier.getKnockbackResistance(armorTier),
"generic.knockback_resistance"); "generic.knockback_resistance");
}
meta.setUnbreakable(unbreakable); meta.setUnbreakable(unbreakable);
meta.setDisplayName(name); meta.setDisplayName(name);
if (lore != null) if (lore != null) {
meta.setLore(lore); meta.setLore(lore);
}
ret.setItemMeta(meta); ret.setItemMeta(meta);
return ret; return ret;
} }
void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName) void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName) {
{ if (meta.hasAttributeModifiers()) {
if (meta.hasAttributeModifiers())
meta.removeAttributeModifier(attribute); meta.removeAttributeModifier(attribute);
}
final AttributeModifier attributeModifier = new AttributeModifier(UUID.randomUUID(), modifierName, value, final AttributeModifier attributeModifier = new AttributeModifier(UUID.randomUUID(), modifierName, value,
AttributeModifier.Operation.ADD_NUMBER, AttributeModifier.Operation.ADD_NUMBER,
EquipmentSlot.CHEST); EquipmentSlot.CHEST);
meta.addAttributeModifier(attribute, attributeModifier); meta.addAttributeModifier(attribute, attributeModifier);
} }
ArmorTier getArmorTier(@Nullable ItemMeta meta) ArmorTier getArmorTier(@Nullable ItemMeta meta) {
{ if (meta == null || !meta.hasAttributeModifiers()) {
if (meta == null || !meta.hasAttributeModifiers())
return ArmorTier.NONE; return ArmorTier.NONE;
}
final @Nullable Integer tierID = meta.getPersistentDataContainer() final @Nullable Integer tierID = meta.getPersistentDataContainer()
.get(ARMOR_TIER_KEY, PersistentDataType.INTEGER); .get(ARMOR_TIER_KEY, PersistentDataType.INTEGER);
if (tierID != null) if (tierID != null) {
return ArmorTier.getArmorTierFromID(tierID); return ArmorTier.getArmorTierFromID(tierID);
}
final Collection<AttributeModifier> attributeModifiers = meta.getAttributeModifiers(Attribute.GENERIC_ARMOR); final Collection<AttributeModifier> attributeModifiers = meta.getAttributeModifiers(Attribute.GENERIC_ARMOR);
if (attributeModifiers == null) if (attributeModifiers == null) {
return ArmorTier.NONE; return ArmorTier.NONE;
}
for (final AttributeModifier attributeModifier : attributeModifiers) for (final AttributeModifier attributeModifier : attributeModifiers) {
{
final ArmorTier armorTier = ArmorTier.getArmorTierFromArmor((int) attributeModifier.getAmount()); final ArmorTier armorTier = ArmorTier.getArmorTierFromArmor((int) attributeModifier.getAmount());
if (armorTier != ArmorTier.NONE) if (armorTier != ArmorTier.NONE) {
return armorTier; return armorTier;
}
} }
return ArmorTier.NONE; return ArmorTier.NONE;
@ -159,10 +165,10 @@ public class NBTEditor
* @param item The item to check. * @param item The item to check.
* @return The {@link ArmorTier} that is on the item. If none is found, {@link ArmorTier#NONE} is returned. * @return The {@link ArmorTier} that is on the item. If none is found, {@link ArmorTier#NONE} is returned.
*/ */
public ArmorTier getArmorTier(@Nullable ItemStack item) public ArmorTier getArmorTier(@Nullable ItemStack item) {
{ if (item == null) {
if (item == null)
return ArmorTier.NONE; return ArmorTier.NONE;
}
return getArmorTier(item.getItemMeta()); 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. * @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. * @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(); final @Nullable ItemMeta meta = item == null ? null : item.getItemMeta();
return meta != null && meta.isUnbreakable(); return meta != null && meta.isUnbreakable();
} }
@ -186,30 +191,32 @@ public class NBTEditor
* @param item The armored elytra to check. * @param item The armored elytra to check.
* @return The color of the armored elytra, if the input is a colored armored elytra, otherwise null. * @return The color of the armored elytra, if the input is a colored armored elytra, otherwise null.
*/ */
public Color getColorOfArmoredElytra(@Nullable ItemStack item) public Color getColorOfArmoredElytra(@Nullable ItemStack item) {
{ if (item == null || item.getType() != Material.ELYTRA || !item.hasItemMeta()) {
if (item == null || item.getType() != Material.ELYTRA || !item.hasItemMeta())
return null; return null;
}
final ItemMeta meta = item.getItemMeta(); final ItemMeta meta = item.getItemMeta();
if (meta == null) if (meta == null) {
return null; return null;
}
final PersistentDataContainer container = meta.getPersistentDataContainer(); final PersistentDataContainer container = meta.getPersistentDataContainer();
if (!container.has(ARMOR_COLOR_KEY, PersistentDataType.INTEGER)) if (!container.has(ARMOR_COLOR_KEY, PersistentDataType.INTEGER)) {
return null; return null;
}
final Integer rgb = container.get(ARMOR_COLOR_KEY, PersistentDataType.INTEGER); final Integer rgb = container.get(ARMOR_COLOR_KEY, PersistentDataType.INTEGER);
return rgb == null ? null : Color.fromRGB(rgb); return rgb == null ? null : Color.fromRGB(rgb);
} }
static ItemMeta getOrCreateItemMeta(ItemStack item) static ItemMeta getOrCreateItemMeta(ItemStack item) {
{
final ItemMeta meta = item.hasItemMeta() ? final ItemMeta meta = item.hasItemMeta() ?
item.getItemMeta() : item.getItemMeta() :
Bukkit.getItemFactory().getItemMeta(item.getType()); Bukkit.getItemFactory().getItemMeta(item.getType());
if (meta == null) if (meta == null) {
throw new IllegalArgumentException("Tried to add armor to invalid item: " + item); throw new IllegalArgumentException("Tried to add armor to invalid item: " + item);
}
return meta; return meta;
} }
} }

View File

@ -1,7 +1,6 @@
package nl.pim16aap2.armoredElytra.util; 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. * 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; package nl.pim16aap2.armoredElytra.util;
public enum AllowedToWearEnum public enum AllowedToWearEnum {
{
BROKEN, NOPERMISSION, ALLOWED BROKEN, NOPERMISSION, ALLOWED
} }

View File

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

View File

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

View File

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

View File

@ -12,8 +12,7 @@ import java.util.List;
* For Lists, every option appears on a new line after a '-'. * 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 ArmoredElytra plugin;
private final FileConfiguration config; private final FileConfiguration config;
private final String optionName; private final String optionName;
@ -22,8 +21,7 @@ public class ConfigOption<V>
private final String[] comment; private final String[] comment;
public ConfigOption(ArmoredElytra plugin, FileConfiguration config, String optionName, V defaultValue, public ConfigOption(ArmoredElytra plugin, FileConfiguration config, String optionName, V defaultValue,
String[] comment) String[] comment) {
{
this.plugin = plugin; this.plugin = plugin;
this.config = config; this.config = config;
this.optionName = optionName; this.optionName = optionName;
@ -33,63 +31,55 @@ public class ConfigOption<V>
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void setValue() private void setValue() {
{ try {
try
{
value = (V) config.get(optionName, defaultValue); 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 + 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)); plugin.myLogger(java.util.logging.Level.WARNING, Util.exceptionToString(e));
value = defaultValue; value = defaultValue;
} }
} }
public V getValue() public V getValue() {
{
return value; return value;
} }
public @Nullable String[] getComment() public @Nullable String[] getComment() {
{
return comment; return comment;
} }
public boolean hasComment() public boolean hasComment() {
{
return comment != null; return comment != null;
} }
@Override @Override
public String toString() public String toString() {
{ StringBuilder string = new StringBuilder();
String string = "";
// Print the comments, if there are any. // Print the comments, if there are any.
if (comment != null) if (comment != null) {
for (String comLine : comment) for (String comLine : comment)
// Prefix every line by a comment-sign (#). // Prefix every line by a comment-sign (#).
string += "# " + comLine + "\n"; string.append("# ").append(comLine).append("\n");
}
string += optionName + ": "; string.append(optionName).append(": ");
if (value.getClass().isAssignableFrom(String.class)) if (value.getClass().isAssignableFrom(String.class)) {
string += "\'" + value.toString() + "\'"; string.append("\'").append(value).append("\'");
else if (value instanceof List<?>) } else if (value instanceof List<?>) {
{
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("\n"); builder.append("\n");
int listSize = ((List<?>) value).size(); int listSize = ((List<?>) value).size();
for (int index = 0; index < listSize; ++index) for (int index = 0; index < listSize; ++index)
// Don't print newline at the end // Don't print newline at the end
builder.append(" - " + ((List<?>) value).get(index) + (index == listSize - 1 ? "" : "\n")); builder.append(" - ").append(((List<?>) value).get(index)).append(index == listSize - 1 ? "" : "\n");
string += builder.toString(); 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.List;
import java.util.Map; 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; 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 * @param plugin The {@link ArmoredElytra} instance to use for obtaining the list of allowed enchantments. See
* {@link ConfigLoader#allowedEnchantments()}. * {@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); this(enchantments);
filter(plugin.getConfigLoader().allowedEnchantments()); filter(plugin.getConfigLoader().allowedEnchantments());
filterMutuallyExclusive(); filterMutuallyExclusive();
@ -35,18 +33,15 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
/** /**
* Copy constructor. * Copy constructor.
*/ */
public EnchantmentContainer(EnchantmentContainer other) public EnchantmentContainer(EnchantmentContainer other) {
{
this(other.enchantments); this(other.enchantments);
} }
public EnchantmentContainer() public EnchantmentContainer() {
{
enchantments = new HashMap<>(); enchantments = new HashMap<>();
} }
private EnchantmentContainer(final Map<Enchantment, Integer> enchantments) private EnchantmentContainer(final Map<Enchantment, Integer> enchantments) {
{
this.enchantments = new HashMap<>(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. * @param plugin The {@link ArmoredElytra} instance to use.
* @return A new {@link EnchantmentContainer} with the enchantments from the item. * @return A new {@link EnchantmentContainer} with the enchantments from the item.
*/ */
public static EnchantmentContainer getEnchantmentsOf(final ItemStack is, final ArmoredElytra plugin) public static EnchantmentContainer getEnchantmentsOf(final ItemStack is, final ArmoredElytra plugin) {
{ if (is == null) {
if (is == null)
return new EnchantmentContainer(Collections.emptyMap(), plugin); return new EnchantmentContainer(Collections.emptyMap(), plugin);
}
return is.getType() == Material.ENCHANTED_BOOK ? return is.getType() == Material.ENCHANTED_BOOK ?
getEnchantmentsFromBook(is, plugin) : getEnchantmentsFromBook(is, plugin) :
getEnchantmentsFromItem(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. * @param plugin The {@link ArmoredElytra} instance to use.
* @return A new {@link EnchantmentContainer} with the enchantments from the item. * @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); 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. * @param plugin The {@link ArmoredElytra} instance to use.
* @return A new enchantment container with the enchantments from the book. * @return A new enchantment container with the enchantments from the book.
*/ */
private static EnchantmentContainer getEnchantmentsFromBook(final ItemStack is, final ArmoredElytra plugin) private static EnchantmentContainer getEnchantmentsFromBook(final ItemStack is, final ArmoredElytra plugin) {
{ if (!is.hasItemMeta()) {
if (!is.hasItemMeta())
return new EnchantmentContainer(new HashMap<>(0), plugin); return new EnchantmentContainer(new HashMap<>(0), plugin);
}
final EnchantmentStorageMeta meta = (EnchantmentStorageMeta) is.getItemMeta(); 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(new HashMap<>(0), plugin);
}
return new EnchantmentContainer(meta.getStoredEnchants(), 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 * @param enchantment The enchantment to get the mutually exclusives of
* @return A linked list containing all the mutually exclusive enchantments * @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<>(); final List<Enchantment> enchantments = new LinkedList<>();
for (final List<Enchantment> mutuallyExclusiveEnchantments : for (final List<Enchantment> mutuallyExclusiveEnchantments :
ArmoredElytra.getInstance().getConfigLoader().getMutuallyExclusiveEnchantments()) ArmoredElytra.getInstance().getConfigLoader().getMutuallyExclusiveEnchantments()) {
{ for (Enchantment mutuallyExclusiveEnchantment : mutuallyExclusiveEnchantments) {
for (Enchantment mutuallyExclusiveEnchantment : mutuallyExclusiveEnchantments) if (mutuallyExclusiveEnchantment.equals(enchantment)) {
{
if (mutuallyExclusiveEnchantment.equals(enchantment))
{
enchantments.addAll( enchantments.addAll(
mutuallyExclusiveEnchantments.stream().filter(i -> !i.equals(enchantment)).toList()); mutuallyExclusiveEnchantments.stream().filter(i -> !i.equals(enchantment)).toList());
break; break;
} }
} }
@ -129,8 +120,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
* *
* @return The total number of enchantments in this container. * @return The total number of enchantments in this container.
*/ */
public int getEnchantmentCount() public int getEnchantmentCount() {
{
return enchantments.size(); 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. * @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) public void filter(final Collection<Enchantment> allowed) {
{ if (!enchantments.isEmpty()) {
if (!enchantments.isEmpty())
enchantments.keySet().retainAll(allowed); enchantments.keySet().retainAll(allowed);
}
} }
/** /**
* Remove any entries from the list of enchantments that are mutually exclusive to each other. * 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 * <br>First instance of a mutually exclusive enchantment gets priority
*/ */
private void filterMutuallyExclusive() private void filterMutuallyExclusive() {
{
final List<Enchantment> disallowedEnchantments = new LinkedList<>(); final List<Enchantment> disallowedEnchantments = new LinkedList<>();
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
{ if (disallowedEnchantments.contains(entry.getKey())) {
if (disallowedEnchantments.contains(entry.getKey())) continue; continue;
}
disallowedEnchantments.addAll(getMutuallyExclusiveEnchantments(entry.getKey())); disallowedEnchantments.addAll(getMutuallyExclusiveEnchantments(entry.getKey()));
} }
disallowedEnchantments.forEach(enchantments.keySet()::remove); 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. * @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 // Clear enchantments before applying new ones
for (Enchantment enchantment : is.getEnchantments().keySet()) for (Enchantment enchantment : is.getEnchantments().keySet())
is.removeEnchantment(enchantment); is.removeEnchantment(enchantment);
@ -177,18 +166,17 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
/** /**
* Merges this container with another one. * Merges this container with another one.
*/ */
public void merge(EnchantmentContainer other) public void merge(EnchantmentContainer other) {
{ if (this == other) {
if (this == other)
throw new IllegalArgumentException("EnchantmentContainers cannot be combined with themselves!"); throw new IllegalArgumentException("EnchantmentContainers cannot be combined with themselves!");
}
enchantments = merge(enchantments, other.enchantments); enchantments = merge(enchantments, other.enchantments);
} }
/** /**
* Gets the number of enchantments in this container. * Gets the number of enchantments in this container.
*/ */
public int size() public int size() {
{
return enchantments.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. * @return True if there are exactly 0 enchantments in this container.
*/ */
public boolean isEmpty() public boolean isEmpty() {
{
return enchantments.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. * @param second The second enchantment container. In case of conflicts, this will take precedence.
* @return The new map of enchantments. * @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)); 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. * @return The new map of enchantments.
*/ */
private static Map<Enchantment, Integer> merge(final Map<Enchantment, Integer> first, private static Map<Enchantment, Integer> merge(final Map<Enchantment, Integer> first,
final Map<Enchantment, Integer> second) final Map<Enchantment, Integer> second) {
{ if (second == null || second.isEmpty()) {
if (second == null || second.isEmpty())
return first; return first;
}
if (first == null || first.isEmpty()) if (first == null || first.isEmpty()) {
return second; return second;
}
final List<Enchantment> blackList = final List<Enchantment> blackList =
second.keySet().stream() second.keySet().stream()
.flatMap(ench -> getMutuallyExclusiveEnchantments(ench).stream()) .flatMap(ench -> getMutuallyExclusiveEnchantments(ench).stream())
.toList(); .toList();
blackList.forEach(first.keySet()::remove); blackList.forEach(first.keySet()::remove);
final Map<Enchantment, Integer> combined = new HashMap<>(first); 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 // Check for enchants with higher level
Integer enchantLevel = combined.get(entry.getKey()); Integer enchantLevel = combined.get(entry.getKey());
if (enchantLevel != null) if (enchantLevel != null) {
{
final int oldLevel = enchantLevel; 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; enchantLevel = entry.getValue() + 1;
else if (entry.getValue() > enchantLevel) } else if (entry.getValue() > enchantLevel) {
enchantLevel = entry.getValue(); enchantLevel = entry.getValue();
}
if (enchantLevel != oldLevel) if (enchantLevel != oldLevel) {
combined.put(entry.getKey(), enchantLevel); combined.put(entry.getKey(), enchantLevel);
} }
else } else {
combined.put(entry.getKey(), entry.getValue()); combined.put(entry.getKey(), entry.getValue());
}
} }
return combined; return combined;
} }
@Override @Override
public String toString() public String toString() {
{
StringBuilder sb = new StringBuilder("["); StringBuilder sb = new StringBuilder("[");
enchantments.forEach((k, v) -> sb.append("\"").append(k).append("\" (").append(v).append("), ")); enchantments.forEach((k, v) -> sb.append("\"").append(k).append("\" (").append(v).append("), "));
String ret = sb.toString(); String ret = sb.toString();
@ -270,8 +256,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
} }
@Override @Override
public Iterator<Map.Entry<Enchantment, Integer>> iterator() public Iterator<Map.Entry<Enchantment, Integer>> iterator() {
{
return enchantments.entrySet().iterator(); return enchantments.entrySet().iterator();
} }
} }

View File

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

View File

@ -34,22 +34,22 @@ import java.util.regex.Pattern;
* *
* @author Parker Hawke - 2008Choco * @author Parker Hawke - 2008Choco
*/ */
public final class UpdateChecker public final class UpdateChecker {
{
public static final IVersionScheme VERSION_SCHEME_DECIMAL = (first, second) -> public static final IVersionScheme VERSION_SCHEME_DECIMAL = (first, second) ->
{ {
String[] firstSplit = splitVersionInfo(first), secondSplit = splitVersionInfo(second); String[] firstSplit = splitVersionInfo(first), secondSplit = splitVersionInfo(second);
if (firstSplit == null || secondSplit == null) if (firstSplit == null || secondSplit == null) {
return 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]); int currentValue = NumberUtils.toInt(firstSplit[i]), newestValue = NumberUtils.toInt(secondSplit[i]);
if (newestValue > currentValue) if (newestValue > currentValue) {
return second; return second;
else if (newestValue < currentValue) } else if (newestValue < currentValue) {
return first; return first;
}
} }
return (secondSplit.length > firstSplit.length) ? second : first; return (secondSplit.length > firstSplit.length) ? second : first;
@ -67,8 +67,7 @@ public final class UpdateChecker
private final int pluginID; private final int pluginID;
private final IVersionScheme versionScheme; 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.plugin = plugin;
this.pluginID = pluginID; this.pluginID = pluginID;
this.versionScheme = versionScheme; this.versionScheme = versionScheme;
@ -80,66 +79,59 @@ public final class UpdateChecker
* *
* @return a future update result * @return a future update result
*/ */
public CompletableFuture<UpdateResult> requestUpdateCheck() public CompletableFuture<UpdateResult> requestUpdateCheck() {
{
return CompletableFuture.supplyAsync( return CompletableFuture.supplyAsync(
() -> () ->
{
int responseCode;
try
{ {
URL url = new URL(String.format(UPDATE_URL, pluginID)); int responseCode;
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); try {
connection.addRequestProperty("User-Agent", USER_AGENT); 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()); InputStreamReader reader = new InputStreamReader(connection.getInputStream());
responseCode = connection.getResponseCode(); responseCode = connection.getResponseCode();
JsonElement element = new JsonParser().parse(reader); JsonElement element = new JsonParser().parse(reader);
if (!element.isJsonArray()) 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); 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") return new UpdateResult(responseCode == 401 ?
.getAsString(); UpdateReason.UNAUTHORIZED_QUERY : UpdateReason.UNKNOWN_ERROR);
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);
});
} }
/** /**
@ -148,8 +140,7 @@ public final class UpdateChecker
* @param updateTime A moment in time to compare the current time to. * @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. * @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(); long currentTime = Instant.now().getEpochSecond();
return currentTime - updateTime; return currentTime - updateTime;
} }
@ -160,16 +151,15 @@ public final class UpdateChecker
* *
* @return the last update check result. null if none. * @return the last update check result. null if none.
*/ */
public UpdateResult getLastResult() public UpdateResult getLastResult() {
{
return lastResult; return lastResult;
} }
private static String[] splitVersionInfo(String version) private static String[] splitVersionInfo(String version) {
{
Matcher matcher = DECIMAL_SCHEME_PATTERN.matcher(version); Matcher matcher = DECIMAL_SCHEME_PATTERN.matcher(version);
if (!matcher.find()) if (!matcher.find()) {
return null; return null;
}
return matcher.group().split("\\."); return matcher.group().split("\\.");
} }
@ -186,8 +176,7 @@ public final class UpdateChecker
* @param versionScheme a custom version scheme parser. Cannot be null * @param versionScheme a custom version scheme parser. Cannot be null
* @return the UpdateChecker instance * @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"); Preconditions.checkArgument(pluginID > 0, "Plugin ID must be greater than 0");
return (instance == null) ? instance = new UpdateChecker(plugin, pluginID, versionScheme) : instance; return (instance == null) ? instance = new UpdateChecker(plugin, pluginID, versionScheme) : instance;
@ -204,8 +193,7 @@ public final class UpdateChecker
* value must be greater than 0 * value must be greater than 0
* @return the UpdateChecker instance * @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); return init(plugin, pluginID, VERSION_SCHEME_DECIMAL);
} }
@ -215,10 +203,9 @@ public final class UpdateChecker
* *
* @return the UpdateChecker instance * @return the UpdateChecker instance
*/ */
public static UpdateChecker get() public static UpdateChecker get() {
{
Preconditions.checkState(instance != null, 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; return instance;
} }
@ -228,8 +215,7 @@ public final class UpdateChecker
* *
* @return true if initialized, false otherwise * @return true if initialized, false otherwise
*/ */
public static boolean isInitialized() public static boolean isInitialized() {
{
return instance != null; return instance != null;
} }
@ -237,8 +223,7 @@ public final class UpdateChecker
* A functional interface to compare two version Strings with similar version schemes. * A functional interface to compare two version Strings with similar version schemes.
*/ */
@FunctionalInterface @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 * 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}. * A constant reason for the result of {@link UpdateResult}.
*/ */
public enum UpdateReason public enum UpdateReason {
{
/** /**
* A new update is available for download. * 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()}. * 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 UpdateReason reason;
private final String newestVersion; private final String newestVersion;
private final long age; private final long age;
@ -317,18 +300,16 @@ public final class UpdateChecker
lastResult = this; 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.reason = reason;
this.newestVersion = newestVersion; this.newestVersion = newestVersion;
this.age = age; this.age = age;
} }
private UpdateResult(final UpdateReason reason) private UpdateResult(final UpdateReason reason) {
{
Preconditions Preconditions
.checkArgument(reason != UpdateReason.NEW_UPDATE && reason != UpdateReason.UP_TO_DATE, .checkArgument(reason != UpdateReason.NEW_UPDATE && reason != UpdateReason.UP_TO_DATE,
"Reasons that might require updates must also provide the latest version String"); "Reasons that might require updates must also provide the latest version String");
this.reason = reason; this.reason = reason;
newestVersion = plugin.getDescription().getVersion(); newestVersion = plugin.getDescription().getVersion();
age = -1; age = -1;
@ -339,8 +320,7 @@ public final class UpdateChecker
* *
* @return the reason * @return the reason
*/ */
public UpdateReason getReason() public UpdateReason getReason() {
{
return reason; return reason;
} }
@ -349,8 +329,7 @@ public final class UpdateChecker
* *
* @return true if requires update, false otherwise * @return true if requires update, false otherwise
*/ */
public boolean requiresUpdate() public boolean requiresUpdate() {
{
return reason == UpdateReason.NEW_UPDATE; return reason == UpdateReason.NEW_UPDATE;
} }
@ -360,8 +339,7 @@ public final class UpdateChecker
* *
* @return the newest version of the plugin * @return the newest version of the plugin
*/ */
public String getNewestVersion() public String getNewestVersion() {
{
return newestVersion; 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. * @return The number of seconds since the last update was released or -1 if unavailable.
*/ */
public long getAge() public long getAge() {
{
return age; return age;
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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