Renames packages, and adds code for storing original metadata

This commit is contained in:
Kristian Knarvik 2023-03-19 13:03:13 +01:00
parent 5730d41bc6
commit 20e1bc4550
53 changed files with 1032 additions and 597 deletions

14
pom.xml
View File

@ -2,7 +2,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>nl.pim16aap2.armoredElytra</groupId> <groupId>net.knarcraft.armoredElytra</groupId>
<artifactId>ArmoredElytra</artifactId> <artifactId>ArmoredElytra</artifactId>
<version>3.0</version> <version>3.0</version>
@ -17,10 +17,10 @@
<version.maven.surefire>3.0.0-M5</version.maven.surefire> <version.maven.surefire>3.0.0-M5</version.maven.surefire>
<version.spigot>1.17.1-R0.1-SNAPSHOT</version.spigot> <version.spigot>1.17.1-R0.1-SNAPSHOT</version.spigot>
<version.bstats>2.2.1</version.bstats> <version.bstats>3.0.1</version.bstats>
<version.checkstyle>9.1</version.checkstyle> <version.checkstyle>10.8.1</version.checkstyle>
<version.mockito>4.0.0</version.mockito> <version.mockito>4.0.0</version.mockito>
<version.junit>5.8.1</version.junit> <version.junit>5.9.2</version.junit>
</properties> </properties>
<repositories> <repositories>
@ -84,6 +84,12 @@
<version>${version.mockito}</version> <version>${version.mockito}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>20.1.0</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -1,22 +1,22 @@
package nl.pim16aap2.armoredElytra; package net.knarcraft.armoredelytra;
import nl.pim16aap2.armoredElytra.handlers.AnvilHandler; import net.knarcraft.armoredelytra.command.ArmoredElytraCommand;
import nl.pim16aap2.armoredElytra.handlers.CommandHandler; import net.knarcraft.armoredelytra.config.ConfigLoader;
import nl.pim16aap2.armoredElytra.handlers.EventHandlers; import net.knarcraft.armoredelytra.config.message.Message;
import nl.pim16aap2.armoredElytra.handlers.FlyDurabilityHandler; import net.knarcraft.armoredelytra.config.message.Messages;
import nl.pim16aap2.armoredElytra.handlers.ItemDropListener; import net.knarcraft.armoredelytra.container.ArmorTierName;
import nl.pim16aap2.armoredElytra.handlers.NetheriteUpgradeListener; import net.knarcraft.armoredelytra.listener.AnvilListener;
import nl.pim16aap2.armoredElytra.handlers.SmithingTableCraftHandler; import net.knarcraft.armoredelytra.listener.FlyDurabilityListener;
import nl.pim16aap2.armoredElytra.handlers.Uninstaller; import net.knarcraft.armoredelytra.listener.ItemDropListener;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.listener.NetheriteUpgradeListener;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.listener.PlayerEventListener;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.listener.SmithingTableCraftHandler;
import nl.pim16aap2.armoredElytra.util.ArmorTierName; import net.knarcraft.armoredelytra.listener.Uninstaller;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.MinecraftVersion; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.UpdateManager; import net.knarcraft.armoredelytra.property.ArmorTier;
import nl.pim16aap2.armoredElytra.util.messages.Message; import net.knarcraft.armoredelytra.property.MinecraftVersion;
import nl.pim16aap2.armoredElytra.util.messages.Messages; import net.knarcraft.armoredelytra.update.UpdateManager;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
@ -35,8 +35,8 @@ 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(
.get(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]); Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]);
private static ArmoredElytra INSTANCE; private static ArmoredElytra INSTANCE;
private Messages messages; private Messages messages;
@ -81,18 +81,18 @@ public class ArmoredElytra extends JavaPlugin implements Listener {
"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 PlayerEventListener(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 ArmoredElytraCommand(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 FlyDurabilityListener(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 AnvilListener(this, true, nbtEditor, durabilityManager, config);
Bukkit.getPluginManager().registerEvents(creationListener, this); Bukkit.getPluginManager().registerEvents(creationListener, this);
if (config.allowUpgradeToNetherite()) { if (config.allowUpgradeToNetherite()) {
@ -114,10 +114,6 @@ public class ArmoredElytra extends JavaPlugin implements Listener {
} }
} }
public MinecraftVersion getMinecraftVersion() {
return minecraftVersion;
}
public Messages getMyMessages() { public Messages getMyMessages() {
return messages; return messages;
} }
@ -178,7 +174,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener {
// 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_USAGE_DENIED, armorTier);
if (!message.equals("NONE")) { if (!message.equals("NONE")) {
messagePlayer(player, ChatColor.RED, message); messagePlayer(player, ChatColor.RED, message);
} }
@ -186,14 +182,14 @@ public class ArmoredElytra extends JavaPlugin implements Listener {
// 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_ELYTRA_RECEIVED, 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_NO_GIVE_PERMISSION, armorTier);
messagePlayer(player, ChatColor.RED, message); messagePlayer(player, ChatColor.RED, message);
} }

View File

@ -1,11 +1,11 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.command;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder.ArmoredElytraBuilder; import net.knarcraft.armoredelytra.config.message.Message;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.metadata.builder.ArmoredElytraBuilder;
import nl.pim16aap2.armoredElytra.util.messages.Message; import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
@ -14,40 +14,39 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field; 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 ArmoredElytraCommand 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 ArmoredElytraCommand(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(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull 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_UNINSTALL_MODE));
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; String tier;
String tier = null;
Player receiver; Player receiver;
boolean allowed = false; boolean allowed;
if (args.length == 1) { if (args.length == 1) {
receiver = player; receiver = player;
@ -66,7 +65,7 @@ public class CommandHandler implements CommandExecutor {
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_UNSUPPORTED_TIER));
return false; return false;
} }

View File

@ -1,6 +1,8 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.config;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import net.knarcraft.armoredelytra.property.ArmorTier;
import net.knarcraft.armoredelytra.util.GenericUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
@ -96,7 +98,7 @@ public class ConfigLoader {
"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 chest-plates 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."
}; };
@ -172,7 +174,7 @@ public class ConfigLoader {
// Only the first one should have the comment. // Only the first one should have the comment.
final @Nullable String[] comment = armorTierId == 1 ? repairComment : null; final @Nullable String[] comment = armorTierId == 1 ? repairComment : null;
final String name = Util.snakeToCamelCase(ArmorTier.getRepairItem(armorTier).name()); final String name = GenericUtil.snakeToCamelCase(ArmorTier.getRepairItem(armorTier).name());
final int defaultRepairCount = ArmorTier.getDefaultRepairCount(armorTier); final int defaultRepairCount = ArmorTier.getDefaultRepairCount(armorTier);
repairCounts[armorTierId] = addNewConfigOption(config, name, defaultRepairCount, comment); repairCounts[armorTierId] = addNewConfigOption(config, name, defaultRepairCount, comment);

View File

@ -1,6 +1,7 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.config;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import net.knarcraft.armoredelytra.util.GenericUtil;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -37,7 +38,7 @@ public class ConfigOption<V> {
} 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, GenericUtil.exceptionToString(e));
value = defaultValue; value = defaultValue;
} }
} }
@ -67,7 +68,7 @@ public class ConfigOption<V> {
string.append(optionName).append(": "); string.append(optionName).append(": ");
if (value.getClass().isAssignableFrom(String.class)) { if (value.getClass().isAssignableFrom(String.class)) {
string.append("\'").append(value).append("\'"); 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");

View File

@ -1,11 +1,12 @@
package nl.pim16aap2.armoredElytra.util.messages; package net.knarcraft.armoredelytra.config.message;
/** /**
* Represents a localizable message. * Represents a message able to be localized.
* *
* @author Pim * @author Pim
*/ */
public enum Message implements MessageVariable { public enum Message implements MessageVariable {
EMPTY(), EMPTY(),
TIER_LEATHER(), TIER_LEATHER(),
@ -22,14 +23,14 @@ public enum Message implements MessageVariable {
TIER_SHORT_DIAMOND(), TIER_SHORT_DIAMOND(),
TIER_SHORT_NETHERITE(), TIER_SHORT_NETHERITE(),
MESSAGES_UNINSTALLMODE(), MESSAGES_UNINSTALL_MODE(),
MESSAGES_UNSUPPORTEDTIER(), MESSAGES_UNSUPPORTED_TIER(),
MESSAGES_REPAIRNEEDED(), MESSAGES_REPAIR_NEEDED(),
MESSAGES_LORE(VARIABLE_TIER_NAME, VARIABLE_TIER_NAME_SHORT), MESSAGES_LORE(VARIABLE_TIER_NAME, VARIABLE_TIER_NAME_SHORT),
MESSAGES_NOGIVEPERMISSION(VARIABLE_TIER_NAME, VARIABLE_TIER_NAME_SHORT), MESSAGES_NO_GIVE_PERMISSION(VARIABLE_TIER_NAME, VARIABLE_TIER_NAME_SHORT),
MESSAGES_USAGEDENIED(VARIABLE_TIER_NAME, VARIABLE_TIER_NAME_SHORT), MESSAGES_USAGE_DENIED(VARIABLE_TIER_NAME, VARIABLE_TIER_NAME_SHORT),
MESSAGES_ELYTRARECEIVED(VARIABLE_TIER_NAME, VARIABLE_TIER_NAME_SHORT), MESSAGES_ELYTRA_RECEIVED(VARIABLE_TIER_NAME, VARIABLE_TIER_NAME_SHORT),
; ;
@ -61,7 +62,7 @@ public enum Message implements MessageVariable {
} }
/** /**
* Gets the names of the variables for the given message.. * Gets the names of the variables for the given message.
* *
* @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.
@ -79,4 +80,5 @@ public enum Message implements MessageVariable {
public static int getVariableCount(final Message msg) { public static int getVariableCount(final Message msg) {
return msg.variableNames.length; return msg.variableNames.length;
} }
} }

View File

@ -1,7 +1,7 @@
package nl.pim16aap2.armoredElytra.util.messages; package net.knarcraft.armoredelytra.config.message;
/** /**
* Represents supported variables in localizable messages. * Represents supported variables in localize-able messages.
* *
* @author Pim * @author Pim
*/ */

View File

@ -1,6 +1,6 @@
package nl.pim16aap2.armoredElytra.util.messages; package net.knarcraft.armoredelytra.config.message;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -24,6 +24,7 @@ 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";
/** /**
@ -65,10 +66,9 @@ public class Messages {
* *
* @param br The {@link BufferedReader} that supplies the text. * @param br The {@link BufferedReader} that supplies the text.
* @param action The action to take for every message and value combination that is encountered. * @param action The action to take for every message and value combination that is encountered.
* @throws IOException * @throws IOException <p>If a problem occurs during the processing of the file</p>
*/ */
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) {
@ -225,4 +225,5 @@ public class Messages {
} }
return files; return files;
} }
} }

