diff --git a/pom.xml b/pom.xml index 8e055ec..f4fb44e 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ com.songoda EpicEnchants 4.0.0 - 1.1.6 + 1.1.7 clean install EpicEnchants-${project.version} @@ -94,7 +94,7 @@ org.spigotmc spigot - 1.15 + 1.16.1 fr.mrmicky diff --git a/src/main/java/com/songoda/epicenchants/.DS_Store b/src/main/java/com/songoda/epicenchants/.DS_Store new file mode 100644 index 0000000..36367fa Binary files /dev/null and b/src/main/java/com/songoda/epicenchants/.DS_Store differ diff --git a/src/main/java/com/songoda/epicenchants/EpicEnchants.java b/src/main/java/com/songoda/epicenchants/EpicEnchants.java index 713660a..0dc47ea 100644 --- a/src/main/java/com/songoda/epicenchants/EpicEnchants.java +++ b/src/main/java/com/songoda/epicenchants/EpicEnchants.java @@ -2,11 +2,12 @@ package com.songoda.epicenchants; import com.songoda.core.SongodaCore; import com.songoda.core.SongodaPlugin; +import com.songoda.core.commands.CommandManager; import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.core.configuration.Config; import com.songoda.core.gui.GuiManager; import com.songoda.core.hooks.EconomyManager; -import com.songoda.epicenchants.command.CommandManager; +import com.songoda.epicenchants.command.commands.*; import com.songoda.epicenchants.listeners.ArmorListener; import com.songoda.epicenchants.listeners.EntityListener; import com.songoda.epicenchants.listeners.PlayerListener; @@ -58,6 +59,21 @@ public class EpicEnchants extends SongodaPlugin { // Run Songoda Updater SongodaCore.registerPlugin(this, 67, CompatibleMaterial.DIAMOND_SWORD); + // setup commands + this.commandManager = new com.songoda.core.commands.CommandManager(this); + this.commandManager.addMainCommand("ee") + .addSubCommand(new CommandReload(this)) + .addSubCommand(new CommandAlchemist(this)) + .addSubCommand(new CommandApply(this)) + .addSubCommand(new CommandEnchanter(this)) + .addSubCommand(new CommandGiveBook(this)) + .addSubCommand(new CommandGiveItemDust(this)) + .addSubCommand(new CommandGiveRandomBook(this)) + .addSubCommand(new CommandGiveScroll(this)) + .addSubCommand(new CommandList(this)) + .addSubCommand(new CommandSettings(this)) + .addSubCommand(new CommandTinkerer(this)); + EconomyManager.load(); // Setup Config @@ -75,7 +91,7 @@ public class EpicEnchants extends SongodaPlugin { this.specialItems = new SpecialItems(this); this.commandManager = new CommandManager(this); this.hookManager = new HookManager(); - this.itemGroup = new ItemGroup(this); + this.itemGroup = new ItemGroup(); groupManager.loadGroups(); enchantManager.loadEnchants(); diff --git a/src/main/java/com/songoda/epicenchants/command/AbstractCommand.java b/src/main/java/com/songoda/epicenchants/command/AbstractCommand.java deleted file mode 100644 index 7bdd9a3..0000000 --- a/src/main/java/com/songoda/epicenchants/command/AbstractCommand.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.songoda.epicenchants.command; - -import com.songoda.epicenchants.EpicEnchants; -import org.bukkit.command.CommandSender; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public abstract class AbstractCommand { - - private final boolean noConsole; - private AbstractCommand parent = null; - private boolean hasArgs = false; - private String command; - - private List subCommand = new ArrayList<>(); - - protected AbstractCommand(AbstractCommand parent, boolean noConsole, String... command) { - if (parent != null) { - this.subCommand = Arrays.asList(command); - } else { - this.command = Arrays.asList(command).get(0); - } - this.parent = parent; - this.noConsole = noConsole; - } - - protected AbstractCommand(boolean noConsole, boolean hasArgs, String... command) { - this.command = Arrays.asList(command).get(0); - - this.hasArgs = hasArgs; - this.noConsole = noConsole; - } - - public AbstractCommand getParent() { - return parent; - } - - public String getCommand() { - return command; - } - - public List getSubCommand() { - return subCommand; - } - - public void addSubCommand(String command) { - subCommand.add(command); - } - - protected abstract ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args); - - protected abstract List onTab(EpicEnchants instance, CommandSender sender, String... args); - - public abstract String getPermissionNode(); - - public abstract String getSyntax(); - - public abstract String getDescription(); - - public boolean hasArgs() { - return hasArgs; - } - - public boolean isNoConsole() { - return noConsole; - } - - public enum ReturnType {SUCCESS, FAILURE, SYNTAX_ERROR} -} diff --git a/src/main/java/com/songoda/epicenchants/command/CommandManager.java b/src/main/java/com/songoda/epicenchants/command/CommandManager.java deleted file mode 100644 index 8711e66..0000000 --- a/src/main/java/com/songoda/epicenchants/command/CommandManager.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.songoda.epicenchants.command; - -import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.commands.*; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class CommandManager implements CommandExecutor { - - private static final List commands = new ArrayList<>(); - private EpicEnchants plugin; - private TabManager tabManager; - - public CommandManager(EpicEnchants plugin) { - this.plugin = plugin; - this.tabManager = new TabManager(this); - - plugin.getCommand("EpicEnchants").setExecutor(this); - - AbstractCommand commandEpicEnchants = addCommand(new CommandEpicEnchants()); - - addCommand(new CommandSettings(commandEpicEnchants)); - addCommand(new CommandReload(commandEpicEnchants)); - addCommand(new CommandApply(commandEpicEnchants)); - addCommand(new CommandList(commandEpicEnchants)); - addCommand(new CommandGiveBook(commandEpicEnchants)); - addCommand(new CommandGiveRandomBook(commandEpicEnchants)); - addCommand(new CommandGiveItemDust(commandEpicEnchants)); - addCommand(new CommandGiveScroll(commandEpicEnchants)); - addCommand(new CommandAlchemist(commandEpicEnchants)); - addCommand(new CommandEnchanter(commandEpicEnchants)); - addCommand(new CommandTinkerer(commandEpicEnchants)); - - for (AbstractCommand abstractCommand : commands) { - if (abstractCommand.getParent() != null) continue; - plugin.getCommand(abstractCommand.getCommand()).setTabCompleter(tabManager); - } - } - - private AbstractCommand addCommand(AbstractCommand abstractCommand) { - commands.add(abstractCommand); - return abstractCommand; - } - - @Override - public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) { - for (AbstractCommand abstractCommand : commands) { - if (abstractCommand.getCommand() != null && abstractCommand.getCommand().equalsIgnoreCase(command.getName().toLowerCase())) { - if (strings.length == 0 || abstractCommand.hasArgs()) { - processRequirements(abstractCommand, commandSender, strings); - return true; - } - } else if (strings.length != 0 && abstractCommand.getParent() != null && abstractCommand.getParent().getCommand().equalsIgnoreCase(command.getName())) { - String cmd = strings[0]; - String cmd2 = strings.length >= 2 ? String.join(" ", strings[0], strings[1]) : null; - for (String cmds : abstractCommand.getSubCommand()) { - if (cmd.equalsIgnoreCase(cmds) || (cmd2 != null && cmd2.equalsIgnoreCase(cmds))) { - processRequirements(abstractCommand, commandSender, strings); - return true; - } - } - } - } - plugin.getLocale().newMessage("&7The command you entered does not exist or is spelt incorrectly.").sendPrefixedMessage(commandSender); - return true; - } - - private void processRequirements(AbstractCommand command, CommandSender sender, String[] strings) { - if (!(sender instanceof Player) && command.isNoConsole()) { - sender.sendMessage("You must be a player to use this commands."); - return; - } - if (command.getPermissionNode() == null || sender.hasPermission(command.getPermissionNode())) { - AbstractCommand.ReturnType returnType = command.runCommand(plugin, sender, strings); - if (returnType == AbstractCommand.ReturnType.SYNTAX_ERROR) { - plugin.getLocale().newMessage("&cInvalid Syntax!").sendPrefixedMessage(sender); - plugin.getLocale().newMessage("&7The valid syntax is: &6" + command.getSyntax() + "&7.").sendPrefixedMessage(sender); - } - return; - } - plugin.getLocale().getMessage("event.general.nopermission").sendPrefixedMessage(sender); - } - - public List getCommands() { - return Collections.unmodifiableList(commands); - } -} diff --git a/src/main/java/com/songoda/epicenchants/command/TabManager.java b/src/main/java/com/songoda/epicenchants/command/TabManager.java deleted file mode 100644 index 1fe6cab..0000000 --- a/src/main/java/com/songoda/epicenchants/command/TabManager.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.songoda.epicenchants.command; - -import com.songoda.epicenchants.EpicEnchants; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; - -import java.util.ArrayList; -import java.util.List; - -public class TabManager implements TabCompleter { - - private final CommandManager commandManager; - - TabManager(CommandManager commandManager) { - this.commandManager = commandManager; - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] strings) { - for (AbstractCommand abstractCommand : commandManager.getCommands()) { - if (abstractCommand.getCommand() != null && abstractCommand.getCommand().equalsIgnoreCase(command.getName().toLowerCase())) { - if (strings.length == 1) { - List subs = new ArrayList<>(); - for (AbstractCommand ac : commandManager.getCommands()) { - if (ac.getSubCommand() == null) continue; - subs.addAll(ac.getSubCommand()); - } - subs.removeIf(s -> !s.toLowerCase().startsWith(strings[0].toLowerCase())); - return subs; - } - } else if (strings.length != 0 && abstractCommand.getParent() != null && abstractCommand.getParent().getCommand().equalsIgnoreCase(command.getName().toLowerCase())) { - String cmd = strings[0]; - String cmd2 = strings.length >= 2 ? String.join(" ", strings[0], strings[1]) : null; - for (String cmds : abstractCommand.getSubCommand()) { - if (cmd.equalsIgnoreCase(cmds) || (cmd2 != null && cmd2.equalsIgnoreCase(cmds))) { - List list = abstractCommand.onTab(EpicEnchants.getInstance(), sender, strings); - String str = strings[strings.length - 1]; - if (list != null && str != null && str.length() >= 1) { - try { - list.removeIf(s -> !s.toLowerCase().startsWith(str.toLowerCase())); - } catch (UnsupportedOperationException ignored) { - } - } - return list; - } - } - } - } - return null; - } -} diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandEpicEnchants.java b/src/main/java/com/songoda/epicenchants/command/commands/CommandEpicEnchants.java deleted file mode 100644 index 9f045b4..0000000 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandEpicEnchants.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.songoda.epicenchants.command.commands; - -import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; -import com.songoda.epicenchants.utils.Methods; -import org.bukkit.command.CommandSender; - -import java.util.List; - -public class CommandEpicEnchants extends AbstractCommand { - - public CommandEpicEnchants() { - super(null, false, "EpicEnchants"); - } - - @Override - protected AbstractCommand.ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { - sender.sendMessage(""); - instance.getLocale().newMessage("&7Version " + instance.getDescription().getVersion() - + " Created with <3 by &5&l&oSongoda").sendPrefixedMessage(sender); - - for (AbstractCommand command : instance.getCommandManager().getCommands()) { - if (command.getPermissionNode() == null || sender.hasPermission(command.getPermissionNode())) { - sender.sendMessage(Methods.formatText("&8 - &a" + command.getSyntax() + "&7 - " + command.getDescription())); - } - } - sender.sendMessage(""); - - return ReturnType.SUCCESS; - } - - @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { - return null; - } - - @Override - public String getPermissionNode() { - return null; - } - - @Override - public String getSyntax() { - return "/EpicEnchants"; - } - - @Override - public String getDescription() { - return "Displays this page."; - } -} diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandAlchemist.java b/src/main/java/com/songoda/epicenchants/commands/CommandAlchemist.java similarity index 56% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandAlchemist.java rename to src/main/java/com/songoda/epicenchants/commands/CommandAlchemist.java index c11b6c2..b8b1fac 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandAlchemist.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandAlchemist.java @@ -1,9 +1,8 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; import com.songoda.epicenchants.menus.AlchemistMenu; -import com.songoda.epicenchants.menus.TinkererMenu; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -11,19 +10,23 @@ import java.util.List; public class CommandAlchemist extends AbstractCommand { - public CommandAlchemist(AbstractCommand parent) { - super(parent, true, "alchemist"); + private final EpicEnchants plugin; + + public CommandAlchemist(EpicEnchants plugin) { + super(true, "alchemist"); + this.plugin = plugin; } + @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { + protected ReturnType runCommand(CommandSender sender, String... args) { Player player = (Player)sender; - new AlchemistMenu(instance, instance.getFileManager().getConfiguration("menus/alchemist-menu")).open(player); + new AlchemistMenu(plugin, plugin.getFileManager().getConfiguration("menus/alchemist-menu")).open(player); return ReturnType.SUCCESS; } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { + protected List onTab(CommandSender sender, String... args) { return null; } @@ -34,7 +37,7 @@ public class CommandAlchemist extends AbstractCommand { @Override public String getSyntax() { - return "/ee alchemist"; + return "alchemist"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandApply.java b/src/main/java/com/songoda/epicenchants/commands/CommandApply.java similarity index 65% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandApply.java rename to src/main/java/com/songoda/epicenchants/commands/CommandApply.java index 6ba0d30..dbba58f 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandApply.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandApply.java @@ -1,12 +1,11 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.CommandCommons; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; import com.songoda.epicenchants.enums.EnchantResult; import com.songoda.epicenchants.objects.Enchant; import com.songoda.epicenchants.utils.Tuple; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -21,47 +20,50 @@ import static com.songoda.epicenchants.utils.single.GeneralUtils.getMessageFromR public class CommandApply extends AbstractCommand { - public CommandApply(AbstractCommand parent) { - super(parent, true, "apply"); + private final EpicEnchants plugin; + + public CommandApply(EpicEnchants plugin) { + super(true, "apply"); + this.plugin = plugin; } - //ee apply [enchant] [level] + //apply [enchant] [level] @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length < 3 || args.length > 5) + protected ReturnType runCommand(CommandSender sender, String... args) { + if (args.length < 2 || args.length > 4) return ReturnType.SYNTAX_ERROR; - Optional optionalEnchant = instance.getEnchantManager().getValue(args[1].replaceAll("_", " ")); + Optional optionalEnchant = plugin.getEnchantManager().getValue(args[0].replaceAll("_", " ")); if (!optionalEnchant.isPresent()) { - instance.getLocale().newMessage("&cNo enchants exist with that name...").sendPrefixedMessage(sender); + plugin.getLocale().newMessage("&cNo enchants exist with that name...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } - if (!CommandCommons.isInt(args[2], sender)) + if (!CommandCommons.isInt(args[1], sender)) return ReturnType.FAILURE; int successRate = 100; int destroyRate = 0; + if (args.length > 2) { + if (!CommandCommons.isInt(args[2], sender)) + return ReturnType.FAILURE; + successRate = Integer.parseInt(args[2]); + } + if (args.length > 3) { if (!CommandCommons.isInt(args[3], sender)) return ReturnType.FAILURE; - successRate = Integer.parseInt(args[3]); - } - - if (args.length > 4) { - if (!CommandCommons.isInt(args[4], sender)) - return ReturnType.FAILURE; - destroyRate = Integer.parseInt(args[4]); + destroyRate = Integer.parseInt(args[3]); } Enchant enchant = optionalEnchant.get(); - int level = Integer.parseInt(args[2]); + int level = Integer.parseInt(args[1]); Player player = (Player) sender; if (!enchant.getItemWhitelist().contains(player.getItemInHand().getType())) { System.out.println("List = " + enchant.getItemWhitelist()); - instance.getLocale().getMessage("command.apply.invaliditem") + plugin.getLocale().getMessage("command.apply.invaliditem") .processPlaceholder("enchant", enchant.getIdentifier()) .sendPrefixedMessage(player); return ReturnType.FAILURE; @@ -69,10 +71,10 @@ public class CommandApply extends AbstractCommand { int slot = player.getInventory().getHeldItemSlot(); ItemStack before = player.getItemInHand(); - Tuple result = instance.getEnchantUtils().apply(before, enchant, level, + Tuple result = plugin.getEnchantUtils().apply(before, enchant, level, successRate, destroyRate); - instance.getLocale().getMessage(getMessageFromResult(result.getRight())) + plugin.getLocale().getMessage(getMessageFromResult(result.getRight())) .processPlaceholder("enchant", enchant.getIdentifier()) .sendPrefixedMessage(player); @@ -86,12 +88,12 @@ public class CommandApply extends AbstractCommand { } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length == 2) { - return instance.getEnchantManager().getValues() + protected List onTab(CommandSender sender, String... args) { + if (args.length == 1) { + return plugin.getEnchantManager().getValues() .stream().map(Enchant::getIdentifier).collect(Collectors.toList()); - } else if (args.length == 3) { - Enchant enchant = instance.getEnchantManager().getValues() + } else if (args.length == 2) { + Enchant enchant = plugin.getEnchantManager().getValues() .stream().findFirst().orElse(null); List levels = new ArrayList<>(); if (enchant != null) { @@ -99,7 +101,7 @@ public class CommandApply extends AbstractCommand { levels.add(String.valueOf(i)); } return levels; - } else if (args.length == 4 || args.length == 5) { + } else if (args.length == 3 || args.length == 4) { List rates = new ArrayList<>(); for (int i = 1; i <= 100; i ++) rates.add(String.valueOf(i)); @@ -115,7 +117,7 @@ public class CommandApply extends AbstractCommand { @Override public String getSyntax() { - return "/ee apply [success-rate] [destroy-rate]"; + return "apply [success-rate] [destroy-rate]"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandEnchanter.java b/src/main/java/com/songoda/epicenchants/commands/CommandEnchanter.java similarity index 58% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandEnchanter.java rename to src/main/java/com/songoda/epicenchants/commands/CommandEnchanter.java index 14dce8a..75e8268 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandEnchanter.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandEnchanter.java @@ -1,7 +1,7 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; import com.songoda.epicenchants.menus.EnchanterMenu; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -10,19 +10,22 @@ import java.util.List; public class CommandEnchanter extends AbstractCommand { - public CommandEnchanter(AbstractCommand parent) { - super(parent, true, "enchanter"); + private final EpicEnchants plugin; + + public CommandEnchanter(EpicEnchants plugin) { + super(true, "enchanter"); + this.plugin = plugin; } @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { + protected ReturnType runCommand(CommandSender sender, String... args) { Player player = (Player)sender; - new EnchanterMenu(instance, instance.getFileManager().getConfiguration("menus/enchanter-menu"), player).open(player); + new EnchanterMenu(plugin, plugin.getFileManager().getConfiguration("menus/enchanter-menu"), player).open(player); return ReturnType.SUCCESS; } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { + protected List onTab(CommandSender sender, String... args) { return null; } @@ -33,7 +36,7 @@ public class CommandEnchanter extends AbstractCommand { @Override public String getSyntax() { - return "/ee enchanter"; + return "enchanter"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandGiveBook.java b/src/main/java/com/songoda/epicenchants/commands/CommandGiveBook.java similarity index 62% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandGiveBook.java rename to src/main/java/com/songoda/epicenchants/commands/CommandGiveBook.java index 3cfc46f..6bf32d8 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandGiveBook.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandGiveBook.java @@ -1,8 +1,8 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.CommandCommons; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; import com.songoda.epicenchants.objects.Enchant; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; @@ -16,27 +16,30 @@ import java.util.stream.Collectors; public class CommandGiveBook extends AbstractCommand { - public CommandGiveBook(AbstractCommand parent) { - super(parent, false, "givebook"); + private final EpicEnchants plugin; + + public CommandGiveBook(EpicEnchants plugin) { + super(false, "givebook"); + this.plugin = plugin; } - //ee givebook [level] [success-rate] [destroy-rate] + //givebook [level] [success-rate] [destroy-rate] @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length < 3 || args.length > 6) + protected ReturnType runCommand(CommandSender sender, String... args) { + if (args.length < 2 || args.length > 5) return ReturnType.SYNTAX_ERROR; - OfflinePlayer target = Bukkit.getPlayer(args[1]); + OfflinePlayer target = Bukkit.getPlayer(args[0]); if (target == null) { - instance.getLocale().newMessage("&cThis player does not exist...").sendPrefixedMessage(sender); + plugin.getLocale().newMessage("&cThis player does not exist...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } - Optional optionalEnchant = instance.getEnchantManager().getValue(args[2].replaceAll("_", " ")); + Optional optionalEnchant = plugin.getEnchantManager().getValue(args[1].replaceAll("_", " ")); if (!optionalEnchant.isPresent()) { - instance.getLocale().newMessage("&cNo enchants exist with that name...").sendPrefixedMessage(sender); + plugin.getLocale().newMessage("&cNo enchants exist with that name...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } @@ -45,26 +48,26 @@ public class CommandGiveBook extends AbstractCommand { int successRate = -1; int destroyRate = -1; + if (args.length > 2) { + if (!CommandCommons.isInt(args[2], sender)) + return ReturnType.FAILURE; + level = Integer.parseInt(args[2]); + } + if (args.length > 3) { if (!CommandCommons.isInt(args[3], sender)) return ReturnType.FAILURE; - level = Integer.parseInt(args[3]); + successRate = Integer.parseInt(args[3]); } if (args.length > 4) { if (!CommandCommons.isInt(args[4], sender)) return ReturnType.FAILURE; - successRate = Integer.parseInt(args[4]); + destroyRate = Integer.parseInt(args[4]); } - if (args.length > 5) { - if (!CommandCommons.isInt(args[5], sender)) - return ReturnType.FAILURE; - destroyRate = Integer.parseInt(args[5]); - } - - if (level != -1 && (level > enchant.getMaxLevel() || level < 1)) { - instance.getLocale().getMessage("command.book." + (level > enchant.getMaxLevel() ? "maxlevel" : "minlevel")) + if (level != -0 && (level > enchant.getMaxLevel() || level < 0)) { + plugin.getLocale().getMessage("command.book." + (level > enchant.getMaxLevel() ? "maxlevel" : "minlevel")) .processPlaceholder("enchant", enchant.getIdentifier()) .processPlaceholder("max_level", enchant.getMaxLevel()) .sendPrefixedMessage(sender); @@ -72,10 +75,10 @@ public class CommandGiveBook extends AbstractCommand { } target.getPlayer().getInventory().addItem(enchant.getBook().get(enchant, level, successRate, destroyRate)); - instance.getLocale().getMessage("command.book.received") + plugin.getLocale().getMessage("command.book.received") .processPlaceholder("enchant", enchant.getIdentifier()) .sendPrefixedMessage(target.getPlayer()); - instance.getLocale().getMessage("command.book.gave") + plugin.getLocale().getMessage("command.book.gave") .processPlaceholder("player", target.getPlayer().getName()) .processPlaceholder("enchant", enchant.getIdentifier()) .sendPrefixedMessage(sender); @@ -83,14 +86,14 @@ public class CommandGiveBook extends AbstractCommand { } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length == 2) { + protected List onTab(CommandSender sender, String... args) { + if (args.length == 1) { return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); - } else if (args.length == 3) { - return instance.getEnchantManager().getValues() + } else if (args.length == 2) { + return plugin.getEnchantManager().getValues() .stream().map(Enchant::getIdentifier).collect(Collectors.toList()); - } else if (args.length == 4) { - Enchant enchant = instance.getEnchantManager().getValues() + } else if (args.length == 3) { + Enchant enchant = plugin.getEnchantManager().getValues() .stream().findFirst().orElse(null); List levels = new ArrayList<>(); if (enchant != null) { @@ -98,7 +101,7 @@ public class CommandGiveBook extends AbstractCommand { levels.add(String.valueOf(i)); } return levels; - } else if (args.length == 5 || args.length == 6) { + } else if (args.length == 4 || args.length == 5) { List rates = new ArrayList<>(); for (int i = 1; i <= 100; i ++) rates.add(String.valueOf(i)); @@ -114,7 +117,7 @@ public class CommandGiveBook extends AbstractCommand { @Override public String getSyntax() { - return "/ee givebook [level] [success-rate] [destroy-rate]"; + return "givebook [level] [success-rate] [destroy-rate]"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandGiveItemDust.java b/src/main/java/com/songoda/epicenchants/commands/CommandGiveItemDust.java similarity index 57% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandGiveItemDust.java rename to src/main/java/com/songoda/epicenchants/commands/CommandGiveItemDust.java index c5fd223..0bde823 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandGiveItemDust.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandGiveItemDust.java @@ -1,9 +1,8 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.CommandCommons; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; -import com.songoda.epicenchants.objects.Enchant; import com.songoda.epicenchants.objects.Group; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; @@ -13,33 +12,35 @@ import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; public class CommandGiveItemDust extends AbstractCommand { + + private final EpicEnchants plugin; - public CommandGiveItemDust(AbstractCommand parent) { - super(parent, false, "giveitemdust"); + public CommandGiveItemDust(EpicEnchants plugin) { + super(false, "giveitemdust"); + this.plugin = plugin; } - //ee giveitemdust [type] [percentage] + //giveitemdust [type] [percentage] @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length < 3 || args.length > 6) + protected ReturnType runCommand(CommandSender sender, String... args) { + if (args.length < 2 || args.length > 5) return ReturnType.SYNTAX_ERROR; - OfflinePlayer target = Bukkit.getPlayer(args[1]); + OfflinePlayer target = Bukkit.getPlayer(args[0]); if (target == null) { - instance.getLocale().newMessage("&cThis player does not exist...").sendPrefixedMessage(sender); + plugin.getLocale().newMessage("&cThis player does not exist...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } - List groups = instance.getGroupManager().getValues().stream() - .filter(group -> group.getIdentifier().equalsIgnoreCase(args[2])).collect(Collectors.toList()); + List groups = plugin.getGroupManager().getValues().stream() + .filter(group -> group.getIdentifier().equalsIgnoreCase(args[1])).collect(Collectors.toList()); if (groups.isEmpty()) { - instance.getLocale().newMessage("&cThe group you entered was no found...").sendPrefixedMessage(sender); + plugin.getLocale().newMessage("&cThe group you entered was no found...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } @@ -48,21 +49,21 @@ public class CommandGiveItemDust extends AbstractCommand { String dustType = null; int percentage = -1; + if (args.length > 2) { + dustType = args[2]; + } + if (args.length > 3) { - dustType = args[3]; - } - - if (args.length > 4) { - if (!CommandCommons.isInt(args[4], sender)) + if (!CommandCommons.isInt(args[3], sender)) return ReturnType.FAILURE; - percentage = Integer.parseInt(args[4]); + percentage = Integer.parseInt(args[3]); } - target.getPlayer().getInventory().addItem(instance.getSpecialItems().getDust(group, dustType, percentage, true)); - instance.getLocale().getMessage("command.dust.received") + target.getPlayer().getInventory().addItem(plugin.getSpecialItems().getDust(group, dustType, percentage, true)); + plugin.getLocale().getMessage("command.dust.received") .processPlaceholder("group", group.getIdentifier()) .sendPrefixedMessage(target.getPlayer()); - instance.getLocale().getMessage("command.dust.gave") + plugin.getLocale().getMessage("command.dust.gave") .processPlaceholder("player", target.getPlayer().getName()) .processPlaceholder("group", group.getIdentifier()) .sendPrefixedMessage(sender); @@ -70,19 +71,19 @@ public class CommandGiveItemDust extends AbstractCommand { } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length == 2) { + protected List onTab(CommandSender sender, String... args) { + if (args.length == 1) { return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); - } else if (args.length == 3) { - return instance.getGroupManager().getValues().stream() + } else if (args.length == 2) { + return plugin.getGroupManager().getValues().stream() .map(Group::getIdentifier).collect(Collectors.toList()); - } else if (args.length == 4) { + } else if (args.length == 3) { List dusts = new ArrayList<>(); - FileConfiguration dustConfig = instance.getFileManager().getConfiguration("items/dusts"); + FileConfiguration dustConfig = plugin.getFileManager().getConfiguration("items/dusts"); dusts.addAll(dustConfig.getConfigurationSection("dusts").getKeys(false)); return dusts; - } else if (args.length == 5) { + } else if (args.length == 4) { List rates = new ArrayList<>(); for (int i = 1; i <= 100; i ++) rates.add(String.valueOf(i)); @@ -98,7 +99,7 @@ public class CommandGiveItemDust extends AbstractCommand { @Override public String getSyntax() { - return "/ee giveitemdust [type] [percentage]"; + return "giveitemdust [type] [percentage]"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandGiveRandomBook.java b/src/main/java/com/songoda/epicenchants/commands/CommandGiveRandomBook.java similarity index 53% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandGiveRandomBook.java rename to src/main/java/com/songoda/epicenchants/commands/CommandGiveRandomBook.java index 6262367..f35535c 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandGiveRandomBook.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandGiveRandomBook.java @@ -1,7 +1,7 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; import com.songoda.epicenchants.objects.Group; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; @@ -13,49 +13,52 @@ import java.util.stream.Collectors; public class CommandGiveRandomBook extends AbstractCommand { - public CommandGiveRandomBook(AbstractCommand parent) { - super(parent, false, "giverandombook"); + private final EpicEnchants plugin; + + public CommandGiveRandomBook(EpicEnchants plugin) { + super(false, "giverandombook"); + this.plugin = plugin; } - //ee giverandombook + //giverandombook @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length < 3 || args.length > 6) + protected ReturnType runCommand(CommandSender sender, String... args) { + if (args.length < 2 || args.length > 6) return ReturnType.SYNTAX_ERROR; - OfflinePlayer target = Bukkit.getPlayer(args[1]); + OfflinePlayer target = Bukkit.getPlayer(args[0]); if (target == null) { - instance.getLocale().newMessage("&cThis player does not exist...").sendPrefixedMessage(sender); + plugin.getLocale().newMessage("&cThis player does not exist...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } - List groups = instance.getGroupManager().getValues().stream() - .filter(group -> group.getIdentifier().equalsIgnoreCase(args[2])).collect(Collectors.toList()); + List groups = plugin.getGroupManager().getValues().stream() + .filter(group -> group.getIdentifier().equalsIgnoreCase(args[1])).collect(Collectors.toList()); if (groups.isEmpty()) { - instance.getLocale().newMessage("&cThe group you entered was no found...").sendPrefixedMessage(sender); + plugin.getLocale().newMessage("&cThe group you entered was no found...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } Group group = groups.get(0); - target.getPlayer().getInventory().addItem(instance.getSpecialItems().getMysteryBook(group)); - instance.getLocale().getMessage("command.randombook.received") + target.getPlayer().getInventory().addItem(plugin.getSpecialItems().getMysteryBook(group)); + plugin.getLocale().getMessage("command.randombook.received") .sendPrefixedMessage(target.getPlayer()); - instance.getLocale().getMessage("command.randombook.gave") + plugin.getLocale().getMessage("command.randombook.gave") .processPlaceholder("player", target.getPlayer().getName()) .sendPrefixedMessage(sender); return ReturnType.SUCCESS; } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length == 2) { + protected List onTab(CommandSender sender, String... args) { + if (args.length == 1) { return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); - } else if (args.length == 3) { - return instance.getGroupManager().getValues().stream() + } else if (args.length == 2) { + return plugin.getGroupManager().getValues().stream() .map(Group::getIdentifier).collect(Collectors.toList()); } return null; @@ -68,7 +71,7 @@ public class CommandGiveRandomBook extends AbstractCommand { @Override public String getSyntax() { - return "/ee giverandombook "; + return "giverandombook "; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandGiveScroll.java b/src/main/java/com/songoda/epicenchants/commands/CommandGiveScroll.java similarity index 56% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandGiveScroll.java rename to src/main/java/com/songoda/epicenchants/commands/CommandGiveScroll.java index c21925c..b84128d 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandGiveScroll.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandGiveScroll.java @@ -1,9 +1,8 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.CommandCommons; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; -import com.songoda.epicenchants.objects.Enchant; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; @@ -15,22 +14,25 @@ import java.util.List; import java.util.stream.Collectors; public class CommandGiveScroll extends AbstractCommand { + + private final EpicEnchants plugin; - public CommandGiveScroll(AbstractCommand parent) { - super(parent, false, "givescroll"); + public CommandGiveScroll(EpicEnchants plugin) { + super(false, "givescroll"); + this.plugin = plugin; } - //ee givescroll [amount] [success-rate] + //givescroll [amount] [success-rate] @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length < 3 || args.length > 6) + protected ReturnType runCommand(CommandSender sender, String... args) { + if (args.length < 2 || args.length > 5) return ReturnType.SYNTAX_ERROR; - String giveType = args[1]; - OfflinePlayer target = Bukkit.getPlayer(args[2]); + String giveType = args[0]; + OfflinePlayer target = Bukkit.getPlayer(args[1]); if (target == null) { - instance.getLocale().newMessage("&cThis player does not exist...").sendPrefixedMessage(sender); + plugin.getLocale().newMessage("&cThis player does not exist...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } @@ -38,52 +40,52 @@ public class CommandGiveScroll extends AbstractCommand { int successRate = -1; + if (args.length > 2) { + if (!CommandCommons.isInt(args[2], sender)) + return ReturnType.FAILURE; + amount = Integer.parseInt(args[2]); + } + if (args.length > 3) { if (!CommandCommons.isInt(args[3], sender)) return ReturnType.FAILURE; - amount = Integer.parseInt(args[3]); - } - - if (args.length > 4) { - if (!CommandCommons.isInt(args[4], sender)) - return ReturnType.FAILURE; - successRate = Integer.parseInt(args[4]); + successRate = Integer.parseInt(args[3]); } String messageKey; switch (giveType.toLowerCase()) { case "whitescroll": - target.getPlayer().getInventory().addItem(instance.getSpecialItems().getWhiteScroll(amount)); + target.getPlayer().getInventory().addItem(plugin.getSpecialItems().getWhiteScroll(amount)); messageKey = "whitescroll"; break; case "blackscroll": messageKey = "blackscroll"; - target.getPlayer().getInventory().addItem(instance.getSpecialItems().getBlackScroll(amount, successRate)); + target.getPlayer().getInventory().addItem(plugin.getSpecialItems().getBlackScroll(amount, successRate)); break; default: - instance.getLocale().getMessage("command.giveunknown") + plugin.getLocale().getMessage("command.giveunknown") .processPlaceholder("unknown", giveType) .sendPrefixedMessage(sender); return ReturnType.FAILURE; } - instance.getLocale().getMessage("command." + messageKey + ".received") + plugin.getLocale().getMessage("command." + messageKey + ".received") .sendPrefixedMessage(target.getPlayer()); - instance.getLocale().getMessage("command." + messageKey + ".gave") + plugin.getLocale().getMessage("command." + messageKey + ".gave") .processPlaceholder("player", target.getName()) .sendPrefixedMessage(sender); return ReturnType.SUCCESS; } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { - if (args.length == 2) { + protected List onTab(CommandSender sender, String... args) { + if (args.length == 1) { return Arrays.asList("whitescroll", "blackscroll"); - } else if (args.length == 3) { + } else if (args.length == 2) { return Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); - } else if (args.length == 4 || args.length == 5) { + } else if (args.length == 3 || args.length == 4) { List rates = new ArrayList<>(); - for (int i = 1; i <= (args.length == 4 ? 10 : 100); i ++) + for (int i = 1; i <= (args.length == 3 ? 10 : 100); i ++) rates.add(String.valueOf(i)); return rates; } @@ -97,7 +99,7 @@ public class CommandGiveScroll extends AbstractCommand { @Override public String getSyntax() { - return "/ee givescroll [amount] [success-rate]"; + return "givescroll [amount] [success-rate]"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandList.java b/src/main/java/com/songoda/epicenchants/commands/CommandList.java similarity index 52% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandList.java rename to src/main/java/com/songoda/epicenchants/commands/CommandList.java index 831e4c2..60b9777 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandList.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandList.java @@ -1,44 +1,38 @@ package com.songoda.epicenchants.command.commands; -import com.songoda.epicenchants.CommandCommons; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; -import com.songoda.epicenchants.enums.EnchantResult; -import com.songoda.epicenchants.objects.Enchant; -import com.songoda.epicenchants.utils.Tuple; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; import java.util.Comparator; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; -import static com.songoda.epicenchants.enums.EnchantResult.BROKEN_FAILURE; -import static com.songoda.epicenchants.utils.single.GeneralUtils.getMessageFromResult; - public class CommandList extends AbstractCommand { + + private final EpicEnchants plugin; - public CommandList(AbstractCommand parent) { - super(parent, true, "list"); + public CommandList(EpicEnchants plugin) { + super(true, "list"); + this.plugin = plugin; } @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { + protected ReturnType runCommand(CommandSender sender, String... args) { if (args.length > 1 && args[1].equalsIgnoreCase("chat")) { - instance.getLocale().newMessage(instance.getEnchantManager().getValues().stream() + plugin.getLocale().newMessage(plugin.getEnchantManager().getValues().stream() .sorted(Comparator.comparing(enchant -> enchant.getGroup().getOrder())) .map(enchant -> enchant.getColoredIdentifier(true)).collect(Collectors.joining("&7, "))) .sendPrefixedMessage(sender); return ReturnType.SUCCESS; } - instance.getInfoManager().getMainInfoMenu().open((Player)sender); + plugin.getInfoManager().getMainInfoMenu().open((Player)sender); return ReturnType.SUCCESS; } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { + protected List onTab(CommandSender sender, String... args) { return null; } @@ -49,7 +43,7 @@ public class CommandList extends AbstractCommand { @Override public String getSyntax() { - return "/ee list [chat]"; + return "list [chat]"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandReload.java b/src/main/java/com/songoda/epicenchants/commands/CommandReload.java similarity index 53% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandReload.java rename to src/main/java/com/songoda/epicenchants/commands/CommandReload.java index 1c76533..88e4aeb 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandReload.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandReload.java @@ -1,26 +1,29 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; import org.bukkit.command.CommandSender; import java.util.List; public class CommandReload extends AbstractCommand { - public CommandReload(AbstractCommand parent) { - super(parent, false, "reload"); + private final EpicEnchants plugin; + + public CommandReload(EpicEnchants plugin) { + super(false, "reload"); + this.plugin = plugin; } @Override - protected AbstractCommand.ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { - instance.reloadConfig(); - instance.getLocale().getMessage("command.reload").sendPrefixedMessage(sender); + protected ReturnType runCommand(CommandSender sender, String... args) { + plugin.reloadConfig(); + plugin.getLocale().getMessage("command.reload").sendPrefixedMessage(sender); return ReturnType.SUCCESS; } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { + protected List onTab(CommandSender sender, String... args) { return null; } @@ -31,7 +34,7 @@ public class CommandReload extends AbstractCommand { @Override public String getSyntax() { - return "/ee reload"; + return "reload"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandSettings.java b/src/main/java/com/songoda/epicenchants/commands/CommandSettings.java similarity index 59% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandSettings.java rename to src/main/java/com/songoda/epicenchants/commands/CommandSettings.java index de0cd3c..3c3b1c9 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandSettings.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandSettings.java @@ -1,27 +1,30 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.core.configuration.editor.PluginConfigGui; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import java.util.List; public class CommandSettings extends AbstractCommand { + + private final EpicEnchants plugin; - public CommandSettings(AbstractCommand parent) { - super(parent, true, "Settings"); + public CommandSettings(EpicEnchants plugin) { + super(true, "Settings"); + this.plugin = plugin; } @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { - instance.getGuiManager().showGUI((Player) sender, new PluginConfigGui(instance)); + protected ReturnType runCommand(CommandSender sender, String... args) { + plugin.getGuiManager().showGUI((Player) sender, new PluginConfigGui(plugin)); return ReturnType.SUCCESS; } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { + protected List onTab(CommandSender sender, String... args) { return null; } @@ -32,7 +35,7 @@ public class CommandSettings extends AbstractCommand { @Override public String getSyntax() { - return "/ee settings"; + return "settings"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/command/commands/CommandTinkerer.java b/src/main/java/com/songoda/epicenchants/commands/CommandTinkerer.java similarity index 56% rename from src/main/java/com/songoda/epicenchants/command/commands/CommandTinkerer.java rename to src/main/java/com/songoda/epicenchants/commands/CommandTinkerer.java index 9e13f38..c025e1d 100644 --- a/src/main/java/com/songoda/epicenchants/command/commands/CommandTinkerer.java +++ b/src/main/java/com/songoda/epicenchants/commands/CommandTinkerer.java @@ -1,8 +1,7 @@ package com.songoda.epicenchants.command.commands; +import com.songoda.core.commands.AbstractCommand; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.command.AbstractCommand; -import com.songoda.epicenchants.menus.EnchanterMenu; import com.songoda.epicenchants.menus.TinkererMenu; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -10,20 +9,23 @@ import org.bukkit.entity.Player; import java.util.List; public class CommandTinkerer extends AbstractCommand { + + private final EpicEnchants plugin; - public CommandTinkerer(AbstractCommand parent) { - super(parent, true, "tinkerer"); + public CommandTinkerer(EpicEnchants plugin) { + super(true, "tinkerer"); + this.plugin = plugin; } @Override - protected ReturnType runCommand(EpicEnchants instance, CommandSender sender, String... args) { + protected ReturnType runCommand(CommandSender sender, String... args) { Player player = (Player)sender; - new TinkererMenu(instance, instance.getFileManager().getConfiguration("menus/tinkerer-menu")).open(player); + new TinkererMenu(plugin, plugin.getFileManager().getConfiguration("menus/tinkerer-menu")).open(player); return ReturnType.SUCCESS; } @Override - protected List onTab(EpicEnchants instance, CommandSender sender, String... args) { + protected List onTab(CommandSender sender, String... args) { return null; } @@ -34,7 +36,7 @@ public class CommandTinkerer extends AbstractCommand { @Override public String getSyntax() { - return "/ee tinkerer"; + return "tinkerer"; } @Override diff --git a/src/main/java/com/songoda/epicenchants/effect/effects/DropHead.java b/src/main/java/com/songoda/epicenchants/effect/effects/DropHead.java index cc11b1b..33a5a58 100644 --- a/src/main/java/com/songoda/epicenchants/effect/effects/DropHead.java +++ b/src/main/java/com/songoda/epicenchants/effect/effects/DropHead.java @@ -31,9 +31,6 @@ public class DropHead extends EffectExecutor { case CHICKEN: skin = "MHF_Chicken"; break; - case PIG_ZOMBIE: - skin = "MHF_PigZombie"; - break; case PIG: skin = "MHF_Pig"; break; diff --git a/src/main/java/com/songoda/epicenchants/menus/InfoMenu.java b/src/main/java/com/songoda/epicenchants/menus/InfoMenu.java index 169b6f9..9f45168 100644 --- a/src/main/java/com/songoda/epicenchants/menus/InfoMenu.java +++ b/src/main/java/com/songoda/epicenchants/menus/InfoMenu.java @@ -1,5 +1,6 @@ package com.songoda.epicenchants.menus; +import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.objects.Enchant; import com.songoda.epicenchants.objects.Group; @@ -48,7 +49,7 @@ public class InfoMenu extends FastInv { slots.stream().filter(slot -> enchantIterator.hasNext()).forEach(slot -> { Enchant enchant = enchantIterator.next(); - String whitelist = instance.getItemGroup().getGroups(enchant.getItemWhitelist()) + String whitelist = instance.getItemGroup().getGroups(enchant.getItemWhitelist().stream().map(CompatibleMaterial::getMaterial).collect(Collectors.toSet())) .stream() .map(s -> StringUtils.capitalize(s.toLowerCase())) .collect(Collectors.joining(", ")); diff --git a/src/main/java/com/songoda/epicenchants/objects/BookItem.java b/src/main/java/com/songoda/epicenchants/objects/BookItem.java index d3583c1..2e32ba6 100644 --- a/src/main/java/com/songoda/epicenchants/objects/BookItem.java +++ b/src/main/java/com/songoda/epicenchants/objects/BookItem.java @@ -1,5 +1,6 @@ package com.songoda.epicenchants.objects; +import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.utils.itemnbtapi.NBTItem; import com.songoda.epicenchants.utils.objects.ItemBuilder; @@ -64,7 +65,8 @@ public class BookItem { } string = string - .replace("{item_group}", "" + instance.getItemGroup().getGroup(enchant.getItemWhitelist()).map(ItemGroup.Group::getName).orElse("N/A")) + .replace("{item_group}", "" + instance.getItemGroup().getGroup(enchant.getItemWhitelist() + .stream().map(CompatibleMaterial::getMaterial).collect(Collectors.toSet())).map(ItemGroup.Group::getName).orElse("N/A")) .replace("{success_rate}", "" + finalSuccessRate) .replace("{destroy_rate}", "" + finalDestroyRate); diff --git a/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java b/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java index 89706fa..2350bb0 100644 --- a/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java +++ b/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java @@ -11,7 +11,6 @@ import com.songoda.epicenchants.utils.itemnbtapi.NBTItem; import com.songoda.epicenchants.utils.objects.ItemBuilder; import com.songoda.epicenchants.utils.settings.Settings; import com.songoda.epicenchants.utils.single.GeneralUtils; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompound.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompound.java index f0e3214..03dd8c3 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompound.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompound.java @@ -1,449 +1,769 @@ package com.songoda.epicenchants.utils.itemnbtapi; +import java.io.OutputStream; +import java.io.Serializable; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.bukkit.inventory.ItemStack; + import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; -import java.io.Serializable; -import java.util.Set; - /** * Base class representing NMS Compounds. For a standalone implementation check * {@link NBTContainer} - * + * * @author tr7zw + * */ public class NBTCompound { - private String compundName; - private NBTCompound parent; + private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); + private final Lock readLock = readWriteLock.readLock(); + private final Lock writeLock = readWriteLock.writeLock(); - protected NBTCompound(NBTCompound owner, String name) { - this.compundName = name; - this.parent = owner; - } + private String compundName; + private NBTCompound parent; - protected void saveCompound() { - if (parent != null) - parent.saveCompound(); - } + protected NBTCompound(NBTCompound owner, String name) { + this.compundName = name; + this.parent = owner; + } - /** - * @return The Compound name - */ - public String getName() { - return compundName; - } + protected Lock getReadLock() { + return readLock; + } - /** - * @return The NMS Compound behind this Object - */ - public Object getCompound() { - return parent.getCompound(); - } + protected Lock getWriteLock() { + return writeLock; + } - protected void setCompound(Object compound) { - parent.setCompound(compound); - } + protected void saveCompound() { + if (parent != null) + parent.saveCompound(); + } - /** - * @return The parent Compound - */ - public NBTCompound getParent() { - return parent; - } + /** + * @return The Compound name + */ + public String getName() { + return compundName; + } - /** - * Merges all data from comp into this compound. This is done in one action, so - * it also works with Tiles/Entities - * - * @param comp - */ - public void mergeCompound(NBTCompound comp) { - NBTReflectionUtil.mergeOtherNBTCompound(this, comp); - saveCompound(); - } + /** + * @return The NMS Compound behind this Object + */ + public Object getCompound() { + return parent.getCompound(); + } - /** - * Setter - * - * @param key - * @param value - */ - public void setString(String key, String value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_STRING, key, value); - saveCompound(); - } + protected void setCompound(Object compound) { + parent.setCompound(compound); + } - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public String getString(String key) { - return (String) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_STRING, key); - } + /** + * @return The parent Compound + */ + public NBTCompound getParent() { + return parent; + } - protected String getContent(String key) { - return NBTReflectionUtil.getContent(this, key); - } - - /** - * Setter - * - * @param key - * @param value - */ - public void setInteger(String key, Integer value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INT, key, value); - saveCompound(); - } - - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public Integer getInteger(String key) { - return (Integer) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_INT, key); - } - - /** - * Setter - * - * @param key - * @param value - */ - public void setDouble(String key, Double value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_DOUBLE, key, value); - saveCompound(); - } - - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public Double getDouble(String key) { - return (Double) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_DOUBLE, key); - } - - /** - * Setter - * - * @param key - * @param value - */ - public void setByte(String key, Byte value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTE, key, value); - saveCompound(); - } - - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public Byte getByte(String key) { - return (Byte) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BYTE, key); - } - - /** - * Setter - * - * @param key - * @param value - */ - public void setShort(String key, Short value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_SHORT, key, value); - saveCompound(); - } - - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public Short getShort(String key) { - return (Short) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_SHORT, key); - } - - /** - * Setter - * - * @param key - * @param value - */ - public void setLong(String key, Long value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_LONG, key, value); - saveCompound(); - } - - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public Long getLong(String key) { - return (Long) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_LONG, key); - } - - /** - * Setter - * - * @param key - * @param value - */ - public void setFloat(String key, Float value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_FLOAT, key, value); - saveCompound(); - } - - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public Float getFloat(String key) { - return (Float) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_FLOAT, key); - } - - /** - * Setter - * - * @param key - * @param value - */ - public void setByteArray(String key, byte[] value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTEARRAY, key, value); - saveCompound(); - } - - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public byte[] getByteArray(String key) { - return (byte[]) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BYTEARRAY, key); - } - - /** - * Setter - * - * @param key - * @param value - */ - public void setIntArray(String key, int[] value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INTARRAY, key, value); - saveCompound(); - } - - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public int[] getIntArray(String key) { - return (int[]) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_INTARRAY, key); - } - - /** - * Setter - * - * @param key - * @param value - */ - public void setBoolean(String key, Boolean value) { - NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BOOLEAN, key, value); - saveCompound(); - } - - protected void set(String key, Object val) { - NBTReflectionUtil.set(this, key, val); - saveCompound(); - } - - /** - * Getter - * - * @param key - * @return The stored value or NMS fallback - */ - public Boolean getBoolean(String key) { - return (Boolean) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BOOLEAN, key); - } - - /** - * Uses Gson to store an {@link Serializable} Object - * - * @param key - * @param value - */ - public void setObject(String key, Object value) { - NBTReflectionUtil.setObject(this, key, value); - saveCompound(); - } - - /** - * Uses Gson to retrieve a stored Object - * - * @param key - * @param type Class of the Object - * @return The created Object or null if empty - */ - public T getObject(String key, Class type) { - return NBTReflectionUtil.getObject(this, key, type); - } - - /** - * @param key - * @return True if the key is set - */ - public Boolean hasKey(String key) { - Boolean b = (Boolean) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_HAS_KEY, key); - if (b == null) - return false; - return b; - } - - /** - * @param key Deletes the given Key - */ - public void removeKey(String key) { - NBTReflectionUtil.remove(this, key); - saveCompound(); - } - - /** - * @return Set of all stored Keys - */ - public Set getKeys() { - return NBTReflectionUtil.getKeys(this); - } - - /** - * Creates a subCompound - * - * @param name Key to use - * @return The subCompound Object - */ - public NBTCompound addCompound(String name) { - if (getType(name) == NBTType.NBTTagCompound) - return getCompound(name); - NBTReflectionUtil.addNBTTagCompound(this, name); - NBTCompound comp = getCompound(name); - if (comp == null) - throw new NbtApiException("Error while adding Compound, got null!"); - saveCompound(); - return comp; - } - - /** - * @param name - * @return The Compound instance or null - */ - public NBTCompound getCompound(String name) { - if (getType(name) != NBTType.NBTTagCompound) - return null; - NBTCompound next = new NBTCompound(this, name); - if (NBTReflectionUtil.valideCompound(next)) - return next; - return null; - } - - /** - * @param name - * @return The retrieved String List - */ - public NBTList getStringList(String name) { - NBTList list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagString, String.class); - saveCompound(); - return list; - } - - /** - * @param name - * @return The retrieved Integer List - */ - public NBTList getIntegerList(String name) { - NBTList list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagInt, Integer.class); - saveCompound(); - return list; - } - - /** - * @param name - * @return The retrieved Compound List - */ - public NBTCompoundList getCompoundList(String name) { - NBTCompoundList list = (NBTCompoundList) NBTReflectionUtil.getList(this, name, NBTType.NBTTagCompound, NBTListCompound.class); - saveCompound(); - return list; - } - - /** - * @param name - * @return The type of the given stored key or null - */ - public NBTType getType(String name) { - if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) - return null; - Object o = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_TYPE, name); - if (o == null) - return null; - return NBTType.valueOf((byte) o); - } - - @Override - public String toString() { - /*StringBuilder result = new StringBuilder(); - for (String key : getKeys()) { - result.append(toString(key)); + /** + * Merges all data from comp into this compound. This is done in one action, so + * it also works with Tiles/Entities + * + * @param comp + */ + public void mergeCompound(NBTCompound comp) { + try { + writeLock.lock(); + NBTReflectionUtil.mergeOtherNBTCompound(this, comp); + saveCompound(); + } finally { + writeLock.unlock(); } - return result.toString();*/ - return asNBTString(); - } + } - /** - * @param key - * @return A string representation of the given key - * @deprecated Just use toString() - */ - @Deprecated - public String toString(String key) { - /*StringBuilder result = new StringBuilder(); - NBTCompound compound = this; - while (compound.getParent() != null) { - result.append(" "); - compound = compound.getParent(); + /** + * Setter + * + * @param key + * @param value + */ + public void setString(String key, String value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_STRING, key, value); + saveCompound(); + } finally { + writeLock.unlock(); } - if (this.getType(key) == NBTType.NBTTagCompound) { - return this.getCompound(key).toString(); - } else { - return result + "-" + key + ": " + getContent(key) + System.lineSeparator(); - }*/ - return asNBTString(); - } + } - /** - * @return A json valid nbt string for this Compound - * @deprecated Just use toString() - */ - @Deprecated - public String asNBTString() { - Object comp = NBTReflectionUtil.gettoCompount(getCompound(), this); - if (comp == null) - return "{}"; - return comp.toString(); - } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public String getString(String key) { + try { + readLock.lock(); + return (String) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_STRING, key); + } finally { + readLock.unlock(); + } + } + + protected String getContent(String key) { + return NBTReflectionUtil.getContent(this, key); + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setInteger(String key, Integer value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INT, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public Integer getInteger(String key) { + try { + readLock.lock(); + return (Integer) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_INT, key); + } finally { + readLock.unlock(); + } + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setDouble(String key, Double value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_DOUBLE, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public Double getDouble(String key) { + try { + readLock.lock(); + return (Double) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_DOUBLE, key); + } finally { + readLock.unlock(); + } + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setByte(String key, Byte value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTE, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public Byte getByte(String key) { + try { + readLock.lock(); + return (Byte) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BYTE, key); + } finally { + readLock.unlock(); + } + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setShort(String key, Short value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_SHORT, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public Short getShort(String key) { + try { + readLock.lock(); + return (Short) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_SHORT, key); + } finally { + readLock.unlock(); + } + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setLong(String key, Long value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_LONG, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public Long getLong(String key) { + try { + readLock.lock(); + return (Long) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_LONG, key); + } finally { + readLock.unlock(); + } + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setFloat(String key, Float value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_FLOAT, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public Float getFloat(String key) { + try { + readLock.lock(); + return (Float) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_FLOAT, key); + } finally { + readLock.unlock(); + } + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setByteArray(String key, byte[] value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTEARRAY, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public byte[] getByteArray(String key) { + try { + readLock.lock(); + return (byte[]) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BYTEARRAY, key); + } finally { + readLock.unlock(); + } + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setIntArray(String key, int[] value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INTARRAY, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public int[] getIntArray(String key) { + try { + readLock.lock(); + return (int[]) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_INTARRAY, key); + } finally { + readLock.unlock(); + } + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setBoolean(String key, Boolean value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BOOLEAN, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + protected void set(String key, Object val) { + NBTReflectionUtil.set(this, key, val); + saveCompound(); + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public Boolean getBoolean(String key) { + try { + readLock.lock(); + return (Boolean) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BOOLEAN, key); + } finally { + readLock.unlock(); + } + } + + /** + * Uses Gson to store an {@link Serializable} Object + * + * @param key + * @param value + */ + public void setObject(String key, Object value) { + try { + writeLock.lock(); + NBTReflectionUtil.setObject(this, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Uses Gson to retrieve a stored Object + * + * @param key + * @param type Class of the Object + * @return The created Object or null if empty + */ + public T getObject(String key, Class type) { + try { + readLock.lock(); + return NBTReflectionUtil.getObject(this, key, type); + } finally { + readLock.unlock(); + } + } + + /** + * Save an ItemStack as a compound under a given key + * + * @param key + * @param item + */ + public void setItemStack(String key, ItemStack item) { + try { + writeLock.lock(); + removeKey(key); + addCompound(key).mergeCompound(NBTItem.convertItemtoNBT(item)); + } finally { + writeLock.unlock(); + } + } + + /** + * Get an ItemStack that was saved at the given key + * + * @param key + * @return + */ + public ItemStack getItemStack(String key) { + try { + readLock.lock(); + NBTCompound comp = getCompound(key); + return NBTItem.convertNBTtoItem(comp); + } finally { + readLock.unlock(); + } + } + + /** + * Setter + * + * @param key + * @param value + */ + public void setUUID(String key, UUID value) { + try { + writeLock.lock(); + NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_UUID, key, value); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ + public UUID getUUID(String key) { + try { + readLock.lock(); + return (UUID) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_UUID, key); + } finally { + readLock.unlock(); + } + } + + /** + * @param key + * @return True if the key is set + */ + public Boolean hasKey(String key) { + try { + readLock.lock(); + Boolean b = (Boolean) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_HAS_KEY, key); + if (b == null) + return false; + return b; + } finally { + readLock.unlock(); + } + } + + /** + * @param key Deletes the given Key + */ + public void removeKey(String key) { + try { + writeLock.lock(); + NBTReflectionUtil.remove(this, key); + saveCompound(); + } finally { + writeLock.unlock(); + } + } + + /** + * @return Set of all stored Keys + */ + public Set getKeys() { + try { + readLock.lock(); + return NBTReflectionUtil.getKeys(this); + } finally { + readLock.unlock(); + } + } + + /** + * Creates a subCompound + * + * @param name Key to use + * @return The subCompound Object + */ + public NBTCompound addCompound(String name) { + try { + writeLock.lock(); + if (getType(name) == NBTType.NBTTagCompound) + return getCompound(name); + NBTReflectionUtil.addNBTTagCompound(this, name); + NBTCompound comp = getCompound(name); + if (comp == null) + throw new NbtApiException("Error while adding Compound, got null!"); + saveCompound(); + return comp; + } finally { + writeLock.unlock(); + } + } + + /** + * @param name + * @return The Compound instance or null + */ + public NBTCompound getCompound(String name) { + try { + readLock.lock(); + if (getType(name) != NBTType.NBTTagCompound) + return null; + NBTCompound next = new NBTCompound(this, name); + if (NBTReflectionUtil.valideCompound(next)) + return next; + return null; + } finally { + readLock.unlock(); + } + } + + /** + * @param name + * @return The retrieved String List + */ + public NBTList getStringList(String name) { + try { + writeLock.lock(); + NBTList list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagString, String.class); + saveCompound(); + return list; + } finally { + writeLock.unlock(); + } + } + + /** + * @param name + * @return The retrieved Integer List + */ + public NBTList getIntegerList(String name) { + try { + writeLock.lock(); + NBTList list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagInt, Integer.class); + saveCompound(); + return list; + } finally { + writeLock.unlock(); + } + } + + /** + * @param name + * @return The retrieved Float List + */ + public NBTList getFloatList(String name) { + try { + writeLock.lock(); + NBTList list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagFloat, Float.class); + saveCompound(); + return list; + } finally { + writeLock.unlock(); + } + } + + /** + * @param name + * @return The retrieved Double List + */ + public NBTList getDoubleList(String name) { + try { + writeLock.lock(); + NBTList list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagDouble, Double.class); + saveCompound(); + return list; + } finally { + writeLock.unlock(); + } + } + + /** + * @param name + * @return The retrieved Long List + */ + public NBTList getLongList(String name) { + try { + writeLock.lock(); + NBTList list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagLong, Long.class); + saveCompound(); + return list; + } finally { + writeLock.unlock(); + } + } + + /** + * @param name + * @return The retrieved Compound List + */ + public NBTCompoundList getCompoundList(String name) { + try { + writeLock.lock(); + NBTCompoundList list = (NBTCompoundList) NBTReflectionUtil.getList(this, name, NBTType.NBTTagCompound, + NBTListCompound.class); + saveCompound(); + return list; + } finally { + writeLock.unlock(); + } + } + + /** + * @param name + * @return The type of the given stored key or null + */ + public NBTType getType(String name) { + try { + readLock.lock(); + if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) { + Object nbtbase = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET, name); + if(nbtbase == null) + return null; + return NBTType.valueOf((byte)ReflectionMethod.COMPOUND_OWN_TYPE.run(nbtbase)); + } + Object o = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_TYPE, name); + if (o == null) + return null; + return NBTType.valueOf((byte) o); + } finally { + readLock.unlock(); + } + } + + public void writeCompound(OutputStream stream) { + try { + writeLock.lock(); + NBTReflectionUtil.writeApiNBT(this, stream); + } finally { + writeLock.unlock(); + } + } + + @Override + public String toString() { + /* + * StringBuilder result = new StringBuilder(); for (String key : getKeys()) { + * result.append(toString(key)); } return result.toString(); + */ + return asNBTString(); + } + + /** + * @deprecated Just use toString() + * @param key + * @return A string representation of the given key + */ + @Deprecated + public String toString(String key) { + /* + * StringBuilder result = new StringBuilder(); NBTCompound compound = this; + * while (compound.getParent() != null) { result.append(" "); compound = + * compound.getParent(); } if (this.getType(key) == NBTType.NBTTagCompound) { + * return this.getCompound(key).toString(); } else { return result + "-" + key + + * ": " + getContent(key) + System.lineSeparator(); } + */ + return asNBTString(); + } + + /** + * @deprecated Just use toString() + * @return A {@link String} representation of the NBT in Mojang JSON. This is different from normal JSON! + */ + @Deprecated + public String asNBTString() { + try { + readLock.lock(); + Object comp = NBTReflectionUtil.gettoCompount(getCompound(), this); + if (comp == null) + return "{}"; + return comp.toString(); + } finally { + readLock.unlock(); + } + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + + /** + * Uses the nbt-string to match this compound with another object. This allows + * two "technically" different Compounds to match, if they have the same content + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + return toString().equals(obj.toString()); + } } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTContainer.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTContainer.java index f5b489a..91c2446 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTContainer.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTContainer.java @@ -1,5 +1,8 @@ package com.songoda.epicenchants.utils.itemnbtapi; +import java.io.InputStream; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper; import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ObjectCreator; import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; @@ -29,9 +32,25 @@ public class NBTContainer extends NBTCompound { */ public NBTContainer(Object nbt) { super(null, null); + if (nbt == null) { + throw new NullPointerException("The NBT-Object can't be null!"); + } + if (!ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().isAssignableFrom(nbt.getClass())) { + throw new NbtApiException("The object '" + nbt.getClass() + "' is not a valid NBT-Object!"); + } this.nbt = nbt; } + /** + * Reads in a NBT InputStream + * + * @param inputsteam + */ + public NBTContainer(InputStream inputsteam) { + super(null, null); + this.nbt = NBTReflectionUtil.readNBT(inputsteam); + } + /** * Parses in a NBT String to a standalone {@link NBTCompound}. Can throw a * {@link NbtApiException} in case something goes wrong. @@ -40,6 +59,9 @@ public class NBTContainer extends NBTCompound { */ public NBTContainer(String nbtString) { super(null, null); + if (nbtString == null) { + throw new NullPointerException("The String can't be null!"); + } try { nbt = ReflectionMethod.PARSE_NBT.run(null, nbtString); } catch (Exception ex) { diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTDoubleList.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTDoubleList.java new file mode 100644 index 0000000..4a7d1af --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTDoubleList.java @@ -0,0 +1,45 @@ +package com.songoda.epicenchants.utils.itemnbtapi; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +/** + * Double implementation for NBTLists + * + * @author tr7zw + * + */ +public class NBTDoubleList extends NBTList { + + protected NBTDoubleList(NBTCompound owner, String name, NBTType type, Object list) { + super(owner, name, type, list); + } + + @Override + protected Object asTag(Double object) { + try { + Constructor con = ClassWrapper.NMS_NBTTAGDOUBLE.getClazz().getDeclaredConstructor(double.class); + con.setAccessible(true); + return con.newInstance(object); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e); + } + } + + @Override + public Double get(int index) { + try { + Object obj = ReflectionMethod.LIST_GET.run(listObject, index); + return Double.valueOf(obj.toString()); + } catch (NumberFormatException nf) { + return 0d; + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTEntity.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTEntity.java index 83885d0..ecd66e8 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTEntity.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTEntity.java @@ -2,6 +2,10 @@ package com.songoda.epicenchants.utils.itemnbtapi; import org.bukkit.entity.Entity; +import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; +import com.songoda.epicenchants.utils.itemnbtapi.utils.annotations.AvaliableSince; +import com.songoda.epicenchants.utils.itemnbtapi.utils.annotations.CheckUtil; + /** * NBT class to access vanilla tags from Entities. Entities don't support custom * tags. Use the NBTInjector for custom tags. Changes will be instantly applied @@ -19,6 +23,9 @@ public class NBTEntity extends NBTCompound { */ public NBTEntity(Entity entity) { super(null, null); + if (entity == null) { + throw new NullPointerException("Entity can't be null!"); + } ent = entity; } @@ -32,4 +39,23 @@ public class NBTEntity extends NBTCompound { NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent)); } + /** + * Gets the NBTCompound used by spigots PersistentDataAPI. This method is only + * available for 1.14+! + * + * @return NBTCompound containing the data of the PersistentDataAPI + */ + @AvaliableSince(version = MinecraftVersion.MC1_14_R1) + public NBTCompound getPersistentDataContainer() { + if (hasKey("BukkitValues")) { + return getCompound("BukkitValues"); + } else { + NBTContainer container = new NBTContainer(); + container.addCompound("BukkitValues").setString("__nbtapi", + "Marker to make the PersistentDataContainer have content"); + mergeCompound(container); + return getCompound("BukkitValues"); + } + } + } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFile.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFile.java index 69852ad..7907ac8 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFile.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFile.java @@ -27,10 +27,13 @@ public class NBTFile extends NBTCompound { */ public NBTFile(File file) throws IOException { super(null, null); + if (file == null) { + throw new NullPointerException("File can't be null!"); + } this.file = file; if (file.exists()) { FileInputStream inputsteam = new FileInputStream(file); - nbt = NBTReflectionUtil.readNBTFile(inputsteam); + nbt = NBTReflectionUtil.readNBT(inputsteam); } else { nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); save(); @@ -43,13 +46,18 @@ public class NBTFile extends NBTCompound { * @throws IOException */ public void save() throws IOException { - if (!file.exists()) { - file.getParentFile().mkdirs(); - if (!file.createNewFile()) - throw new IOException("Unable to create file at " + file.getAbsolutePath()); + try { + getWriteLock().lock(); + if (!file.exists()) { + file.getParentFile().mkdirs(); + if (!file.createNewFile()) + throw new IOException("Unable to create file at " + file.getAbsolutePath()); + } + FileOutputStream outStream = new FileOutputStream(file); + NBTReflectionUtil.writeNBT(nbt, outStream); + } finally { + getWriteLock().unlock(); } - FileOutputStream outStream = new FileOutputStream(file); - NBTReflectionUtil.saveNBTFile(nbt, outStream); } /** diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFloatList.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFloatList.java new file mode 100644 index 0000000..3d98d40 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFloatList.java @@ -0,0 +1,45 @@ +package com.songoda.epicenchants.utils.itemnbtapi; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +/** + * Float implementation for NBTLists + * + * @author tr7zw + * + */ +public class NBTFloatList extends NBTList { + + protected NBTFloatList(NBTCompound owner, String name, NBTType type, Object list) { + super(owner, name, type, list); + } + + @Override + protected Object asTag(Float object) { + try { + Constructor con = ClassWrapper.NMS_NBTTAGFLOAT.getClazz().getDeclaredConstructor(float.class); + con.setAccessible(true); + return con.newInstance(object); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e); + } + } + + @Override + public Float get(int index) { + try { + Object obj = ReflectionMethod.LIST_GET.run(listObject, index); + return Float.valueOf(obj.toString()); + } catch (NumberFormatException nf) { + return 0f; + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTGameProfile.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTGameProfile.java new file mode 100644 index 0000000..6a48db0 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTGameProfile.java @@ -0,0 +1,30 @@ +package com.songoda.epicenchants.utils.itemnbtapi; + +import com.mojang.authlib.GameProfile; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ObjectCreator; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +public class NBTGameProfile { + + /** + * Convert a GameProfile to NBT. The NBT then can be modified or be stored + * + * @param profile + * @return A NBTContainer with all the GameProfile data + */ + public static NBTCompound toNBT(GameProfile profile) { + return new NBTContainer(ReflectionMethod.GAMEPROFILE_SERIALIZE.run(null, ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(), profile)); + } + + /** + * Reconstructs a GameProfile from a NBTCompound + * + * @param compound Has to contain GameProfile data + * @return The reconstructed GameProfile + */ + public static GameProfile fromNBT(NBTCompound compound) { + return (GameProfile) ReflectionMethod.GAMEPROFILE_DESERIALIZE.run(null, NBTReflectionUtil.gettoCompount(compound.getCompound(), compound)); + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTItem.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTItem.java index 3167390..13c0b59 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTItem.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTItem.java @@ -1,6 +1,8 @@ package com.songoda.epicenchants.utils.itemnbtapi; +import org.bukkit.Material; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; @@ -14,6 +16,8 @@ import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMet public class NBTItem extends NBTCompound { private ItemStack bukkitItem; + private boolean directApply; + private ItemStack originalSrcStack = null; /** * Constructor for NBTItems. The ItemStack will be cloned! @@ -21,11 +25,27 @@ public class NBTItem extends NBTCompound { * @param item */ public NBTItem(ItemStack item) { + this(item, false); + } + + /** + * Constructor for NBTItems. The ItemStack will be cloned! If directApply is true, + * all changed will be mapped to the original item. Changes to the NBTItem will overwrite changes done + * to the original item in that case. + * + * @param item + * @param directApply + */ + public NBTItem(ItemStack item, boolean directApply) { super(null, null); - if (item == null) { - throw new NullPointerException("ItemStack can't be null!"); + if (item == null || item.getType() == Material.AIR) { + throw new NullPointerException("ItemStack can't be null/Air!"); } + this.directApply = directApply; bukkitItem = item.clone(); + if(directApply) { + this.originalSrcStack = item; + } } @Override @@ -40,6 +60,58 @@ public class NBTItem extends NBTCompound { bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack); } + /** + * Apply stored NBT tags to the provided ItemStack. + *

+ * Note: This will completely override current item's {@link ItemMeta}. + * If you still want to keep the original item's NBT tags, see + * {@link #mergeNBT(ItemStack)} and {@link #mergeCustomNBT(ItemStack)}. + * + * @param item ItemStack that should get the new NBT data + */ + public void applyNBT(ItemStack item) { + if (item == null || item.getType() == Material.AIR) { + throw new NullPointerException("ItemStack can't be null/Air!"); + } + NBTItem nbti = new NBTItem(new ItemStack(item.getType())); + nbti.mergeCompound(this); + item.setItemMeta(nbti.getItem().getItemMeta()); + } + + /** + * Merge all NBT tags to the provided ItemStack. + * + * @param item ItemStack that should get the new NBT data + */ + public void mergeNBT(ItemStack item) { + NBTItem nbti = new NBTItem(item); + nbti.mergeCompound(this); + item.setItemMeta(nbti.getItem().getItemMeta()); + } + + /** + * Merge only custom (non-vanilla) NBT tags to the provided ItemStack. + * + * @param item ItemStack that should get the new NBT data + */ + public void mergeCustomNBT(ItemStack item) { + if (item == null || item.getType() == Material.AIR) { + throw new NullPointerException("ItemStack can't be null/Air!"); + } + ItemMeta meta = item.getItemMeta(); + NBTReflectionUtil.getUnhandledNBTTags(meta).putAll(NBTReflectionUtil.getUnhandledNBTTags(bukkitItem.getItemMeta())); + item.setItemMeta(meta); + } + + /** + * Remove all custom (non-vanilla) NBT tags from the NBTItem. + */ + public void clearCustomNBT() { + ItemMeta meta = bukkitItem.getItemMeta(); + NBTReflectionUtil.getUnhandledNBTTags(meta).clear(); + bukkitItem.setItemMeta(meta); + } + /** * @return The modified ItemStack */ @@ -83,4 +155,11 @@ public class NBTItem extends NBTCompound { NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp)); } + @Override + protected void saveCompound() { + if(directApply) { + applyNBT(originalSrcStack); + } + } + } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java index 0eeafd9..a7f152f 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java @@ -31,14 +31,14 @@ public abstract class NBTList implements List { this.type = type; this.listObject = list; } - + /** * @return Name of this list-compound */ - public String getName(){ + public String getName() { return listName; } - + /** * @return The Compound's parent Object */ @@ -55,6 +55,7 @@ public abstract class NBTList implements List { @Override public boolean add(T element) { try { + parent.getWriteLock().lock(); if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) { ReflectionMethod.LIST_ADD.run(listObject, size(), asTag(element)); } else { @@ -64,12 +65,15 @@ public abstract class NBTList implements List { return true; } catch (Exception ex) { throw new NbtApiException(ex); + } finally { + parent.getWriteLock().unlock(); } } @Override public void add(int index, T element) { try { + parent.getWriteLock().lock(); if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) { ReflectionMethod.LIST_ADD.run(listObject, index, asTag(element)); } else { @@ -78,37 +82,48 @@ public abstract class NBTList implements List { save(); } catch (Exception ex) { throw new NbtApiException(ex); + } finally { + parent.getWriteLock().unlock(); } } @Override public T set(int index, T element) { try { + parent.getWriteLock().lock(); T prev = get(index); ReflectionMethod.LIST_SET.run(listObject, index, asTag(element)); save(); return prev; } catch (Exception ex) { throw new NbtApiException(ex); + } finally { + parent.getWriteLock().unlock(); } } public T remove(int i) { try { + parent.getWriteLock().lock(); T old = get(i); ReflectionMethod.LIST_REMOVE_KEY.run(listObject, i); save(); return old; } catch (Exception ex) { throw new NbtApiException(ex); + } finally { + parent.getWriteLock().unlock(); } } public int size() { try { + parent.getReadLock().lock(); return (int) ReflectionMethod.LIST_SIZE.run(listObject); } catch (Exception ex) { throw new NbtApiException(ex); + } finally { + parent.getReadLock().unlock(); } } @@ -133,96 +148,141 @@ public abstract class NBTList implements List { @Override public boolean contains(Object o) { - for (int i = 0; i < size(); i++) { - if (o.equals(get(i))) - return true; + try { + parent.getReadLock().lock(); + for (int i = 0; i < size(); i++) { + if (o.equals(get(i))) + return true; + } + return false; + } finally { + parent.getReadLock().unlock(); } - return false; } @Override public int indexOf(Object o) { - for (int i = 0; i < size(); i++) { - if (o.equals(get(i))) - return i; + try { + parent.getReadLock().lock(); + for (int i = 0; i < size(); i++) { + if (o.equals(get(i))) + return i; + } + return -1; + } finally { + parent.getReadLock().unlock(); } - return -1; } @Override public boolean addAll(Collection c) { - int size = size(); - for (T ele : c) { - add(ele); + try { + parent.getWriteLock().lock(); + int size = size(); + for (T ele : c) { + add(ele); + } + return size != size(); + } finally { + parent.getWriteLock().unlock(); } - return size != size(); } @Override public boolean addAll(int index, Collection c) { - int size = size(); - for (T ele : c) { - add(index++, ele); + try { + parent.getWriteLock().lock(); + int size = size(); + for (T ele : c) { + add(index++, ele); + } + return size != size(); + } finally { + parent.getWriteLock().unlock(); } - return size != size(); } @Override public boolean containsAll(Collection c) { - for (Object ele : c) { - if (!contains(ele)) - return false; + try { + parent.getReadLock().lock(); + for (Object ele : c) { + if (!contains(ele)) + return false; + } + return true; + } finally { + parent.getReadLock().unlock(); } - return true; } @Override public int lastIndexOf(Object o) { - int index = -1; - for (int i = 0; i < size(); i++) { - if (o.equals(get(i))) - index = i; + try { + parent.getReadLock().lock(); + int index = -1; + for (int i = 0; i < size(); i++) { + if (o.equals(get(i))) + index = i; + } + return index; + } finally { + parent.getReadLock().unlock(); } - return index; } @Override public boolean removeAll(Collection c) { - int size = size(); - for (Object obj : c) { - remove(obj); + try { + parent.getWriteLock().lock(); + int size = size(); + for (Object obj : c) { + remove(obj); + } + return size != size(); + } finally { + parent.getWriteLock().unlock(); } - return size != size(); } @Override public boolean retainAll(Collection c) { - int size = size(); - for (Object obj : c) { - for (int i = 0; i < size(); i++) { - if (!obj.equals(get(i))) { - remove(i--); + try { + parent.getWriteLock().lock(); + int size = size(); + for (Object obj : c) { + for (int i = 0; i < size(); i++) { + if (!obj.equals(get(i))) { + remove(i--); + } } } + return size != size(); + } finally { + parent.getWriteLock().unlock(); } - return size != size(); } @Override public boolean remove(Object o) { - int size = size(); - int id = -1; - while ((id = indexOf(o)) != -1) { - remove(id); + try { + parent.getWriteLock().lock(); + int size = size(); + int id = -1; + while ((id = indexOf(o)) != -1) { + remove(id); + } + return size != size(); + } finally { + parent.getWriteLock().unlock(); } - return size != size(); } @Override public Iterator iterator() { return new Iterator() { - private int index = 0; + private int index = -1; @Override public boolean hasNext() { @@ -235,6 +295,12 @@ public abstract class NBTList implements List { throw new NoSuchElementException(); return get(++index); } + + @Override + public void remove() { + NBTList.this.remove(index); + index--; + } }; } @@ -248,7 +314,7 @@ public abstract class NBTList implements List { final NBTList list = this; return new ListIterator() { - int index = startIndex; + int index = startIndex - 1; @Override public void add(T e) { @@ -262,7 +328,7 @@ public abstract class NBTList implements List { @Override public boolean hasPrevious() { - return index > 0; + return index >= 0 && index <= size(); } @Override @@ -279,7 +345,9 @@ public abstract class NBTList implements List { @Override public T previous() { - return get(--index); + if (!hasPrevious()) + throw new NoSuchElementException("Id: " + (index - 1)); + return get(index--); } @Override @@ -290,6 +358,7 @@ public abstract class NBTList implements List { @Override public void remove() { list.remove(index); + index--; } @Override @@ -301,35 +370,60 @@ public abstract class NBTList implements List { @Override public Object[] toArray() { - Object[] ar = new Object[size()]; - for (int i = 0; i < size(); i++) - ar[i] = get(i); - return ar; + try { + parent.getReadLock().lock(); + Object[] ar = new Object[size()]; + for (int i = 0; i < size(); i++) + ar[i] = get(i); + return ar; + } finally { + parent.getReadLock().unlock(); + } } @SuppressWarnings("unchecked") @Override public E[] toArray(E[] a) { - E[] ar = Arrays.copyOf(a, size()); - Arrays.fill(ar, null); - Class arrayclass = a.getClass().getComponentType(); - for (int i = 0; i < size(); i++) { - T obj = get(i); - if (arrayclass.isInstance(obj)) { - ar[i] = (E) get(i); - } else { - throw new ArrayStoreException("The array does not match the objects stored in the List."); + try { + parent.getReadLock().lock(); + E[] ar = Arrays.copyOf(a, size()); + Arrays.fill(ar, null); + Class arrayclass = a.getClass().getComponentType(); + for (int i = 0; i < size(); i++) { + T obj = get(i); + if (arrayclass.isInstance(obj)) { + ar[i] = (E) get(i); + } else { + throw new ArrayStoreException("The array does not match the objects stored in the List."); + } } + return ar; + } finally { + parent.getReadLock().unlock(); } - return ar; } @Override public List subList(int fromIndex, int toIndex) { - ArrayList list = new ArrayList<>(); - for (int i = fromIndex; i < toIndex; i++) - list.add(get(i)); - return list; + try { + parent.getReadLock().lock(); + ArrayList list = new ArrayList<>(); + for (int i = fromIndex; i < toIndex; i++) + list.add(get(i)); + return list; + } finally { + parent.getReadLock().unlock(); + } + } + + @Override + public String toString() { + try { + parent.getReadLock().lock(); + return listObject.toString(); + } finally { + parent.getReadLock().unlock(); + } } } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTLongList.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTLongList.java new file mode 100644 index 0000000..a5c2516 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTLongList.java @@ -0,0 +1,45 @@ +package com.songoda.epicenchants.utils.itemnbtapi; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +/** + * Long implementation for NBTLists + * + * @author tr7zw + * + */ +public class NBTLongList extends NBTList { + + protected NBTLongList(NBTCompound owner, String name, NBTType type, Object list) { + super(owner, name, type, list); + } + + @Override + protected Object asTag(Long object) { + try { + Constructor con = ClassWrapper.NMS_NBTTAGLONG.getClazz().getDeclaredConstructor(long.class); + con.setAccessible(true); + return con.newInstance(object); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e); + } + } + + @Override + public Long get(int index) { + try { + Object obj = ReflectionMethod.LIST_GET.run(listObject, index); + return Long.valueOf(obj.toString().replace("L", "")); + } catch (NumberFormatException nf) { + return 0l; + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTReflectionUtil.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTReflectionUtil.java index 17dcefb..22704f0 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTReflectionUtil.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTReflectionUtil.java @@ -1,14 +1,17 @@ package com.songoda.epicenchants.utils.itemnbtapi; -import java.io.FileInputStream; -import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; import java.io.Serializable; +import java.lang.reflect.Field; import java.util.ArrayDeque; import java.util.Deque; +import java.util.Map; import java.util.Set; import org.bukkit.block.BlockState; import org.bukkit.entity.Entity; +import org.bukkit.inventory.meta.ItemMeta; import com.songoda.epicenchants.utils.itemnbtapi.utils.GsonWrapper; import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; @@ -25,6 +28,17 @@ import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMet */ public class NBTReflectionUtil { + private static Field field_unhandledTags = null; + + static { + try { + field_unhandledTags = ClassWrapper.CRAFT_METAITEM.getClazz().getDeclaredField("unhandledTags"); + field_unhandledTags.setAccessible(true); + } catch (NoSuchFieldException e) { + + } + } + /** * Hidden constructor */ @@ -47,12 +61,12 @@ public class NBTReflectionUtil { } /** - * Reads in a FileInputStream as NMS Compound + * Reads in a InputStream as NMS Compound * * @param stream InputStream of any NBT file * @return NMS Compound */ - public static Object readNBTFile(FileInputStream stream) { + public static Object readNBT(InputStream stream) { try { return ReflectionMethod.NBTFILE_READ.run(null, stream); } catch (Exception e) { @@ -61,17 +75,38 @@ public class NBTReflectionUtil { } /** - * Writes a NMS Compound to a FileOutputStream + * Writes a NMS Compound to an OutputStream * * @param nbt NMS Compound * @param stream Stream to write to * @return ??? */ - public static Object saveNBTFile(Object nbt, FileOutputStream stream) { + public static Object writeNBT(Object nbt, OutputStream stream) { try { return ReflectionMethod.NBTFILE_WRITE.run(null, nbt, stream); } catch (Exception e) { - throw new NbtApiException("Exception while saving a NBT File!", e); + throw new NbtApiException("Exception while writing NBT!", e); + } + } + + /** + * Writes a Compound to an OutputStream + * + * @param comp Compound + * @param stream Stream to write to + */ + public static void writeApiNBT(NBTCompound comp, OutputStream stream) { + try { + Object nbttag = comp.getCompound(); + if (nbttag == null) { + nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(comp)) + return; + Object workingtag = gettoCompount(nbttag, comp); + ReflectionMethod.NBTFILE_WRITE.run(null, workingtag, stream); + } catch (Exception e) { + throw new NbtApiException("Exception while writing NBT!", e); } } @@ -99,10 +134,11 @@ public class NBTReflectionUtil { */ public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) { try { + Object nmsComp = gettoCompount(nbtcompound.getCompound(), nbtcompound); if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_11_R1.getVersionId()) { - return ObjectCreator.NMS_COMPOUNDFROMITEM.getInstance(nbtcompound.getCompound()); + return ObjectCreator.NMS_COMPOUNDFROMITEM.getInstance(nmsComp); } else { - return ReflectionMethod.NMSITEM_CREATESTACK.run(null, nbtcompound.getCompound()); + return ReflectionMethod.NMSITEM_CREATESTACK.run(null, nmsComp); } } catch (Exception e) { throw new NbtApiException("Exception while converting NBTCompound to NMS ItemStack!", e); @@ -124,6 +160,21 @@ public class NBTReflectionUtil { } } + /** + * Gets a live copy of non-vanilla NBT tags. + * + * @param meta ItemMeta from which tags should be retrieved + * @return Map containing unhandled (custom) NBT tags + */ + @SuppressWarnings("unchecked") + public static Map getUnhandledNBTTags(ItemMeta meta) { + try { + return (Map) field_unhandledTags.get(meta); + } catch (Exception e) { + throw new NbtApiException("Exception while getting unhandled tags from ItemMeta!", e); + } + } + /** * Gets the Vanilla NBT Compound from a given NMS Entity * @@ -166,10 +217,15 @@ public class NBTReflectionUtil { */ public static Object getTileEntityNBTTagCompound(BlockState tile) { try { - Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ()); Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld()); Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld); - Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos); + Object o = null; + if(MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) { + o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY_1_7_10.run(nmsworld, tile.getX(), tile.getY(), tile.getZ()); + }else { + Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ()); + o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos); + } Object tag = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance(); Object answer = ReflectionMethod.TILEENTITY_GET_NBT.run(o, tag); if (answer == null) @@ -188,11 +244,21 @@ public class NBTReflectionUtil { */ public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) { try { - Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ()); Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld()); Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld); - Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos); - ReflectionMethod.TILEENTITY_SET_NBT.run(o, comp); + Object o = null; + if(MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) { + o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY_1_7_10.run(nmsworld, tile.getX(), tile.getY(), tile.getZ()); + }else { + Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ()); + o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos); + } + if(MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_16_R1.getVersionId()) { + Object blockData = ReflectionMethod.TILEENTITY_GET_BLOCKDATA.run(o); + ReflectionMethod.TILEENTITY_SET_NBT.run(o, blockData, comp); + }else { + ReflectionMethod.TILEENTITY_SET_NBT_LEGACY1151.run(o, comp); + } } catch (Exception e) { throw new NbtApiException("Exception while setting NBTData for a TileEntity!", e); } @@ -232,8 +298,9 @@ public class NBTReflectionUtil { if (nbttag == null) { nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); } - if (!valideCompound(comp)) + if (!valideCompound(comp)) { return; + } Object workingtag = gettoCompount(nbttag, comp); try { ReflectionMethod.COMPOUND_SET.run(workingtag, name, @@ -277,10 +344,10 @@ public class NBTReflectionUtil { /** * Merges the second {@link NBTCompound} into the first one * - * @param comp Target for the merge - * @param nbtcompound Data to merge + * @param comp Target for the merge + * @param nbtcompoundSrc Data to merge */ - public static void mergeOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) { + public static void mergeOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompoundSrc) { Object rootnbttag = comp.getCompound(); if (rootnbttag == null) { rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); @@ -288,8 +355,15 @@ public class NBTReflectionUtil { if (!valideCompound(comp)) throw new NbtApiException("The Compound wasn't able to be linked back to the root!"); Object workingtag = gettoCompount(rootnbttag, comp); + Object rootnbttagSrc = nbtcompoundSrc.getCompound(); + if (rootnbttagSrc == null) { + rootnbttagSrc = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(nbtcompoundSrc)) + throw new NbtApiException("The Compound wasn't able to be linked back to the root!"); + Object workingtagSrc = gettoCompount(rootnbttagSrc, nbtcompoundSrc); try { - ReflectionMethod.COMPOUND_MERGE.run(workingtag, nbtcompound.getCompound()); + ReflectionMethod.COMPOUND_MERGE.run(workingtag, workingtagSrc); comp.setCompound(rootnbttag); } catch (Exception e) { throw new NbtApiException("Exception while merging two NBTCompounds!", e); @@ -372,6 +446,12 @@ public class NBTReflectionUtil { return (NBTList) new NBTCompoundList(comp, key, type, nbt); } else if (clazz == Integer.class) { return (NBTList) new NBTIntegerList(comp, key, type, nbt); + } else if (clazz == Float.class) { + return (NBTList) new NBTFloatList(comp, key, type, nbt); + } else if (clazz == Double.class) { + return (NBTList) new NBTDoubleList(comp, key, type, nbt); + } else if (clazz == Long.class) { + return (NBTList) new NBTLongList(comp, key, type, nbt); } else { return null; } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTTileEntity.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTTileEntity.java index f71f970..e630e78 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTTileEntity.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTTileEntity.java @@ -2,6 +2,10 @@ package com.songoda.epicenchants.utils.itemnbtapi; import org.bukkit.block.BlockState; +import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; +import com.songoda.epicenchants.utils.itemnbtapi.utils.annotations.AvaliableSince; +import com.songoda.epicenchants.utils.itemnbtapi.utils.annotations.CheckUtil; + /** * NBT class to access vanilla tags from TileEntities. TileEntities don't * support custom tags. Use the NBTInjector for custom tags. Changes will be @@ -20,6 +24,9 @@ public class NBTTileEntity extends NBTCompound { */ public NBTTileEntity(BlockState tile) { super(null, null); + if (tile == null || (MinecraftVersion.isAtLeastVersion(MinecraftVersion.MC1_8_R3) && !tile.isPlaced())) { + throw new NullPointerException("Tile can't be null/not placed!"); + } this.tile = tile; } @@ -33,4 +40,23 @@ public class NBTTileEntity extends NBTCompound { NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound); } + /** + * Gets the NBTCompound used by spigots PersistentDataAPI. This method is only + * available for 1.14+! + * + * @return NBTCompound containing the data of the PersistentDataAPI + */ + @AvaliableSince(version = MinecraftVersion.MC1_14_R1) + public NBTCompound getPersistentDataContainer() { + if (hasKey("PublicBukkitValues")) { + return getCompound("PublicBukkitValues"); + } else { + NBTContainer container = new NBTContainer(); + container.addCompound("PublicBukkitValues").setString("__nbtapi", + "Marker to make the PersistentDataContainer have content"); + mergeCompound(container); + return getCompound("PublicBukkitValues"); + } + } + } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ApiMetricsLite.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ApiMetricsLite.java index 37c7abe..76e6768 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ApiMetricsLite.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ApiMetricsLite.java @@ -1,377 +1,387 @@ -package com.songoda.epicenchants.utils.itemnbtapi.utils; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.RegisteredServiceProvider; -import org.bukkit.plugin.ServicePriority; - -import javax.net.ssl.HttpsURLConnection; -import java.io.*; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.Timer; -import java.util.TimerTask; -import java.util.UUID; -import java.util.logging.Level; -import java.util.zip.GZIPOutputStream; -import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.logger; - -/** - * bStats collects some data for plugin authors. - *

- * Check out https://bStats.org/ to learn more about bStats! - * - * This class is modified by tr7zw to work when the api is shaded into other peoples plugins. - */ -public class ApiMetricsLite { - - private static final String PLUGINNAME = "ItemNBTAPI"; // DO NOT CHANGE THE NAME! else it won't link the data on bStats - private static final String PLUGINVERSION = "2.2.0-SNAPSHOT"; // In case you fork the nbt-api for internal use in your network, plugins and so on, you *may* add that to the version here. (2.x.x-Timolia or something like that?) - // Not sure how good of an idea that is, so maybe just leave it as is ¯\_(ツ)_/¯ - - // The version of this bStats class - public static final int B_STATS_VERSION = 1; - - // The version of the NBT-Api bStats - public static final int NBT_BSTATS_VERSION = 1; - - // The url to which the data is sent - private static final String URL = "https://bStats.org/submitData/bukkit"; - - // Is bStats enabled on this server? - private boolean enabled; - - // Should failed requests be logged? - private static boolean logFailedRequests; - - // Should the sent data be logged? - private static boolean logSentData; - - // Should the response text be logged? - private static boolean logResponseStatusText; - - // The uuid of the server - private static String serverUUID; - - // The plugin - private Plugin plugin; - - /** - * Class constructor. - * - */ - public ApiMetricsLite() { - - // The register method just uses any enabled plugin it can find to register. This *shouldn't* cause any problems, since the plugin isn't used any other way. - // Register our service - for(Plugin plug : Bukkit.getPluginManager().getPlugins()) { - plugin = plug; - if(plugin != null) - break; - } - if(plugin == null) { - return;// Didn't find any plugin that could work - } - - // Get the config file - File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); - File configFile = new File(bStatsFolder, "config.yml"); - YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); - - // Check if the config file exists - if (!config.isSet("serverUuid")) { - - // Add default values - config.addDefault("enabled", true); - // Every server gets it's unique random id. - config.addDefault("serverUuid", UUID.randomUUID().toString()); - // Should failed request be logged? - config.addDefault("logFailedRequests", false); - // Should the sent data be logged? - config.addDefault("logSentData", false); - // Should the response text be logged? - config.addDefault("logResponseStatusText", false); - - // Inform the server owners about bStats - config.options().header( - "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + - "To honor their work, you should not disable it.\n" + - "This has nearly no effect on the server performance!\n" + - "Check out https://bStats.org/ to learn more :)" - ).copyDefaults(true); - try { - config.save(configFile); - } catch (IOException ignored) { } - } - - // Load the data - serverUUID = config.getString("serverUuid"); - logFailedRequests = config.getBoolean("logFailedRequests", false); - enabled = config.getBoolean("enabled", true); - logSentData = config.getBoolean("logSentData", false); - logResponseStatusText = config.getBoolean("logResponseStatusText", false); - if (enabled) { - boolean found = false; - // Search for all other bStats Metrics classes to see if we are the first one - for (Class service : Bukkit.getServicesManager().getKnownServices()) { - try { - service.getField("NBT_BSTATS_VERSION"); // Create only one instance of the nbt-api bstats. - return; - } catch (NoSuchFieldException ignored) { } - try { - service.getField("B_STATS_VERSION"); // Our identifier :) - found = true; // We aren't the first - break; - } catch (NoSuchFieldException ignored) { } - } - // Register our service - Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal); - if (!found) { - logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!"); - // We are the first! - startSubmitting(); - } - } - } - - /** - * Checks if bStats is enabled. - * - * @return Whether bStats is enabled or not. - */ - public boolean isEnabled() { - return enabled; - } - - /** - * Starts the Scheduler which submits our data every 30 minutes. - */ - private void startSubmitting() { - final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags - timer.scheduleAtFixedRate(new TimerTask() { - @Override - public void run() { - if (!plugin.isEnabled()) { // Plugin was disabled - timer.cancel(); - return; - } - // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler - // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;) - Bukkit.getScheduler().runTask(plugin, () -> submitData()); - } - }, 1000l * 60l * 5l, 1000l * 60l * 30l); - // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start - // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted! - // WARNING: Just don't do it! - } - - /** - * Gets the plugin specific data. - * This method is called using Reflection. - * - * @return The plugin specific data. - */ - public JsonObject getPluginData() { - JsonObject data = new JsonObject(); - - data.addProperty("pluginName", PLUGINNAME); // Append the name of the plugin - data.addProperty("pluginVersion", PLUGINVERSION); // Append the version of the plugin - data.add("customCharts", new JsonArray()); - - return data; - } - - /** - * Gets the server specific data. - * - * @return The server specific data. - */ - private JsonObject getServerData() { - // Minecraft specific data - int playerAmount; - try { - // Around MC 1.8 the return type was changed to a collection from an array, - // This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; - Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); - playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class) - ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() - : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; - } catch (Exception e) { - playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed - } - int onlineMode = Bukkit.getOnlineMode() ? 1 : 0; - String bukkitVersion = Bukkit.getVersion(); - String bukkitName = Bukkit.getName(); - - // OS/Java specific data - String javaVersion = System.getProperty("java.version"); - String osName = System.getProperty("os.name"); - String osArch = System.getProperty("os.arch"); - String osVersion = System.getProperty("os.version"); - int coreCount = Runtime.getRuntime().availableProcessors(); - - JsonObject data = new JsonObject(); - - data.addProperty("serverUUID", serverUUID); - - data.addProperty("playerAmount", playerAmount); - data.addProperty("onlineMode", onlineMode); - data.addProperty("bukkitVersion", bukkitVersion); - data.addProperty("bukkitName", bukkitName); - - data.addProperty("javaVersion", javaVersion); - data.addProperty("osName", osName); - data.addProperty("osArch", osArch); - data.addProperty("osVersion", osVersion); - data.addProperty("coreCount", coreCount); - - return data; - } - - /** - * Collects the data and sends it afterwards. - */ - private void submitData() { - final JsonObject data = getServerData(); - - JsonArray pluginData = new JsonArray(); - // Search for all other bStats Metrics classes to get their plugin data - for (Class service : Bukkit.getServicesManager().getKnownServices()) { - try { - service.getField("B_STATS_VERSION"); // Our identifier :) - - for (RegisteredServiceProvider provider : Bukkit.getServicesManager().getRegistrations(service)) { - try { - Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider()); - if (plugin instanceof JsonObject) { - pluginData.add((JsonObject) plugin); - } else { // old bstats version compatibility - try { - Class jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject"); - if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) { - Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString"); - jsonStringGetter.setAccessible(true); - String jsonString = (String) jsonStringGetter.invoke(plugin); - JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject(); - pluginData.add(object); - } - } catch (ClassNotFoundException e) { - // minecraft version 1.14+ - if (logFailedRequests) { - logger.log(Level.WARNING, "[NBTAPI][BSTATS] Encountered exception while posting request!", e); - // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time - //this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e); - } - continue; // continue looping since we cannot do any other thing. - } - } - } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { - } - } - } catch (NoSuchFieldException ignored) { } - } - - data.add("plugins", pluginData); - - // Create a new thread for the connection to the bStats server - new Thread(new Runnable() { - @Override - public void run() { - try { - // Send the data - sendData(plugin, data); - } catch (Exception e) { - // Something went wrong! :( - if (logFailedRequests) { - logger.log(Level.WARNING, "[NBTAPI][BSTATS] Could not submit plugin stats of " + plugin.getName(), e); - // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time - //plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e); - } - } - } - }).start(); - } - - /** - * Sends the data to the bStats server. - * - * @param plugin Any plugin. It's just used to get a logger instance. - * @param data The data to send. - * @throws Exception If the request failed. - */ - private static void sendData(Plugin plugin, JsonObject data) throws Exception { - if (data == null) { - throw new IllegalArgumentException("Data cannot be null!"); - } - if (Bukkit.isPrimaryThread()) { - throw new IllegalAccessException("This method must not be called from the main thread!"); - } - if (logSentData) { - System.out.println("[NBTAPI][BSTATS] Sending data to bStats: " + data.toString()); - // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time - //plugin.getLogger().info("Sending data to bStats: " + data.toString()); - } - HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); - - // Compress the data to save bandwidth - byte[] compressedData = compress(data.toString()); - - // Add headers - connection.setRequestMethod("POST"); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request - connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); - connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format - connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); - - // Send data - connection.setDoOutput(true); - DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); - outputStream.write(compressedData); - outputStream.flush(); - outputStream.close(); - - InputStream inputStream = connection.getInputStream(); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); - - StringBuilder builder = new StringBuilder(); - String line; - while ((line = bufferedReader.readLine()) != null) { - builder.append(line); - } - bufferedReader.close(); - if (logResponseStatusText) { - logger.info("[NBTAPI][BSTATS] Sent data to bStats and received response: " + builder.toString()); - // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time - //plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString()); - } - } - - /** - * Gzips the given String. - * - * @param str The string to gzip. - * @return The gzipped String. - * @throws IOException If the compression failed. - */ - private static byte[] compress(final String str) throws IOException { - if (str == null) { - return new byte[0]; - } - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - GZIPOutputStream gzip = new GZIPOutputStream(outputStream); - gzip.write(str.getBytes(StandardCharsets.UTF_8)); - gzip.close(); - return outputStream.toByteArray(); - } - -} +package com.songoda.epicenchants.utils.itemnbtapi.utils; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.bukkit.plugin.ServicePriority; + +import javax.net.ssl.HttpsURLConnection; +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Timer; +import java.util.TimerTask; +import java.util.UUID; +import java.util.logging.Level; +import java.util.zip.GZIPOutputStream; +import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.logger; + +/** + * bStats collects some data for plugin authors. + *

+ * Check out https://bStats.org/ to learn more about bStats! + * + * This class is modified by tr7zw to work when the api is shaded into other peoples plugins. + */ +public class ApiMetricsLite { + + private static final String PLUGINNAME = "ItemNBTAPI"; // DO NOT CHANGE THE NAME! else it won't link the data on bStats + + // The version of this bStats class + public static final int B_STATS_VERSION = 1; + + // The version of the NBT-Api bStats + public static final int NBT_BSTATS_VERSION = 1; + + // The url to which the data is sent + private static final String URL = "https://bStats.org/submitData/bukkit"; + + // Is bStats enabled on this server? + private boolean enabled; + + // Should failed requests be logged? + private static boolean logFailedRequests; + + // Should the sent data be logged? + private static boolean logSentData; + + // Should the response text be logged? + private static boolean logResponseStatusText; + + // The uuid of the server + private static String serverUUID; + + // The plugin + private Plugin plugin; + + /** + * Class constructor. + * + */ + public ApiMetricsLite() { + + // The register method just uses any enabled plugin it can find to register. This *shouldn't* cause any problems, since the plugin isn't used any other way. + // Register our service + for(Plugin plug : Bukkit.getPluginManager().getPlugins()) { + plugin = plug; + if(plugin != null) + break; + } + if(plugin == null) { + return;// Didn't find any plugin that could work + } + + // Get the config file + File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); + File configFile = new File(bStatsFolder, "config.yml"); + YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); + + // Check if the config file exists + if (!config.isSet("serverUuid")) { + + // Add default values + config.addDefault("enabled", true); + // Every server gets it's unique random id. + config.addDefault("serverUuid", UUID.randomUUID().toString()); + // Should failed request be logged? + config.addDefault("logFailedRequests", false); + // Should the sent data be logged? + config.addDefault("logSentData", false); + // Should the response text be logged? + config.addDefault("logResponseStatusText", false); + + // Inform the server owners about bStats + config.options().header( + "bStats collects some data for plugin authors like how many servers are using their plugins.\n" + + "To honor their work, you should not disable it.\n" + + "This has nearly no effect on the server performance!\n" + + "Check out https://bStats.org/ to learn more :)" + ).copyDefaults(true); + try { + config.save(configFile); + } catch (IOException ignored) { } + } + + // Load the data + serverUUID = config.getString("serverUuid"); + logFailedRequests = config.getBoolean("logFailedRequests", false); + enabled = config.getBoolean("enabled", true); + logSentData = config.getBoolean("logSentData", false); + logResponseStatusText = config.getBoolean("logResponseStatusText", false); + if (enabled) { + boolean found = false; + // Search for all other bStats Metrics classes to see if we are the first one + for (Class service : Bukkit.getServicesManager().getKnownServices()) { + try { + service.getField("NBT_BSTATS_VERSION"); // Create only one instance of the nbt-api bstats. + return; + } catch (NoSuchFieldException ignored) { } + try { + service.getField("B_STATS_VERSION"); // Our identifier :) + found = true; // We aren't the first + break; + } catch (NoSuchFieldException ignored) { } + } + boolean fFound = found; + // Register our service + if(Bukkit.isPrimaryThread()){ + Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal); + if (!fFound) { + logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!"); + // We are the first! + startSubmitting(); + } + }else{ + Bukkit.getScheduler().runTask(plugin, () -> { + Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal); + if (!fFound) { + logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!"); + // We are the first! + startSubmitting(); + } + }); + } + } + } + + /** + * Checks if bStats is enabled. + * + * @return Whether bStats is enabled or not. + */ + public boolean isEnabled() { + return enabled; + } + + /** + * Starts the Scheduler which submits our data every 30 minutes. + */ + private void startSubmitting() { + final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + if (!plugin.isEnabled()) { // Plugin was disabled + timer.cancel(); + return; + } + // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler + // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;) + Bukkit.getScheduler().runTask(plugin, () -> submitData()); + } + }, 1000l * 60l * 5l, 1000l * 60l * 30l); + // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start + // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted! + // WARNING: Just don't do it! + } + + /** + * Gets the plugin specific data. + * This method is called using Reflection. + * + * @return The plugin specific data. + */ + public JsonObject getPluginData() { + JsonObject data = new JsonObject(); + + data.addProperty("pluginName", PLUGINNAME); // Append the name of the plugin + data.addProperty("pluginVersion", MinecraftVersion.VERSION); // Append the version of the plugin + data.add("customCharts", new JsonArray()); + + return data; + } + + /** + * Gets the server specific data. + * + * @return The server specific data. + */ + private JsonObject getServerData() { + // Minecraft specific data + int playerAmount; + try { + // Around MC 1.8 the return type was changed to a collection from an array, + // This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; + Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); + playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class) + ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() + : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; + } catch (Exception e) { + playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed + } + int onlineMode = Bukkit.getOnlineMode() ? 1 : 0; + String bukkitVersion = Bukkit.getVersion(); + String bukkitName = Bukkit.getName(); + + // OS/Java specific data + String javaVersion = System.getProperty("java.version"); + String osName = System.getProperty("os.name"); + String osArch = System.getProperty("os.arch"); + String osVersion = System.getProperty("os.version"); + int coreCount = Runtime.getRuntime().availableProcessors(); + + JsonObject data = new JsonObject(); + + data.addProperty("serverUUID", serverUUID); + + data.addProperty("playerAmount", playerAmount); + data.addProperty("onlineMode", onlineMode); + data.addProperty("bukkitVersion", bukkitVersion); + data.addProperty("bukkitName", bukkitName); + + data.addProperty("javaVersion", javaVersion); + data.addProperty("osName", osName); + data.addProperty("osArch", osArch); + data.addProperty("osVersion", osVersion); + data.addProperty("coreCount", coreCount); + + return data; + } + + /** + * Collects the data and sends it afterwards. + */ + private void submitData() { + final JsonObject data = getServerData(); + + JsonArray pluginData = new JsonArray(); + // Search for all other bStats Metrics classes to get their plugin data + for (Class service : Bukkit.getServicesManager().getKnownServices()) { + try { + service.getField("B_STATS_VERSION"); // Our identifier :) + + for (RegisteredServiceProvider provider : Bukkit.getServicesManager().getRegistrations(service)) { + try { + Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider()); + if (plugin instanceof JsonObject) { + pluginData.add((JsonObject) plugin); + } else { // old bstats version compatibility + try { + Class jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject"); + if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) { + Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString"); + jsonStringGetter.setAccessible(true); + String jsonString = (String) jsonStringGetter.invoke(plugin); + JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject(); + pluginData.add(object); + } + } catch (ClassNotFoundException e) { + // minecraft version 1.14+ + if (logFailedRequests) { + logger.log(Level.WARNING, "[NBTAPI][BSTATS] Encountered exception while posting request!", e); + // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time + //this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e); + } + continue; // continue looping since we cannot do any other thing. + } + } + } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { + } + } + } catch (NoSuchFieldException ignored) { } + } + + data.add("plugins", pluginData); + + // Create a new thread for the connection to the bStats server + new Thread(new Runnable() { + @Override + public void run() { + try { + // Send the data + sendData(plugin, data); + } catch (Exception e) { + // Something went wrong! :( + if (logFailedRequests) { + logger.log(Level.WARNING, "[NBTAPI][BSTATS] Could not submit plugin stats of " + plugin.getName(), e); + // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time + //plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e); + } + } + } + }).start(); + } + + /** + * Sends the data to the bStats server. + * + * @param plugin Any plugin. It's just used to get a logger instance. + * @param data The data to send. + * @throws Exception If the request failed. + */ + private static void sendData(Plugin plugin, JsonObject data) throws Exception { + if (data == null) { + throw new IllegalArgumentException("Data cannot be null!"); + } + if (Bukkit.isPrimaryThread()) { + throw new IllegalAccessException("This method must not be called from the main thread!"); + } + if (logSentData) { + System.out.println("[NBTAPI][BSTATS] Sending data to bStats: " + data.toString()); + // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time + //plugin.getLogger().info("Sending data to bStats: " + data.toString()); + } + HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection(); + + // Compress the data to save bandwidth + byte[] compressedData = compress(data.toString()); + + // Add headers + connection.setRequestMethod("POST"); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request + connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); + connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format + connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION); + + // Send data + connection.setDoOutput(true); + DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); + outputStream.write(compressedData); + outputStream.flush(); + outputStream.close(); + + InputStream inputStream = connection.getInputStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + + StringBuilder builder = new StringBuilder(); + String line; + while ((line = bufferedReader.readLine()) != null) { + builder.append(line); + } + bufferedReader.close(); + if (logResponseStatusText) { + logger.info("[NBTAPI][BSTATS] Sent data to bStats and received response: " + builder.toString()); + // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time + //plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString()); + } + } + + /** + * Gzips the given String. + * + * @param str The string to gzip. + * @return The gzipped String. + * @throws IOException If the compression failed. + */ + private static byte[] compress(final String str) throws IOException { + if (str == null) { + return new byte[0]; + } + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + GZIPOutputStream gzip = new GZIPOutputStream(outputStream); + gzip.write(str.getBytes(StandardCharsets.UTF_8)); + gzip.close(); + return outputStream.toByteArray(); + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/MinecraftVersion.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/MinecraftVersion.java index 46fbcb9..adccdfc 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/MinecraftVersion.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/MinecraftVersion.java @@ -16,27 +16,22 @@ import org.bukkit.Bukkit; @SuppressWarnings("javadoc") public enum MinecraftVersion { UNKNOWN(Integer.MAX_VALUE), // Use the newest known mappings - MC1_7_R4(174), - MC1_8_R3(183), - MC1_9_R1(191), - MC1_9_R2(192), - MC1_10_R1(1101), - MC1_11_R1(1111), - MC1_12_R1(1121), - MC1_13_R1(1131), - MC1_13_R2(1132), - MC1_14_R1(1141), - MC1_15_R1(1151); + MC1_7_R4(174), MC1_8_R3(183), MC1_9_R1(191), MC1_9_R2(192), MC1_10_R1(1101), MC1_11_R1(1111), MC1_12_R1(1121), + MC1_13_R1(1131), MC1_13_R2(1132), MC1_14_R1(1141), MC1_15_R1(1151), MC1_16_R1(1161); private static MinecraftVersion version; private static Boolean hasGsonSupport; private static boolean bStatsDisabled = false; private static boolean disablePackageWarning = false; + private static boolean updateCheckDisabled = false; /** * Logger used by the api */ public static final Logger logger = Logger.getLogger("NBTAPI"); + // NBT-API Version + protected static final String VERSION = "2.5.0-SNAPSHOT"; + private final int versionId; MinecraftVersion(int versionId) { @@ -49,6 +44,16 @@ public enum MinecraftVersion { public int getVersionId() { return versionId; } + + /** + * Returns true if the current versions is at least the given Version + * + * @param version The minimum version + * @return + */ + public static boolean isAtLeastVersion(MinecraftVersion version) { + return getVersion().getVersionId() >= version.getVersionId(); + } /** * Getter for this servers MinecraftVersion. Also init's bStats and checks the @@ -78,11 +83,20 @@ public enum MinecraftVersion { private static void init() { try { - if (!bStatsDisabled) + if (hasGsonSupport() && !bStatsDisabled) new ApiMetricsLite(); } catch (Exception ex) { - logger.log(Level.WARNING, "[NBTAPI] Error enabeling Metrics!", ex); + logger.log(Level.WARNING, "[NBTAPI] Error enabling Metrics!", ex); } + + if (hasGsonSupport() && !updateCheckDisabled) + new Thread(() -> { + try { + VersionChecker.checkForUpdates(); + } catch (Exception ex) { + logger.log(Level.WARNING, "[NBTAPI] Error while checking for updates!", ex); + } + }).start(); // Maven's Relocate is clever and changes strings, too. So we have to use this // little "trick" ... :D (from bStats) final String defaultPackage = new String(new byte[] { 'd', 'e', '.', 't', 'r', '7', 'z', 'w', '.', 'c', 'h', @@ -128,6 +142,14 @@ public enum MinecraftVersion { bStatsDisabled = true; } + /** + * Disables the update check. Uses Spiget to get the current version and prints + * a warning when outdated. + */ + public static void disableUpdateCheck() { + updateCheckDisabled = true; + } + /** * Forcefully disables the log message for plugins not shading the API to * another location. This may be helpful for networks or development diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/VersionChecker.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/VersionChecker.java new file mode 100644 index 0000000..2c97002 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/VersionChecker.java @@ -0,0 +1,106 @@ +package com.songoda.epicenchants.utils.itemnbtapi.utils; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.logging.Level; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import com.songoda.epicenchants.utils.itemnbtapi.NBTItem; + +/** + * This class uses the Spiget API to check for updates + * + */ +public class VersionChecker { + + private static final String USER_AGENT = "nbt-api Version check"; + private static final String REQUEST_URL = "https://api.spiget.org/v2/resources/7939/versions?size=100"; + + protected static void checkForUpdates() throws Exception { + URL url = new URL(REQUEST_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.addRequestProperty("User-Agent", USER_AGENT);// Set + // User-Agent + + // If you're not sure if the request will be successful, + // you need to check the response code and use #getErrorStream if it + // returned an error code + InputStream inputStream = connection.getInputStream(); + InputStreamReader reader = new InputStreamReader(inputStream); + + // This could be either a JsonArray or JsonObject + JsonElement element = new JsonParser().parse(reader); + if (element.isJsonArray()) { + // Is JsonArray + JsonArray updates = (JsonArray) element; + JsonObject latest = (JsonObject) updates.get(updates.size() - 1); + int versionDifference = getVersionDifference(latest.get("name").getAsString()); + if (versionDifference == -1) { // Outdated + MinecraftVersion.logger.log(Level.WARNING, + "[NBTAPI] The NBT-API at '" + NBTItem.class.getPackage() + "' seems to be outdated!"); + MinecraftVersion.logger.log(Level.WARNING, "[NBTAPI] Current Version: '" + MinecraftVersion.VERSION + + "' Newest Version: " + latest.get("name").getAsString() + "'"); + MinecraftVersion.logger.log(Level.WARNING, + "[NBTAPI] Please update the nbt-api or the plugin that contains the api!"); + + } else if (versionDifference == 0) { + MinecraftVersion.logger.log(Level.INFO, "[NBTAPI] The NBT-API seems to be up-to-date!"); + } else if (versionDifference == 1) { + MinecraftVersion.logger.log(Level.WARNING, "[NBTAPI] The NBT-API at '" + NBTItem.class.getPackage() + + "' seems to be a future Version, not yet released on Spigot!"); + MinecraftVersion.logger.log(Level.WARNING, "[NBTAPI] Current Version: '" + MinecraftVersion.VERSION + + "' Newest Version: " + latest.get("name").getAsString() + "'"); + } + } else { + // wut?! + MinecraftVersion.logger.log(Level.WARNING, + "[NBTAPI] Error when looking for Updates! Got non Json Array: '" + element.toString() + "'"); + } + } + + // -1 = we are outdated + // 0 = up to date + // 1 = using a future version + // This method is only able to compare the Format 0.0.0(-SNAPSHOT) + private static int getVersionDifference(String version) { + String current = MinecraftVersion.VERSION; + if (current.equals(version)) + return 0; + String pattern = "\\."; + if (current.split(pattern).length != 3 || version.split(pattern).length != 3) + return -1; + int curMaj = Integer.parseInt(current.split(pattern)[0]); + int curMin = Integer.parseInt(current.split(pattern)[1]); + String curPatch = current.split(pattern)[2]; + int relMaj = Integer.parseInt(version.split(pattern)[0]); + int relMin = Integer.parseInt(version.split(pattern)[1]); + String relPatch = version.split(pattern)[2]; + if (curMaj < relMaj) + return -1; + if (curMaj > relMaj) + return 1; + if (curMin < relMin) + return -1; + if (curMin > relMin) + return 1; + int curPatchN = Integer.parseInt(curPatch.split("-")[0]); + int relPatchN = Integer.parseInt(relPatch.split("-")[0]); + if (curPatchN < relPatchN) + return -1; + if (curPatchN > relPatchN) + return 1; + if (!relPatch.contains("-") && curPatch.contains("-")) + return -1; // Release has no - but we do = We use a Snapshot of the + // release + if (relPatch.contains("-") && curPatch.contains("-")) + return 0; // Release and cur are Snapshots/alpha/beta + return 1; + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/AvaliableSince.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/AvaliableSince.java new file mode 100644 index 0000000..a9a6676 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/AvaliableSince.java @@ -0,0 +1,17 @@ +package com.songoda.epicenchants.utils.itemnbtapi.utils.annotations; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; + +@Retention(RUNTIME) +@Target({ METHOD }) +public @interface AvaliableSince { + + MinecraftVersion version(); + +} \ No newline at end of file diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/CheckUtil.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/CheckUtil.java new file mode 100644 index 0000000..aa40d8d --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/CheckUtil.java @@ -0,0 +1,16 @@ +package com.songoda.epicenchants.utils.itemnbtapi.utils.annotations; + +import java.lang.reflect.Method; + +import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException; +import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; + +public class CheckUtil { + + public static boolean isAvaliable(Method method) { + if(MinecraftVersion.getVersion().getVersionId() < method.getAnnotation(AvaliableSince.class).version().getVersionId()) + throw new NbtApiException("The Method '" + method.getName() + "' is only avaliable for the Versions " + method.getAnnotation(AvaliableSince.class).version() + "+, but still got called!"); + return true; + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ClassWrapper.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ClassWrapper.java index 3aa04c3..0cb10e9 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ClassWrapper.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ClassWrapper.java @@ -15,18 +15,22 @@ import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.l @SuppressWarnings("javadoc") public enum ClassWrapper { CRAFT_ITEMSTACK(PackageWrapper.CRAFTBUKKIT, "inventory.CraftItemStack"), +CRAFT_METAITEM(PackageWrapper.CRAFTBUKKIT, "inventory.CraftMetaItem"), CRAFT_ENTITY(PackageWrapper.CRAFTBUKKIT, "entity.CraftEntity"), CRAFT_WORLD(PackageWrapper.CRAFTBUKKIT, "CraftWorld"), NMS_NBTBASE(PackageWrapper.NMS, "NBTBase"), NMS_NBTTAGSTRING(PackageWrapper.NMS, "NBTTagString"), NMS_NBTTAGINT(PackageWrapper.NMS, "NBTTagInt"), +NMS_NBTTAGFLOAT(PackageWrapper.NMS, "NBTTagFloat"), +NMS_NBTTAGDOUBLE(PackageWrapper.NMS, "NBTTagDouble"), +NMS_NBTTAGLONG(PackageWrapper.NMS, "NBTTagLong"), NMS_ITEMSTACK(PackageWrapper.NMS, "ItemStack"), NMS_NBTTAGCOMPOUND(PackageWrapper.NMS, "NBTTagCompound"), NMS_NBTTAGLIST(PackageWrapper.NMS, "NBTTagList"), NMS_NBTCOMPRESSEDSTREAMTOOLS(PackageWrapper.NMS, "NBTCompressedStreamTools"), NMS_MOJANGSONPARSER(PackageWrapper.NMS, "MojangsonParser"), NMS_TILEENTITY(PackageWrapper.NMS, "TileEntity"), -NMS_BLOCKPOSITION(PackageWrapper.NMS, "BlockPosition"), +NMS_BLOCKPOSITION(PackageWrapper.NMS, "BlockPosition", MinecraftVersion.MC1_8_R3, null), NMS_WORLDSERVER(PackageWrapper.NMS, "WorldServer"), NMS_MINECRAFTSERVER(PackageWrapper.NMS, "MinecraftServer"), NMS_WORLD(PackageWrapper.NMS, "World"), @@ -35,7 +39,11 @@ NMS_ENTITYTYPES(PackageWrapper.NMS, "EntityTypes"), NMS_REGISTRYSIMPLE(PackageWrapper.NMS, "RegistrySimple", MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_12_R1), NMS_REGISTRYMATERIALS(PackageWrapper.NMS, "RegistryMaterials"), NMS_IREGISTRY(PackageWrapper.NMS, "IRegistry"), -NMS_MINECRAFTKEY(PackageWrapper.NMS, "MinecraftKey"); +NMS_MINECRAFTKEY(PackageWrapper.NMS, "MinecraftKey", MinecraftVersion.MC1_8_R3, null), +NMS_GAMEPROFILESERIALIZER(PackageWrapper.NMS, "GameProfileSerializer"), +NMS_IBLOCKDATA(PackageWrapper.NMS, "IBlockData", MinecraftVersion.MC1_8_R3, null), +GAMEPROFILE("com.mojang.authlib.GameProfile", MinecraftVersion.MC1_8_R3) +; private Class clazz; private boolean enabled = false; @@ -60,6 +68,18 @@ NMS_MINECRAFTKEY(PackageWrapper.NMS, "MinecraftKey"); } } + ClassWrapper(String path, MinecraftVersion from){ + if(from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId()) { + return; + } + enabled = true; + try{ + clazz = Class.forName(path); + }catch(Exception ex){ + logger.log(Level.WARNING, "[NBTAPI] Error while trying to resolve the class '" + path + "'!", ex); + } + } + /** * @return The wrapped class */ diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ObjectCreator.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ObjectCreator.java index 8c68fc0..307ea34 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ObjectCreator.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ObjectCreator.java @@ -16,40 +16,41 @@ import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.l */ @SuppressWarnings("javadoc") public enum ObjectCreator { - NMS_NBTTAGCOMPOUND(null, null, ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()), - NMS_BLOCKPOSITION(null, null, ClassWrapper.NMS_BLOCKPOSITION.getClazz(), int.class, int.class, int.class), - NMS_COMPOUNDFROMITEM(MinecraftVersion.MC1_11_R1, null, ClassWrapper.NMS_ITEMSTACK.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()), - ; + NMS_NBTTAGCOMPOUND(null, null, ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()), + NMS_BLOCKPOSITION(null, null, ClassWrapper.NMS_BLOCKPOSITION.getClazz(), int.class, int.class, int.class), + NMS_COMPOUNDFROMITEM(MinecraftVersion.MC1_11_R1, null, ClassWrapper.NMS_ITEMSTACK.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),; - private Constructor construct; - private Class targetClass; + private Constructor construct; + private Class targetClass; + + ObjectCreator(MinecraftVersion from, MinecraftVersion to, Class clazz, Class... args) { + if (clazz == null) + return; + if (from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId()) + return; + if (to != null && MinecraftVersion.getVersion().getVersionId() > to.getVersionId()) + return; + try { + this.targetClass = clazz; + construct = clazz.getDeclaredConstructor(args); + construct.setAccessible(true); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Unable to find the constructor for the class '" + clazz.getName() + "'", ex); + } + } + + /** + * Creates an Object instance with given args + * + * @param args + * @return Object created + */ + public Object getInstance(Object... args) { + try { + return construct.newInstance(args); + } catch (Exception ex) { + throw new NbtApiException("Exception while creating a new instance of '" + targetClass + "'", ex); + } + } - ObjectCreator(MinecraftVersion from, MinecraftVersion to, Class clazz, Class... args){ - if(from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId()) - return; - if(to != null && MinecraftVersion.getVersion().getVersionId() > to.getVersionId()) - return; - try{ - this.targetClass = clazz; - construct = clazz.getDeclaredConstructor(args); - construct.setAccessible(true); - }catch(Exception ex){ - logger.log(Level.SEVERE, "Unable to find the constructor for the class '" + clazz.getName() + "'", ex); - } - } - - /** - * Creates an Object instance with given args - * - * @param args - * @return Object created - */ - public Object getInstance(Object... args){ - try{ - return construct.newInstance(args); - }catch(Exception ex){ - throw new NbtApiException("Exception while creating a new instance of '" + targetClass + "'", ex); - } - } - } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/PackageWrapper.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/PackageWrapper.java index 12d78c8..bc3f301 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/PackageWrapper.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/PackageWrapper.java @@ -8,13 +8,13 @@ package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings; */ @SuppressWarnings("javadoc") public enum PackageWrapper { - NMS("net.minecraft.server"), - CRAFTBUKKIT("org.bukkit.craftbukkit"), + NMS(new String(new byte[] {'n', 'e', 't', '.', 'm', 'i', 'n', 'e', 'c', 'r', 'a', 'f', 't', '.', 's', 'e', 'r', 'v', 'e', 'r'})), + CRAFTBUKKIT(new String(new byte[] {'o', 'r', 'g', '.', 'b', 'u', 'k', 'k', 'i', 't', '.', 'c', 'r', 'a', 'f', 't', 'b', 'u', 'k', 'k', 'i', 't'})), ; private final String uri; - PackageWrapper(String uri) { + private PackageWrapper(String uri) { this.uri = uri; } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java index 29ff274..6c767b4 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java @@ -1,182 +1,192 @@ -package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings; - -import java.io.InputStream; -import java.io.OutputStream; -import java.lang.reflect.Method; -import org.bukkit.inventory.ItemStack; - -import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException; -import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; - -/** - * This class caches method reflections, keeps track of method name changes between versions and allows early checking for problems - * - * @author tr7zw - * - */ -@SuppressWarnings("javadoc") -public enum ReflectionMethod { - - COMPOUND_SET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, float.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setFloat")), - COMPOUND_SET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setString")), - COMPOUND_SET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setInt")), - COMPOUND_SET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, byte[].class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByteArray")), - COMPOUND_SET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int[].class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setIntArray")), - COMPOUND_SET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, long.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setLong")), - COMPOUND_SET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, short.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setShort")), - COMPOUND_SET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, byte.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByte")), - COMPOUND_SET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, double.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setDouble")), - COMPOUND_SET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, boolean.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setBoolean")), - COMPOUND_MERGE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping! - COMPOUND_SET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "set")), - COMPOUND_GET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")), - COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getList")), - - COMPOUND_GET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getFloat")), - COMPOUND_GET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")), - COMPOUND_GET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getInt")), - COMPOUND_GET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getByteArray")), - COMPOUND_GET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getIntArray")), - COMPOUND_GET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getLong")), - COMPOUND_GET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getShort")), - COMPOUND_GET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getByte")), - COMPOUND_GET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getDouble")), - COMPOUND_GET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getBoolean")), - COMPOUND_GET_COMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getCompound")), - - NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTag")), - NMSITEM_SAVE(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "save")), - NMSITEM_CREATESTACK(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_10_R1, new Since(MinecraftVersion.MC1_7_R4, "createStack")), - - COMPOUND_REMOVE_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "remove")), - COMPOUND_HAS_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "hasKey")), - COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d"), new Since(MinecraftVersion.MC1_15_R1, "e")), //FIXME: No Spigot mapping! - COMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")), - - LISTCOMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")), - LIST_REMOVE_KEY(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a"), new Since(MinecraftVersion.MC1_9_R1, "remove")), - LIST_SIZE(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "size")), - LIST_SET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a"), new Since(MinecraftVersion.MC1_13_R1, "set")), - LEGACY_LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_13_R2, new Since(MinecraftVersion.MC1_7_R4, "add")), - LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_14_R1, new Since(MinecraftVersion.MC1_14_R1, "add")), - LIST_GET_STRING(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")), - LIST_GET_COMPOUND(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")), - LIST_GET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "g"), new Since(MinecraftVersion.MC1_9_R1, "h"), new Since(MinecraftVersion.MC1_12_R1, "i"), new Since(MinecraftVersion.MC1_13_R1, "get")), - - ITEMSTACK_SET_TAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setTag")), - ITEMSTACK_NMSCOPY(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ItemStack.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asNMSCopy")), - ITEMSTACK_BUKKITMIRROR(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_ITEMSTACK.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asCraftMirror")), - - CRAFT_WORLD_GET_HANDLE(ClassWrapper.CRAFT_WORLD.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")), - NMS_WORLD_GET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTileEntity")), - NMS_WORLD_SET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz(), ClassWrapper.NMS_TILEENTITY.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setTileEntity")), - NMS_WORLD_REMOVE_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "t"), new Since(MinecraftVersion.MC1_9_R1, "s"), new Since(MinecraftVersion.MC1_13_R1, "n"), new Since(MinecraftVersion.MC1_14_R1, "removeTileEntity")), - - TILEENTITY_LOAD_LEGACY191(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTSERVER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_9_R1, MinecraftVersion.MC1_9_R1, new Since(MinecraftVersion.MC1_9_R1, "a")), //FIXME: No Spigot mapping! - TILEENTITY_LOAD_LEGACY183(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_9_R2, new Since(MinecraftVersion.MC1_8_R3, "c"), new Since(MinecraftVersion.MC1_9_R1, "a"), new Since(MinecraftVersion.MC1_9_R2, "c")), //FIXME: No Spigot mapping! - TILEENTITY_LOAD_LEGACY1121(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_WORLD.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_10_R1, MinecraftVersion.MC1_12_R1, new Since(MinecraftVersion.MC1_10_R1, "a"), new Since(MinecraftVersion.MC1_12_R1, "create")), - TILEENTITY_LOAD(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_12_R1, "create")), - - TILEENTITY_GET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "save")), - TILEENTITY_SET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"), new Since(MinecraftVersion.MC1_12_R1, "load")), - - CRAFT_ENTITY_GET_HANDLE(ClassWrapper.CRAFT_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")), - NMS_ENTITY_SET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "f")), //FIXME: No Spigot mapping! - NMS_ENTITY_GET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "e"), new Since(MinecraftVersion.MC1_12_R1, "save")), - NMS_ENTITY_GETSAVEID(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_14_R1,new Since(MinecraftVersion.MC1_14_R1, "getSaveID")), - - NBTFILE_READ(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{InputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping! - NBTFILE_WRITE(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), OutputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping! - - - PARSE_NBT(ClassWrapper.NMS_MOJANGSONPARSER.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "parse")), - REGISTRY_KEYSET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "keySet")), - REGISTRY_GET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "get")), - REGISTRY_SET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class, Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "a")), //FIXME: No Spigot mapping! - REGISTRY_GET_INVERSE (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "b")), //FIXME: No Spigot mapping! - REGISTRYMATERIALS_KEYSET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "keySet")), - REGISTRYMATERIALS_GET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTKEY.getClazz()}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "get")), - - - ; - - private MinecraftVersion removedAfter; - private Since targetVersion; - private Method method; - private boolean loaded = false; - private boolean compatible = false; - private String methodName = null; - - ReflectionMethod(Class targetClass, Class[] args, MinecraftVersion addedSince, MinecraftVersion removedAfter, Since... methodnames){ - this.removedAfter = removedAfter; - MinecraftVersion server = MinecraftVersion.getVersion(); - if(server.compareTo(addedSince) < 0 || (this.removedAfter != null && server.getVersionId() > this.removedAfter.getVersionId()))return; - compatible = true; - Since target = methodnames[0]; - for(Since s : methodnames){ - if(s.version.getVersionId() <= server.getVersionId() && target.version.getVersionId() < s.version.getVersionId()) - target = s; - } - targetVersion = target; - try{ - method = targetClass.getMethod(targetVersion.name, args); - method.setAccessible(true); - loaded = true; - methodName = targetVersion.name; - }catch(NullPointerException | NoSuchMethodException | SecurityException ex){ - System.out.println("[NBTAPI] Unable to find the method '" + targetVersion.name + "' in '" + targetClass.getSimpleName() + "' Enum: " + this); //NOSONAR This gets loaded before the logger is loaded - } - } - - ReflectionMethod(Class targetClass, Class[] args, MinecraftVersion addedSince, Since... methodnames){ - this(targetClass, args, addedSince, null, methodnames); - } - - /** - * Runs the method on a given target object using the given args. - * - * @param target - * @param args - * @return Value returned by the method - */ - public Object run(Object target, Object... args){ - if(method == null) - throw new NbtApiException("Method not loaded! '" + this + "'"); - try{ - return method.invoke(target, args); - }catch(Exception ex){ - throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded + ", Enum: " + this, ex); - } - } - - /** - * @return The MethodName, used in this Minecraft Version - */ - public String getMethodName() { - return methodName; - } - - /** - * @return Has this method been linked - */ - public boolean isLoaded() { - return loaded; - } - - /** - * @return Is this method available in this Minecraft Version - */ - public boolean isCompatible() { - return compatible; - } - - protected static class Since{ - public final MinecraftVersion version; - public final String name; - public Since(MinecraftVersion version, String name) { - this.version = version; - this.name = name; - } - } - -} +package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings; + +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.util.UUID; + +import org.bukkit.inventory.ItemStack; + +import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException; +import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; + +/** + * This class caches method reflections, keeps track of method name changes between versions and allows early checking for problems + * + * @author tr7zw + * + */ +@SuppressWarnings("javadoc") +public enum ReflectionMethod { + + COMPOUND_SET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, float.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setFloat")), + COMPOUND_SET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setString")), + COMPOUND_SET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setInt")), + COMPOUND_SET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, byte[].class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByteArray")), + COMPOUND_SET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int[].class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setIntArray")), + COMPOUND_SET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, long.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setLong")), + COMPOUND_SET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, short.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setShort")), + COMPOUND_SET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, byte.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByte")), + COMPOUND_SET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, double.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setDouble")), + COMPOUND_SET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, boolean.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setBoolean")), + COMPOUND_SET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, UUID.class}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "a")), + COMPOUND_MERGE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a")), //FIXME: No Spigot mapping! + COMPOUND_SET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "set")), + COMPOUND_GET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")), + COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getList")), + COMPOUND_OWN_TYPE(ClassWrapper.NMS_NBTBASE.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTypeId")), // Only needed for 1.7.10 getType + + COMPOUND_GET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getFloat")), + COMPOUND_GET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")), + COMPOUND_GET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getInt")), + COMPOUND_GET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getByteArray")), + COMPOUND_GET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getIntArray")), + COMPOUND_GET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getLong")), + COMPOUND_GET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getShort")), + COMPOUND_GET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getByte")), + COMPOUND_GET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getDouble")), + COMPOUND_GET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getBoolean")), + COMPOUND_GET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "a")), + COMPOUND_GET_COMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getCompound")), + + NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTag")), + NMSITEM_SAVE(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "save")), + NMSITEM_CREATESTACK(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_10_R1, new Since(MinecraftVersion.MC1_7_R4, "createStack")), + + COMPOUND_REMOVE_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "remove")), + COMPOUND_HAS_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "hasKey")), + COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d"), new Since(MinecraftVersion.MC1_15_R1, "e"), new Since(MinecraftVersion.MC1_16_R1, "d")), //FIXME: No Spigot mapping! + COMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")), + + LISTCOMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")), + LIST_REMOVE_KEY(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"), new Since(MinecraftVersion.MC1_9_R1, "remove")), + LIST_SIZE(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "size")), + LIST_SET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"), new Since(MinecraftVersion.MC1_13_R1, "set")), + LEGACY_LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_13_R2, new Since(MinecraftVersion.MC1_7_R4, "add")), + LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_14_R1, new Since(MinecraftVersion.MC1_14_R1, "add")), + LIST_GET_STRING(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")), + LIST_GET_COMPOUND(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")), + LIST_GET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get"), new Since(MinecraftVersion.MC1_8_R3, "g"), new Since(MinecraftVersion.MC1_9_R1, "h"), new Since(MinecraftVersion.MC1_12_R1, "i"), new Since(MinecraftVersion.MC1_13_R1, "get")), + + ITEMSTACK_SET_TAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setTag")), + ITEMSTACK_NMSCOPY(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ItemStack.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asNMSCopy")), + ITEMSTACK_BUKKITMIRROR(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_ITEMSTACK.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asCraftMirror")), + + CRAFT_WORLD_GET_HANDLE(ClassWrapper.CRAFT_WORLD.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")), + NMS_WORLD_GET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "getTileEntity")), + NMS_WORLD_SET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz(), ClassWrapper.NMS_TILEENTITY.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "setTileEntity")), + NMS_WORLD_REMOVE_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "t"), new Since(MinecraftVersion.MC1_9_R1, "s"), new Since(MinecraftVersion.MC1_13_R1, "n"), new Since(MinecraftVersion.MC1_14_R1, "removeTileEntity")), + + NMS_WORLD_GET_TILEENTITY_1_7_10(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{int.class, int.class, int.class}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTileEntity")), + + TILEENTITY_LOAD_LEGACY191(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTSERVER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_9_R1, MinecraftVersion.MC1_9_R1, new Since(MinecraftVersion.MC1_9_R1, "a")), //FIXME: No Spigot mapping! + TILEENTITY_LOAD_LEGACY183(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_9_R2, new Since(MinecraftVersion.MC1_8_R3, "c"), new Since(MinecraftVersion.MC1_9_R1, "a"), new Since(MinecraftVersion.MC1_9_R2, "c")), //FIXME: No Spigot mapping! + TILEENTITY_LOAD_LEGACY1121(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_WORLD.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_10_R1, MinecraftVersion.MC1_12_R1, new Since(MinecraftVersion.MC1_10_R1, "a"), new Since(MinecraftVersion.MC1_12_R1, "create")), + TILEENTITY_LOAD_LEGACY1151(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_13_R1, MinecraftVersion.MC1_15_R1, new Since(MinecraftVersion.MC1_12_R1, "create")), + TILEENTITY_LOAD(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_IBLOCKDATA.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "create")), + + TILEENTITY_GET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "b"), new Since(MinecraftVersion.MC1_9_R1, "save")), + TILEENTITY_SET_NBT_LEGACY1151(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_15_R1, new Since(MinecraftVersion.MC1_7_R4, "a"), new Since(MinecraftVersion.MC1_12_R1, "load")), + TILEENTITY_SET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_IBLOCKDATA.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "load")), + TILEENTITY_GET_BLOCKDATA(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "getBlock")), + + CRAFT_ENTITY_GET_HANDLE(ClassWrapper.CRAFT_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")), + NMS_ENTITY_SET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "f"), new Since(MinecraftVersion.MC1_16_R1, "load")), //FIXME: No Spigot mapping! + NMS_ENTITY_GET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "e"), new Since(MinecraftVersion.MC1_12_R1, "save")), + NMS_ENTITY_GETSAVEID(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_14_R1,new Since(MinecraftVersion.MC1_14_R1, "getSaveID")), + + NBTFILE_READ(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{InputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping! + NBTFILE_WRITE(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), OutputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping! + + PARSE_NBT(ClassWrapper.NMS_MOJANGSONPARSER.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "parse")), + REGISTRY_KEYSET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "keySet")), + REGISTRY_GET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "get")), + REGISTRY_SET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class, Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "a")), //FIXME: No Spigot mapping! + REGISTRY_GET_INVERSE (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "b")), //FIXME: No Spigot mapping! + REGISTRYMATERIALS_KEYSET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "keySet")), + REGISTRYMATERIALS_GET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTKEY.getClazz()}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "get")), + REGISTRYMATERIALS_GETKEY (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_13_R2, new Since(MinecraftVersion.MC1_13_R2, "getKey")), + + GAMEPROFILE_DESERIALIZE (ClassWrapper.NMS_GAMEPROFILESERIALIZER.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "deserialize")), + GAMEPROFILE_SERIALIZE (ClassWrapper.NMS_GAMEPROFILESERIALIZER.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), ClassWrapper.GAMEPROFILE.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "serialize")); + + private MinecraftVersion removedAfter; + private Since targetVersion; + private Method method; + private boolean loaded = false; + private boolean compatible = false; + private String methodName = null; + + ReflectionMethod(Class targetClass, Class[] args, MinecraftVersion addedSince, MinecraftVersion removedAfter, Since... methodnames){ + this.removedAfter = removedAfter; + MinecraftVersion server = MinecraftVersion.getVersion(); + if(server.compareTo(addedSince) < 0 || (this.removedAfter != null && server.getVersionId() > this.removedAfter.getVersionId()))return; + compatible = true; + Since target = methodnames[0]; + for(Since s : methodnames){ + if(s.version.getVersionId() <= server.getVersionId() && target.version.getVersionId() < s.version.getVersionId()) + target = s; + } + targetVersion = target; + try{ + method = targetClass.getMethod(targetVersion.name, args); + method.setAccessible(true); + loaded = true; + methodName = targetVersion.name; + }catch(NullPointerException | NoSuchMethodException | SecurityException ex){ + System.out.println("[NBTAPI] Unable to find the method '" + targetVersion.name + "' in '" + targetClass.getSimpleName() + "' Enum: " + this); //NOSONAR This gets loaded before the logger is loaded + } + } + + ReflectionMethod(Class targetClass, Class[] args, MinecraftVersion addedSince, Since... methodnames){ + this(targetClass, args, addedSince, null, methodnames); + } + + /** + * Runs the method on a given target object using the given args. + * + * @param target + * @param args + * @return Value returned by the method + */ + public Object run(Object target, Object... args){ + if(method == null) + throw new NbtApiException("Method not loaded! '" + this + "'"); + try{ + return method.invoke(target, args); + }catch(Exception ex){ + throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded + ", Enum: " + this, ex); + } + } + + /** + * @return The MethodName, used in this Minecraft Version + */ + public String getMethodName() { + return methodName; + } + + /** + * @return Has this method been linked + */ + public boolean isLoaded() { + return loaded; + } + + /** + * @return Is this method available in this Minecraft Version + */ + public boolean isCompatible() { + return compatible; + } + + protected static class Since{ + public final MinecraftVersion version; + public final String name; + public Since(MinecraftVersion version, String name) { + this.version = version; + this.name = name; + } + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java b/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java index 8d57e56..8c27a2a 100644 --- a/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java +++ b/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java @@ -2,87 +2,60 @@ package com.songoda.epicenchants.utils.single; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; -import com.songoda.core.compatibility.ServerVersion; -import com.songoda.epicenchants.EpicEnchants; +import com.songoda.core.compatibility.CompatibleMaterial; import org.apache.commons.lang.StringUtils; import org.bukkit.Material; import java.util.*; import java.util.stream.Collectors; +import static com.songoda.core.compatibility.CompatibleMaterial.*; import static com.songoda.epicenchants.utils.single.ItemGroup.Group.*; -import static org.bukkit.Material.*; public class ItemGroup { - private Multimap groupMap; + private final Multimap groupMap; - public ItemGroup(EpicEnchants instance) { + public ItemGroup() { groupMap = HashMultimap.create(); - if (com.songoda.core.compatibility.ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) setupMaster(); - else setupLegacy(); - } - private void setupMaster() { - groupMap.putAll(AXES, Arrays.asList(DIAMOND_AXE, GOLDEN_AXE, IRON_AXE, STONE_AXE, WOODEN_AXE)); + groupMap.putAll(AXES, Arrays.asList(NETHERITE_AXE, DIAMOND_AXE, GOLDEN_AXE, IRON_AXE, STONE_AXE, WOODEN_AXE)); - groupMap.putAll(PICKAXES, Arrays.asList(DIAMOND_PICKAXE, GOLDEN_PICKAXE, IRON_PICKAXE, STONE_PICKAXE, WOODEN_PICKAXE)); + groupMap.putAll(PICKAXES, Arrays.asList(NETHERITE_PICKAXE, DIAMOND_PICKAXE, GOLDEN_PICKAXE, IRON_PICKAXE, STONE_PICKAXE, WOODEN_PICKAXE)); - groupMap.putAll(HOES, Arrays.asList(DIAMOND_HOE, GOLDEN_HOE, IRON_HOE, STONE_HOE, WOODEN_HOE)); + groupMap.putAll(HOES, Arrays.asList(NETHERITE_HOE, DIAMOND_HOE, GOLDEN_HOE, IRON_HOE, STONE_HOE, WOODEN_HOE)); - groupMap.putAll(SHOVELS, Arrays.asList(DIAMOND_SHOVEL, GOLDEN_SHOVEL, IRON_SHOVEL, STONE_SHOVEL, WOODEN_SHOVEL)); + groupMap.putAll(SHOVELS, Arrays.asList(NETHERITE_SHOVEL, DIAMOND_SHOVEL, GOLDEN_SHOVEL, IRON_SHOVEL, STONE_SHOVEL, WOODEN_SHOVEL)); - groupMap.putAll(SWORDS, Arrays.asList(DIAMOND_SWORD, GOLDEN_SWORD, IRON_SWORD, STONE_SWORD, WOODEN_SWORD)); + groupMap.putAll(SWORDS, Arrays.asList(NETHERITE_SWORD, DIAMOND_SWORD, GOLDEN_SWORD, IRON_SWORD, STONE_SWORD, WOODEN_SWORD)); groupMap.put(BOWS, BOW); - groupMap.putAll(BOOTS, Arrays.asList(DIAMOND_BOOTS, GOLDEN_BOOTS, IRON_BOOTS, LEATHER_BOOTS)); + groupMap.putAll(BOOTS, Arrays.asList(NETHERITE_BOOTS, DIAMOND_BOOTS, GOLDEN_BOOTS, IRON_BOOTS, LEATHER_BOOTS)); - groupMap.putAll(LEGGINGS, Arrays.asList(DIAMOND_LEGGINGS, GOLDEN_LEGGINGS, IRON_LEGGINGS, LEATHER_LEGGINGS)); + groupMap.putAll(LEGGINGS, Arrays.asList(NETHERITE_LEGGINGS, DIAMOND_LEGGINGS, GOLDEN_LEGGINGS, IRON_LEGGINGS, LEATHER_LEGGINGS)); - groupMap.putAll(CHESTPLATES, Arrays.asList(DIAMOND_CHESTPLATE, GOLDEN_CHESTPLATE, IRON_CHESTPLATE, LEATHER_CHESTPLATE)); + groupMap.putAll(CHESTPLATES, Arrays.asList(NETHERITE_CHESTPLATE, DIAMOND_CHESTPLATE, GOLDEN_CHESTPLATE, IRON_CHESTPLATE, LEATHER_CHESTPLATE)); - groupMap.putAll(HELMETS, Arrays.asList(DIAMOND_HELMET, GOLDEN_HELMET, IRON_HELMET, LEATHER_HELMET)); + groupMap.putAll(HELMETS, Arrays.asList(NETHERITE_HELMET, DIAMOND_HELMET, GOLDEN_HELMET, IRON_HELMET, LEATHER_HELMET)); groupMap.put(TRIDENTS, TRIDENT); } - private void setupLegacy() { - groupMap.putAll(AXES, Arrays.asList(DIAMOND_AXE, Material.valueOf("GOLD_AXE"), IRON_AXE, STONE_AXE, Material.valueOf("WOOD_AXE"))); - - groupMap.putAll(PICKAXES, Arrays.asList(DIAMOND_PICKAXE, Material.valueOf("GOLD_PICKAXE"), IRON_PICKAXE, STONE_PICKAXE, Material.valueOf("WOOD_PICKAXE"))); - - groupMap.putAll(HOES, Arrays.asList(DIAMOND_HOE, Material.valueOf("GOLD_HOE"), IRON_HOE, STONE_HOE, Material.valueOf("WOOD_HOE"))); - - groupMap.putAll(SHOVELS, Arrays.asList(Material.valueOf("DIAMOND_SPADE"), Material.valueOf("GOLD_SPADE"), Material.valueOf("IRON_SPADE"), Material.valueOf("STONE_SPADE"), Material.valueOf("WOOD_SPADE"))); - - groupMap.putAll(SWORDS, Arrays.asList(DIAMOND_SWORD, Material.valueOf("GOLD_SWORD"), IRON_SWORD, STONE_SWORD, Material.valueOf("WOOD_SWORD"))); - - groupMap.put(BOWS, BOW); - - groupMap.putAll(BOOTS, Arrays.asList(DIAMOND_BOOTS, Material.valueOf("GOLD_BOOTS"), IRON_BOOTS, LEATHER_BOOTS)); - - groupMap.putAll(LEGGINGS, Arrays.asList(DIAMOND_LEGGINGS, Material.valueOf("GOLD_LEGGINGS"), IRON_LEGGINGS, LEATHER_LEGGINGS)); - - groupMap.putAll(CHESTPLATES, Arrays.asList(DIAMOND_CHESTPLATE, Material.valueOf("GOLD_CHESTPLATE"), IRON_CHESTPLATE, LEATHER_CHESTPLATE)); - - groupMap.putAll(HELMETS, Arrays.asList(DIAMOND_HELMET, Material.valueOf("GOLD_HELMET"), IRON_HELMET, LEATHER_HELMET)); - } - public Set get(String key) { Optional optionalGroup = Group.from(key); Set output = new HashSet<>(); optionalGroup.ifPresent(group -> output.addAll(getMaterials(group))); - if (Material.matchMaterial(key) != null) { - output.add(Material.matchMaterial(key)); + if (CompatibleMaterial.getMaterial(key) != null) { + output.add(CompatibleMaterial.getMaterial(key).getMaterial()); } return output; } - public Set getGroups(Set materials) { + public Set getGroups(Set materials) { Set groups = new HashSet<>(); for (int i = 0; i < 5; i++) { @@ -92,11 +65,11 @@ public class ItemGroup { }); } - groups.addAll(materials.stream().map(Material::toString).collect(Collectors.toSet())); + groups.addAll(materials.stream().map(CompatibleMaterial::toString).collect(Collectors.toSet())); return groups; } - public Optional getGroup(Set materials) { + public Optional getGroup(Set materials) { Optional group = Arrays.stream(Group.values()) .filter(s -> !s.getChildren().isEmpty() && s.getChildren().stream().allMatch(child -> materials.containsAll(groupMap.get(child)))) .findFirst(); @@ -113,7 +86,7 @@ public class ItemGroup { for (int i = 0; i < 5; i++) { if (group.getChildren().isEmpty()) - out.addAll(groupMap.get(group)); + out.addAll(groupMap.get(group).stream().map(CompatibleMaterial::getMaterial).collect(Collectors.toList())); else out.addAll(group.getChildren().stream().map(this::getMaterials).flatMap(Collection::stream).collect(Collectors.toSet())); } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 60823d1..00d75bf 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -6,6 +6,6 @@ website: https://songoda.com/ softdepend: [Vault, PlayerPoints, UltimateBottles, PlaceholderAPI] api-version: 1.13 commands: - epicenchants: - aliases: [ee] - ussage: /ee reload \ No newline at end of file + ee: + aliases: [epicenchants] + ussage: reload \ No newline at end of file diff --git a/src/main/resources/version-dependent/legacy/menus/enchanter-menu.yml b/src/main/resources/version-dependent/legacy/menus/enchanter-menu.yml index 52cc5c3..e91d945 100644 --- a/src/main/resources/version-dependent/legacy/menus/enchanter-menu.yml +++ b/src/main/resources/version-dependent/legacy/menus/enchanter-menu.yml @@ -15,7 +15,7 @@ contents: - "&7Examine to receive a random" - "&fsimple &7enchantment book." - "" - - "&fUse &f/ee list simple &7to view a list" + - "&fUse &flist simple &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP" @@ -31,7 +31,7 @@ contents: - "&7Examine to receive a random" - "&aunique &7enchantment book." - "" - - "&fUse &a/ee list unique &7to view a list" + - "&fUse &alist unique &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP" @@ -47,7 +47,7 @@ contents: - "&7Examine to receive a random" - "&belite &7enchantment book." - "" - - "&fUse &b/ee list elite &7to view a list" + - "&fUse &blist elite &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP" @@ -63,7 +63,7 @@ contents: - "&7Examine to receive a random" - "&eultimate &7enchantment book." - "" - - "&fUse &e/ee list simple &7to view a list" + - "&fUse &elist simple &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP" @@ -79,7 +79,7 @@ contents: - "&7Examine to receive a random" - "&6legendary &7enchantment book." - "" - - "&fUse &6/ee list simple &7to view a list" + - "&fUse &6list simple &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP" diff --git a/src/main/resources/version-dependent/master/menus/enchanter-menu.yml b/src/main/resources/version-dependent/master/menus/enchanter-menu.yml index a3ddaa8..9cb5e27 100644 --- a/src/main/resources/version-dependent/master/menus/enchanter-menu.yml +++ b/src/main/resources/version-dependent/master/menus/enchanter-menu.yml @@ -14,7 +14,7 @@ contents: - "&7Examine to receive a random" - "&fsimple &7enchantment book." - "" - - "&fUse &f/ee list simple &7to view a list" + - "&fUse &flist simple &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP" @@ -29,7 +29,7 @@ contents: - "&7Examine to receive a random" - "&aunique &7enchantment book." - "" - - "&fUse &a/ee list unique &7to view a list" + - "&fUse &alist unique &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP" @@ -44,7 +44,7 @@ contents: - "&7Examine to receive a random" - "&belite &7enchantment book." - "" - - "&fUse &b/ee list elite &7to view a list" + - "&fUse &blist elite &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP" @@ -59,7 +59,7 @@ contents: - "&7Examine to receive a random" - "&eultimate &7enchantment book." - "" - - "&fUse &e/ee list simple &7to view a list" + - "&fUse &elist simple &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP" @@ -74,7 +74,7 @@ contents: - "&7Examine to receive a random" - "&6legendary &7enchantment book." - "" - - "&fUse &6/ee list simple &7to view a list" + - "&fUse &6list simple &7to view a list" - "&fof possible enchants you could unlock!" - "" - "&b&lCOST &r&f{exp_cost} EXP"