diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml new file mode 100644 index 0000000..77beb54 --- /dev/null +++ b/.idea/dictionaries/project.xml @@ -0,0 +1,7 @@ + + + + enchantbookplus + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6000659..142f066 100644 --- a/pom.xml +++ b/pom.xml @@ -51,10 +51,9 @@ provided - org.jetbrains - annotations - 26.0.2-1 - compile + org.jspecify + jspecify + 1.0.0 diff --git a/src/main/java/pro/cloudnode/smp/enchantbookplus/ConfigEnchantmentEntry.java b/src/main/java/pro/cloudnode/smp/enchantbookplus/ConfigEnchantmentEntry.java index f48a60b..a305ac3 100644 --- a/src/main/java/pro/cloudnode/smp/enchantbookplus/ConfigEnchantmentEntry.java +++ b/src/main/java/pro/cloudnode/smp/enchantbookplus/ConfigEnchantmentEntry.java @@ -3,21 +3,22 @@ import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.enchantments.Enchantment; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; +import java.util.OptionalInt; import java.util.stream.Collectors; +@NullMarked public class ConfigEnchantmentEntry { /** * Name of the enchantment. */ - public final @NotNull String name; + public final String name; /** * Maximum level of the enchantment. @@ -40,57 +41,14 @@ public class ConfigEnchantmentEntry { protected final boolean multiplyCostByLevel; /** - * Maximum level of the enchantment. - */ - public final @NotNull Optional getMaxLevel() { - if (Optional.ofNullable(maxLevel).isEmpty()) - return Optional.empty(); - - if (maxLevelRelative) - return Optional.of(getEnchantment().getMaxLevel() + maxLevel); - - return Optional.of(maxLevel); - } - - /** - * Cost of the enchantment. - */ - public final int getCost() { - return cost; - } - - /** - * Multiply cost by level. - */ - public final boolean getMultiplyCostByLevel() { - return multiplyCostByLevel; - } - - /** - * Get enchantment - */ - public final Enchantment getEnchantment() { - return Registry.ENCHANTMENT.get(NamespacedKey.minecraft(name)); - } - - /** - * Is enchantment - * - * @param enchantment The enchantment - */ - public final boolean isEnchantment(final @NotNull Enchantment enchantment) { - return name.equalsIgnoreCase(enchantment.getKey().getKey()); - } - - /** - * @param name Name of the enchantment. - * @param maxLevel Maximum level of the enchantment. - * @param maxLevelRelative Max level relative - * @param cost Cost of the enchantment. + * @param name Name of the enchantment. + * @param maxLevel Maximum level of the enchantment. + * @param maxLevelRelative Max level relative + * @param cost Cost of the enchantment. * @param multiplyCostByLevel Multiply cost by level. */ public ConfigEnchantmentEntry( - final @NotNull String name, + final String name, final @Nullable Integer maxLevel, final boolean maxLevelRelative, final int cost, @@ -108,42 +66,38 @@ public ConfigEnchantmentEntry( * * @param configValue Config object */ - public static @NotNull ConfigEnchantmentEntry configValue( - final @NotNull Map<@NotNull String, @NotNull Object> configValue + public static ConfigEnchantmentEntry configValue( + final Map configValue ) throws NumberFormatException, IndexOutOfBoundsException, ClassCastException { final String name = (String) Objects.requireNonNull(configValue.get("name")); - final @Nullable Integer maxLevel; + final Integer maxLevel; final boolean maxLevelRelative; if (!configValue.containsKey("max-level")) { maxLevel = null; maxLevelRelative = false; - } - - else { + } else { if (!(configValue.get("max-level") instanceof final String string)) { maxLevel = (Integer) configValue.get("max-level"); maxLevelRelative = false; - } - - else { + } else { if (string.startsWith("+")) { maxLevel = Integer.parseInt(string.substring(1)); maxLevelRelative = true; - } - else { + } else { maxLevel = Integer.parseInt(string); maxLevelRelative = false; } } } - if (!configValue.containsKey("cost")) + if (!configValue.containsKey("cost")) { return new ConfigEnchantmentEntry(name, maxLevel, maxLevelRelative, 0, false); + } - if (!(configValue.get("cost") instanceof final @NotNull String costString)) + if (!(configValue.get("cost") instanceof final String costString)) { return new ConfigEnchantmentEntry( name, maxLevel, @@ -151,8 +105,9 @@ public ConfigEnchantmentEntry( (Integer) configValue.get("cost"), false ); + } - if (costString.startsWith("*")) + if (costString.startsWith("*")) { return new ConfigEnchantmentEntry( name, maxLevel, @@ -160,25 +115,18 @@ public ConfigEnchantmentEntry( Integer.parseInt(costString.substring(1)), true ); + } - return new ConfigEnchantmentEntry( - name, - maxLevel, - maxLevelRelative, - Integer.parseInt(costString), - false - ); + return new ConfigEnchantmentEntry(name, maxLevel, maxLevelRelative, Integer.parseInt(costString), false); } - /** * From config object array * * @param configValue Config object array */ - public static @NotNull List<@NotNull ConfigEnchantmentEntry> configArray( - final @NotNull ArrayList<@NotNull Map<@NotNull String, @NotNull Object>> configValue - ) throws NumberFormatException, IndexOutOfBoundsException, ClassCastException { + public static List configArray(final ArrayList> configValue) + throws NumberFormatException, IndexOutOfBoundsException, ClassCastException { return configValue.stream().map(ConfigEnchantmentEntry::configValue).collect(Collectors.toList()); } @@ -188,31 +136,36 @@ public ConfigEnchantmentEntry( * @param configValue Config object */ private static boolean isValidConfigValue(final @Nullable Object configValue) { - if (configValue == null) + if (configValue == null) { return false; + } - if (!(configValue instanceof final ArrayList arrayList)) + if (!(configValue instanceof final ArrayList arrayList)) { return false; + } for (final Object object : arrayList) { - if (!(object instanceof final Map hashMap)) + if (!(object instanceof final Map hashMap)) { return false; + } - if (!hashMap.containsKey("name")) + if (!hashMap.containsKey("name")) { return false; + } - if (!(hashMap.get("name") instanceof String)) + if (!(hashMap.get("name") instanceof String)) { return false; + } - if (hashMap.containsKey("max-level") && - !(hashMap.get("max-level") instanceof String) && - !(hashMap.get("max-level") instanceof Integer)) + if (hashMap.containsKey("max-level") && !(hashMap.get("max-level") instanceof String) && !(hashMap.get( + "max-level") instanceof Integer)) { return false; + } - if (hashMap.containsKey("cost") && - !(hashMap.get("cost") instanceof String) && - !(hashMap.get("cost") instanceof Integer)) + if (hashMap.containsKey("cost") && !(hashMap.get("cost") instanceof String) + && !(hashMap.get("cost") instanceof Integer)) { return false; + } } return true; @@ -223,16 +176,61 @@ private static boolean isValidConfigValue(final @Nullable Object configValue) { * * @param configValue Config object */ - public static @NotNull List<@NotNull ConfigEnchantmentEntry> config( - final @Nullable Object configValue - ) throws IllegalArgumentException, IndexOutOfBoundsException, ClassCastException { - if (!isValidConfigValue(configValue)) + public static List config(final @Nullable Object configValue) + throws IllegalArgumentException, IndexOutOfBoundsException, ClassCastException { + if (!isValidConfigValue(configValue)) { throw new IllegalArgumentException("Invalid config value"); + } //noinspection unchecked return configArray((ArrayList>) configValue); } + /** + * Maximum level of the enchantment. + */ + public final OptionalInt getMaxLevel() { + if (maxLevel == null) { + return OptionalInt.empty(); + } + + if (maxLevelRelative) { + return OptionalInt.of(getEnchantment().getMaxLevel() + maxLevel); + } + + return OptionalInt.of(maxLevel); + } + + /** + * Cost of the enchantment. + */ + public final int getCost() { + return cost; + } + + /** + * Multiply cost by level. + */ + public final boolean getMultiplyCostByLevel() { + return multiplyCostByLevel; + } + + /** + * Get enchantment + */ + public final Enchantment getEnchantment() { + return Objects.requireNonNull(Registry.ENCHANTMENT.get(NamespacedKey.minecraft(name))); + } + + /** + * Is enchantment + * + * @param enchantment The enchantment + */ + public final boolean isEnchantment(final Enchantment enchantment) { + return name.equalsIgnoreCase(enchantment.getKey().getKey()); + } + public static final class AllConfigEnchantmentEntry extends ConfigEnchantmentEntry { private AllConfigEnchantmentEntry( final @Nullable Integer maxLevel, @@ -243,9 +241,7 @@ private AllConfigEnchantmentEntry( super("ALL", maxLevel, maxLevelRelative, cost, multiplyCostByLevel); } - public static @NotNull AllConfigEnchantmentEntry from( - final @NotNull ConfigEnchantmentEntry configEnchantmentEntry - ) { + public static AllConfigEnchantmentEntry from(final ConfigEnchantmentEntry configEnchantmentEntry) { return new AllConfigEnchantmentEntry( configEnchantmentEntry.maxLevel, configEnchantmentEntry.maxLevelRelative, @@ -254,7 +250,7 @@ private AllConfigEnchantmentEntry( ); } - public @NotNull ConfigEnchantmentEntry enchant(final @NotNull Enchantment enchantment) { + public ConfigEnchantmentEntry enchant(final Enchantment enchantment) { return new ConfigEnchantmentEntry( enchantment.getKey().getKey(), this.maxLevel, diff --git a/src/main/java/pro/cloudnode/smp/enchantbookplus/EnchantBookPlus.java b/src/main/java/pro/cloudnode/smp/enchantbookplus/EnchantBookPlus.java index cdc6e1d..695d27e 100644 --- a/src/main/java/pro/cloudnode/smp/enchantbookplus/EnchantBookPlus.java +++ b/src/main/java/pro/cloudnode/smp/enchantbookplus/EnchantBookPlus.java @@ -2,8 +2,8 @@ import org.bukkit.enchantments.Enchantment; import org.bukkit.plugin.java.JavaPlugin; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; import pro.cloudnode.smp.enchantbookplus.event.PrepareAnvil; import java.util.ArrayList; @@ -13,7 +13,17 @@ import java.util.logging.Level; import java.util.stream.Collectors; +@NullMarked public final class EnchantBookPlus extends JavaPlugin { + /** + * Config enchantments cache + */ + private List configEnchantments = new ArrayList<>(); + /** + * "ALL" enchantment cache + */ + private ConfigEnchantmentEntry.@Nullable AllConfigEnchantmentEntry allConfigEnchantment; + /** * Register event listeners. */ @@ -24,24 +34,14 @@ private void registerEvents() { /** * Config enchantments cache */ - private @NotNull List<@NotNull ConfigEnchantmentEntry> configEnchantments = new ArrayList<>(); - - /** - * Config enchantments cache - */ - @NotNull List<@NotNull ConfigEnchantmentEntry> getConfigEnchantments() { + private List getConfigEnchantments() { return configEnchantments; } /** * "ALL" enchantment cache */ - private @Nullable ConfigEnchantmentEntry.AllConfigEnchantmentEntry allConfigEnchantment; - - /** - * "ALL" enchantment cache - */ - public @NotNull Optional getAllConfigEnchantment() { + public Optional getAllConfigEnchantment() { return Optional.ofNullable(allConfigEnchantment); } @@ -50,14 +50,12 @@ private void registerEvents() { * * @param enchantment The Minecraft enchantment */ - public @NotNull Optional<@NotNull ConfigEnchantmentEntry> getConfigEnchantment(final @NotNull Enchantment enchantment) { + public Optional getConfigEnchantment(final Enchantment enchantment) { final Optional entry = getConfigEnchantments().stream() .filter(c -> c.isEnchantment(enchantment)) .findFirst(); - return entry.isEmpty() - ? getAllConfigEnchantment().map(a -> a.enchant(enchantment)) - : entry; + return entry.isEmpty() ? getAllConfigEnchantment().map(a -> a.enchant(enchantment)) : entry; } /** @@ -70,8 +68,7 @@ void reload() { try { enchants = ConfigEnchantmentEntry.config(getConfig().get("enchantments")); - } - catch (final IllegalArgumentException | IndexOutOfBoundsException | ClassCastException exception) { + } catch (final IllegalArgumentException | IndexOutOfBoundsException | ClassCastException exception) { getLogger().log(Level.SEVERE, "Failed to load config", exception); getServer().getPluginManager().disablePlugin(this); return; diff --git a/src/main/java/pro/cloudnode/smp/enchantbookplus/MainCommand.java b/src/main/java/pro/cloudnode/smp/enchantbookplus/MainCommand.java index 06116b2..e1790ba 100644 --- a/src/main/java/pro/cloudnode/smp/enchantbookplus/MainCommand.java +++ b/src/main/java/pro/cloudnode/smp/enchantbookplus/MainCommand.java @@ -5,39 +5,42 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.bukkit.plugin.PluginDescriptionFile; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NullMarked; import java.util.List; +@NullMarked public final class MainCommand implements CommandExecutor, TabCompleter { - private final @NotNull EnchantBookPlus plugin; + private final EnchantBookPlus plugin; - public MainCommand(final @NotNull EnchantBookPlus plugin) { + public MainCommand(final EnchantBookPlus plugin) { this.plugin = plugin; } @Override public boolean onCommand( - final @NotNull CommandSender sender, - final @NotNull Command command, - final @NotNull String label, - final @NotNull String @NotNull [] args + final CommandSender sender, + final Command command, + final String label, + final String[] args ) { - if (args.length == 1 && args[0].equalsIgnoreCase("reload")) - return reload(sender, command); + if (args.length == 1 && args[0].equalsIgnoreCase("reload")) { + return reload(sender); + } return overview(sender); } @Override - public @NotNull List onTabComplete( - final @NotNull CommandSender sender, - final @NotNull Command command, - final @NotNull String label, - final @NotNull String @NotNull [] args + public List onTabComplete( + final CommandSender sender, + final Command command, + final String label, + final String[] args ) { - if (sender.hasPermission(Permissions.RELOAD)) + if (sender.hasPermission(Permissions.RELOAD)) { return List.of("reload"); + } return List.of(); } @@ -46,10 +49,12 @@ public boolean onCommand( * Plugin overview */ @SuppressWarnings("SameReturnValue") - public boolean overview(final @NotNull CommandSender sender) { + public boolean overview(final CommandSender sender) { PluginDescriptionFile description = plugin.getDescription(); - sender.sendMessage("§a" + description.getName() + " §fv" + description.getVersion() + " by §7" - + String.join(", ", description.getAuthors())); + sender.sendMessage("§a" + description.getName() + " §fv" + description.getVersion() + " by §7" + String.join( + ", ", + description.getAuthors() + )); return true; } @@ -58,9 +63,10 @@ public boolean overview(final @NotNull CommandSender sender) { * Reload plugin configuration */ @SuppressWarnings("SameReturnValue") - public boolean reload(final @NotNull CommandSender sender, final @NotNull Command command) { - if (!sender.hasPermission(Permissions.RELOAD)) + public boolean reload(final CommandSender sender) { + if (!sender.hasPermission(Permissions.RELOAD)) { return overview(sender); + } plugin.reload(); diff --git a/src/main/java/pro/cloudnode/smp/enchantbookplus/Permissions.java b/src/main/java/pro/cloudnode/smp/enchantbookplus/Permissions.java index 1e28772..fe0c9a7 100644 --- a/src/main/java/pro/cloudnode/smp/enchantbookplus/Permissions.java +++ b/src/main/java/pro/cloudnode/smp/enchantbookplus/Permissions.java @@ -5,16 +5,17 @@ import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.PluginManager; -import org.jetbrains.annotations.NotNull; +import org.jspecify.annotations.NullMarked; +@NullMarked public final class Permissions { - public static @NotNull String enchant(final @NotNull Enchantment enchantment) { + public final static String RELOAD = "enchantbookplus.reload"; + + public static String enchant(final Enchantment enchantment) { return "enchantbookplus.enchant." + enchantment.getKey().getKey(); } - public final static @NotNull String RELOAD = "enchantbookplus.reload"; - - public static void init(final @NotNull EnchantBookPlus plugin) { + public static void init(final EnchantBookPlus plugin) { final PluginManager pm = plugin.getServer().getPluginManager(); pm.addPermission(new Permission( @@ -23,13 +24,12 @@ public static void init(final @NotNull EnchantBookPlus plugin) { PermissionDefault.OP )); - for (Enchantment enchantment : Registry.ENCHANTMENT) + for (Enchantment enchantment : Registry.ENCHANTMENT) { pm.addPermission(new Permission( enchant(enchantment), - "Allow enchanting " - + enchantment.getKey() - + "above the vanilla level, as configured in the plugin", + "Allow enchanting " + enchantment.getKey() + "above the vanilla level, as configured in the plugin", PermissionDefault.TRUE )); + } } } diff --git a/src/main/java/pro/cloudnode/smp/enchantbookplus/event/PrepareAnvil.java b/src/main/java/pro/cloudnode/smp/enchantbookplus/event/PrepareAnvil.java index c8e8a4e..a2a0e97 100644 --- a/src/main/java/pro/cloudnode/smp/enchantbookplus/event/PrepareAnvil.java +++ b/src/main/java/pro/cloudnode/smp/enchantbookplus/event/PrepareAnvil.java @@ -8,8 +8,7 @@ import org.bukkit.inventory.AnvilInventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.EnchantmentStorageMeta; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NullMarked; import pro.cloudnode.smp.enchantbookplus.ConfigEnchantmentEntry; import pro.cloudnode.smp.enchantbookplus.EnchantBookPlus; import pro.cloudnode.smp.enchantbookplus.Permissions; @@ -18,40 +17,45 @@ import java.util.Map; import java.util.Optional; +@NullMarked public final class PrepareAnvil implements Listener { - final @NotNull EnchantBookPlus plugin; + final EnchantBookPlus plugin; - public PrepareAnvil(final @NotNull EnchantBookPlus plugin) { + public PrepareAnvil(final EnchantBookPlus plugin) { this.plugin = plugin; } @EventHandler - public void onPrepareAnvil(final @NotNull PrepareAnvilEvent event) { + public void onPrepareAnvil(final PrepareAnvilEvent event) { final Optional result = Optional.ofNullable(event.getResult()); - if (result.isEmpty()) + if (result.isEmpty()) { return; + } final AnvilInventory inventory = event.getInventory(); - final @Nullable ItemStack item = inventory.getItem(0); - if (item == null) + final ItemStack item = inventory.getItem(0); + if (item == null) { return; + } - final @Nullable ItemStack upgrade = inventory.getItem(1); - if (upgrade == null) + final ItemStack upgrade = inventory.getItem(1); + if (upgrade == null) { return; + } - final Map itemEnchants = item.getType() == Material.ENCHANTED_BOOK && - item.getItemMeta() instanceof final EnchantmentStorageMeta itemMeta - ? itemMeta.getStoredEnchants() - : item.getEnchantments(); + final Map itemEnchants = item.getType() == Material.ENCHANTED_BOOK + && item.getItemMeta() instanceof final EnchantmentStorageMeta itemMeta + ? itemMeta.getStoredEnchants() + : item.getEnchantments(); - final Map upgradeEnchants = upgrade.getType() == Material.ENCHANTED_BOOK && - upgrade.getItemMeta() instanceof final EnchantmentStorageMeta upgradeMeta - ? upgradeMeta.getStoredEnchants() - : upgrade.getEnchantments(); - if (upgradeEnchants.isEmpty()) + final Map upgradeEnchants = upgrade.getType() == Material.ENCHANTED_BOOK + && upgrade.getItemMeta() instanceof final EnchantmentStorageMeta upgradeMeta + ? upgradeMeta.getStoredEnchants() + : upgrade.getEnchantments(); + if (upgradeEnchants.isEmpty()) { return; + } final Map upgrades = new HashMap<>(); @@ -60,15 +64,18 @@ public void onPrepareAnvil(final @NotNull PrepareAnvilEvent event) { for (final Map.Entry entry : upgradeEnchants.entrySet()) { final Enchantment enchantment = entry.getKey(); - if (!event.getView().getPlayer().hasPermission(Permissions.enchant(enchantment))) + if (!event.getView().getPlayer().hasPermission(Permissions.enchant(enchantment))) { continue; + } - if (enchantment.getMaxLevel() == 1) + if (enchantment.getMaxLevel() == 1) { continue; + } final Optional configEnchantment = plugin.getConfigEnchantment(enchantment); - if (configEnchantment.isEmpty()) + if (configEnchantment.isEmpty()) { continue; + } final int upgradeLevel = entry.getValue(); @@ -76,50 +83,56 @@ public void onPrepareAnvil(final @NotNull PrepareAnvilEvent event) { if (itemEnchants.containsKey(enchantment)) { final int itemLevel = itemEnchants.get(enchantment); - if (itemLevel > upgradeLevel) + if (itemLevel > upgradeLevel) { finalLevel = itemLevel; - else if (itemLevel == upgradeLevel) + } else if (itemLevel == upgradeLevel) { finalLevel = upgradeLevel + 1; - else + } else { finalLevel = upgradeLevel; - } - else + } + } else { finalLevel = upgradeLevel; + } - if (finalLevel <= enchantment.getMaxLevel()) + if (finalLevel <= enchantment.getMaxLevel()) { continue; + } - if (configEnchantment.get().getMaxLevel().isPresent() && - finalLevel > configEnchantment.get().getMaxLevel().get()) { + if (configEnchantment.get().getMaxLevel().isPresent() && finalLevel > configEnchantment.get() + .getMaxLevel() + .getAsInt()) { // guard against vanilla downgrade - upgrades.put(enchantment, configEnchantment.get().getMaxLevel().get()); + upgrades.put(enchantment, configEnchantment.get().getMaxLevel().getAsInt()); continue; } - if (finalLevel > upgradeLevel) - cost += configEnchantment.get().getMultiplyCostByLevel() - ? configEnchantment.get().getCost() * (finalLevel - enchantment.getMaxLevel()) - : configEnchantment.get().getCost(); + if (finalLevel > upgradeLevel) { + cost += configEnchantment.get().getMultiplyCostByLevel() ? configEnchantment.get().getCost() * ( + finalLevel - enchantment.getMaxLevel()) : configEnchantment.get().getCost(); + } upgrades.put(enchantment, finalLevel); } - if (upgrades.isEmpty()) return; + if (upgrades.isEmpty()) { + return; + } inventory.setRepairCost(inventory.getRepairCost() + cost); for (final Map.Entry entry : upgrades.entrySet()) { if (result.get().getItemMeta() instanceof final EnchantmentStorageMeta resultMeta) { - if (!resultMeta.getStoredEnchants().containsKey(entry.getKey())) + if (!resultMeta.getStoredEnchants().containsKey(entry.getKey())) { continue; + } resultMeta.addStoredEnchant(entry.getKey(), entry.getValue(), true); result.get().setItemMeta(resultMeta); - } - else { - if (!result.get().getEnchantments().containsKey(entry.getKey())) + } else { + if (!result.get().getEnchantments().containsKey(entry.getKey())) { continue; + } result.get().addUnsafeEnchantment(entry.getKey(), entry.getValue()); }