View File

@ -1,9 +1,10 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.container;
/** /**
* @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) {
@ -26,4 +27,5 @@ public class ArmorTierName {
public void setShortName(final String shortName) { public void setShortName(final String shortName) {
this.shortName = shortName; this.shortName = shortName;
} }
} }

View File

@ -1,6 +1,7 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.container;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import net.knarcraft.armoredelytra.config.ConfigLoader;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -151,9 +152,9 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
} }
/** /**
* Applies the enchantments to an itemstack. * Applies the enchantments to an item-stack.
* *
* @param is The itemstack to apply the enchantments to. * @param is The item-stack 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
@ -219,7 +220,7 @@ public class EnchantmentContainer implements Iterable<Map.Entry<Enchantment, Int
final List<Enchantment> blackList = final List<Enchantment> blackList =
second.keySet().stream() second.keySet().stream()
.flatMap(ench -> getMutuallyExclusiveEnchantments(ench).stream()) .flatMap(enchantment -> getMutuallyExclusiveEnchantments(enchantment).stream())
.toList(); .toList();
blackList.forEach(first.keySet()::remove); blackList.forEach(first.keySet()::remove);

View File

@ -1,20 +1,24 @@
package nl.pim16aap2.armoredElytra.lib.armorequip; package net.knarcraft.armoredelytra.event;
import net.knarcraft.armoredelytra.property.ArmorChangeMethod;
import net.knarcraft.armoredelytra.property.ArmorType;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable; import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent; import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/** /**
* @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 ArmorChangeMethod equipType;
private final ArmorType type; private final ArmorType type;
private ItemStack oldArmorPiece, newArmorPiece; private ItemStack oldArmorPiece, newArmorPiece;
@ -26,7 +30,7 @@ public final class ArmorEquipEvent extends PlayerEvent implements Cancellable {
* @param oldArmorPiece The ItemStack of the armor removed. * @param oldArmorPiece The ItemStack of the armor removed.
* @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 ArmorChangeMethod 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;
@ -40,6 +44,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.
*/ */
@SuppressWarnings("unused")
public static HandlerList getHandlerList() { public static HandlerList getHandlerList() {
return handlers; return handlers;
} }
@ -50,7 +55,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 HandlerList getHandlers() { public @NotNull HandlerList getHandlers() {
return handlers; return handlers;
} }
@ -79,67 +84,36 @@ public final class ArmorEquipEvent extends PlayerEvent implements Cancellable {
} }
/** /**
* Returns the last equipped armor piece, could be a piece of armor, {@link Material#Air}, or null. * Gets the previous (current) item in the armor slot.
*
* @return <p>The previously equipped armor piece, could be a piece of armor, {@link Material#AIR}, or null.</p>
*/ */
public ItemStack getOldArmorPiece() { public ItemStack getOldArmorPiece() {
return oldArmorPiece; return oldArmorPiece;
} }
public 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 ItemStack getNewArmorPiece() { public ItemStack getNewArmorPiece() {
return newArmorPiece; return newArmorPiece;
} }
public 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 un-equip an armor piece.
*/ */
public EquipMethod getMethod() { public ArmorChangeMethod getMethod() {
return equipType; return equipType;
} }
public enum EquipMethod {
/**
* When you shift click an armor piece to equip or unequip
*/
SHIFT_CLICK,
/**
* When you drag and drop the item to equip or unequip
*/
DRAG,
/**
* When you manually equip or unequip the item. Use to be DRAG
*/
PICK_DROP,
/**
* When you right click an armor piece in the hotbar without the inventory open to equip.
*/
HOTBAR,
/**
* When you press the hotbar slot number while hovering over the armor slot to equip or unequip
*/
HOTBAR_SWAP,
/**
* When in range of a dispenser that shoots an armor piece to equip.<br> Requires the spigot version to have
* {@link org.bukkit.event.block.BlockDispenseArmorEvent} implemented.
*/
DISPENSER,
/**
* When an armor piece is removed due to it losing all durability.
*/
BROKE,
/**
* When you die causing all armor to unequip
*/
DEATH,
}
} }

View File

@ -1,12 +1,12 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.config.ConfigLoader;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.Action; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.property.Action;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.property.ArmorTier;
import nl.pim16aap2.armoredElytra.util.Util; import net.knarcraft.armoredelytra.util.GenericUtil;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -23,17 +23,12 @@ 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 AnvilListener extends ArmoredElytraHandler implements Listener {
protected AnvilHandler(ArmoredElytra plugin, boolean creationEnabled, public AnvilListener(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,
DurabilityManager durabilityManager, ConfigLoader config) {
super(plugin, true, nbtEditor, durabilityManager, config);
}
// Valid inputs: // Valid inputs:
// - Elytra (armored or not) + chestplate -> Create Armored Elytra // - Elytra (armored or not) + chestplate -> Create Armored Elytra
// - Elytra (armored) + enchanted book -> Enchant // - Elytra (armored) + enchanted book -> Enchant
@ -56,7 +51,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener {
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 (GenericUtil.isChestPlate(matTwo)) {
return creationEnabled ? Action.CREATE : Action.NONE; return creationEnabled ? Action.CREATE : Action.NONE;
} }
@ -127,7 +122,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener {
final ArmorTier newArmorTier; final ArmorTier newArmorTier;
if (action == Action.CREATE) { if (action == Action.CREATE) {
newArmorTier = Util.armorToTier(itemB); newArmorTier = GenericUtil.armorToTier(itemB);
} else if (action == Action.COMBINE) { } else if (action == Action.COMBINE) {
newArmorTier = nbtEditor.getArmorTier(itemB); newArmorTier = nbtEditor.getArmorTier(itemB);
} else { } else {

View File

@ -1,6 +1,9 @@
package nl.pim16aap2.armoredElytra.lib.armorequip; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorEquipEvent.EquipMethod; import net.knarcraft.armoredelytra.event.ArmorEquipEvent;
import net.knarcraft.armoredelytra.property.ArmorChangeMethod;
import net.knarcraft.armoredelytra.property.ArmorType;
import net.knarcraft.armoredelytra.util.ItemHelper;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -26,6 +29,7 @@ import java.util.List;
* @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) {
@ -34,7 +38,7 @@ public class ArmorListener implements Listener {
@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;
} }
@ -47,7 +51,7 @@ public class ArmorListener implements Listener {
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) {
@ -82,7 +86,7 @@ public class ArmorListener implements Listener {
e.getWhoClicked().getInventory().getLeggings())) || e.getWhoClicked().getInventory().getLeggings())) ||
newArmorType.equals(ArmorType.BOOTS) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getBoots()))) { newArmorType.equals(ArmorType.BOOTS) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getBoots()))) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(),
EquipMethod.SHIFT_CLICK, newArmorType, ArmorChangeMethod.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);
@ -94,11 +98,11 @@ public class ArmorListener implements Listener {
} 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 un-equip the item
// to or from. // to or from.
// e.getRawSlot() == The slot the item is going to. // e.getRawSlot() == The slot the item is going to.
// 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
@ -110,23 +114,23 @@ public class ArmorListener implements Listener {
newArmorPiece = hotbarItem; newArmorPiece = hotbarItem;
oldArmorPiece = e.getClickedInventory().getItem(e.getSlot()); oldArmorPiece = e.getClickedInventory().getItem(e.getSlot());
} else } else
// Unequipping // Un-equipping
{ {
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. // un-equip 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; ArmorChangeMethod method = ArmorChangeMethod.PICK_DROP;
if (e.getAction().equals(InventoryAction.HOTBAR_SWAP) || numberkey) { if (e.getAction().equals(InventoryAction.HOTBAR_SWAP) || numberKey) {
method = EquipMethod.HOTBAR_SWAP; method = ArmorChangeMethod.HOTBAR_SWAP;
} }
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), method, newArmorType, ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), method, newArmorType,
oldArmorPiece, newArmorPiece); oldArmorPiece, newArmorPiece);
@ -147,7 +151,7 @@ public class ArmorListener implements Listener {
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)
@ -163,7 +167,7 @@ public class ArmorListener implements Listener {
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(), ArmorChangeMethod.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);
@ -184,12 +188,12 @@ public class ArmorListener implements Listener {
// 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; return;
} }
if (type != null && type.getSlot() == event.getRawSlots().stream().findFirst().orElse(0)) { 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(), ArmorChangeMethod.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()) {
@ -200,25 +204,31 @@ public class ArmorListener implements Listener {
} }
@EventHandler @EventHandler
public void itemBreakEvent(PlayerItemBreakEvent e) { public void itemBreakEvent(PlayerItemBreakEvent itemBreakEvent) {
ArmorType type = ArmorType.matchType(e.getBrokenItem()); ArmorType armorType = ArmorType.matchType(itemBreakEvent.getBrokenItem());
if (type != null) { if (armorType == null) {
Player p = e.getPlayer(); return;
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, EquipMethod.BROKE, type, e.getBrokenItem(), null); }
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) { Player player = itemBreakEvent.getPlayer();
ItemStack i = e.getBrokenItem().clone(); ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(player, ArmorChangeMethod.BROKEN, armorType,
i.setAmount(1); itemBreakEvent.getBrokenItem(), null);
i.setDurability((short) (i.getDurability() - 1)); Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (type.equals(ArmorType.HELMET)) {
p.getInventory().setHelmet(i); if (armorEquipEvent.isCancelled()) {
} else if (type.equals(ArmorType.CHESTPLATE)) { ItemStack brokenItem = itemBreakEvent.getBrokenItem().clone();
p.getInventory().setChestplate(i); brokenItem.setAmount(1);
} else if (type.equals(ArmorType.LEGGINGS)) { if (!ItemHelper.updateDamage(brokenItem, ItemHelper.getDamage(brokenItem) + 1)) {
p.getInventory().setLeggings(i); throw new IllegalArgumentException("Cannot update damage for non-damageable item!");
} else if (type.equals(ArmorType.BOOTS)) { }
p.getInventory().setBoots(i); if (armorType.equals(ArmorType.HELMET)) {
} player.getInventory().setHelmet(brokenItem);
} else if (armorType.equals(ArmorType.CHESTPLATE)) {
player.getInventory().setChestplate(brokenItem);
} else if (armorType.equals(ArmorType.LEGGINGS)) {
player.getInventory().setLeggings(brokenItem);
} else if (armorType.equals(ArmorType.BOOTS)) {
player.getInventory().setBoots(brokenItem);
} }
} }
} }
@ -229,7 +239,7 @@ public class ArmorListener implements Listener {
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, ArmorChangeMethod.DEATH,
type, oldArmor, null)); type, oldArmor, null));
// No way to cancel a death event. // No way to cancel a death event.
} }
@ -241,4 +251,5 @@ public class ArmorListener implements Listener {
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

@ -1,10 +1,10 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder.ArmoredElytraBuilder; import net.knarcraft.armoredelytra.config.ConfigLoader;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.metadata.builder.ArmoredElytraBuilder;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -15,7 +15,8 @@ import javax.annotation.CheckReturnValue;
* *
* @author Pim * @author Pim
*/ */
abstract class ArmoredElytraHandler { public 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;
@ -62,4 +63,5 @@ abstract class ArmoredElytraHandler {
} }
return true; return true;
} }
} }

View File

@ -0,0 +1,33 @@
package net.knarcraft.armoredelytra.listener;
import net.knarcraft.armoredelytra.event.ArmorEquipEvent;
import net.knarcraft.armoredelytra.property.ArmorChangeMethod;
import net.knarcraft.armoredelytra.property.ArmorType;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockDispenseArmorEvent;
/**
* @author Arnah
* @since Feb 08, 2019
*/
public class DispenserArmorListener implements Listener {
@EventHandler
public void dispenseArmorEvent(BlockDispenseArmorEvent event) {
ArmorType type = ArmorType.matchType(event.getItem());
if (type == null || !(event.getTargetEntity() instanceof Player p)) {
return;
}
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, ArmorChangeMethod.DISPENSER, type, null,
event.getItem());
Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
event.setCancelled(true);
}
}
}

View File

@ -1,21 +1,21 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.property.ArmorTier;
import nl.pim16aap2.armoredElytra.util.Util; import net.knarcraft.armoredelytra.util.GenericUtil;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; 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 FlyDurabilityListener 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 FlyDurabilityListener(boolean disableDurability, NBTEditor nbtEditor, DurabilityManager durabilityManager) {
this.disableDurability = disableDurability; this.disableDurability = disableDurability;
this.nbtEditor = nbtEditor; this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager; this.durabilityManager = durabilityManager;
@ -46,7 +46,7 @@ public class FlyDurabilityHandler implements Listener {
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()); GenericUtil.moveChestplateToInventory(e.getPlayer());
} }
} }
} }

View File

@ -1,7 +1,7 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;

View File

@ -0,0 +1,30 @@
package net.knarcraft.armoredelytra.listener;
import net.knarcraft.armoredelytra.ArmoredElytra;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
public class LoginListener implements Listener {
private final ArmoredElytra plugin;
private final String message;
public LoginListener(ArmoredElytra plugin, String message) {
this.plugin = plugin;
this.message = message;
}
@EventHandler
public void onLogin(PlayerLoginEvent event) {
Player player = event.getPlayer();
if (player.hasPermission("armoredElytra.admin")) {
// Slight delay so the player actually receives the message;
Bukkit.getScheduler().runTaskLater(plugin, () -> plugin.messagePlayer(player, ChatColor.AQUA, message), 10);
}
}
}

View File

@ -1,10 +1,10 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.config.ConfigLoader;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
@ -36,11 +36,7 @@ public class NetheriteUpgradeListener extends SmithingTableListener {
return; return;
} }
event.setResult(armoredElytraBuilder event.setResult(armoredElytraBuilder.newBuilder().ofElytra(itemStackA).upgradeToTier(ArmorTier.NETHERITE).build());
.newBuilder()
.ofElytra(itemStackA)
.upgradeToTier(ArmorTier.NETHERITE)
.build());
} }
private boolean validInput(@Nullable ItemStack itemStackA, @Nullable ItemStack itemStackB) { private boolean validInput(@Nullable ItemStack itemStackA, @Nullable ItemStack itemStackB) {

View File

@ -1,16 +1,15 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorEquipEvent; import net.knarcraft.armoredelytra.config.message.Message;
import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorListener; import net.knarcraft.armoredelytra.event.ArmorEquipEvent;
import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorType; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.lib.armorequip.DispenserArmorListener; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.property.AllowedToWearEnum;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.property.ArmorChangeMethod;
import nl.pim16aap2.armoredElytra.util.AllowedToWearEnum; import net.knarcraft.armoredelytra.property.ArmorTier;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.property.ArmorType;
import nl.pim16aap2.armoredElytra.util.Util; import net.knarcraft.armoredelytra.util.GenericUtil;
import nl.pim16aap2.armoredElytra.util.messages.Message;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
@ -26,13 +25,13 @@ 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 PlayerEventListener 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 PlayerEventListener(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager) {
this.plugin = plugin; this.plugin = plugin;
this.nbtEditor = nbtEditor; this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager; this.durabilityManager = durabilityManager;
@ -50,11 +49,11 @@ public class EventHandlers implements Listener {
if (armorTier.equals(ArmorTier.NONE)) { if (armorTier.equals(ArmorTier.NONE)) {
return AllowedToWearEnum.ALLOWED; return AllowedToWearEnum.ALLOWED;
} }
if (Util.isBroken(elytra)) { if (GenericUtil.isBroken(elytra)) {
return AllowedToWearEnum.BROKEN; return AllowedToWearEnum.BROKEN;
} }
if (!plugin.playerHasWearPerm(player, armorTier)) { if (!plugin.playerHasWearPerm(player, armorTier)) {
return AllowedToWearEnum.NOPERMISSION; return AllowedToWearEnum.NO_PERMISSION;
} }
return AllowedToWearEnum.ALLOWED; return AllowedToWearEnum.ALLOWED;
} }
@ -98,7 +97,7 @@ public class EventHandlers implements Listener {
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); GenericUtil.moveChestplateToInventory(p);
} }
} }
@ -117,28 +116,31 @@ public class EventHandlers implements Listener {
} }
@EventHandler @EventHandler
public void onEquip(ArmorEquipEvent e) { public void onEquip(ArmorEquipEvent equipEvent) {
if (e.getMethod().equals(ArmorEquipEvent.EquipMethod.DEATH) || //If death caused it, or the item actually broke, do nothing
e.getMethod().equals(ArmorEquipEvent.EquipMethod.BROKE)) { if (equipEvent.getMethod().equals(ArmorChangeMethod.DEATH) ||
equipEvent.getMethod().equals(ArmorChangeMethod.BROKEN)) {
return; return;
} }
if (!e.getType().equals(ArmorType.CHESTPLATE) || //Check if an elytra is involved
e.getNewArmorPiece() == null || if (!equipEvent.getType().equals(ArmorType.CHESTPLATE) ||
!e.getNewArmorPiece().getType().equals(Material.ELYTRA)) { equipEvent.getNewArmorPiece() == null ||
!equipEvent.getNewArmorPiece().getType().equals(Material.ELYTRA)) {
return; return;
} }
final ArmorTier armorTier = nbtEditor.getArmorTier(e.getNewArmorPiece()); final ArmorTier armorTier = nbtEditor.getArmorTier(equipEvent.getNewArmorPiece());
final AllowedToWearEnum allowed = isAllowedToWear(e.getNewArmorPiece(), e.getPlayer(), armorTier); final AllowedToWearEnum allowed = isAllowedToWear(equipEvent.getNewArmorPiece(), equipEvent.getPlayer(),
armorTier);
switch (allowed) { switch (allowed) {
case BROKEN -> { case BROKEN -> {
plugin.messagePlayer(e.getPlayer(), plugin.getMyMessages().getString(Message.MESSAGES_REPAIRNEEDED)); plugin.messagePlayer(equipEvent.getPlayer(), plugin.getMyMessages().getString(Message.MESSAGES_REPAIR_NEEDED));
e.setCancelled(true); equipEvent.setCancelled(true);
} }
case NOPERMISSION -> { case NO_PERMISSION -> {
plugin.usageDeniedMessage(e.getPlayer(), armorTier); plugin.usageDeniedMessage(equipEvent.getPlayer(), armorTier);
e.setCancelled(true); equipEvent.setCancelled(true);
} }
default -> { default -> {
} }

View File

@ -1,11 +1,11 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.config.ConfigLoader;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.property.ArmorTier;
import nl.pim16aap2.armoredElytra.util.Util; import net.knarcraft.armoredelytra.util.GenericUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -20,7 +20,7 @@ public class SmithingTableCraftHandler extends SmithingTableListener {
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 AnvilListener(plugin, false, nbtEditor, durabilityManager, config), plugin);
} }
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
@ -45,11 +45,11 @@ public class SmithingTableCraftHandler extends SmithingTableListener {
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 || !GenericUtil.isChestPlate(itemStackB)) {
return ArmorTier.NONE; return ArmorTier.NONE;
} }
return Util.armorToTier(itemStackB.getType()); return GenericUtil.armorToTier(itemStackB.getType());
} }
@Override @Override

View File

@ -1,10 +1,10 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.config.ConfigLoader;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@ -15,7 +15,7 @@ import org.bukkit.inventory.SmithingInventory;
import java.util.logging.Level; import java.util.logging.Level;
abstract class SmithingTableListener extends ArmoredElytraHandler implements Listener { public 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);

View File

@ -1,8 +1,8 @@
package nl.pim16aap2.armoredElytra.handlers; package net.knarcraft.armoredelytra.listener;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -68,4 +68,5 @@ public class Uninstaller implements Listener {
} }
}.runTaskLater(plugin, 20); }.runTaskLater(plugin, 20);
} }
} }

View File

@ -1,8 +1,8 @@
package nl.pim16aap2.armoredElytra.nbtEditor; package net.knarcraft.armoredelytra.metadata;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.config.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.property.ArmorTier;
import nl.pim16aap2.armoredElytra.util.Util; import net.knarcraft.armoredelytra.util.GenericUtil;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -12,7 +12,7 @@ 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];
private final int[] maxDurabilities = new int[ArmorTier.values().length]; private final int[] maxDurabilityValues = new int[ArmorTier.values().length];
private final NBTEditor nbtEditor; private final NBTEditor nbtEditor;
private final ConfigLoader config; private final ConfigLoader config;
@ -78,7 +78,7 @@ public class DurabilityManager {
(otherMaxDurability - otherDurability) - (otherMaxDurability - otherDurability) -
(currentMaxDurability - currentDurability); (currentMaxDurability - currentDurability);
return Util.between(combinedDurability, 0, targetMaxDurability); return GenericUtil.between(combinedDurability, 0, targetMaxDurability);
} }
/** /**
@ -97,7 +97,7 @@ public class DurabilityManager {
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);
final int newDurability = Util.between(currentDurability + durabilityLoss, 0, getMaxDurability(currentTier)); final int newDurability = GenericUtil.between(currentDurability + durabilityLoss, 0, getMaxDurability(currentTier));
setDurability(armoredElytra, newDurability, providedTier); setDurability(armoredElytra, newDurability, providedTier);
return newDurability; return newDurability;
} }
@ -257,7 +257,7 @@ public class DurabilityManager {
* @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 maxDurabilityValues[armorTier.ordinal()];
} }
/** /**
@ -282,22 +282,22 @@ public class DurabilityManager {
*/ */
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 GenericUtil.between((int) Math.ceil(relativeDurability * newMax), 0, newMax);
} }
/** /**
* Initializes the {@link #maxDurabilities} and {@link #repairAmounts} arrays. * Initializes the {@link #maxDurabilityValues} and {@link #repairAmounts} arrays.
*/ */
private void init() { private void init() {
repairAmounts[0] = 0; repairAmounts[0] = 0;
maxDurabilities[0] = ELYTRA_MAX_DURABILITY; maxDurabilityValues[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);
maxDurabilities[idx] = maxDurability; this.maxDurabilityValues[idx] = maxDurability;
final int steps = Math.max(1, config.getFullRepairItemCount(armorTier)); final int steps = Math.max(1, config.getFullRepairItemCount(armorTier));
repairAmounts[idx] = (int) Math.ceil((float) maxDurability / steps); repairAmounts[idx] = (int) Math.ceil((float) maxDurability / steps);

View File

@ -1,7 +1,7 @@
package nl.pim16aap2.armoredElytra.nbtEditor; package net.knarcraft.armoredelytra.metadata;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Color; import org.bukkit.Color;
import org.bukkit.Material; import org.bukkit.Material;
@ -14,6 +14,7 @@ import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection; import java.util.Collection;
@ -29,12 +30,39 @@ public class NBTEditor {
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");
private static final NamespacedKey ORIGINAL_METADATA_KEY = new NamespacedKey(ArmoredElytra.getInstance(),
"ORIGINAL_METADATA");
/**
* Updates the original metadata for the given item.
*
* @param itemStack <p>The item to update.</p>
* @param metadata <p>The original metadata to store.</p>
*/
public void updateOriginalMetadata(@NotNull ItemStack itemStack, @NotNull OriginalMetadata metadata) {
final ItemMeta meta = getOrCreateItemMeta(itemStack);
meta.getPersistentDataContainer().set(ORIGINAL_METADATA_KEY, new PersistentMetadata(), metadata);
itemStack.setItemMeta(meta);
}
/**
* Gets the original metadata for the given item.
*
* @param itemStack <p>The item to get metadata for.</p>
* @return <p>The stored metadata, or null if none has been stored.</p>
*/
public @Nullable OriginalMetadata getOriginalMetadata(@NotNull ItemStack itemStack) {
final @Nullable ItemMeta meta = itemStack.getItemMeta();
return Objects.requireNonNull(meta, "Meta cannot be null for armored elytras!"
).getPersistentDataContainer().get(ORIGINAL_METADATA_KEY, new PersistentMetadata());
}
/** /**
* 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.
* *
* @param itemStack The item for which to retrieve the real durability. * @param itemStack <p>The item for which to retrieve the real durability.</p>
* @param providedTier The armor tier of the armored elytra. If this is null, it will be retrieved from NBT. * @param providedTier <p>The armor tier of the armored elytra. If this is null, it will be retrieved from NBT.</p>
* @return The real durability of the itemstack if the itemstack has the AE durability attribute, or -1 otherwise. * @return <p>The real durability of the item-stack if the item-stack has the AE durability attribute, or -1 otherwise.</p>
*/ */
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();
@ -49,8 +77,8 @@ public class NBTEditor {
} }
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;
} }
@ -58,7 +86,7 @@ public class NBTEditor {
/** /**
* Updates the durability values of an item. * Updates the durability values of an item.
* *
* @param itemStack The itemstack to which the durability values will be applied. * @param itemStack The item-stack to which the durability values will be applied.
* @param realDurability The real durability to store in NBT. * @param realDurability The real durability to store in NBT.
* @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}.
@ -74,6 +102,10 @@ public class NBTEditor {
itemStack.setItemMeta(meta); itemStack.setItemMeta(meta);
} }
//TODO: To be able to properly split the elytra from the armor, information of which metadata belongs to what needs
// to be stored. Notably, which item which enchantment belongs to. Which item the name and lore was taken from.
// Note that enchantments could be taken from both.
/** /**
* Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link * Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link
* ArmorTier#NONE} has no effect (besides making a copy of the item). * ArmorTier#NONE} has no effect (besides making a copy of the item).
@ -127,18 +159,25 @@ public class NBTEditor {
return returnedItem; return returnedItem;
} }
void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName) { /**
* Overwrites the attribute modifier for the given attribute, on the chest slot
*
* @param meta <p>The metadata to edit</p>
* @param attribute <p>The attribute to modify</p>
* @param value <p>The new value of the attribute</p>
* @param modifierName <p>The name of the attribute modifier</p>
*/
private 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) { private ArmorTier getArmorTier(@Nullable ItemMeta meta) {
if (meta == null || !meta.hasAttributeModifiers()) { if (meta == null || !meta.hasAttributeModifiers()) {
return ArmorTier.NONE; return ArmorTier.NONE;
} }
@ -215,13 +254,19 @@ public class NBTEditor {
return rgb == null ? null : Color.fromRGB(rgb); return rgb == null ? null : Color.fromRGB(rgb);
} }
static ItemMeta getOrCreateItemMeta(ItemStack item) { /**
final ItemMeta meta = item.hasItemMeta() ? * Gets existing metadata, or creates new metadata for the given item
item.getItemMeta() : *
* @param item <p>The item to get item meta for</p>
* @return <p>The existing or new item meta</p>
*/
private static ItemMeta getOrCreateItemMeta(ItemStack item) {
final ItemMeta meta = item.hasItemMeta() ? 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

@ -0,0 +1,166 @@
package net.knarcraft.armoredelytra.metadata;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
* An object for storing the original metadata for an armored elytra.
*
* <p>The intended usage of this class is to keep track of the original metadata of the armor and the elytra for each
* armored elytra, to prevent problems when splitting them. If an armor used to upgrade the armored elytra has a custom
* name or lore, and none is stored already, the name and lore should be updated. Additionally, any enchantments found
* on armor used to upgrade the armored elytra should be combined with the original armor enchantments.</p>
*/
public class OriginalMetadata implements Serializable {
private Set<Enchantment> armorEnchantments = new HashSet<>();
private Set<Enchantment> elytraEnchantments = new HashSet<>();
private String elytraLore;
private String elytraName;
private String armorLore;
private String armorName;
public OriginalMetadata() {
}
/**
* Gets the armor enchantments stored in this metadata.
*
* @return <p>The stored armor enchantments.</p>
*/
public @NotNull Set<Enchantment> getArmorEnchantments() {
return new HashSet<>(armorEnchantments);
}
/**
* Gets the elytra enchantments stored in this metadata.
*
* @return <p>The stored elytra enchantments.</p>
*/
public @NotNull Set<Enchantment> getElytraEnchantments() {
return new HashSet<>(elytraEnchantments);
}
/**
* Gets the original lore of this elytra.
*
* @return <p>The original elytra lore.</p>
*/
public @Nullable String getElytraLore() {
return this.elytraLore;
}
/**
* Gets the original name of this elytra.
*
* @return <p>The original elytra name.</p>
*/
public @Nullable String getElytraName() {
return this.elytraName;
}
/**
* Gets the original lore of this armor.
*
* @return <p>The original armor lore.</p>
*/
public @Nullable String getArmorLore() {
return this.armorLore;
}
/**
* Gets the original name of this armor.
*
* @return <p>The original armor name.</p>
*/
public @Nullable String getArmorName() {
return this.armorName;
}
/**
* Sets the stored lore of this armored elytra's armor.
*
* @param armorLore <p>The armor lore to store.</p>
* @return <p>This original metadata.</p>
*/
public OriginalMetadata setArmorLore(@NotNull String armorLore) {
this.armorLore = armorLore;
return this;
}
/**
* Sets the stored elytra lore of this armored elytra's elytra.
*
* @param elytraLore <p>The elytra lore to store.</p>
* @return <p>This original metadata.</p>
*/
public OriginalMetadata setElytraLore(@NotNull String elytraLore) {
this.elytraLore = elytraLore;
return this;
}
/**
* Sets the stored elytra name of this armored elytra's elytra.
*
* @param elytraName <p>The elytra name to store.</p>
* @return <p>This original metadata.</p>
*/
public OriginalMetadata setElytraName(@NotNull String elytraName) {
this.elytraName = elytraName;
return this;
}
/**
* Sets the stored armor name of this armored elytra's armor.
*
* @param armorName <p>The armor name to store.</p>
* @return <p>This original metadata.</p>
*/
public OriginalMetadata setArmorName(@NotNull String armorName) {
this.armorName = armorName;
return this;
}
/**
* Sets the stored enchantments for this armored elytra's armor.
*
* @param armorEnchantments <p>The armor enchantments to store.</p>
* @return <p>This original metadata.</p>
*/
public OriginalMetadata setArmorEnchantments(@NotNull Set<Enchantment> armorEnchantments) {
this.armorEnchantments = armorEnchantments;
return this;
}
/**
* Sets the stored enchantments for this armored elytra's elytra.
*
* @param elytraEnchantments <p>The elytra enchantments to store.</p>
* @return <p>This original metadata.</p>
*/
public OriginalMetadata setElytraEnchantments(@NotNull Set<Enchantment> elytraEnchantments) {
this.elytraEnchantments = elytraEnchantments;
return this;
}
/**
* Adds the given enchantments to armor enchantments.
*
* <p>The purpose of this method is to combine enchantments for the original chestplate, and any chest-plates used
* to upgrade the armored elytra.</p>
*
* @param enchantments <p>The enchantments to add</p>
* @return <p>This original metadata.</p>
*/
public OriginalMetadata addArmorEnchantments(@NotNull Set<Enchantment> enchantments) {
this.armorEnchantments.addAll(enchantments);
return this;
}
}

View File

@ -0,0 +1,52 @@
package net.knarcraft.armoredelytra.metadata;
import org.bukkit.persistence.PersistentDataAdapterContext;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* A persistent data type for persistently storing the original metadata of an armored elytra
*/
public class PersistentMetadata implements PersistentDataType<byte[], OriginalMetadata> {
@NotNull
@Override
public Class<byte[]> getPrimitiveType() {
return byte[].class;
}
@NotNull
@Override
public Class<OriginalMetadata> getComplexType() {
return OriginalMetadata.class;
}
@Override
public byte @NotNull [] toPrimitive(@NotNull OriginalMetadata complex, @NotNull PersistentDataAdapterContext context) {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
objectOutputStream.writeObject(complex);
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@NotNull
@Override
public OriginalMetadata fromPrimitive(byte @NotNull [] primitive, @NotNull PersistentDataAdapterContext context) {
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(primitive);
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream)) {
return (OriginalMetadata) objectInputStream.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,11 +1,11 @@
package nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder; package net.knarcraft.armoredelytra.metadata.builder;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.config.ConfigLoader;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.container.EnchantmentContainer;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.EnchantmentContainer; import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import javax.annotation.Nullable; import javax.annotation.Nullable;

View File

@ -1,12 +1,12 @@
package nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder; package net.knarcraft.armoredelytra.metadata.builder;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager; import net.knarcraft.armoredelytra.config.ConfigLoader;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import net.knarcraft.armoredelytra.container.EnchantmentContainer;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.metadata.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.metadata.NBTEditor;
import nl.pim16aap2.armoredElytra.util.EnchantmentContainer; import net.knarcraft.armoredelytra.property.ArmorTier;
import nl.pim16aap2.armoredElytra.util.Util; import net.knarcraft.armoredelytra.util.GenericUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Color; import org.bukkit.Color;
import org.bukkit.Material; import org.bukkit.Material;
@ -16,9 +16,7 @@ import org.bukkit.inventory.meta.LeatherArmorMeta;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
import static nl.pim16aap2.armoredElytra.util.Util.getTextureIdFromArmorTier; public final class Builder implements ItemCreator, ItemCombinator, ItemMetadataSetter {
final class Builder implements ItemCreator, ItemCombinator, ItemMetadataSetter {
private static final Color DEFAULT_LEATHER_COLOR = Bukkit.getServer().getItemFactory().getDefaultLeatherColor(); private static final Color DEFAULT_LEATHER_COLOR = Bukkit.getServer().getItemFactory().getDefaultLeatherColor();
@ -116,7 +114,7 @@ final class Builder implements ItemCreator, ItemCombinator, ItemMetadataSetter {
if (textureId != null) { if (textureId != null) {
this.textureId = textureId; this.textureId = textureId;
} else if (newArmorTier != null) { } else if (newArmorTier != null) {
this.textureId = getTextureIdFromArmorTier(newArmorTier); this.textureId = GenericUtil.getTextureIdFromArmorTier(newArmorTier);
} else { } else {
this.textureId = null; this.textureId = null;
} }
@ -159,7 +157,7 @@ final class Builder implements ItemCreator, ItemCombinator, ItemMetadataSetter {
public ItemMetadataSetter combineWith(ItemStack item, ArmorTier armorTier) { public ItemMetadataSetter combineWith(ItemStack item, ArmorTier armorTier) {
// Note: This method is almost always run. Important building steps should happen here. // Note: This method is almost always run. Important building steps should happen here.
if (armorTier == ArmorTier.NONE && !Util.isChestPlate(item)) { if (armorTier == ArmorTier.NONE && !GenericUtil.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!");
} }
@ -181,7 +179,7 @@ final class Builder implements ItemCreator, ItemCombinator, ItemMetadataSetter {
@Override @Override
public ItemMetadataSetter combineWith(ItemStack item) { public ItemMetadataSetter 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) : GenericUtil.armorToTier(item.getType());
return combineWith(item, armorTier); return combineWith(item, armorTier);
} }

View File

@ -1,7 +1,7 @@
package nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder; package net.knarcraft.armoredelytra.metadata.builder;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.container.EnchantmentContainer;
import nl.pim16aap2.armoredElytra.util.EnchantmentContainer; import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
/** /**

View File

@ -1,6 +1,6 @@
package nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder; package net.knarcraft.armoredelytra.metadata.builder;
import nl.pim16aap2.armoredElytra.util.ArmorTier; import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
/** /**

View File

@ -1,6 +1,6 @@
package nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder; package net.knarcraft.armoredelytra.metadata.builder;
import nl.pim16aap2.armoredElytra.util.ConfigLoader; import net.knarcraft.armoredelytra.config.ConfigLoader;
import org.bukkit.Color; import org.bukkit.Color;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;

View File

@ -1,6 +1,7 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.property;
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.
*/ */
@ -30,4 +31,5 @@ public enum Action {
* Blocks an otherwise valid input. * Blocks an otherwise valid input.
*/ */
BLOCK BLOCK
} }

View File

@ -0,0 +1,7 @@
package net.knarcraft.armoredelytra.property;
public enum AllowedToWearEnum {
BROKEN, NO_PERMISSION, ALLOWED
}

View File

@ -0,0 +1,49 @@
package net.knarcraft.armoredelytra.property;
/**
* A representation of all the ways a piece of equipped armor can change
*/
public enum ArmorChangeMethod {
/**
* When you shift click an armor piece to equip or un-equip
*/
SHIFT_CLICK,
/**
* When you drag and drop the item to equip or un-equip
*/
DRAG,
/**
* When you manually equip or un-equip the item. Use to be DRAG
*/
PICK_DROP,
/**
* When you right-click an armor piece in the hotbar without the inventory open to equip.
*/
HOTBAR,
/**
* When you press the hotbar slot number while hovering over the armor slot to equip or un-equip
*/
HOTBAR_SWAP,
/**
* When in range of a dispenser that shoots an armor piece to equip.<br> Requires the spigot version to have
* {@link org.bukkit.event.block.BlockDispenseArmorEvent} implemented.
*/
DISPENSER,
/**
* When an armor piece is removed due to it losing all durability.
*/
BROKEN,
/**
* When you die causing all armor to un-equip
*/
DEATH,
}

View File

@ -1,4 +1,4 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.property;
import org.bukkit.Material; import org.bukkit.Material;

View File

@ -1,4 +1,4 @@
package nl.pim16aap2.armoredElytra.lib.armorequip; package net.knarcraft.armoredelytra.property;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -8,6 +8,7 @@ import org.bukkit.inventory.ItemStack;
* @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),
@ -49,4 +50,5 @@ public enum ArmorType {
public int getSlot() { public int getSlot() {
return slot; return slot;
} }
} }

View File

@ -1,4 +1,4 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.property;
public enum MinecraftVersion { public enum MinecraftVersion {
v1_6, v1_6,

View File

@ -1,12 +1,11 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.update;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.io.IOException; import java.io.IOException;
@ -16,8 +15,6 @@ import java.net.URL;
import java.time.Instant; import java.time.Instant;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* A utility class to assist in checking for updates for plugins uploaded to * A utility class to assist in checking for updates for plugins uploaded to
@ -35,39 +32,19 @@ 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) ->
{
String[] firstSplit = splitVersionInfo(first), secondSplit = splitVersionInfo(second);
if (firstSplit == null || secondSplit == null) {
return null;
}
for (int i = 0; i < Math.min(firstSplit.length, secondSplit.length); i++) {
int currentValue = NumberUtils.toInt(firstSplit[i]), newestValue = NumberUtils.toInt(secondSplit[i]);
if (newestValue > currentValue) {
return second;
} else if (newestValue < currentValue) {
return first;
}
}
return (secondSplit.length > firstSplit.length) ? second : first;
};
private static final String USER_AGENT = "ArmoredElytra-update-checker"; private static final String USER_AGENT = "ArmoredElytra-update-checker";
private static final String UPDATE_URL = "https://api.spiget.org/v2/resources/%d/versions?size=1&sort=-releaseDate"; private static final String UPDATE_URL = "https://api.spiget.org/v2/resources/%d/versions?size=1&sort=-releaseDate";
private static final Pattern DECIMAL_SCHEME_PATTERN = Pattern.compile("\\d+(?:\\.\\d+)*");
private static UpdateChecker instance; private static UpdateChecker instance;
private UpdateResult lastResult = null; UpdateResult lastResult = null;
private final ArmoredElytra plugin; final ArmoredElytra plugin;
private final int pluginID; private final int pluginID;
private final IVersionScheme versionScheme; private final VersionScheme versionScheme;
private UpdateChecker(final ArmoredElytra plugin, final int pluginID, final IVersionScheme versionScheme) { private UpdateChecker(final ArmoredElytra plugin, final int pluginID, final VersionScheme versionScheme) {
this.plugin = plugin; this.plugin = plugin;
this.pluginID = pluginID; this.pluginID = pluginID;
this.versionScheme = versionScheme; this.versionScheme = versionScheme;
@ -81,8 +58,7 @@ public final class UpdateChecker {
*/ */
public CompletableFuture<UpdateResult> requestUpdateCheck() { public CompletableFuture<UpdateResult> requestUpdateCheck() {
return CompletableFuture.supplyAsync( return CompletableFuture.supplyAsync(
() -> () -> {
{
int responseCode; int responseCode;
try { try {
URL url = new URL(String.format(UPDATE_URL, pluginID)); URL url = new URL(String.format(UPDATE_URL, pluginID));
@ -94,7 +70,7 @@ public final class UpdateChecker {
JsonElement element = new JsonParser().parse(reader); JsonElement element = new JsonParser().parse(reader);
if (!element.isJsonArray()) { if (!element.isJsonArray()) {
return new UpdateResult(UpdateReason.INVALID_JSON); return new UpdateResult(this, UpdateReason.INVALID_JSON);
} }
reader.close(); reader.close();
@ -115,21 +91,21 @@ public final class UpdateChecker {
String latest = versionScheme.compareVersions(current, newest); String latest = versionScheme.compareVersions(current, newest);
if (latest == null) { if (latest == null) {
return new UpdateResult(UpdateReason.UNSUPPORTED_VERSION_SCHEME); return new UpdateResult(this, UpdateReason.UNSUPPORTED_VERSION_SCHEME);
} else if (latest.equals(current)) { } else if (latest.equals(current)) {
return new UpdateResult(current.equals(newest) ? return new UpdateResult(this, current.equals(newest) ?
UpdateReason.UP_TO_DATE : UpdateReason.UP_TO_DATE :
UpdateReason.UNRELEASED_VERSION, current, age); UpdateReason.UNRELEASED_VERSION, current, age);
} else if (latest.equals(newest)) { } else if (latest.equals(newest)) {
return new UpdateResult(UpdateReason.NEW_UPDATE, latest, age); return new UpdateResult(this, UpdateReason.NEW_UPDATE, latest, age);
} }
} catch (IOException e) { } catch (IOException e) {
return new UpdateResult(UpdateReason.COULD_NOT_CONNECT); return new UpdateResult(this, UpdateReason.COULD_NOT_CONNECT);
} catch (JsonSyntaxException e) { } catch (JsonSyntaxException e) {
return new UpdateResult(UpdateReason.INVALID_JSON); return new UpdateResult(this, UpdateReason.INVALID_JSON);
} }
return new UpdateResult(responseCode == 401 ? return new UpdateResult(this, responseCode == 401 ?
UpdateReason.UNAUTHORIZED_QUERY : UpdateReason.UNKNOWN_ERROR); UpdateReason.UNAUTHORIZED_QUERY : UpdateReason.UNKNOWN_ERROR);
}); });
} }
@ -155,28 +131,20 @@ public final class UpdateChecker {
return lastResult; return lastResult;
} }
private static String[] splitVersionInfo(String version) {
Matcher matcher = DECIMAL_SCHEME_PATTERN.matcher(version);
if (!matcher.find()) {
return null;
}
return matcher.group().split("\\.");
}
/** /**
* Initializes this update checker with the specified values and return its instance. If an instance of * Initializes this update checker with the specified values and return its instance. If an instance of
* UpdateChecker has already been initialized, this method will act similarly to {@link #get()} (which is * UpdateChecker has already been initialized, this method will act similarly to {@link #get()} (which is
* recommended after initialization). * recommended after initialization).
* *
* @param plugin the plugin for which to check updates. Cannot be null * @param plugin the plugin for which to check updates. Cannot be null
* @param pluginID the ID of the plugin as identified in the SpigotMC resource link. For example, * @param pluginID <p>The ID of the plugin as identified in the SpigotMC resource link. For example,
* "https://www.spigotmc.org/resources/veinminer.<b>12038</b>/" would expect "12038" as a * "<a href="https://www.spigotmc.org/resources/veinminer/12038/">
* value. The value must be greater than 0 * https://www.spigotmc.org/resources/veinminer/<b>12038</b>/</a>" would expect "12038" as a
* value. The value must be greater than 0</p>
* @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 VersionScheme 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;
@ -188,13 +156,14 @@ public final class UpdateChecker {
* recommended after initialization). * recommended after initialization).
* *
* @param plugin the plugin for which to check updates. Cannot be null * @param plugin the plugin for which to check updates. Cannot be null
* @param pluginID the ID of the plugin as identified in the SpigotMC resource link. For example, * @param pluginID <p>The ID of the plugin as identified in the SpigotMC resource link. For example,
* "https://www.spigotmc.org/resources/veinminer.<b>12038</b>/" would expect "12038" as a value. The * "<a href="https://www.spigotmc.org/resources/veinminer/12038/">
* value must be greater than 0 * https://www.spigotmc.org/resources/veinminer/<b>12038</b>/</a>" would expect "12038" as a value. The
* value must be greater than 0</p>
* @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, new VersionScheme());
} }
/** /**
@ -219,137 +188,4 @@ public final class UpdateChecker {
return instance != null; return instance != null;
} }
/**
* A functional interface to compare two version Strings with similar version schemes.
*/
@FunctionalInterface
public interface IVersionScheme {
/**
* Compare two versions and return the higher of the two. If null is returned, it is assumed that at least one
* of the two versions are unsupported by this version scheme parser.
*
* @param first the first version to check
* @param second the second version to check
* @return the greater of the two versions. null if unsupported version schemes
*/
String compareVersions(String first, String second);
}
/**
* A constant reason for the result of {@link UpdateResult}.
*/
public enum UpdateReason {
/**
* A new update is available for download.
* <p>
* This is the only reason that requires an update.
*/
NEW_UPDATE,
/**
* A successful connection to the SpiGet API could not be established.
*/
COULD_NOT_CONNECT,
/**
* The JSON retrieved from SpiGet was invalid or malformed.
*/
INVALID_JSON,
/**
* A 401 error was returned by the SpiGet API.
*/
UNAUTHORIZED_QUERY,
/**
* The version of the plugin installed on the server is greater than the one uploaded to SpigotMC's resources
* section.
*/
UNRELEASED_VERSION,
/**
* An unknown error occurred.
*/
UNKNOWN_ERROR,
/**
* The plugin uses an unsupported version scheme, therefore a proper comparison between versions could not be
* made.
*/
UNSUPPORTED_VERSION_SCHEME,
/**
* The plugin is up to date with the version released on SpigotMC's resources section.
*/
UP_TO_DATE
}
/**
* Represents a result for an update query performed by {@link UpdateChecker#requestUpdateCheck()}.
*/
public final class UpdateResult {
private final UpdateReason reason;
private final String newestVersion;
private final long age;
{
lastResult = this;
}
private UpdateResult(final UpdateReason reason, final String newestVersion, final long age) {
this.reason = reason;
this.newestVersion = newestVersion;
this.age = age;
}
private UpdateResult(final UpdateReason reason) {
Preconditions
.checkArgument(reason != UpdateReason.NEW_UPDATE && reason != UpdateReason.UP_TO_DATE,
"Reasons that might require updates must also provide the latest version String");
this.reason = reason;
newestVersion = plugin.getDescription().getVersion();
age = -1;
}
/**
* Gets the constant reason of this result.
*
* @return the reason
*/
public UpdateReason getReason() {
return reason;
}
/**
* Checks whether or not this result requires the user to update.
*
* @return true if requires update, false otherwise
*/
public boolean requiresUpdate() {
return reason == UpdateReason.NEW_UPDATE;
}
/**
* Gets the latest version of the plugin. This may be the currently installed version, it may not be. This
* depends entirely on the result of the update.
*
* @return the newest version of the plugin
*/
public String getNewestVersion() {
return newestVersion;
}
/**
* Gets the number of seconds since the last update was released.
*
* @return The number of seconds since the last update was released or -1 if unavailable.
*/
public long getAge() {
return age;
}
}
} }

View File

@ -1,6 +1,6 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.update;
import nl.pim16aap2.armoredElytra.ArmoredElytra; import net.knarcraft.armoredelytra.ArmoredElytra;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
@ -76,4 +76,5 @@ public final class UpdateManager {
} }
} }
} }
} }

View File

@ -0,0 +1,52 @@
package net.knarcraft.armoredelytra.update;
/**
* A constant reason for the result of {@link UpdateResult}.
*/
public enum UpdateReason {
/**
* A new update is available for download.
* <p>
* This is the only reason that requires an update.
*/
NEW_UPDATE,
/**
* A successful connection to the SpiGet API could not be established.
*/
COULD_NOT_CONNECT,
/**
* The JSON retrieved from SpiGet was invalid or malformed.
*/
INVALID_JSON,
/**
* A 401 error was returned by the SpiGet API.
*/
UNAUTHORIZED_QUERY,
/**
* The version of the plugin installed on the server is greater than the one uploaded to SpigotMC's resources
* section.
*/
UNRELEASED_VERSION,
/**
* An unknown error occurred.
*/
UNKNOWN_ERROR,
/**
* The plugin uses an unsupported version scheme, therefore a proper comparison between versions could not be
* made.
*/
UNSUPPORTED_VERSION_SCHEME,
/**
* The plugin is up-to-date with the version released on SpigotMC's resources section.
*/
UP_TO_DATE
}

View File

@ -0,0 +1,67 @@
package net.knarcraft.armoredelytra.update;
import com.google.common.base.Preconditions;
/**
* Represents a result for an update query performed by {@link UpdateChecker#requestUpdateCheck()}.
*/
public final class UpdateResult {
private final UpdateReason reason;
private final String newestVersion;
private final long age;
UpdateResult(UpdateChecker updateChecker, final UpdateReason reason, final String newestVersion, final long age) {
updateChecker.lastResult = this;
this.reason = reason;
this.newestVersion = newestVersion;
this.age = age;
}
UpdateResult(UpdateChecker updateChecker, final UpdateReason reason) {
Preconditions
.checkArgument(reason != UpdateReason.NEW_UPDATE && reason != UpdateReason.UP_TO_DATE,
"Reasons that might require updates must also provide the latest version String");
this.reason = reason;
newestVersion = updateChecker.plugin.getDescription().getVersion();
age = -1;
}
/**
* Gets the constant reason of this result.
*
* @return the reason
*/
public UpdateReason getReason() {
return reason;
}
/**
* Checks whether this result requires the user to update.
*
* @return true if an update is required, false otherwise
*/
public boolean requiresUpdate() {
return reason == UpdateReason.NEW_UPDATE;
}
/**
* Gets the latest version of the plugin. This may be the currently installed version, it may not be. This
* depends entirely on the result of the update.
*
* @return the newest version of the plugin
*/
public String getNewestVersion() {
return newestVersion;
}
/**
* Gets the number of seconds since the last update was released.
*
* @return The number of seconds since the last update was released or -1 if unavailable.
*/
public long getAge() {
return age;
}
}

View File

@ -0,0 +1,51 @@
package net.knarcraft.armoredelytra.update;
import org.apache.commons.lang.math.NumberUtils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A functional interface to compare two version Strings with similar version schemes.
*/
public class VersionScheme {
private static final Pattern DECIMAL_SCHEME_PATTERN = Pattern.compile("\\d+(?:\\.\\d+)*");
/**
* Compare two versions and return the higher of the two. If null is returned, it is assumed that at least one
* of the two versions are unsupported by this version scheme parser.
*
* @param first the first version to check
* @param second the second version to check
* @return the greater of the two versions. null if unsupported version schemes
*/
String compareVersions(String first, String second) {
String[] firstSplit = splitVersionInfo(first), secondSplit = splitVersionInfo(second);
if (firstSplit == null || secondSplit == null) {
return null;
}
for (int i = 0; i < Math.min(firstSplit.length, secondSplit.length); i++) {
int currentValue = NumberUtils.toInt(firstSplit[i]), newestValue = NumberUtils.toInt(secondSplit[i]);
if (newestValue > currentValue) {
return second;
} else if (newestValue < currentValue) {
return first;
}
}
return (secondSplit.length > firstSplit.length) ? second : first;
}
private static String[] splitVersionInfo(String version) {
Matcher matcher = DECIMAL_SCHEME_PATTERN.matcher(version);
if (!matcher.find()) {
return null;
}
return matcher.group().split("\\.");
}
}

View File

@ -1,5 +1,6 @@
package nl.pim16aap2.armoredElytra.util; package net.knarcraft.armoredelytra.util;
import net.knarcraft.armoredelytra.property.ArmorTier;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -12,7 +13,7 @@ import java.io.StringWriter;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
public class Util { public final class GenericUtil {
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));
@ -27,7 +28,7 @@ public class Util {
// 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 ItemHelper.getDurability(item) >= ItemHelper.getMaxDurability(item);
} }
// Get the armor tier from a chest plate. // Get the armor tier from a chest plate.

View File

@ -0,0 +1,117 @@
package net.knarcraft.armoredelytra.util;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
/**
* A helper class for getting information about items
*/
public final class ItemHelper {
private ItemHelper() {
}
/**
* Gets whether the given item is repairable
*
* @param item <p>The item to check</p>
* @return <p>True if the item is repairable</p>
*/
public static boolean isRepairable(ItemStack item) {
return item.getItemMeta() instanceof Damageable && getMaxDurability(item) > 0;
}
/**
* Gets the max durability of an item
*
* @param itemStack <p>The item to get the durability of</p>
* @return <p>The max durability of the item</p>
*/
public static short getMaxDurability(ItemStack itemStack) {
return itemStack.getType().getMaxDurability();
}
/**
* Gets the current durability of the given item
*
* @param itemStack <p>The item to get the durability of</p>
* @return <p>The durability of the item</p>
*/
public static short getDurability(ItemStack itemStack) {
Damageable damageable = (Damageable) itemStack.getItemMeta();
int maxDurability = getMaxDurability(itemStack);
if (damageable != null) {
return (short) (maxDurability - damageable.getDamage());
} else {
return (short) maxDurability;
}
}
/**
* Gets the damage done to the given item
*
* @param itemStack <p>The damage done to the item</p>
* @return <p>The damage done to the item</p>
*/
public static short getDamage(ItemStack itemStack) {
Damageable damageable = (Damageable) itemStack.getItemMeta();
if (damageable != null) {
return (short) damageable.getDamage();
} else {
return 0;
}
}
/**
* Updates the damage done to an item
*
* @param item <p>The item to update damage for</p>
* @param newDamage <p>The new damage done</p>
* @return <p>True if the damage was updated. False if not damageable.</p>
*/
public static boolean updateDamage(ItemStack item, int newDamage) {
ItemMeta meta = item.getItemMeta();
if (!(meta instanceof Damageable damageable)) {
return false;
}
damageable.setDamage(newDamage);
item.setItemMeta(meta);
return true;
}
/**
* Gets a complete list of all reforge-able materials
*
* @return <p>A complete list of reforge-able materials</p>
*/
public static List<Material> getAllReforgeAbleMaterials() {
List<Material> reforgeAbleMaterials = new ArrayList<>();
for (Material material : Material.values()) {
ItemStack item = new ItemStack(material);
if (isRepairable(item)) {
reforgeAbleMaterials.add(material);
}
}
return reforgeAbleMaterials;
}
/**
* Checks whether the given material is an anvil
*
* @param material <p>The material to check</p>
* @param requireDamaged <p>Whether only a damaged anvil should count</p>
* @return <p>True if the given material is an anvil</p>
*/
public static boolean isAnvil(Material material, boolean requireDamaged) {
boolean isDamagedAnvil = material == Material.CHIPPED_ANVIL || material == Material.DAMAGED_ANVIL;
boolean isAnvil = isDamagedAnvil || material == Material.ANVIL;
return (requireDamaged && isDamagedAnvil) || (!requireDamaged && isAnvil);
}
}

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
# This file contains all the (partial) sentences used in this plugin. # This file contains all the (partial) sentences used in this plugin.
# You can change which file will be used in the config.yml. # You can change which file will be used in the config.yml.
# The format is "key=value" (without quotation marks). You can modify the values, but not the keys. # The format is "key=value" (without quotation marks). You can modify the values, but not the keys.
# Order doesn't matter and you can use comments if you so desire. # Order doesn't matter, and you can use comments if you so desire.
# Please do note that white space does matter! (so spaces at the end of lines, for example). # Please do note that white space does matter! (so spaces at the end of lines, for example).
# The long names (without 'SHORT') are the names the elytras will have. # The long names (without 'SHORT') are the names the elytras will have.
TIER.Leather=&2Leather Armored Elytra TIER.Leather=&2Leather Armored Elytra

View File

@ -1,7 +1,7 @@
# This file contains all the (partial) sentences used in this plugin. # This file contains all the (partial) sentences used in this plugin.
# You can change which file will be used in the config.yml. # You can change which file will be used in the config.yml.
# The format is "key=value" (without quotation marks). You can modify the values, but not the keys. # The format is "key=value" (without quotation marks). You can modify the values, but not the keys.
# Order doesn't matter and you can use comments if you so desire. # Order doesn't matter, and you can use comments if you so desire.
# Please do note that white space does matter! (so spaces at the end of lines, for example). # Please do note that white space does matter! (so spaces at the end of lines, for example).
# The long names (without 'SHORT') are the names the elytras will have. # The long names (without 'SHORT') are the names the elytras will have.
TIER.Leather=&2Elytra corazzata di pelle TIER.Leather=&2Elytra corazzata di pelle

View File

@ -1,7 +1,7 @@
# This file contains all the (partial) sentences used in this plugin. # This file contains all the (partial) sentences used in this plugin.
# You can change which file will be used in the config.yml. # You can change which file will be used in the config.yml.
# The format is "key=value" (without quotation marks). You can modify the values, but not the keys. # The format is "key=value" (without quotation marks). You can modify the values, but not the keys.
# Order doesn't matter and you can use comments if you so desire. # Order doesn't matter, and you can use comments if you so desire.
# Please do note that white space does matter! (so spaces at the end of lines, for example). # Please do note that white space does matter! (so spaces at the end of lines, for example).
# The long names (without 'SHORT') are the names the elytras will have. # The long names (without 'SHORT') are the names the elytras will have.
TIER.Leather=&2皮革裝甲鞘翅 TIER.Leather=&2皮革裝甲鞘翅

View File

@ -0,0 +1,18 @@
package net.knarcraft.armoredelytra.util;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class GenericUtilTest {
@Test
void testSnakeToCamelCase() {
Assertions.assertEquals("testCase", GenericUtil.snakeToCamelCase("TeSt_Case"));
Assertions.assertEquals("testCase", GenericUtil.snakeToCamelCase("____test_case"));
Assertions.assertEquals("", GenericUtil.snakeToCamelCase("________"));
Assertions.assertEquals("testCase", GenericUtil.snakeToCamelCase("TeSt__Case____"));
Assertions.assertEquals("t", GenericUtil.snakeToCamelCase("_T_"));
Assertions.assertEquals("testcase", GenericUtil.snakeToCamelCase("TeStCase"));
}
}

View File

@ -1,16 +0,0 @@
package nl.pim16aap2.armoredElytra.util;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class UtilTest {
@Test
void testSnakeToCamelCase() {
Assertions.assertEquals("testCase", Util.snakeToCamelCase("TeSt_Case"));
Assertions.assertEquals("testCase", Util.snakeToCamelCase("____test_case"));
Assertions.assertEquals("", Util.snakeToCamelCase("________"));
Assertions.assertEquals("testCase", Util.snakeToCamelCase("TeSt__Case____"));
Assertions.assertEquals("t", Util.snakeToCamelCase("_T_"));
Assertions.assertEquals("testcase", Util.snakeToCamelCase("TeStCase"));
}
}