diff --git a/core/pom.xml b/core/pom.xml index c552aba..4480468 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -5,7 +5,7 @@ EpicEnchants-Parent com.songoda - 1.0.1-ALPHA + 1.0.3-ALPHA 4.0.0 @@ -83,7 +83,7 @@ com.github.tr7zw Item-NBT-API - 9c5f6575a8 + master-SNAPSHOT compile @@ -100,5 +100,12 @@ 1.7 provided + + + com.songoda + UltimateBottles + 1.0 + provided + \ No newline at end of file diff --git a/core/src/main/java/com/songoda/epicenchants/Action.java b/core/src/main/java/com/songoda/epicenchants/Action.java new file mode 100644 index 0000000..ecb4d46 --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/Action.java @@ -0,0 +1,63 @@ +package com.songoda.epicenchants; + +import com.songoda.epicenchants.objects.Placeholder; +import org.bukkit.Effect; +import org.bukkit.Sound; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; + +import static com.songoda.epicenchants.utils.single.GeneralUtils.color; + +public class Action { + private FileConfiguration config; + private String prefix; + + public void perform(CommandSender sender, String node, Placeholder... placeholders) { + if (config.isString(node)) { + sender.sendMessage(getMessage(node, placeholders)); + return; + } + + if (!config.isConfigurationSection(node)) { + return; + } + + ConfigurationSection section = config.getConfigurationSection(node); + + if (section.isString("message")) { + sender.sendMessage(getMessage(node + ".message", placeholders)); + } + + if (!(sender instanceof Player)) { + return; + } + + Player player = (Player) sender; + + if (section.isString("sound")) { + player.playSound(player.getLocation(), Sound.valueOf(section.getString("sound").toUpperCase()), 1F, 1F); + } + + if (section.isString("effect")) { + player.playEffect(player.getEyeLocation(), Effect.valueOf(section.getString("effect")), 10); + } + + } + + public String getMessage(String node, Placeholder... placeholders) { + String string = config.getString(node); + + for (Placeholder placeholder : placeholders) { + string = string.replace(placeholder.getPlaceholder(), placeholder.getToReplace().toString()); + } + + return color(string); + } + + public void load(FileConfiguration config) { + this.config = config; + this.prefix = config.getString("general.prefix"); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/EpicEnchants.java b/core/src/main/java/com/songoda/epicenchants/EpicEnchants.java index be9bd4c..370dc6c 100644 --- a/core/src/main/java/com/songoda/epicenchants/EpicEnchants.java +++ b/core/src/main/java/com/songoda/epicenchants/EpicEnchants.java @@ -1,47 +1,42 @@ package com.songoda.epicenchants; import co.aikar.commands.BukkitCommandManager; -import co.aikar.commands.InvalidCommandArgument; -import com.songoda.epicenchants.commands.EnchantCommand; -import com.songoda.epicenchants.enums.GiveType; -import com.songoda.epicenchants.listeners.*; -import com.songoda.epicenchants.managers.EnchantManager; -import com.songoda.epicenchants.managers.FileManager; -import com.songoda.epicenchants.managers.GroupManager; -import com.songoda.epicenchants.managers.InfoManager; +import com.songoda.epicenchants.hooks.HookManager; +import com.songoda.epicenchants.listeners.ArmorListener; +import com.songoda.epicenchants.listeners.EntityListener; +import com.songoda.epicenchants.listeners.PlayerListener; +import com.songoda.epicenchants.listeners.item.*; +import com.songoda.epicenchants.managers.*; import com.songoda.epicenchants.objects.Enchant; import com.songoda.epicenchants.utils.EnchantUtils; -import com.songoda.epicenchants.utils.FastInv; import com.songoda.epicenchants.utils.SpecialItems; +import com.songoda.epicenchants.utils.objects.FastInv; import lombok.Getter; import net.milkbowl.vault.economy.Economy; import org.bukkit.Bukkit; import org.bukkit.event.Listener; import org.bukkit.plugin.java.JavaPlugin; -import java.io.File; -import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; -import java.util.Objects; import java.util.stream.Collectors; -import java.util.stream.IntStream; -import static com.songoda.epicenchants.utils.GeneralUtils.color; +import static com.songoda.epicenchants.utils.single.GeneralUtils.color; import static org.bukkit.Bukkit.getConsoleSender; @Getter public class EpicEnchants extends JavaPlugin { private BukkitCommandManager commandManager; - private Economy economy; private EnchantManager enchantManager; private InfoManager infoManager; private GroupManager groupManager; - private EnchantUtils enchantUtils; private FileManager fileManager; + private HookManager hookManager; + private SpecialItems specialItems; - private Locale locale; + private Action action; + private Economy economy; + private EnchantUtils enchantUtils; @Override public void onEnable() { @@ -49,10 +44,9 @@ public class EpicEnchants extends JavaPlugin { getConsoleSender().sendMessage(color("&7" + getDescription().getName() + " " + getDescription().getVersion() + " by &5Songoda <3&7!")); getConsoleSender().sendMessage(color("&7Action: &aEnabling&7...")); - Locale.init(this); FastInv.init(this); - this.locale = Locale.getLocale(getConfig().getString("language")); + this.action = new Action(); this.fileManager = new FileManager(this); this.groupManager = new GroupManager(this); this.enchantManager = new EnchantManager(this); @@ -60,17 +54,20 @@ public class EpicEnchants extends JavaPlugin { this.infoManager = new InfoManager(this); this.specialItems = new SpecialItems(this); this.economy = getServer().getServicesManager().getRegistration(Economy.class).getProvider(); + this.commandManager = new CommandManager(this); + this.hookManager = new HookManager(); - fileManager.createFiles(); + fileManager.loadFiles(); groupManager.loadGroups(); enchantManager.loadEnchants(); infoManager.loadMenus(); + action.load(fileManager.getConfiguration("actions")); + hookManager.setup(); - setupCommands(); setupListeners(); - if (!enchantManager.getEnchants().isEmpty()) { - getLogger().info("Successfully loaded enchants: " + enchantManager.getEnchants().stream().map(Enchant::getIdentifier).collect(Collectors.joining(", "))); + if (!enchantManager.getValues().isEmpty()) { + getLogger().info("Successfully loaded enchants: " + enchantManager.getValues().stream().map(Enchant::getIdentifier).collect(Collectors.joining(", "))); } getConsoleSender().sendMessage(color("&a=============================")); @@ -84,28 +81,6 @@ public class EpicEnchants extends JavaPlugin { getConsoleSender().sendMessage(color("&a=============================")); } - private void setupCommands() { - this.commandManager = new BukkitCommandManager(this); - - commandManager.registerDependency(EpicEnchants.class, "instance", this); - - commandManager.getCommandCompletions().registerCompletion("enchants", c -> enchantManager.getEnchants().stream().map(Enchant::getIdentifier).collect(Collectors.toList())); - commandManager.getCommandCompletions().registerCompletion("enchantFiles", c -> fileManager.getYmlFiles("enchants").orElse(Collections.emptyList()).stream().map(File::getName).collect(Collectors.toList())); - commandManager.getCommandCompletions().registerCompletion("giveType", c -> Arrays.stream(GiveType.values()).map(s -> s.toString().replace("_", "").toLowerCase()).collect(Collectors.toList())); - commandManager.getCommandCompletions().registerCompletion("levels", c -> IntStream.rangeClosed(1, c.getContextValue(Enchant.class).getMaxLevel()).boxed().map(Objects::toString).collect(Collectors.toList())); - commandManager.getCommandCompletions().registerCompletion("increment", c -> IntStream.rangeClosed(0, 100).filter(i -> i % 10 == 0).boxed().map(Objects::toString).collect(Collectors.toList())); - - commandManager.getCommandContexts().registerContext(Enchant.class, c -> enchantManager.getEnchant(c.popFirstArg()).orElseThrow(() -> new InvalidCommandArgument("No enchant exists by that name"))); - commandManager.getCommandContexts().registerContext(File.class, c -> enchantManager.getEnchantFile(c.popFirstArg()).orElseThrow(() -> new InvalidCommandArgument("No EnchantFile exists by that name"))); - - commandManager.getCommandContexts().registerContext(GiveType.class, c -> Arrays.stream(GiveType.values()) - .filter(s -> s.toString().toLowerCase().replace("_", "").equalsIgnoreCase(c.popFirstArg())) - .findFirst() - .orElseThrow(() -> new InvalidCommandArgument("No item by that type."))); - - commandManager.registerCommand(new EnchantCommand()); - } - private void setupListeners() { EpicEnchants instance = this; new HashSet() {{ @@ -114,15 +89,17 @@ public class EpicEnchants extends JavaPlugin { add(new PlayerListener(instance)); add(new EntityListener(instance)); add(new WhiteScrollListener(instance)); + add(new BlackScrollListener(instance)); + add(new DustListener(instance)); }}.forEach(listener -> Bukkit.getPluginManager().registerEvents(listener, this)); } public void reload() { reloadConfig(); - locale.reloadMessages(); - + fileManager.loadFiles(); enchantManager.loadEnchants(); groupManager.loadGroups(); infoManager.loadMenus(); + action.load(fileManager.getConfiguration("actions")); } } diff --git a/core/src/main/java/com/songoda/epicenchants/Locale.java b/core/src/main/java/com/songoda/epicenchants/Locale.java deleted file mode 100644 index 251451b..0000000 --- a/core/src/main/java/com/songoda/epicenchants/Locale.java +++ /dev/null @@ -1,401 +0,0 @@ -package com.songoda.epicenchants; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.songoda.epicenchants.objects.Placeholder; -import org.bukkit.ChatColor; -import org.bukkit.plugin.java.JavaPlugin; - -import java.io.*; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * Assists in the creation of multiple localizations and languages, - * as well as the generation of default .lang files - * - * @author Parker Hawke - 2008Choco - */ -public class Locale { - - private static final List LOCALES = Lists.newArrayList(); - private static final Pattern NODE_PATTERN = Pattern.compile("(\\w+(?:\\.{1}\\w+)*)\\s*=\\s*\"(.*)\""); - private static final String FILE_EXTENSION = ".lang"; - private static JavaPlugin plugin; - private static File localeFolder; - - private static String defaultLocale; - - private final Map nodes = new HashMap<>(); - - private final File file; - private final String name, region; - - private Locale(String name, String region) { - if (plugin == null) - throw new IllegalStateException("Cannot generate locales without first initializing the class (Locale#init(JavaPlugin))"); - - this.name = name.toLowerCase(); - this.region = region.toUpperCase(); - - String fileName = name + "_" + region + FILE_EXTENSION; - this.file = new File(localeFolder, fileName); - - if (this.reloadMessages()) return; - - plugin.getLogger().info("Loaded locale " + fileName); - } - - /** - * Initialize the locale class to generate information and search for localizations. - * This must be called before any other methods in the Locale class can be invoked. - * Note that this will also call {@link #searchForLocales()}, so there is no need to - * invoke it for yourself after the initialization - * - * @param plugin the plugin instance - */ - public static void init(JavaPlugin plugin) { - Locale.plugin = plugin; - - if (localeFolder == null) { - localeFolder = new File(plugin.getDataFolder(), "locales/"); - } - - localeFolder.mkdirs(); - Locale.searchForLocales(); - Locale.saveDefaultLocale("en_US"); - } - - /** - * Find all .lang file locales under the "locales" folder - */ - public static void searchForLocales() { - if (!localeFolder.exists()) { - localeFolder.mkdirs(); - } - - for (File file : localeFolder.listFiles()) { - String name = file.getName(); - if (!name.endsWith(".lang")) continue; - - String fileName = name.substring(0, name.lastIndexOf('.')); - String[] localeValues = fileName.split("_"); - - if (localeValues.length != 2) continue; - if (localeExists(localeValues[0] + "_" + localeValues[1])) continue; - - LOCALES.add(new Locale(localeValues[0], localeValues[1])); - plugin.getLogger().info("Found and loaded locale \"" + fileName + "\""); - } - } - - /** - * Get a locale by its entire proper name (i.e. "en_US") - * - * @param name the full name of the locale - * @return locale of the specified name - */ - public static Locale getLocale(String name) { - for (Locale locale : LOCALES) - if (locale.getLanguageTag().equalsIgnoreCase(name)) return locale; - return null; - } - - /** - * Get a locale from the cache by its name (i.e. "en" from "en_US") - * - * @param name the name of the language - * @return locale of the specified language. Null if not cached - */ - public static Locale getLocaleByName(String name) { - for (Locale locale : LOCALES) - if (locale.getName().equalsIgnoreCase(name)) return locale; - return null; - } - - /** - * Get a locale from the cache by its region (i.e. "US" from "en_US") - * - * @param region the name of the region - * @return locale of the specified region. Null if not cached - */ - public static Locale getLocaleByRegion(String region) { - for (Locale locale : LOCALES) - if (locale.getRegion().equalsIgnoreCase(region)) return locale; - return null; - } - - /** - * Check whether a locale exists and is registered or not - * - * @param name the whole language tag (i.e. "en_US") - * @return true if it exists - */ - public static boolean localeExists(String name) { - for (Locale locale : LOCALES) - if (locale.getLanguageTag().equals(name)) return true; - return false; - } - - /** - * Save a default locale file from the project source directory, to the locale folder - * - * @param in file to save - * @param fileName the name of the file to save - * @return true if the operation was successful, false otherwise - */ - public static boolean saveDefaultLocale(InputStream in, String fileName) { - if (!localeFolder.exists()) localeFolder.mkdirs(); - - if (!fileName.endsWith(FILE_EXTENSION)) - fileName = (fileName.lastIndexOf(".") == -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.'))) + FILE_EXTENSION; - - File destinationFile = new File(localeFolder, fileName); - if (destinationFile.exists()) { - return compareFiles(plugin.getResource(fileName), destinationFile); - } - - try (OutputStream outputStream = new FileOutputStream(destinationFile)) { - copy(in == null ? plugin.getResource(fileName) : in, outputStream); - - fileName = fileName.substring(0, fileName.lastIndexOf('.')); - String[] localeValues = fileName.split("_"); - - if (localeValues.length != 2) return false; - - LOCALES.add(new Locale(localeValues[0], localeValues[1])); - if (defaultLocale == null) defaultLocale = fileName; - - return true; - } catch (IOException e) { - return false; - } - } - - /** - * Save a default locale file from the project source directory, to the locale folder - * - * @param fileName the name of the file to save - * @return true if the operation was successful, false otherwise - */ - public static boolean saveDefaultLocale(String fileName) { - return saveDefaultLocale(null, fileName); - } - - /** - * Clear all current locale data - */ - public static void clearLocaleData() { - for (Locale locale : LOCALES) - locale.nodes.clear(); - LOCALES.clear(); - } - - // Write new changes to existing files, if any at all - private static boolean compareFiles(InputStream defaultFile, File existingFile) { - // Look for default - if (defaultFile == null) { - defaultFile = plugin.getResource(defaultLocale != null ? defaultLocale : "en_US"); - if (defaultFile == null) return false; // No default at all - } - - boolean changed = false; - - List defaultLines, existingLines; - try (BufferedReader defaultReader = new BufferedReader(new InputStreamReader(defaultFile)); - BufferedReader existingReader = new BufferedReader(new FileReader(existingFile)); - BufferedWriter writer = new BufferedWriter(new FileWriter(existingFile, true))) { - defaultLines = defaultReader.lines().collect(Collectors.toList()); - existingLines = existingReader.lines().map(s -> s.split("\\s*=")[0]).collect(Collectors.toList()); - - for (String defaultValue : defaultLines) { - if (defaultValue.isEmpty() || defaultValue.startsWith("#")) continue; - - String key = defaultValue.split("\\s*=")[0]; - - if (!existingLines.contains(key)) { - if (!changed) { - writer.newLine(); - writer.newLine(); - writer.write("# New messages for " + plugin.getName() + " v" + plugin.getDescription().getVersion()); - } - - writer.newLine(); - writer.write(defaultValue); - - changed = true; - } - } - } catch (IOException e) { - return false; - } - - return changed; - } - - private static void copy(InputStream input, OutputStream output) { - int n; - byte[] buffer = new byte[1024 * 4]; - - try { - while ((n = input.read(buffer)) != -1) { - output.write(buffer, 0, n); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Get a message set for a specific node - * - * @param node the node to get - * @return the message for the specified node - */ - public String getMessage(String node) { - return ChatColor.translateAlternateColorCodes('&', this.getMessageOrDefault(node, node)); - } - - /** - * Get a message set for a specific node with prefix - * - * @param node the node to get - * @return the message for the specified node - */ - public String getMessageWithPrefix(String node) { - return ChatColor.translateAlternateColorCodes('&', getPrefix() + this.getMessageOrDefault(node, node)); - } - - /** - * Get a message set for a specific node with prefix - * - * @param node the node to get - * @return the message for the specified node - */ - public String getMessageWithPrefix(String node, Placeholder... placeholders) { - return ChatColor.translateAlternateColorCodes('&', getPrefix() + getMessage(node, placeholders)); - } - - /** - * Get a message set for a specific node and replace its params with a supplied arguments. - * - * @param node the node to get - * @return the message for the specified node - */ - public String getMessage(String node, Placeholder... placeholders) { - String message = getMessage(node); - for (Placeholder placeholder : placeholders) { - message = message.replace(placeholder.getPlaceholder(), placeholder.getToReplace().toString()); - } - return message; - } - - /** - * Get a message set for a specific node - * - * @param node the node to get - * @param defaultValue the default value given that a value for the node was not found - * @return the message for the specified node. Default if none found - */ - public String getMessageOrDefault(String node, String defaultValue) { - return this.nodes.getOrDefault(node, defaultValue); - } - - /** - * Clear the previous message cache and load new messages directly from file - * - * @return reload messages from file - */ - public boolean reloadMessages() { - if (!this.file.exists()) { - plugin.getLogger().warning("Could not find file for locale " + this.name); - return false; - } - - this.nodes.clear(); // Clear previous data (if any) - - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - String line; - for (int lineNumber = 0; (line = reader.readLine()) != null; lineNumber++) { - if (line.isEmpty() || line.startsWith("#") /* Comment */) continue; - - Matcher matcher = NODE_PATTERN.matcher(line); - if (!matcher.find()) { - System.err.println("Invalid locale syntax at (line=" + lineNumber + ")"); - continue; - } - - nodes.put(matcher.group(1), matcher.group(2)); - } - } catch (IOException e) { - e.printStackTrace(); - return false; - } - return true; - } - - /** - * Get the file that represents this locale - * - * @return the locale file (.lang) - */ - public File getFile() { - return file; - } - - /** - * Return the entire locale tag (i.e. "en_US") - * - * @return the language tag - */ - public String getLanguageTag() { - return name + "_" + region; - } - - /** - * Get an immutable list of all currently loaded locales - * - * @return list of all locales - */ - public static List getLocales() { - return ImmutableList.copyOf(LOCALES); - } - - /** - * Get the key-value map of nodes to messages - * - * @return node-message map - */ - public Map getMessageNodeMap() { - return ImmutableMap.copyOf(nodes); - } - - /** - * Get the name of the language that this locale is based on. - * (i.e. "en" for English, or "fr" for French) - * - * @return the name of the language - */ - public String getName() { - return name; - } - - public String getPrefix() { - return getMessage("general.nametag.prefix") + " "; - } - - /** - * Get the name of the region that this locale is from. - * (i.e. "US" for United States or "CA" for Canada) - * - * @return the name of the region - */ - public String getRegion() { - return region; - } -} \ No newline at end of file diff --git a/core/src/main/java/com/songoda/epicenchants/commands/EnchantCommand.java b/core/src/main/java/com/songoda/epicenchants/commands/EnchantCommand.java index 025f395..f7500da 100644 --- a/core/src/main/java/com/songoda/epicenchants/commands/EnchantCommand.java +++ b/core/src/main/java/com/songoda/epicenchants/commands/EnchantCommand.java @@ -1,22 +1,22 @@ package com.songoda.epicenchants.commands; import co.aikar.commands.BaseCommand; +import co.aikar.commands.CommandHelp; import co.aikar.commands.annotation.*; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.enums.EnchantResult; import com.songoda.epicenchants.menus.EnchanterMenu; +import com.songoda.epicenchants.menus.TinkererMenu; import com.songoda.epicenchants.objects.Enchant; +import com.songoda.epicenchants.objects.Group; import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.io.File; - import static com.songoda.epicenchants.enums.EnchantResult.BROKEN_FAILURE; import static com.songoda.epicenchants.objects.Placeholder.of; -import static com.songoda.epicenchants.utils.GeneralUtils.getMessageFromResult; +import static com.songoda.epicenchants.utils.single.GeneralUtils.getMessageFromResult; @CommandAlias("epicenchants|ee") public class EnchantCommand extends BaseCommand { @@ -24,38 +24,55 @@ public class EnchantCommand extends BaseCommand { @Dependency("instance") private EpicEnchants instance; - @Default - @Subcommand("enchanter") + @Subcommand("%enchanter") @Description("Opens the Enchanter") - public void onGui(Player player) { + @CommandPermission("epicenchants.enchanter") + public void onEnchanter(Player player) { new EnchanterMenu(instance, instance.getFileManager().getConfiguration("menus/enchanter-menu"), player).open(player); } - //ee give book {player} {enchant} {group} + @Subcommand("%tinkerer") + @Description("Opens the Tinkerer") + @CommandPermission("epicenchants.tinkerer") + public void onTinkerer(Player player) { + new TinkererMenu(instance, instance.getFileManager().getConfiguration("menus/tinkerer-menu")).open(player); + } + + //ee give book [player] [enchant] @Subcommand("give book") @CommandCompletion("@players @enchants @levels @increment @increment") @Description("Give enchant books to players") - @CommandPermission("epicenchants.give") + @CommandPermission("epicenchants.give.book") public void onGiveBook(CommandSender sender, @Flags("other") Player target, Enchant enchant, @Optional Integer level, @Optional Integer successRate, @Optional Integer destroyRate) { if (level != null && level > enchant.getMaxLevel()) { - sender.sendMessage(instance.getLocale().getMessageWithPrefix("command.book.maxlevel", + instance.getAction().perform(sender, "command.book.max-level", of("enchant", enchant.getIdentifier()), - of("max-level", enchant.getMaxLevel()))); + of("max-level", enchant.getMaxLevel())); return; } - target.getInventory().addItem(enchant.getBookItem().get(enchant, level, successRate, destroyRate)); - target.sendMessage(instance.getLocale().getMessageWithPrefix("command.book.received", of("enchant", enchant.getIdentifier()))); - sender.sendMessage(instance.getLocale().getMessageWithPrefix("command.book.gave", of("player", target.getName()), of("enchant", enchant.getIdentifier()))); + + target.getInventory().addItem(enchant.getBook().get(enchant, level, successRate, destroyRate)); + instance.getAction().perform(target, "command.book.received", of("enchant", enchant.getIdentifier())); + instance.getAction().perform(sender, "command.book.gave", of("player", target.getName()), of("enchant", enchant.getIdentifier())); } - //ee give item {player} {giveType} {group} + //ee give item dust [player] [group] + @Subcommand("give item dust") + @CommandCompletion("@players @groups @dustTypes @nothing") + @CommandPermission("epicenchants.give.item.dust") + public void onGiveDust(CommandSender sender, @Flags("other") Player target, Group group, @Optional String dustType, @Optional Integer percentage) { + target.getInventory().addItem(instance.getSpecialItems().getDust(group, dustType, percentage)); + instance.getAction().perform(target, "command.dust.received", of("group", group.getIdentifier())); + instance.getAction().perform(sender, "command.dust.gave", of("player", target.getName()), of("group", group.getIdentifier())); + } + + //ee give item [giveType] [player] @Subcommand("give item") @CommandCompletion("@players @giveType @nothing @nothing") @Description("Give enchant books to players") - @CommandPermission("epicenchants.give") + @CommandPermission("epicenchants.give.item") public void onGiveItem(CommandSender sender, @Flags("other") Player target, String giveType, @Optional Integer amount, @Optional Integer successRate) { String messageKey; - switch (giveType.toLowerCase()) { case "whitescroll": target.getInventory().addItem(instance.getSpecialItems().getWhiteScroll(amount)); @@ -69,23 +86,28 @@ public class EnchantCommand extends BaseCommand { return; } - target.sendMessage(instance.getLocale().getMessageWithPrefix("command." + messageKey + ".received")); - sender.sendMessage(instance.getLocale().getMessageWithPrefix("command." + messageKey + ".gave", of("player", target.getName()))); + instance.getAction().perform(target, "command." + messageKey + ".received"); + instance.getAction().perform(sender, "command." + messageKey + ".gave", of("player", target.getName())); } - //ee apply {enchant} {group} + //ee apply [enchant] [level] @Subcommand("apply") @CommandCompletion("@enchants @nothing") @Description("Apply enchant to item in hand") @CommandPermission("epicenchants.apply") public void onApply(Player player, Enchant enchant, int level, @Optional Integer successRate, @Optional Integer destroyRate) { + if (player.getItemInHand() == null) { + instance.getAction().perform(player, "command.apply.noitem", of("enchant", enchant.getIdentifier())); + return; + } + int slot = player.getInventory().getHeldItemSlot(); ItemStack before = player.getItemInHand(); Pair result = instance.getEnchantUtils().apply(before, enchant, level, successRate == null ? 100 : successRate, destroyRate == null ? 0 : destroyRate); - player.sendMessage(instance.getLocale().getMessageWithPrefix(getMessageFromResult(result.getRight()), of("enchant", enchant.getIdentifier()))); + instance.getAction().perform(player, getMessageFromResult(result.getRight()), of("enchant", enchant.getIdentifier())); if (result.getRight() == BROKEN_FAILURE) { player.getInventory().clear(slot); @@ -105,27 +127,16 @@ public class EnchantCommand extends BaseCommand { //ee reload [enchantFileName] @Subcommand("reload") - @CommandAlias("load") - @Description("Reload all config files, or reload/load specific enchant files") + @Description("Reload all config files.") @CommandCompletion("@enchantFiles") @CommandPermission("epicenchants.reload") - public void onReload(CommandSender sender, @Optional File fileName) { - if (fileName == null) { - instance.reload(); - sender.sendMessage(instance.getLocale().getMessageWithPrefix("command.reload")); - return; - } - - try { - instance.getEnchantManager().loadEnchant(fileName); - } catch (Exception e) { - sender.sendMessage(instance.getLocale().getMessageWithPrefix("command.filereload.failed", of("file-name", fileName.getName()))); - Bukkit.getConsoleSender().sendMessage("Something went wrong loading the enchant from file " + fileName.getName()); - Bukkit.getConsoleSender().sendMessage("Please check to make sure there are no errors in the file."); - e.printStackTrace(); - return; - } - sender.sendMessage(instance.getLocale().getMessageWithPrefix("command.filereload.success", of("file-name", fileName.getName()))); + public void onReload(CommandSender sender) { + instance.reload(); + instance.getAction().perform(sender, "command.reload"); + } + @HelpCommand + public void doHelp(CommandSender sender, CommandHelp help) { + help.showHelp(); } } diff --git a/core/src/main/java/com/songoda/epicenchants/effect/EffectExecutor.java b/core/src/main/java/com/songoda/epicenchants/effect/EffectExecutor.java index 56f6cde..12948ac 100644 --- a/core/src/main/java/com/songoda/epicenchants/effect/EffectExecutor.java +++ b/core/src/main/java/com/songoda/epicenchants/effect/EffectExecutor.java @@ -3,7 +3,7 @@ package com.songoda.epicenchants.effect; import com.songoda.epicenchants.enums.EventType; import com.songoda.epicenchants.enums.TriggerType; import com.songoda.epicenchants.objects.LeveledModifier; -import com.songoda.epicenchants.utils.GeneralUtils; +import com.songoda.epicenchants.utils.single.GeneralUtils; import lombok.Getter; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.LivingEntity; @@ -12,21 +12,17 @@ import org.bukkit.event.Event; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; import java.util.function.Consumer; -import static com.songoda.epicenchants.effect.EffectExecutor.Who.OPPONENT; -import static com.songoda.epicenchants.effect.EffectExecutor.Who.WEARER; +import static com.songoda.epicenchants.effect.EffectExecutor.Who.*; public abstract class EffectExecutor { @Getter private final ConfigurationSection section; @Getter private final TriggerType triggerType; - private TriggerType[] allowedEffects; - public EffectExecutor(ConfigurationSection section, TriggerType... allowedEffects) { + public EffectExecutor(ConfigurationSection section) { this.section = section; this.triggerType = TriggerType.valueOf(section.getString("trigger")); - this.allowedEffects = allowedEffects; } public void testAndRun(@NotNull Player wearer, @Nullable LivingEntity opponent, int level, TriggerType type, Event event, EventType eventType) { @@ -34,10 +30,6 @@ public abstract class EffectExecutor { return; } - if (allowedEffects.length != 0 && Arrays.stream(allowedEffects).noneMatch(t -> t == triggerType)) { - throw new IllegalStateException(section.getName() + " cannot be triggered by " + triggerType.toString()); - } - if (section.isString("chance") && !GeneralUtils.chance(LeveledModifier.of(section.getString("chance")).get(level, 100))) { return; } diff --git a/core/src/main/java/com/songoda/epicenchants/effect/effects/DropItem.java b/core/src/main/java/com/songoda/epicenchants/effect/effects/DropItem.java new file mode 100644 index 0000000..ec688bd --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/effect/effects/DropItem.java @@ -0,0 +1,22 @@ +package com.songoda.epicenchants.effect.effects; + +import com.songoda.epicenchants.effect.EffectExecutor; +import com.songoda.epicenchants.enums.EventType; +import com.songoda.epicenchants.utils.objects.ItemBuilder; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class DropItem extends EffectExecutor { + public DropItem(ConfigurationSection section) { + super(section); + } + + @Override + public void execute(@NotNull Player wearer, @Nullable LivingEntity opponent, int level, EventType eventType) { + consume(entity -> entity.getLocation().getWorld().dropItemNaturally(entity.getLocation(), + new ItemBuilder(getSection(), ((Player) entity)).build()), wearer, opponent); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/effect/effects/Fly.java b/core/src/main/java/com/songoda/epicenchants/effect/effects/Fly.java index 8f58b90..1eb3983 100644 --- a/core/src/main/java/com/songoda/epicenchants/effect/effects/Fly.java +++ b/core/src/main/java/com/songoda/epicenchants/effect/effects/Fly.java @@ -8,12 +8,10 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import static com.songoda.epicenchants.enums.EventType.ON; -import static com.songoda.epicenchants.enums.TriggerType.HELD_ITEM; -import static com.songoda.epicenchants.enums.TriggerType.STATIC_EFFECT; public class Fly extends EffectExecutor { public Fly(ConfigurationSection section) { - super(section, STATIC_EFFECT, HELD_ITEM); + super(section); } @Override diff --git a/core/src/main/java/com/songoda/epicenchants/effect/effects/Message.java b/core/src/main/java/com/songoda/epicenchants/effect/effects/Message.java index 9bd505a..283423f 100644 --- a/core/src/main/java/com/songoda/epicenchants/effect/effects/Message.java +++ b/core/src/main/java/com/songoda/epicenchants/effect/effects/Message.java @@ -7,7 +7,7 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import static com.songoda.epicenchants.utils.GeneralUtils.color; +import static com.songoda.epicenchants.utils.single.GeneralUtils.color; public class Message extends EffectExecutor { public Message(ConfigurationSection section) { diff --git a/core/src/main/java/com/songoda/epicenchants/effect/effects/ModifyExp.java b/core/src/main/java/com/songoda/epicenchants/effect/effects/ModifyExp.java index e13e069..a472c9d 100644 --- a/core/src/main/java/com/songoda/epicenchants/effect/effects/ModifyExp.java +++ b/core/src/main/java/com/songoda/epicenchants/effect/effects/ModifyExp.java @@ -2,7 +2,8 @@ package com.songoda.epicenchants.effect.effects; import com.songoda.epicenchants.effect.EffectExecutor; import com.songoda.epicenchants.enums.EventType; -import com.songoda.epicenchants.utils.Experience; +import com.songoda.epicenchants.objects.LeveledModifier; +import com.songoda.epicenchants.utils.single.Experience; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -18,7 +19,12 @@ public class ModifyExp extends EffectExecutor { public void execute(@NotNull Player wearer, @Nullable LivingEntity opponent, int level, EventType eventType) { consume(entity -> { if (entity instanceof Player) { - Experience.changeExp(((Player) entity), (int) getAmount().get(level, 0)); + Player player = (Player) entity; + if (getSection().getString("amount").endsWith("L")) { + player.setLevel((int) (player.getLevel() + LeveledModifier.of(getSection().getString("amount").replace("L", "")).get(level, 0))); + } else { + Experience.changeExp(player, (int) getAmount().get(level, 0)); + } } }, wearer, opponent); } diff --git a/core/src/main/java/com/songoda/epicenchants/effect/effects/StealExp.java b/core/src/main/java/com/songoda/epicenchants/effect/effects/StealExp.java new file mode 100644 index 0000000..db29ef1 --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/effect/effects/StealExp.java @@ -0,0 +1,41 @@ +package com.songoda.epicenchants.effect.effects; + +import com.songoda.epicenchants.effect.EffectExecutor; +import com.songoda.epicenchants.enums.EventType; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.songoda.epicenchants.utils.single.Experience.*; + +public class StealExp extends EffectExecutor { + public StealExp(ConfigurationSection section) { + super(section); + } + + @Override + public void execute(@NotNull Player wearer, @Nullable LivingEntity entity, int level, EventType eventType) { + double amount = getAmount().get(level, 0); + + if (!(entity instanceof Player)) { + return; + } + + Player opponent = (Player) entity; + + + if (getExp(opponent) - amount <= 0) { + changeExp(opponent, 0); + } else { + changeExp(opponent, (int) -amount); + } + + if (getExp(wearer) + amount <= 0) { + changeExp(wearer, 0); + } else { + changeExp(wearer, (int) amount); + } + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/effect/effects/Throw.java b/core/src/main/java/com/songoda/epicenchants/effect/effects/Throw.java index 9c32143..4a7da32 100644 --- a/core/src/main/java/com/songoda/epicenchants/effect/effects/Throw.java +++ b/core/src/main/java/com/songoda/epicenchants/effect/effects/Throw.java @@ -47,7 +47,8 @@ public class Throw extends EffectExecutor { vector = new Vector(); } - if (vector.length() != 0) + if (vector.length() != 0) { livingEntity.setVelocity(vector); + } } } diff --git a/core/src/main/java/com/songoda/epicenchants/effect/effects/Tnt.java b/core/src/main/java/com/songoda/epicenchants/effect/effects/Tnt.java index 4b49c40..df6edb1 100644 --- a/core/src/main/java/com/songoda/epicenchants/effect/effects/Tnt.java +++ b/core/src/main/java/com/songoda/epicenchants/effect/effects/Tnt.java @@ -2,10 +2,9 @@ package com.songoda.epicenchants.effect.effects; import com.songoda.epicenchants.effect.EffectExecutor; import com.songoda.epicenchants.enums.EventType; +import com.songoda.epicenchants.objects.LeveledModifier; import org.bukkit.configuration.ConfigurationSection; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; +import org.bukkit.entity.*; import org.jetbrains.annotations.NotNull; public class Tnt extends EffectExecutor { @@ -15,6 +14,11 @@ public class Tnt extends EffectExecutor { @Override public void execute(@NotNull Player wearer, LivingEntity opponent, int level, EventType eventType) { - consume(player -> player.getWorld().spawnEntity(player.getLocation(), EntityType.PRIMED_TNT), wearer, opponent); + consume(player -> { + for (int i = 0; i < LeveledModifier.of(getSection().getString("amount")).get(level, 1); i++) { + TNTPrimed tntPrimed = (TNTPrimed) player.getWorld().spawnEntity(player.getLocation(), EntityType.PRIMED_TNT); + tntPrimed.setFuseTicks((int) LeveledModifier.of(getSection().getString("fuse")).get(level, 60)); + } + }, wearer, opponent); } } diff --git a/core/src/main/java/com/songoda/epicenchants/enums/EnchantResult.java b/core/src/main/java/com/songoda/epicenchants/enums/EnchantResult.java index 8a7820a..002a9c2 100644 --- a/core/src/main/java/com/songoda/epicenchants/enums/EnchantResult.java +++ b/core/src/main/java/com/songoda/epicenchants/enums/EnchantResult.java @@ -1,5 +1,5 @@ package com.songoda.epicenchants.enums; public enum EnchantResult { - SUCCESS, FAILURE, BROKEN_FAILURE, CONFLICT, MAXED_OUT, ALREADY_APPLIED + SUCCESS, FAILURE, BROKEN_FAILURE, CONFLICT, MAXED_OUT, ALREADY_APPLIED, PROTECTED } diff --git a/core/src/main/java/com/songoda/epicenchants/enums/GiveType.java b/core/src/main/java/com/songoda/epicenchants/enums/GiveType.java index b3631bc..e51c094 100644 --- a/core/src/main/java/com/songoda/epicenchants/enums/GiveType.java +++ b/core/src/main/java/com/songoda/epicenchants/enums/GiveType.java @@ -1,5 +1,5 @@ package com.songoda.epicenchants.enums; public enum GiveType { - WHITE_SCROLL, BLACK_SCROLL + WHITE_SCROLL, BLACK_SCROLL, DUST } diff --git a/core/src/main/java/com/songoda/epicenchants/enums/ItemType.java b/core/src/main/java/com/songoda/epicenchants/enums/ItemType.java new file mode 100644 index 0000000..52adccb --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/enums/ItemType.java @@ -0,0 +1,5 @@ +package com.songoda.epicenchants.enums; + +public enum ItemType { + BOOK, ENCHANTED, NONE +} diff --git a/core/src/main/java/com/songoda/epicenchants/enums/TriggerType.java b/core/src/main/java/com/songoda/epicenchants/enums/TriggerType.java index f07e5bc..a509a77 100644 --- a/core/src/main/java/com/songoda/epicenchants/enums/TriggerType.java +++ b/core/src/main/java/com/songoda/epicenchants/enums/TriggerType.java @@ -20,6 +20,7 @@ public enum TriggerType { EXPLOSION_DAMAGE, FALL_DAMAGE, FIRE_DAMAGE, + POISON_DAMAGE, HELD_ITEM, STATIC_EFFECT, diff --git a/core/src/main/java/com/songoda/epicenchants/hooks/FactionsHook.java b/core/src/main/java/com/songoda/epicenchants/hooks/FactionsHook.java new file mode 100644 index 0000000..be08360 --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/hooks/FactionsHook.java @@ -0,0 +1,9 @@ +package com.songoda.epicenchants.hooks; + +import org.bukkit.entity.Player; + +public interface FactionsHook { + String getRelationToLocation(Player player); + + boolean isFriendly(Player player, Player other); +} diff --git a/core/src/main/java/com/songoda/epicenchants/hooks/HookManager.java b/core/src/main/java/com/songoda/epicenchants/hooks/HookManager.java new file mode 100644 index 0000000..5a43f46 --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/hooks/HookManager.java @@ -0,0 +1,21 @@ +package com.songoda.epicenchants.hooks; + +import com.songoda.ultimatebottles.UltimateBottles; +import lombok.Getter; +import org.bukkit.Bukkit; + +import java.util.Optional; + +@Getter +public class HookManager { + private FactionsHook factionsHook; + private UltimateBottles ultimateBottles; + + public void setup() { + ultimateBottles = Bukkit.getPluginManager().isPluginEnabled("UltimateBottles") ? (UltimateBottles) Bukkit.getPluginManager().getPlugin("UltimateBottles") : null; + } + + public Optional getUltimateBottles() { + return Optional.ofNullable(ultimateBottles); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/listeners/BlackScrollListener.java b/core/src/main/java/com/songoda/epicenchants/listeners/BlackScrollListener.java deleted file mode 100644 index 9a4bdcc..0000000 --- a/core/src/main/java/com/songoda/epicenchants/listeners/BlackScrollListener.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.songoda.epicenchants.listeners; - -import com.songoda.epicenchants.EpicEnchants; -import de.tr7zw.itemnbtapi.NBTItem; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.inventory.InventoryAction; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryType; -import org.jetbrains.annotations.Nullable; - -public class BlackScrollListener { - private final EpicEnchants instance; - - public BlackScrollListener(EpicEnchants instance) { - this.instance = instance; - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onInventoryClick(InventoryClickEvent event) { - if (event.getCursor() == null || event.getCurrentItem() == null || event.getAction() != InventoryAction.SWAP_WITH_CURSOR || event.getClickedInventory().getType() == InventoryType.CREATIVE) { - return; - } - - @Nullable NBTItem nbtItem = new NBTItem(event.getCursor()); - NBTItem toApplyTo = new NBTItem(event.getCurrentItem()); - - if (nbtItem == null) { - return; - } - - if (!nbtItem.getBoolean("black-scroll")) { - return; - } - - if (toApplyTo.getCompound("enchants") == null || toApplyTo.getCompound("enchants").getKeys().isEmpty()) { - event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix("blackscroll.noenchants")); - return; - } - - //TODO: Blackscroll - - event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix("blackscroll.success")); - } -} diff --git a/core/src/main/java/com/songoda/epicenchants/listeners/BookListener.java b/core/src/main/java/com/songoda/epicenchants/listeners/BookListener.java deleted file mode 100644 index 1877cdd..0000000 --- a/core/src/main/java/com/songoda/epicenchants/listeners/BookListener.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.songoda.epicenchants.listeners; - -import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.enums.EnchantResult; -import com.songoda.epicenchants.events.EnchantApplyEvent; -import com.songoda.epicenchants.objects.Enchant; -import com.songoda.epicenchants.utils.GeneralUtils; -import de.tr7zw.itemnbtapi.NBTItem; -import org.apache.commons.lang3.tuple.Pair; -import org.bukkit.Bukkit; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryAction; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Nullable; - -import static com.songoda.epicenchants.enums.EnchantResult.*; -import static com.songoda.epicenchants.objects.Placeholder.of; - -public class BookListener implements Listener { - private final EpicEnchants instance; - - public BookListener(EpicEnchants instance) { - this.instance = instance; - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onInventoryClick(InventoryClickEvent event) { - if (event.getCursor() == null || event.getCurrentItem() == null || event.getAction() != InventoryAction.SWAP_WITH_CURSOR || event.getClickedInventory().getType() == InventoryType.CREATIVE) { - return; - } - - @Nullable NBTItem nbtItem = new NBTItem(event.getCursor()); - ItemStack toApplyTo = event.getCurrentItem(); - - if (nbtItem == null) { - return; - } - - if (!nbtItem.getBoolean("book-item")) { - return; - } - - Enchant enchant = instance.getEnchantManager().getEnchant(nbtItem.getString("enchant")).orElseThrow(() -> new IllegalStateException("Book without enchant!")); - - if (!enchant.getItemWhitelist().contains(toApplyTo.getType())) { - event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix("enchant.invalidmaterial", of("enchant", enchant.getIdentifier()))); - return; - } - - int level = nbtItem.getInteger("level"); - int successRate = nbtItem.getInteger("success-rate"); - int destroyRate = nbtItem.getInteger("destroy-rate"); - - EnchantApplyEvent enchantEvent = new EnchantApplyEvent(toApplyTo, enchant, level, successRate, destroyRate); - Bukkit.getPluginManager().callEvent(enchantEvent); - - if (enchantEvent.isCancelled()) { - return; - } - - Pair result = instance.getEnchantUtils().apply(toApplyTo, enchant, enchantEvent.getLevel(), enchantEvent.getSuccessRate(), enchantEvent.getDestroyRate()); - - event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix(GeneralUtils.getMessageFromResult(result.getRight()), - of("enchant", enchant.getIdentifier()))); - event.setCancelled(true); - - if (result.getRight() == BROKEN_FAILURE) { - event.getClickedInventory().clear(event.getSlot()); - } - - if (result.getRight() != CONFLICT && result.getRight() != MAXED_OUT && result.getRight() != ALREADY_APPLIED) { - if (event.getCursor().getAmount() > 1) { - ItemStack toSet = event.getCursor(); - toSet.setAmount(toSet.getAmount() - 1); - event.getWhoClicked().setItemOnCursor(toSet); - } else { - event.getWhoClicked().setItemOnCursor(null); - } - } - - event.getClickedInventory().setItem(event.getSlot(), result.getLeft()); - - } -} diff --git a/core/src/main/java/com/songoda/epicenchants/listeners/EntityListener.java b/core/src/main/java/com/songoda/epicenchants/listeners/EntityListener.java index 5c57a09..fb6c91a 100644 --- a/core/src/main/java/com/songoda/epicenchants/listeners/EntityListener.java +++ b/core/src/main/java/com/songoda/epicenchants/listeners/EntityListener.java @@ -3,17 +3,11 @@ package com.songoda.epicenchants.listeners; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.enums.TriggerType; import de.tr7zw.itemnbtapi.NBTEntity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Monster; -import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; +import org.bukkit.entity.*; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.event.entity.*; import org.bukkit.projectiles.ProjectileSource; import static com.songoda.epicenchants.enums.TriggerType.*; @@ -110,6 +104,9 @@ public class EntityListener implements Listener { case ENTITY_EXPLOSION: instance.getEnchantUtils().handlePlayer(((Player) event.getEntity()), null, event, EXPLOSION_DAMAGE); break; + case POISON: + instance.getEnchantUtils().handlePlayer(((Player) event.getEntity()), null, event, POISON_DAMAGE); + break; } } diff --git a/core/src/main/java/com/songoda/epicenchants/listeners/WhiteScrollListener.java b/core/src/main/java/com/songoda/epicenchants/listeners/WhiteScrollListener.java deleted file mode 100644 index 55be3a2..0000000 --- a/core/src/main/java/com/songoda/epicenchants/listeners/WhiteScrollListener.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.songoda.epicenchants.listeners; - -import com.songoda.epicenchants.EpicEnchants; -import de.tr7zw.itemnbtapi.NBTItem; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryAction; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryType; - -public class WhiteScrollListener implements Listener { - private final EpicEnchants instance; - - public WhiteScrollListener(EpicEnchants instance) { - this.instance = instance; - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onInventoryClick(InventoryClickEvent event) { - if (event.getCursor() == null || event.getCurrentItem() == null || event.getAction() != InventoryAction.SWAP_WITH_CURSOR || event.getClickedInventory().getType() == InventoryType.CREATIVE) { - return; - } - - NBTItem nbtItem = new NBTItem(event.getCursor()); - NBTItem toApplyTo = new NBTItem(event.getCurrentItem()); - - if (nbtItem == null) { - return; - } - - if (!nbtItem.getBoolean("white-scroll")) { - return; - } - - if (toApplyTo.hasKey("protected")) { - event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix("whitescroll.alreadyapplied")); - return; - } - - toApplyTo.setBoolean("protected", true); - event.getWhoClicked().sendMessage(instance.getLocale().getMessageWithPrefix("whitescroll.applied")); - - //TODO: add lore - - event.getWhoClicked().setItemOnCursor(null); - event.getClickedInventory().setItem(event.getSlot(), toApplyTo.getItem()); - } -} diff --git a/core/src/main/java/com/songoda/epicenchants/listeners/item/BlackScrollListener.java b/core/src/main/java/com/songoda/epicenchants/listeners/item/BlackScrollListener.java new file mode 100644 index 0000000..671dcce --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/listeners/item/BlackScrollListener.java @@ -0,0 +1,42 @@ +package com.songoda.epicenchants.listeners.item; + +import com.songoda.epicenchants.EpicEnchants; +import com.songoda.epicenchants.objects.Enchant; +import de.tr7zw.itemnbtapi.NBTCompound; +import de.tr7zw.itemnbtapi.NBTItem; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +import static com.songoda.epicenchants.utils.single.GeneralUtils.getRandomElement; + +public class BlackScrollListener extends ItemListener { + public BlackScrollListener(EpicEnchants instance) { + super(instance); + } + + @Override + void onApply(InventoryClickEvent event, NBTItem cursor, NBTItem current) { + if (!cursor.hasKey("black-scroll") || !cursor.getBoolean("black-scroll")) { + return; + } + + event.setCancelled(true); + NBTCompound compound = current.getCompound("enchants"); + + if (compound == null || compound.getKeys().isEmpty()) { + instance.getAction().perform(event.getWhoClicked(), "blackscroll.noenchants"); + return; + } + + String id = getRandomElement(compound.getKeys()); + int level = compound.getInteger(id); + Enchant enchant = instance.getEnchantManager().getValueUnsafe(id); + ItemStack toSet = instance.getEnchantUtils().removeEnchant(event.getCurrentItem(), enchant); + + event.getWhoClicked().getInventory().addItem(enchant.getBook().get(enchant, level, cursor.getInteger("success-rate"), 100)); + event.setCurrentItem(toSet); + + instance.getAction().perform(event.getWhoClicked(), "blackscroll.success"); + useItem(event); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/listeners/item/BookListener.java b/core/src/main/java/com/songoda/epicenchants/listeners/item/BookListener.java new file mode 100644 index 0000000..68a9e99 --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/listeners/item/BookListener.java @@ -0,0 +1,91 @@ +package com.songoda.epicenchants.listeners.item; + +import com.songoda.epicenchants.EpicEnchants; +import com.songoda.epicenchants.enums.EnchantResult; +import com.songoda.epicenchants.events.EnchantApplyEvent; +import com.songoda.epicenchants.objects.Enchant; +import com.songoda.epicenchants.objects.Group; +import com.songoda.epicenchants.utils.single.GeneralUtils; +import de.tr7zw.itemnbtapi.NBTItem; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.Bukkit; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.Optional; + +import static com.songoda.epicenchants.enums.EnchantResult.*; +import static com.songoda.epicenchants.objects.Placeholder.of; + +public class BookListener extends ItemListener { + public BookListener(EpicEnchants instance) { + super(instance); + } + + @Override + void onApply(InventoryClickEvent event, NBTItem cursor, NBTItem current) { + if (!cursor.hasKey("book-item") || !cursor.getBoolean("book-item")) { + return; + } + + event.setCancelled(true); + + ItemStack toApply = event.getCurrentItem(); + Enchant enchant = instance.getEnchantManager().getValue(cursor.getString("enchant")).orElseThrow(() -> new IllegalStateException("Book without enchant!")); + + if (!enchant.getItemWhitelist().contains(current.getItem().getType())) { + return; + } + + int level = cursor.getInteger("level"); + int successRate = cursor.getInteger("success-rate"); + int destroyRate = cursor.getInteger("destroy-rate"); + + EnchantApplyEvent enchantEvent = new EnchantApplyEvent(toApply, enchant, level, successRate, destroyRate); + Bukkit.getPluginManager().callEvent(enchantEvent); + + if (enchantEvent.isCancelled()) { + return; + } + + Pair result = instance.getEnchantUtils().apply(toApply, enchant, enchantEvent.getLevel(), enchantEvent.getSuccessRate(), enchantEvent.getDestroyRate()); + + instance.getAction().perform(event.getWhoClicked(), GeneralUtils.getMessageFromResult(result.getRight()), + of("enchant", enchant.getIdentifier())); + + if (result.getRight() == BROKEN_FAILURE) { + event.getClickedInventory().clear(event.getSlot()); + } + + if (result.getRight() != CONFLICT && result.getRight() != MAXED_OUT && result.getRight() != ALREADY_APPLIED) { + useItem(event); + } + + event.getClickedInventory().setItem(event.getSlot(), result.getLeft()); + } + + @Override + void onClick(PlayerInteractEvent event, NBTItem clicked) { + if (!clicked.hasKey("mystery-book") || !clicked.getBoolean("mystery-book")) { + return; + } + + event.setCancelled(true); + + if (event.getPlayer().getInventory().firstEmpty() == -1) { + return; + } + + Group group = instance.getGroupManager().getValueUnsafe(clicked.getString("group")); + Optional enchant = instance.getEnchantManager().getRandomEnchant(group); + + if (!enchant.isPresent()) { + instance.getAction().perform(event.getPlayer(), "event.purchase.noenchant"); + return; + } + + useItem(event); + event.getPlayer().getInventory().addItem(enchant.get().getBook().get(enchant.get())); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/listeners/item/DustListener.java b/core/src/main/java/com/songoda/epicenchants/listeners/item/DustListener.java new file mode 100644 index 0000000..b5f380d --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/listeners/item/DustListener.java @@ -0,0 +1,65 @@ +package com.songoda.epicenchants.listeners.item; + +import com.songoda.epicenchants.EpicEnchants; +import com.songoda.epicenchants.objects.Enchant; +import com.songoda.epicenchants.objects.Group; +import de.tr7zw.itemnbtapi.NBTItem; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; + +import java.util.concurrent.ThreadLocalRandom; + +public class DustListener extends ItemListener { + public DustListener(EpicEnchants instance) { + super(instance); + } + + @Override + void onApply(InventoryClickEvent event, NBTItem cursor, NBTItem current) { + if (!cursor.hasKey("dust") || !cursor.getBoolean("dust")) { + return; + } + + if (!current.hasKey("book-item") || !current.getBoolean("book-item")) { + return; + } + + Enchant enchant = instance.getEnchantManager().getValue(current.getString("enchant")).orElseThrow(() -> new IllegalStateException("Book without enchant!")); + + if (!enchant.getGroup().equals(instance.getGroupManager().getValue(cursor.getString("group")).orElseThrow(() -> new IllegalStateException("Dust without group!")))) { + return; + } + + int successRate = current.getInteger("success-rate"); + + if (successRate == 100) { + return; + } + + successRate = successRate + cursor.getInteger("percentage") > 100 ? 100 : successRate + cursor.getInteger("percentage"); + + event.setCurrentItem(enchant.getBook().get(enchant, current.getInteger("level"), successRate, current.getInteger("destroy-rate"))); + + event.setCancelled(true); + useItem(event); + } + + @Override + void onClick(PlayerInteractEvent event, NBTItem clicked) { + if (!clicked.hasKey("secret-dust") || !clicked.getBoolean("secret-dust")) { + return; + } + + event.setCancelled(true); + + if (event.getPlayer().getInventory().firstEmpty() == -1) { + return; + } + + Group group = instance.getGroupManager().getValueUnsafe(clicked.getString("group")); + int rate = ThreadLocalRandom.current().nextInt(clicked.getInteger("min-rate"), clicked.getInteger("max-rate")); + + useItem(event); + event.getPlayer().getInventory().addItem(instance.getSpecialItems().getDust(group, null, rate)); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/listeners/item/ItemListener.java b/core/src/main/java/com/songoda/epicenchants/listeners/item/ItemListener.java new file mode 100644 index 0000000..bc24eef --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/listeners/item/ItemListener.java @@ -0,0 +1,78 @@ +package com.songoda.epicenchants.listeners.item; + +import com.songoda.epicenchants.EpicEnchants; +import de.tr7zw.itemnbtapi.NBTItem; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryAction; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; + +public abstract class ItemListener implements Listener { + final EpicEnchants instance; + + ItemListener(EpicEnchants instance) { + this.instance = instance; + } + + abstract void onApply(InventoryClickEvent event, NBTItem cursor, NBTItem current); + + void onClick(PlayerInteractEvent event, NBTItem clicked) { + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onInventoryClick(InventoryClickEvent event) { + if (event.getCursor() == null || event.getCurrentItem() == null || event.getAction() != InventoryAction.SWAP_WITH_CURSOR) { + return; + } + + onApply(event, new NBTItem(event.getCursor()), new NBTItem(event.getCurrentItem())); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_AIR) { + return; + } + + if (event.getItem() == null || event.getItem().getType() == Material.AIR) { + return; + } + + onClick(event, new NBTItem(event.getItem())); + } + + void useItem(InventoryClickEvent event) { + if (event.getCursor().getAmount() > 1) { + ItemStack cursor = event.getCursor(); + cursor.setAmount(cursor.getAmount() - 1); + event.getWhoClicked().setItemOnCursor(cursor); + return; + } + + event.getWhoClicked().setItemOnCursor(null); + } + + void useItem(PlayerInteractEvent event) { + int slot = event.getPlayer().getInventory().getHeldItemSlot(); + + try { + if (event.getHand() == EquipmentSlot.OFF_HAND) slot = 40; + } catch (Exception ignore) { + } + + if (event.getItem().getAmount() > 1) { + ItemStack item = event.getItem(); + item.setAmount(item.getAmount() - 1); + event.getPlayer().getInventory().setItem(slot, item); + return; + } + + event.getPlayer().getInventory().clear(slot); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/listeners/item/WhiteScrollListener.java b/core/src/main/java/com/songoda/epicenchants/listeners/item/WhiteScrollListener.java new file mode 100644 index 0000000..8e4c87f --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/listeners/item/WhiteScrollListener.java @@ -0,0 +1,36 @@ +package com.songoda.epicenchants.listeners.item; + +import com.songoda.epicenchants.EpicEnchants; +import com.songoda.epicenchants.utils.objects.ItemBuilder; +import de.tr7zw.itemnbtapi.NBTItem; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class WhiteScrollListener extends ItemListener { + + public WhiteScrollListener(EpicEnchants instance) { + super(instance); + } + + @Override + void onApply(InventoryClickEvent event, NBTItem cursor, NBTItem current) { + if (!cursor.hasKey("white-scroll") || !cursor.getBoolean("white-scroll")) { + return; + } + + event.setCancelled(true); + + if (current.hasKey("protected")) { + instance.getAction().perform(event.getWhoClicked(), "white-scroll.already-applied"); + return; + } + + current.setBoolean("protected", true); + instance.getAction().perform(event.getWhoClicked(), "white-scroll.applied"); + + ItemStack toSet = new ItemBuilder(current.getItem()).addLore(instance.getSpecialItems().getWhiteScrollLore()).build(); + + event.getClickedInventory().setItem(event.getSlot(), toSet); + useItem(event); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/managers/CommandManager.java b/core/src/main/java/com/songoda/epicenchants/managers/CommandManager.java new file mode 100644 index 0000000..60db785 --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/managers/CommandManager.java @@ -0,0 +1,79 @@ +package com.songoda.epicenchants.managers; + +import co.aikar.commands.BukkitCommandManager; +import co.aikar.commands.InvalidCommandArgument; +import com.songoda.epicenchants.EpicEnchants; +import com.songoda.epicenchants.commands.EnchantCommand; +import com.songoda.epicenchants.enums.GiveType; +import com.songoda.epicenchants.objects.Enchant; +import com.songoda.epicenchants.objects.Group; + +import java.io.File; +import java.util.Arrays; +import java.util.Collections; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class CommandManager extends BukkitCommandManager { + public CommandManager(EpicEnchants instance) { + super(instance); + + // DEPENDENCIES + + registerDependency(EpicEnchants.class, "instance", instance); + + // COMPLETIONS + + getCommandCompletions().registerCompletion("enchants", c -> + instance.getEnchantManager().getValues().stream().map(Enchant::getIdentifier).collect(Collectors.toList())); + + getCommandCompletions().registerCompletion("enchantFiles", c -> + instance.getFileManager().getYmlFiles("enchants").orElse(Collections.emptyList()).stream().map(File::getName).collect(Collectors.toList())); + + getCommandCompletions().registerCompletion("giveType", c -> + Arrays.stream(GiveType.values()).map(s -> s.toString().replace("_", "").toLowerCase()).collect(Collectors.toList())); + + getCommandCompletions().registerCompletion("levels", c -> + IntStream.rangeClosed(1, c.getContextValue(Enchant.class).getMaxLevel()).boxed().map(Objects::toString).collect(Collectors.toList())); + + getCommandCompletions().registerCompletion("increment", c -> + IntStream.rangeClosed(0, 100).filter(i -> i % 10 == 0).boxed().map(Objects::toString).collect(Collectors.toList())); + + getCommandCompletions().registerCompletion("groups", c -> + instance.getGroupManager().getValues().stream().map(Group::getIdentifier).collect(Collectors.toList())); + + getCommandCompletions().registerCompletion("dustTypes", c -> + instance.getFileManager().getConfiguration("items/dusts.yml").getConfigurationSection("dusts").getKeys(false)); + + // CONTEXTS + + getCommandContexts().registerContext(Enchant.class, c -> + instance.getEnchantManager().getValue(c.popFirstArg()).orElseThrow(() -> + new InvalidCommandArgument("No enchant exists by that name", false))); + + getCommandContexts().registerContext(GiveType.class, c -> Arrays.stream(GiveType.values()) + .filter(s -> s.toString().toLowerCase().replace("_", "").equalsIgnoreCase(c.popFirstArg())) + .findFirst() + .orElseThrow(() -> new InvalidCommandArgument("No item by that type.", false))); + + getCommandContexts().registerContext(Group.class, c -> instance.getGroupManager().getValue(c.popFirstArg()).orElseThrow(() -> + new InvalidCommandArgument("No group exists by that name", false))); + + // REPLACEMENTS + + getCommandReplacements().addReplacements( + "enchanter", instance.getConfig().getString("commands.enchanter"), + "alchemist", instance.getConfig().getString("commands.alchemist"), + "tinkerer", instance.getConfig().getString("commands.tinkerer") + ); + + // API + + enableUnstableAPI("help"); + + // COMMANDS + + registerCommand(new EnchantCommand()); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/managers/EnchantManager.java b/core/src/main/java/com/songoda/epicenchants/managers/EnchantManager.java index 2c886e5..c910a9d 100644 --- a/core/src/main/java/com/songoda/epicenchants/managers/EnchantManager.java +++ b/core/src/main/java/com/songoda/epicenchants/managers/EnchantManager.java @@ -7,31 +7,21 @@ import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import java.io.File; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; import java.util.stream.Collectors; -import static com.songoda.epicenchants.utils.ConfigParser.parseEnchant; -import static java.io.File.separator; +import static com.songoda.epicenchants.utils.single.ConfigParser.parseEnchant; -public class EnchantManager { - private final Map enchantMap; - private final EpicEnchants instance; +public class EnchantManager extends Manager { public EnchantManager(EpicEnchants instance) { - this.instance = instance; - this.enchantMap = new HashMap<>(); - } - - public Optional getEnchant(String identifier) { - return Optional.ofNullable(enchantMap.get(identifier)); - } - - public void addEnchant(Enchant enchant) { - enchantMap.put(enchant.getIdentifier(), enchant); + super(instance); } public Collection getEnchants(Group group) { - return Collections.unmodifiableCollection(enchantMap.values().stream().filter(s -> s.getGroup().equals(group)).collect(Collectors.toList())); + return Collections.unmodifiableCollection(getValues().stream().filter(s -> s.getGroup().equals(group)).collect(Collectors.toList())); } public Optional getRandomEnchant(Group group) { @@ -39,15 +29,6 @@ public class EnchantManager { return tierList.stream().skip((int) (tierList.size() * Math.random())).findFirst(); } - public Collection getEnchants() { - return Collections.unmodifiableCollection(enchantMap.values()); - } - - - public Enchant getEnchantUnsafe(String identifier) { - return getEnchant(identifier).orElse(null); - } - public void loadEnchants() { instance.getFileManager().getYmlFiles("enchants").ifPresent(list -> list.forEach(file -> { try { @@ -61,12 +42,9 @@ public class EnchantManager { } public void loadEnchant(File file) throws Exception { - addEnchant(parseEnchant(instance, YamlConfiguration.loadConfiguration(file))); + Enchant enchant = parseEnchant(instance, YamlConfiguration.loadConfiguration(file)); + add(enchant.getIdentifier(), enchant); } - - public Optional getEnchantFile(String path) { - File file = new File(instance.getDataFolder() + separator + "enchants" + separator + path); - return file.exists() ? Optional.of(file) : Optional.empty(); - } - } + + diff --git a/core/src/main/java/com/songoda/epicenchants/managers/FileManager.java b/core/src/main/java/com/songoda/epicenchants/managers/FileManager.java index 71c9943..60fa08e 100644 --- a/core/src/main/java/com/songoda/epicenchants/managers/FileManager.java +++ b/core/src/main/java/com/songoda/epicenchants/managers/FileManager.java @@ -2,6 +2,7 @@ package com.songoda.epicenchants.managers; import com.songoda.epicenchants.EpicEnchants; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Bukkit; import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; @@ -15,27 +16,31 @@ import static java.io.File.separator; import static java.util.Arrays.asList; import static org.apache.commons.lang3.tuple.Pair.of; -public class FileManager { - private final EpicEnchants instance; - private final Map configurationMap; +public class FileManager extends Manager { + + private final LinkedHashSet> files = new LinkedHashSet<>(asList(of("menus/main-info-menu.yml", true), + of("menus/enchanter-menu.yml", true), + of("menus/tinkerer-menu.yml", true), + of("menus/groups/simple-menu.yml", false), + of("menus/groups/unique-menu.yml", false), + of("menus/groups/elite-menu.yml", false), + of("menus/groups/ultimate-menu.yml", false), + of("menus/groups/legendary-menu.yml", false), + of("enchants/example-enchant.yml", false), + of("config.yml", true), + of("groups.yml", true), + of("actions.yml", true), + of("items/special-items.yml", true), + of("items/dusts.yml", true) + )); public FileManager(EpicEnchants instance) { - this.instance = instance; - this.configurationMap = new HashMap<>(); + super(instance); } - public void createFiles() { + public void loadFiles() { Set recentDirs = new HashSet<>(); - asList(of("menus/main-info-menu.yml", true), - of("menus/enchanter-menu.yml", true), - of("menus/groups/simple-menu.yml", false), - of("menus/groups/unique-menu.yml", false), - of("menus/groups/elite-menu.yml", false), - of("menus/groups/ultimate-menu.yml", false), - of("menus/groups/legendary-menu.yml", false), - of("enchants/example-enchant.yml", false), - of("config.yml", true), - of("groups.yml", true)).forEach(pair -> { + files.forEach(pair -> { File file = new File(instance.getDataFolder() + separator + pair.getLeft()); if (!file.exists() && (pair.getRight() || (!file.getParent().equals(instance.getDataFolder().getPath()) @@ -57,13 +62,13 @@ public class FileManager { } catch (IOException | InvalidConfigurationException e) { e.printStackTrace(); } - configurationMap.put(pair.getLeft().replace(".yml", ""), configuration); + add(pair.getLeft().replace(".yml", ""), configuration); } }); } public FileConfiguration getConfiguration(String key) { - return configurationMap.get(key); + return getValueUnsafe(key); } public Optional> getYmlFiles(String directory) { diff --git a/core/src/main/java/com/songoda/epicenchants/managers/GroupManager.java b/core/src/main/java/com/songoda/epicenchants/managers/GroupManager.java index 37c350f..822bdc6 100644 --- a/core/src/main/java/com/songoda/epicenchants/managers/GroupManager.java +++ b/core/src/main/java/com/songoda/epicenchants/managers/GroupManager.java @@ -2,34 +2,19 @@ package com.songoda.epicenchants.managers; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.objects.Group; -import com.songoda.epicenchants.utils.ConfigParser; +import com.songoda.epicenchants.utils.single.ConfigParser; import org.bukkit.configuration.ConfigurationSection; -import java.util.*; - -public class GroupManager { - private final Map groupMap; - private final EpicEnchants instance; - +public class GroupManager extends Manager { public GroupManager(EpicEnchants instance) { - this.instance = instance; - this.groupMap = new HashMap<>(); - } - - public Optional getGroup(String identifier) { - return Optional.ofNullable(groupMap.get(identifier)); - } - - public void addGroup(Group group) { - groupMap.put(group.getIdentifier(), group); + super(instance); } public void loadGroups() { ConfigurationSection config = instance.getFileManager().getConfiguration("groups").getConfigurationSection("groups"); - config.getKeys(false).forEach(key -> addGroup(ConfigParser.parseGroup(config.getConfigurationSection(key)))); + config.getKeys(false).forEach(key -> { + Group group = ConfigParser.parseGroup(config.getConfigurationSection(key)); + add(group.getIdentifier(), group); + }); } - - public Collection getGroups() { - return Collections.unmodifiableCollection(groupMap.values()); - } -} +} \ No newline at end of file diff --git a/core/src/main/java/com/songoda/epicenchants/managers/InfoManager.java b/core/src/main/java/com/songoda/epicenchants/managers/InfoManager.java index 3e9c9cd..1b8938c 100644 --- a/core/src/main/java/com/songoda/epicenchants/managers/InfoManager.java +++ b/core/src/main/java/com/songoda/epicenchants/managers/InfoManager.java @@ -31,7 +31,7 @@ public class InfoManager { instance.getFileManager().getYmlFiles("menus/groups").ifPresent(list -> list.forEach(file -> { try { YamlConfiguration config = YamlConfiguration.loadConfiguration(file); - infoMenus.put(instance.getGroupManager().getGroup(config.getString("group")) + infoMenus.put(instance.getGroupManager().getValue(config.getString("group")) .orElseThrow(() -> new IllegalArgumentException("Invalid group: " + config.getString("group"))), new InfoMenu(instance, config)); } catch (Exception e) { Bukkit.getConsoleSender().sendMessage("Something went wrong loading the menu from file " + file.getName()); diff --git a/core/src/main/java/com/songoda/epicenchants/managers/Manager.java b/core/src/main/java/com/songoda/epicenchants/managers/Manager.java new file mode 100644 index 0000000..e7c2d0c --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/managers/Manager.java @@ -0,0 +1,33 @@ +package com.songoda.epicenchants.managers; + +import com.songoda.epicenchants.EpicEnchants; + +import java.util.*; + +public abstract class Manager { + + final EpicEnchants instance; + private final Map map; + + public Manager(EpicEnchants instance) { + this.instance = instance; + this.map = new HashMap<>(); + } + + public Optional getValue(K key) { + return Optional.ofNullable(map.get(key)); + } + + public void add(K key, V value) { + map.put(key, value); + } + + public V getValueUnsafe(K key) { + return getValue(key).orElse(null); + } + + public Collection getValues() { + return Collections.unmodifiableCollection(map.values()); + } + +} diff --git a/core/src/main/java/com/songoda/epicenchants/menus/AlchemistMenu.java b/core/src/main/java/com/songoda/epicenchants/menus/AlchemistMenu.java new file mode 100644 index 0000000..297eecc --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/menus/AlchemistMenu.java @@ -0,0 +1,34 @@ +package com.songoda.epicenchants.menus; + +import com.songoda.epicenchants.EpicEnchants; +import com.songoda.epicenchants.utils.objects.FastInv; +import com.songoda.epicenchants.utils.objects.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.configuration.file.FileConfiguration; + +import static com.songoda.epicenchants.utils.single.GeneralUtils.*; + +public class AlchemistMenu extends FastInv { + public AlchemistMenu(EpicEnchants instance, FileConfiguration config) { + super(config.getInt("rows") * 9, color(config.getString("title"))); + + if (config.isConfigurationSection("fill")) { + fill(new ItemBuilder(config.getConfigurationSection("fill")).build()); + } + + config.getConfigurationSection("contents").getKeys(false) + .stream() + .map(s -> "contents." + s) + .map(config::getConfigurationSection) + .forEach(section -> { + addItem(getSlots(config.getString("slot")), new ItemBuilder(section).build(), event -> { + if (section.getName().equalsIgnoreCase("left-item") || section.getName().equalsIgnoreCase("right-item")) { + if (getInventory().getItem(event.getSlot()) != null && getInventory().getItem(event.getSlot()).getType() != Material.AIR) { + event.getPlayer().getInventory().addItem(getInventory().getItem(event.getSlot())); + getInventory().clear(event.getSlot()); + } + } + }); + }); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/menus/EnchanterMenu.java b/core/src/main/java/com/songoda/epicenchants/menus/EnchanterMenu.java index b7f16b2..397cf52 100644 --- a/core/src/main/java/com/songoda/epicenchants/menus/EnchanterMenu.java +++ b/core/src/main/java/com/songoda/epicenchants/menus/EnchanterMenu.java @@ -1,20 +1,16 @@ package com.songoda.epicenchants.menus; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.objects.Enchant; import com.songoda.epicenchants.objects.Group; -import com.songoda.epicenchants.utils.FastInv; -import com.songoda.epicenchants.utils.ItemBuilder; +import com.songoda.epicenchants.utils.objects.FastInv; +import com.songoda.epicenchants.utils.objects.ItemBuilder; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.Optional; - import static com.songoda.epicenchants.objects.Placeholder.of; -import static com.songoda.epicenchants.utils.Experience.changeExp; -import static com.songoda.epicenchants.utils.Experience.getExp; -import static com.songoda.epicenchants.utils.GeneralUtils.color; +import static com.songoda.epicenchants.utils.single.Experience.*; +import static com.songoda.epicenchants.utils.single.GeneralUtils.*; public class EnchanterMenu extends FastInv { public EnchanterMenu(EpicEnchants instance, FileConfiguration config, Player player) { @@ -33,7 +29,7 @@ public class EnchanterMenu extends FastInv { double ecoCost = section.getDouble("eco-cost"); double xpLeft = expCost - player.getLevel() < 0 ? 0 : expCost - player.getLevel(); double ecoLeft = ecoCost - instance.getEconomy().getBalance(player) < 0 ? 0 : ecoCost - instance.getEconomy().getBalance(player); - Group group = instance.getGroupManager().getGroup(section.getString("group").toUpperCase()) + Group group = instance.getGroupManager().getValue(section.getString("group").toUpperCase()) .orElseThrow(() -> new IllegalArgumentException("Invalid group set in enchanter: " + section.getString("group"))); ItemStack itemStack = new ItemBuilder(section, of("exp_cost", expCost), @@ -41,24 +37,17 @@ public class EnchanterMenu extends FastInv { of("exp_left", xpLeft), of("eco_left", ecoLeft)).build(); - addItem(section.getInt("slot"), itemStack, event -> { - + addItem(getSlots(section.getString("slot")), itemStack, event -> { if (!instance.getEconomy().has((player), ecoCost) || getExp(player) < expCost) { - player.sendMessage(instance.getLocale().getPrefix() + instance.getLocale().getMessage("event.purchase.cannotafford")); - return; - } - - Optional enchant = instance.getEnchantManager().getRandomEnchant(group); - - if (!enchant.isPresent()) { - player.sendMessage(instance.getLocale().getPrefix() + instance.getLocale().getMessage("event.purchase.noenchant")); + instance.getAction().perform(player, "enchanter.cannot-afford"); return; } instance.getEconomy().withdrawPlayer(player, ecoCost); + instance.getAction().perform(player, "event.purchase.success", of("group-name", group.getName()), of("group_color", group.getColor())); + changeExp(player, (int) -expCost); - player.getInventory().addItem(enchant.get().getBookItem().get(enchant.get())); - player.sendMessage(instance.getLocale().getMessageWithPrefix("event.purchase.success", of("group-name", group.getName()))); + player.getInventory().addItem(instance.getSpecialItems().getMysteryBook(group)); }); }); } diff --git a/core/src/main/java/com/songoda/epicenchants/menus/InfoMenu.java b/core/src/main/java/com/songoda/epicenchants/menus/InfoMenu.java index 977ad91..963d0a1 100644 --- a/core/src/main/java/com/songoda/epicenchants/menus/InfoMenu.java +++ b/core/src/main/java/com/songoda/epicenchants/menus/InfoMenu.java @@ -3,8 +3,8 @@ package com.songoda.epicenchants.menus; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.objects.Enchant; import com.songoda.epicenchants.objects.Group; -import com.songoda.epicenchants.utils.FastInv; -import com.songoda.epicenchants.utils.ItemBuilder; +import com.songoda.epicenchants.utils.objects.FastInv; +import com.songoda.epicenchants.utils.objects.ItemBuilder; import org.apache.commons.lang.StringUtils; import org.bukkit.configuration.file.FileConfiguration; @@ -13,14 +13,14 @@ import java.util.Set; import java.util.stream.Collectors; import static com.songoda.epicenchants.objects.Placeholder.of; -import static com.songoda.epicenchants.utils.GeneralUtils.color; +import static com.songoda.epicenchants.utils.single.GeneralUtils.color; import static java.util.Arrays.stream; public class InfoMenu extends FastInv { public InfoMenu(EpicEnchants instance, FileConfiguration config) { super(config.getInt("size"), color(config.getString("title"))); - Group group = instance.getGroupManager().getGroup(config.getString("group")).orElseThrow(() -> new IllegalArgumentException("Invalid group: " + config.getString("group"))); + Group group = instance.getGroupManager().getValue(config.getString("group")).orElseThrow(() -> new IllegalArgumentException("Invalid group: " + config.getString("group"))); String[] split = config.getString("slots").split(","); Set slots = stream(split, 0, split.length) diff --git a/core/src/main/java/com/songoda/epicenchants/menus/MainInfoMenu.java b/core/src/main/java/com/songoda/epicenchants/menus/MainInfoMenu.java index 7bab700..5a4b727 100644 --- a/core/src/main/java/com/songoda/epicenchants/menus/MainInfoMenu.java +++ b/core/src/main/java/com/songoda/epicenchants/menus/MainInfoMenu.java @@ -2,11 +2,11 @@ package com.songoda.epicenchants.menus; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.objects.Group; -import com.songoda.epicenchants.utils.FastInv; -import com.songoda.epicenchants.utils.ItemBuilder; +import com.songoda.epicenchants.utils.objects.FastInv; +import com.songoda.epicenchants.utils.objects.ItemBuilder; import org.bukkit.configuration.file.FileConfiguration; -import static com.songoda.epicenchants.utils.GeneralUtils.color; +import static com.songoda.epicenchants.utils.single.GeneralUtils.color; public class MainInfoMenu extends FastInv { @@ -18,7 +18,7 @@ public class MainInfoMenu extends FastInv { .map(config::getConfigurationSection) .forEach(section -> { addItem(section.getInt("slot"), new ItemBuilder(section).build(), event -> { - Group group = instance.getGroupManager().getGroup(section.getString("group")) + Group group = instance.getGroupManager().getValue(section.getString("group")) .orElseThrow(() -> new IllegalArgumentException("Invalid group: " + section.getString("group"))); instance.getInfoManager().getMenu(group).ifPresent(menu -> menu.open(event.getPlayer())); }); diff --git a/core/src/main/java/com/songoda/epicenchants/menus/TinkererMenu.java b/core/src/main/java/com/songoda/epicenchants/menus/TinkererMenu.java new file mode 100644 index 0000000..fe8b3a5 --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/menus/TinkererMenu.java @@ -0,0 +1,235 @@ +package com.songoda.epicenchants.menus; + +import com.songoda.epicenchants.EpicEnchants; +import com.songoda.epicenchants.enums.ItemType; +import com.songoda.epicenchants.objects.Enchant; +import com.songoda.epicenchants.utils.objects.FastInv; +import com.songoda.epicenchants.utils.objects.ItemBuilder; +import de.tr7zw.itemnbtapi.NBTCompound; +import de.tr7zw.itemnbtapi.NBTItem; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import static com.songoda.epicenchants.enums.ItemType.*; +import static com.songoda.epicenchants.objects.Placeholder.of; +import static com.songoda.epicenchants.utils.single.GeneralUtils.*; +import static java.util.Arrays.stream; + +public class TinkererMenu extends FastInv { + private final Map slotMap; + private final EpicEnchants instance; + private final FileConfiguration config; + + public TinkererMenu(EpicEnchants instance, FileConfiguration config) { + super(config.getInt("rows") * 9, color(config.getString("title"))); + + this.slotMap = getSlotMap(config); + this.instance = instance; + this.config = config; + + if (config.isConfigurationSection("fill")) { + fill(new ItemBuilder(config.getConfigurationSection("fill")).build()); + } + + config.getConfigurationSection("contents").getKeys(false) + .stream() + .map(s -> "contents." + s) + .map(config::getConfigurationSection) + .forEach(section -> { + addItem(getSlots(section.getString("slot")), new ItemBuilder(section).build(), event -> { + if (section.getName().equalsIgnoreCase("accept-left") || section.getName().equalsIgnoreCase("accept-right")) { + slotMap.values().stream().map(slot -> getInventory().getItem(slot)).filter(Objects::nonNull).forEach(event.getPlayer().getInventory()::addItem); + slotMap.keySet().forEach(slot -> getInventory().clear(slot)); + event.getPlayer().closeInventory(); + instance.getAction().perform(event.getPlayer(), "tinkerer.accepted"); + return; + } + + if (section.getName().equalsIgnoreCase("deposit-all")) { + int count = (int) stream(event.getPlayer().getInventory().getContents()).filter(i -> isTinkerable(i) != NONE).count(); + + if (count == 0) { + instance.getAction().perform(event.getPlayer(), "tinkerer.no-items"); + return; + } + + Inventory inventory = event.getPlayer().getInventory(); + + int amount = 0; + + for (int i = 0; i < inventory.getSize(); i++) { + ItemStack itemStack = inventory.getItem(i); + ItemType itemType = isTinkerable(itemStack); + + if (itemType == NONE) { + continue; + } + + for (int j = 0; j < itemStack.getAmount(); j++) { + if (!handleItem(itemStack, itemType)) { + continue; + } + + amount++; + + if (itemStack.getAmount() > 1) { + itemStack.setAmount(itemStack.getAmount() - 1); + inventory.setItem(i, itemStack); + continue; + } + + inventory.clear(i); + } + } + + instance.getAction().perform(event.getPlayer(), "tinkerer.deposited-all", of("amount", amount)); + } + }); + }); + + // Player clicked an item in tinkerer + onClick(event -> { + if (event.getEvent().getClickedInventory() == null) { + return; + } + + int slot = event.getSlot(); + + if (!slotMap.keySet().contains(slot)) { + return; + } + + if (getInventory().getItem(slot) != null && getInventory().getItem(slot).getType() != Material.AIR) { + event.getPlayer().getInventory().addItem(getInventory().getItem(slot)); + getInventory().clear(slot); + getInventory().clear(slotMap.get(slot)); + } + }); + + // Player clicked his own inv + onClick(event -> { + if (event.getEvent().getClickedInventory() == null || event.getEvent().getClickedInventory().getType() != InventoryType.PLAYER) { + return; + } + + ItemStack itemStack = event.getItem(); + ItemType itemType = isTinkerable(itemStack); + + if (itemType == NONE) { + return; + } + + if (handleItem(itemStack, itemType)) { + if (itemStack.getAmount() > 1) { + itemStack.setAmount(itemStack.getAmount() - 1); + return; + } + + event.getEvent().getClickedInventory().clear(event.getEvent().getSlot()); + } + }); + + onClose(event -> slotMap.keySet().stream().filter(s -> getInventory().getItem(s) != null).forEach(s -> { + instance.getAction().perform(event.getPlayer(), "tinkerer.cancelled"); + event.getPlayer().getInventory().addItem(getInventory().getItem(s)); + })); + } + + private ItemType isTinkerable(ItemStack itemStack) { + if (itemStack == null || itemStack.getType() == Material.AIR) { + return NONE; + } + + NBTItem nbtItem = new NBTItem(itemStack); + + if (nbtItem.hasKey("book-item")) { + return BOOK; + } + + if (!instance.getHookManager().getUltimateBottles().isPresent()) { + return NONE; + } + + if (!itemStack.getEnchantments().isEmpty() || (nbtItem.getCompound("enchants") != null && !nbtItem.getCompound("enchants").getKeys().isEmpty())) { + if (getExpAmount(itemStack) == 0) { + return NONE; + } + + return ENCHANTED; + } + + return NONE; + } + + private boolean handleItem(ItemStack itemStack, ItemType itemType) { + Optional> emptySlot = slotMap.entrySet().stream().filter(slot -> getInventory().getItem(slot.getKey()) == null || getInventory().getItem(slot.getKey()).getType() == Material.AIR).findFirst(); + + if (!emptySlot.isPresent()) { + return false; + } + + ItemStack finalItemStack = itemStack.clone(); + finalItemStack.setAmount(1); + + addItem(emptySlot.get().getKey(), finalItemStack); + + switch (itemType) { + case BOOK: + getInventory().setItem(emptySlot.get().getValue(), instance.getSpecialItems().getSecretDust(new NBTItem(finalItemStack))); + break; + case ENCHANTED: + getInventory().setItem(emptySlot.get().getValue(), instance.getHookManager().getUltimateBottles().get().createBottle("Tinkerer", getExpAmount(finalItemStack))); + break; + } + + return true; + } + + private LinkedHashMap getSlotMap(FileConfiguration config) { + return stream(config.getString("slots").split(" ")).map(s -> s.replace(")", "").replace("(", "")) + .collect(Collectors.toMap( + s -> Integer.parseInt(s.split(",")[0]), + s -> Integer.parseInt(s.split(",")[1]), + (u, v) -> { + throw new IllegalStateException(String.format("Duplicate key %s", u)); + }, + LinkedHashMap::new) + ); + } + + private int getExpAmount(ItemStack itemStack) { + AtomicInteger total = new AtomicInteger(); + ConfigurationSection section = config.getConfigurationSection("exp-table-per-level"); + + itemStack.getEnchantments().forEach((enchantment, level) -> { + total.addAndGet(section.getInt(enchantment.getName(), section.getInt("DEFAULT")) * level); + }); + + NBTItem nbtItem = new NBTItem(itemStack); + + if (!nbtItem.hasKey("enchants")) { + return total.get(); + } + + NBTCompound enchantments = nbtItem.getCompound("enchants"); + + if (enchantments == null) { + return total.get(); + } + + enchantments.getKeys().forEach(key -> { + Enchant enchant = instance.getEnchantManager().getValueUnsafe(key); + total.addAndGet(section.getInt(enchant.getIdentifier(), enchant.getGroup().getTinkererExp()) * enchantments.getInteger(key)); + }); + + return total.get(); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/objects/BookItem.java b/core/src/main/java/com/songoda/epicenchants/objects/BookItem.java index 719ae83..9a6e72b 100644 --- a/core/src/main/java/com/songoda/epicenchants/objects/BookItem.java +++ b/core/src/main/java/com/songoda/epicenchants/objects/BookItem.java @@ -1,7 +1,7 @@ package com.songoda.epicenchants.objects; import co.aikar.commands.annotation.Optional; -import com.songoda.epicenchants.utils.ItemBuilder; +import com.songoda.epicenchants.utils.objects.ItemBuilder; import de.tr7zw.itemnbtapi.NBTItem; import lombok.Builder; import org.bukkit.Material; diff --git a/core/src/main/java/com/songoda/epicenchants/objects/Condition.java b/core/src/main/java/com/songoda/epicenchants/objects/Condition.java index e4ae98a..b15c8fe 100644 --- a/core/src/main/java/com/songoda/epicenchants/objects/Condition.java +++ b/core/src/main/java/com/songoda/epicenchants/objects/Condition.java @@ -1,11 +1,13 @@ package com.songoda.epicenchants.objects; import org.bukkit.Bukkit; +import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; +import java.util.Arrays; public class Condition { private final String string; @@ -18,15 +20,32 @@ public class Condition { return new Condition(string); } - public boolean get(Player player, int level, boolean def) { + public boolean get(Player wearer, LivingEntity attacker, int level, boolean def) { if (string == null || string.isEmpty()) { return true; } ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript"); + String toValidate = string; + + for (Placeholder pair : Arrays.asList( + Placeholder.of("level", level), + Placeholder.of("wearer_health", wearer.getHealth()), + Placeholder.of("attacker_health", attacker.getHealth()), + Placeholder.of("wearer_food", wearer.getFoodLevel()), + Placeholder.of("attacker_food", attacker instanceof Player ? ((Player) attacker).getFoodLevel() : 0), + Placeholder.of("wearer_is_sneaking", wearer.isSneaking()), + Placeholder.of("attacker_is_sneaking", attacker instanceof Player && ((Player) attacker).isSneaking()), + Placeholder.of("world", wearer.getWorld().getName()), + Placeholder.of("players_near", wearer.getNearbyEntities(4, 4, 4).size()), + Placeholder.of("wearer_on_fire", wearer.getFireTicks() != 0), + Placeholder.of("attacker_on_fire", attacker.getFireTicks() != 0) + )) { + toValidate = toValidate.replace(pair.getPlaceholder(), pair.getToReplace().toString()); + } try { - return Boolean.parseBoolean(scriptEngine.eval(string.replace("{level}", "" + level)).toString()); + return Boolean.parseBoolean(scriptEngine.eval(toValidate).toString()); } catch (ScriptException | NumberFormatException e) { Bukkit.getLogger().warning("[EpicEnchants] One of your condition expressions is not properly formatted."); return def; diff --git a/core/src/main/java/com/songoda/epicenchants/objects/Enchant.java b/core/src/main/java/com/songoda/epicenchants/objects/Enchant.java index 526fd25..a2ed465 100644 --- a/core/src/main/java/com/songoda/epicenchants/objects/Enchant.java +++ b/core/src/main/java/com/songoda/epicenchants/objects/Enchant.java @@ -28,14 +28,18 @@ public class Enchant { private Set description; @Nullable private String format; @Nullable private BookItem bookItem; - private LeveledModifier modifyDamage; + private Condition condition; public void onAction(@NotNull Player wearer, @Nullable LivingEntity opponent, Event event, int level, TriggerType triggerType, EventType eventType) { + if (!condition.get(wearer, opponent, level, false)) { + return; + } + effectExecutors.forEach(effect -> effect.testAndRun(wearer, opponent, level, triggerType, event, eventType)); mobs.forEach(mobWrapper -> mobWrapper.trySpawn(wearer, opponent, level, triggerType)); } - public BookItem getBookItem() { + public BookItem getBook() { return bookItem != null ? bookItem : group.getBookItem(); } diff --git a/core/src/main/java/com/songoda/epicenchants/objects/Group.java b/core/src/main/java/com/songoda/epicenchants/objects/Group.java index fa93be9..4c554a9 100644 --- a/core/src/main/java/com/songoda/epicenchants/objects/Group.java +++ b/core/src/main/java/com/songoda/epicenchants/objects/Group.java @@ -13,4 +13,5 @@ public class Group { private int slotsUsed; private BookItem bookItem; private int destroyRateMin, destroyRateMax, successRateMin, successRateMax; + private int tinkererExp; } diff --git a/core/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java b/core/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java index 69a06f6..2c89f63 100644 --- a/core/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java +++ b/core/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java @@ -5,6 +5,9 @@ import com.songoda.epicenchants.enums.EnchantResult; import com.songoda.epicenchants.enums.EventType; import com.songoda.epicenchants.enums.TriggerType; import com.songoda.epicenchants.objects.Enchant; +import com.songoda.epicenchants.utils.objects.ItemBuilder; +import com.songoda.epicenchants.utils.single.GeneralUtils; +import com.songoda.epicenchants.utils.single.RomanNumber; import de.tr7zw.itemnbtapi.NBTCompound; import de.tr7zw.itemnbtapi.NBTItem; import org.apache.commons.lang3.tuple.Pair; @@ -31,13 +34,12 @@ public class EnchantUtils { } public Pair apply(ItemStack itemStack, Enchant enchant, int level, int successRate, int destroyRate) { - if (!GeneralUtils.chance(successRate)) { - return GeneralUtils.chance(destroyRate) ? Pair.of(new ItemStack(Material.AIR), BROKEN_FAILURE) : Pair.of(itemStack, FAILURE); - } + boolean hasProtection = new NBTItem(itemStack).hasKey("protected"); Map enchantMap = getEnchants(itemStack); - if (enchantMap.keySet().stream().anyMatch(s -> enchant.getConflict().contains(s.getIdentifier()))) { + if (enchantMap.keySet().stream().anyMatch(s -> enchant.getConflict().contains(s.getIdentifier())) || + enchant.getConflict().stream().anyMatch(s -> enchantMap.keySet().stream().map(Enchant::getIdentifier).collect(Collectors.toList()).contains(s))) { return Pair.of(itemStack, CONFLICT); } @@ -49,9 +51,30 @@ public class EnchantUtils { return Pair.of(itemStack, ALREADY_APPLIED); } + if (!GeneralUtils.chance(successRate)) { + if (GeneralUtils.chance(destroyRate)) { + if (hasProtection) { + NBTItem nbtItem = new ItemBuilder(itemStack).removeLore(instance.getSpecialItems().getWhiteScrollLore()).nbt(); + nbtItem.removeKey("protected"); + return Pair.of(nbtItem.getItem(), PROTECTED); + } + return Pair.of(new ItemStack(Material.AIR), BROKEN_FAILURE); + } + return Pair.of(itemStack, FAILURE); + } + ItemBuilder itemBuilder = new ItemBuilder(itemStack); + + if (hasProtection) { + itemBuilder.removeLore(instance.getSpecialItems().getWhiteScrollLore()); + } + itemBuilder.removeLore(enchant.getFormat().replace("{level}", "").trim()); - itemBuilder.addLore(enchant.getFormat().replace("{level}", "" + level)); + itemBuilder.addLore(enchant.getFormat().replace("{level}", "" + (instance.getConfig().getBoolean("roman-numbers") ? RomanNumber.toRoman(level) : level))); + + if (hasProtection) { + itemBuilder.addLore(instance.getSpecialItems().getWhiteScrollLore()); + } NBTItem nbtItem = itemBuilder.nbt(); @@ -64,18 +87,24 @@ public class EnchantUtils { } public Map getEnchants(ItemStack itemStack) { - if (itemStack == null) { + if (itemStack == null || itemStack.getType() == Material.AIR) { return Collections.emptyMap(); } - NBTCompound compound = new NBTItem(itemStack).getCompound("enchants"); + NBTItem nbtItem = new NBTItem(itemStack); + + if (!nbtItem.hasNBTData() || nbtItem.hasKey("enchants")) { + return Collections.emptyMap(); + } + + NBTCompound compound = nbtItem.getCompound("enchants"); if (compound == null) { return Collections.emptyMap(); } - return compound.getKeys().stream().filter(key -> instance.getEnchantManager().getEnchantUnsafe(key) != null) - .collect(Collectors.toMap(key -> instance.getEnchantManager().getEnchantUnsafe(key), compound::getInteger)); + return compound.getKeys().stream().filter(key -> instance.getEnchantManager().getValueUnsafe(key) != null) + .collect(Collectors.toMap(key -> instance.getEnchantManager().getValueUnsafe(key), compound::getInteger)); } public void handlePlayer(@NotNull Player player, @Nullable LivingEntity opponent, Event event, TriggerType triggerType) { @@ -91,4 +120,21 @@ public class EnchantUtils { enchant.onAction(player, opponent, event, level, triggerType, EventType.NONE); })); } + + public ItemStack removeEnchant(ItemStack itemStack, Enchant enchant) { + if (itemStack == null) { + return null; + } + + NBTItem nbtItem = new NBTItem(itemStack); + + if (nbtItem.getCompound("enchants") == null || nbtItem.getCompound("enchants").getInteger(enchant.getIdentifier()) == null) { + return itemStack; + } + + nbtItem.getCompound("enchants").removeKey(enchant.getIdentifier()); + ItemBuilder output = new ItemBuilder(nbtItem.getItem()); + output.removeLore(enchant.getFormat().replace("{level}", "").trim()); + return output.build(); + } } diff --git a/core/src/main/java/com/songoda/epicenchants/utils/GeneralUtils.java b/core/src/main/java/com/songoda/epicenchants/utils/GeneralUtils.java deleted file mode 100644 index fcc15d2..0000000 --- a/core/src/main/java/com/songoda/epicenchants/utils/GeneralUtils.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.songoda.epicenchants.utils; - -import com.songoda.epicenchants.enums.EnchantResult; -import org.bukkit.ChatColor; - -import java.util.concurrent.ThreadLocalRandom; - -public class GeneralUtils { - public static boolean chance(int chance) { - return chance((double) chance); - } - - public static boolean chance(double chance) { - return ThreadLocalRandom.current().nextDouble(101) < chance; - } - - public static String color(String input) { - return format(input, "", null); - } - - public static String format(String input, String placeholder, Object toReplace) { - return ChatColor.translateAlternateColorCodes('&', input).replaceAll(placeholder, toReplace == null ? "" : toReplace.toString()); - } - - public static String getMessageFromResult(EnchantResult result) { - switch (result) { - case FAILURE: - return "enchant.failure"; - case BROKEN_FAILURE: - return "enchant.brokenfailure"; - case SUCCESS: - return "enchant.success"; - case CONFLICT: - return "enchant.conflict"; - case MAXED_OUT: - return "enchant.maxedout"; - case ALREADY_APPLIED: - return "enchant.alreadyapplied"; - } - - return ""; - } -} diff --git a/core/src/main/java/com/songoda/epicenchants/utils/SpecialItems.java b/core/src/main/java/com/songoda/epicenchants/utils/SpecialItems.java index e4caf9b..994267c 100644 --- a/core/src/main/java/com/songoda/epicenchants/utils/SpecialItems.java +++ b/core/src/main/java/com/songoda/epicenchants/utils/SpecialItems.java @@ -1,12 +1,18 @@ package com.songoda.epicenchants.utils; import com.songoda.epicenchants.EpicEnchants; +import com.songoda.epicenchants.objects.Group; +import com.songoda.epicenchants.utils.objects.ItemBuilder; import de.tr7zw.itemnbtapi.NBTItem; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; import java.util.concurrent.ThreadLocalRandom; import static com.songoda.epicenchants.objects.Placeholder.of; +import static com.songoda.epicenchants.utils.single.GeneralUtils.color; public class SpecialItems { private final EpicEnchants instance; @@ -16,7 +22,7 @@ public class SpecialItems { } public ItemStack getWhiteScroll(Integer amount) { - NBTItem nbtItem = new ItemBuilder(instance.getFileManager().getConfiguration("special-items").getConfigurationSection("white-scroll")).nbt(); + NBTItem nbtItem = new ItemBuilder(instance.getFileManager().getConfiguration("items/special-items").getConfigurationSection("white-scroll")).nbt(); nbtItem.setBoolean("white-scroll", true); ItemStack itemStack = nbtItem.getItem(); @@ -28,11 +34,11 @@ public class SpecialItems { } public ItemStack getBlackScroll(Integer amount, Integer chance) { - int percentage = chance == null ? ThreadLocalRandom.current().nextInt(instance.getConfig().getInt("rates.black-scroll-min"), instance.getConfig().getInt("rates.black-scroll-max") + 1) : chance; - NBTItem nbtItem = new ItemBuilder(instance.getFileManager().getConfiguration("special-items").getConfigurationSection("black-scroll"), of("percentage", percentage)).nbt(); + int successRate = chance == null ? ThreadLocalRandom.current().nextInt(instance.getConfig().getInt("rates.black-scroll-min"), instance.getConfig().getInt("rates.black-scroll-max") + 1) : chance; + NBTItem nbtItem = new ItemBuilder(instance.getFileManager().getConfiguration("items/special-items").getConfigurationSection("black-scroll"), of("success-rate", successRate)).nbt(); nbtItem.setBoolean("black-scroll", true); - nbtItem.setInteger("percentage", percentage); + nbtItem.setInteger("success-rate", successRate); ItemStack itemStack = nbtItem.getItem(); @@ -42,4 +48,79 @@ public class SpecialItems { return itemStack; } + + public ItemStack getMysteryBook(Group group) { + NBTItem nbtItem = new ItemBuilder(instance.getFileManager().getConfiguration("items/special-items").getConfigurationSection("mystery-book"), + of("group-color", group.getColor()), + of("group-name", group.getName())).nbt(); + + nbtItem.setBoolean("mystery-book", true); + nbtItem.setString("group", group.getIdentifier()); + return nbtItem.getItem(); + } + + + public ItemStack getSecretDust(NBTItem book) { + Group group = instance.getEnchantManager().getValueUnsafe(book.getString("enchant")).getGroup(); + return getSecretDust(group, (int) Math.floor(book.getInteger("success-rate") / 10.0)); + } + + public ItemStack getSecretDust(Group group, int max) { + NBTItem nbtItem = new ItemBuilder(instance.getFileManager().getConfiguration("items/dusts").getConfigurationSection("secret-dust"), + of("group-color", group.getColor()), + of("group-name", group.getName()), + of("max-rate", max), + of("min-rate", 0)).nbt(); + + nbtItem.setBoolean("secret-dust", true); + nbtItem.setString("group", group.getIdentifier()); + nbtItem.setInteger("max-rate", max); + nbtItem.setInteger("min-rate", 1); + return nbtItem.getItem(); + } + + public ItemStack getDust(Group group, @Nullable String type, @Nullable Integer percentage) { + FileConfiguration dustConfig = instance.getFileManager().getConfiguration("items/dusts"); + int random = ThreadLocalRandom.current().nextInt(101); + int counter = 0; + + if (type == null) { + for (String s : dustConfig.getConfigurationSection("dusts").getKeys(false)) { + int chance = dustConfig.getConfigurationSection("dusts." + s).getInt("chance"); + if (random < (chance + counter) && random >= counter) { + type = s; + } + counter += chance; + } + } + + ConfigurationSection config = dustConfig.getConfigurationSection("dusts." + (type == null ? "mystery" : type)); + + if (config.isInt("min-rate") && config.isInt("max-rate")) { + int minRate = config.getInt("min-rate"); + int maxRate = config.getInt("max-rate"); + percentage = ThreadLocalRandom.current().nextInt(minRate, maxRate + 1); + } else if (percentage == null) { + percentage = ThreadLocalRandom.current().nextInt(0, 10); + } + + NBTItem nbtItem = new ItemBuilder(config, + of("group-color", group.getColor()), + of("group-name", group.getName()), + of("percentage", percentage)).nbt(); + + if (type != null && type.equalsIgnoreCase("mystery")) { + return nbtItem.getItem(); + } + + nbtItem.setBoolean("dust", true); + nbtItem.setInteger("percentage", percentage); + nbtItem.setString("group", group.getIdentifier()); + + return nbtItem.getItem(); + } + + public String getWhiteScrollLore() { + return color(instance.getFileManager().getConfiguration("special-items").getConfigurationSection("white-scroll").getString("format")); + } } diff --git a/core/src/main/java/com/songoda/epicenchants/utils/FastInv.java b/core/src/main/java/com/songoda/epicenchants/utils/objects/FastInv.java similarity index 97% rename from core/src/main/java/com/songoda/epicenchants/utils/FastInv.java rename to core/src/main/java/com/songoda/epicenchants/utils/objects/FastInv.java index 3231a82..c595de5 100644 --- a/core/src/main/java/com/songoda/epicenchants/utils/FastInv.java +++ b/core/src/main/java/com/songoda/epicenchants/utils/objects/FastInv.java @@ -1,4 +1,4 @@ -package com.songoda.epicenchants.utils; +package com.songoda.epicenchants.utils.objects; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -12,10 +12,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitTask; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * A fast API to easily create advanced GUI. @@ -99,61 +96,58 @@ public class FastInv implements InventoryHolder { } } - private static Listener getListener() { - return new Listener() { + public static class FastInvClickEvent extends FastInvEvent { + private final InventoryClickEvent event; + private final InventoryAction action; + private final ClickType clickType; + private final ItemStack item; + private final int slot; - @EventHandler - public void onClick(InventoryClickEvent event) { - if (event.getInventory().getHolder() instanceof FastInv && event.getWhoClicked() instanceof Player) { - int slot = event.getRawSlot(); - FastInv inv = (FastInv) event.getInventory().getHolder(); + private FastInvClickEvent(Player player, FastInv inventory, InventoryClickEvent event, int slot, ItemStack item, + boolean cancelled, InventoryAction action, ClickType clickType) { + super(player, inventory, cancelled); + this.event = event; + this.slot = slot; + this.item = item; + this.action = action; + this.clickType = clickType; + } - FastInvClickEvent clickEvent = new FastInvClickEvent((Player) event.getWhoClicked(), inv, slot, - event.getCurrentItem(), true, event.getAction(), event.getClick()); + /** + * @return The action of the event + */ + public InventoryAction getAction() { + return this.action; + } - if (inv.itemListeners.containsKey(slot)) { - inv.itemListeners.get(slot).onClick(clickEvent); - } + /** + * @return The click type + */ + public ClickType getClickType() { + return this.clickType; + } - inv.clickListeners.forEach(listener -> listener.onClick(clickEvent)); + /** + * Get the clicked {@link ItemStack} + * + * @return The clicked item + */ + public ItemStack getItem() { + return this.item; + } - if (clickEvent.isCancelled()) { - event.setCancelled(true); - } - } - } + /** + * Get the number of the clicked slot + * + * @return The slot number + */ + public int getSlot() { + return this.slot; + } - @EventHandler - public void onClose(InventoryCloseEvent event) { - if (event.getInventory().getHolder() instanceof FastInv && event.getPlayer() instanceof Player) { - Player player = (Player) event.getPlayer(); - FastInv inv = (FastInv) event.getInventory().getHolder(); - - FastInvCloseEvent closeEvent = new FastInvCloseEvent(player, inv, false); - inv.closeListeners.forEach(listener -> listener.onClose(closeEvent)); - - Bukkit.getScheduler().runTask(plugin, () -> { - // Tiny delay to prevent errors. - if (closeEvent.isCancelled() && player.isOnline()) { - player.openInventory(inv.getInventory()); - } else if (inv.getInventory().getViewers().isEmpty() && inv.cancelTasksOnClose) { - inv.cancelTasks(); - } - }); - } - } - - @EventHandler - public void onDisable(PluginDisableEvent event) { - if (event.getPlugin().equals(plugin)) { - for (Player player : Bukkit.getOnlinePlayers()) { - if (player.getOpenInventory().getTopInventory().getHolder() instanceof FastInv) { - player.closeInventory(); - } - } - } - } - }; + public InventoryClickEvent getEvent() { + return event; + } } /** @@ -420,7 +414,6 @@ public class FastInv implements InventoryHolder { } public static abstract class FastInvEvent { - private boolean cancelled; private final FastInv inventory; private final Player player; @@ -468,53 +461,61 @@ public class FastInv implements InventoryHolder { } } - public static class FastInvClickEvent extends FastInvEvent { + private static Listener getListener() { + return new Listener() { - private final InventoryAction action; - private final ClickType clickType; - private final ItemStack item; - private final int slot; + @EventHandler + public void onClick(InventoryClickEvent event) { + if (event.getInventory().getHolder() instanceof FastInv && event.getWhoClicked() instanceof Player) { + int slot = event.getRawSlot(); + FastInv inv = (FastInv) event.getInventory().getHolder(); - private FastInvClickEvent(Player player, FastInv inventory, int slot, ItemStack item, - boolean cancelled, InventoryAction action, ClickType clickType) { - super(player, inventory, cancelled); - this.slot = slot; - this.item = item; - this.action = action; - this.clickType = clickType; - } + FastInvClickEvent clickEvent = new FastInvClickEvent((Player) event.getWhoClicked(), inv, event, slot, + event.getCurrentItem(), true, event.getAction(), event.getClick()); - /** - * @return The action of the event - */ - public InventoryAction getAction() { - return this.action; - } + if (inv.itemListeners.containsKey(slot)) { + inv.itemListeners.get(slot).onClick(clickEvent); + } - /** - * @return The click type - */ - public ClickType getClickType() { - return this.clickType; - } + inv.clickListeners.forEach(listener -> listener.onClick(clickEvent)); - /** - * Get the clicked {@link ItemStack} - * - * @return The clicked item - */ - public ItemStack getItem() { - return this.item; - } + if (clickEvent.isCancelled()) { + event.setCancelled(true); + } + } + } - /** - * Get the number of the clicked slot - * - * @return The slot number - */ - public int getSlot() { - return this.slot; - } + @EventHandler + public void onClose(InventoryCloseEvent event) { + if (event.getInventory().getHolder() instanceof FastInv && event.getPlayer() instanceof Player) { + Player player = (Player) event.getPlayer(); + FastInv inv = (FastInv) event.getInventory().getHolder(); + + FastInvCloseEvent closeEvent = new FastInvCloseEvent(player, inv, false); + inv.closeListeners.forEach(listener -> listener.onClose(closeEvent)); + + Bukkit.getScheduler().runTask(plugin, () -> { + // Tiny delay to prevent errors. + if (closeEvent.isCancelled() && player.isOnline()) { + player.openInventory(inv.getInventory()); + } else if (inv.getInventory().getViewers().isEmpty() && inv.cancelTasksOnClose) { + inv.cancelTasks(); + } + }); + } + } + + @EventHandler + public void onDisable(PluginDisableEvent event) { + if (event.getPlugin().equals(plugin)) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getOpenInventory().getTopInventory().getHolder() instanceof FastInv) { + player.closeInventory(); + } + } + } + } + }; } public static class FastInvCloseEvent extends FastInvEvent { diff --git a/core/src/main/java/com/songoda/epicenchants/utils/ItemBuilder.java b/core/src/main/java/com/songoda/epicenchants/utils/objects/ItemBuilder.java similarity index 86% rename from core/src/main/java/com/songoda/epicenchants/utils/ItemBuilder.java rename to core/src/main/java/com/songoda/epicenchants/utils/objects/ItemBuilder.java index f7e46eb..732468d 100644 --- a/core/src/main/java/com/songoda/epicenchants/utils/ItemBuilder.java +++ b/core/src/main/java/com/songoda/epicenchants/utils/objects/ItemBuilder.java @@ -1,11 +1,15 @@ -package com.songoda.epicenchants.utils; +package com.songoda.epicenchants.utils.objects; import com.songoda.epicenchants.objects.Placeholder; +import com.songoda.epicenchants.utils.single.ConfigParser; +import com.songoda.epicenchants.utils.single.GeneralUtils; +import com.songoda.epicenchants.utils.single.XMaterial; import com.songoda.epicenchants.wrappers.EnchantmentWrapper; import de.tr7zw.itemnbtapi.NBTItem; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -14,7 +18,7 @@ import org.bukkit.inventory.meta.SkullMeta; import java.util.*; import java.util.stream.Collectors; -import static com.songoda.epicenchants.utils.GeneralUtils.color; +import static com.songoda.epicenchants.utils.single.GeneralUtils.color; public class ItemBuilder { @@ -41,8 +45,16 @@ public class ItemBuilder { this(new ItemStack(material, amount, data)); } + public ItemBuilder(ConfigurationSection section, Player player, Placeholder... placeholders) { + this(section, placeholders); + + if (item.getType() == Material.LEGACY_SKULL_ITEM) { + ((SkullMeta) item.getItemMeta()).setOwningPlayer(player); + } + } + public ItemBuilder(ConfigurationSection section, Placeholder... placeholders) { - this(Material.valueOf(section.getString("material")), (byte) (section.contains("data") ? section.getInt("data") : 0)); + this(XMaterial.requestXMaterial(section.getString("material"), (byte) (section.contains("data") ? section.getInt("data") : 0)).parseItem()); if (section.contains("enchants")) { section.getStringList("enchants").stream() @@ -147,6 +159,23 @@ public class ItemBuilder { return this; } + public ItemBuilder removeLore(int index) { + if (!meta.hasLore()) { + return this; + } + + List lore = meta.getLore(); + + if (index >= lore.size()) { + return this; + } + + lore.remove(index); + + meta.setLore(lore); + return this; + } + public ItemBuilder addLore(String... lore) { return addLore(Arrays.asList(lore)); } diff --git a/core/src/main/java/com/songoda/epicenchants/utils/ConfigParser.java b/core/src/main/java/com/songoda/epicenchants/utils/single/ConfigParser.java similarity index 93% rename from core/src/main/java/com/songoda/epicenchants/utils/ConfigParser.java rename to core/src/main/java/com/songoda/epicenchants/utils/single/ConfigParser.java index c927de6..d0fe990 100644 --- a/core/src/main/java/com/songoda/epicenchants/utils/ConfigParser.java +++ b/core/src/main/java/com/songoda/epicenchants/utils/single/ConfigParser.java @@ -1,12 +1,10 @@ -package com.songoda.epicenchants.utils; +package com.songoda.epicenchants.utils.single; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.effect.EffectManager; import com.songoda.epicenchants.enums.TriggerType; -import com.songoda.epicenchants.objects.BookItem; -import com.songoda.epicenchants.objects.Enchant; -import com.songoda.epicenchants.objects.Group; -import com.songoda.epicenchants.objects.LeveledModifier; +import com.songoda.epicenchants.objects.*; +import com.songoda.epicenchants.utils.objects.ItemBuilder; import com.songoda.epicenchants.wrappers.EnchantmentWrapper; import com.songoda.epicenchants.wrappers.MobWrapper; import org.bukkit.Material; @@ -20,18 +18,19 @@ import java.util.HashSet; import java.util.Objects; import java.util.stream.Collectors; -import static com.songoda.epicenchants.utils.GeneralUtils.color; +import static com.songoda.epicenchants.utils.single.GeneralUtils.color; public class ConfigParser { public static Enchant parseEnchant(EpicEnchants instance, FileConfiguration config) { return Enchant.builder() .identifier(config.getString("identifier")) - .group(instance.getGroupManager().getGroup(config.getString("group").toUpperCase()).orElseThrow(() -> new IllegalArgumentException("Invalid group: " + config.getString("group")))) + .group(instance.getGroupManager().getValue(config.getString("group").toUpperCase()).orElseThrow(() -> new IllegalArgumentException("Invalid group: " + config.getString("group")))) .maxLevel(config.getInt("max-level")) .format(color(config.getString("applied-format"))) .bookItem(parseBookItem(config.getConfigurationSection("book-item"))) .itemWhitelist((config.isList("item-whitelist") ? config.getStringList("item-whitelist").stream().map(Material::valueOf).collect(Collectors.toSet()) : Collections.emptySet())) .conflict(config.isList("conflicting-enchants") ? new HashSet<>(config.getStringList("conflicting-enchants")) : Collections.emptySet()) + .condition(Condition.of(config.getString("condition"))) .mobs(config.isConfigurationSection("mobs") ? config.getConfigurationSection("mobs").getKeys(false).stream() .map(s -> "mobs." + s) .map(config::getConfigurationSection) @@ -89,6 +88,7 @@ public class ConfigParser { .color(section.getString("group-color")) .bookItem(parseBookItem(section.getConfigurationSection("book-item"))) .slotsUsed(section.getInt("slots-used")) + .tinkererExp(section.getInt("tinkerer-exp-per-level")) .destroyRateMin(section.getInt("rates.destroy-min")) .destroyRateMax(section.getInt("rates.destroy-max")) .successRateMin(section.getInt("rates.success-min")) diff --git a/core/src/main/java/com/songoda/epicenchants/utils/Experience.java b/core/src/main/java/com/songoda/epicenchants/utils/single/Experience.java similarity index 98% rename from core/src/main/java/com/songoda/epicenchants/utils/Experience.java rename to core/src/main/java/com/songoda/epicenchants/utils/single/Experience.java index d3d3990..0828b99 100644 --- a/core/src/main/java/com/songoda/epicenchants/utils/Experience.java +++ b/core/src/main/java/com/songoda/epicenchants/utils/single/Experience.java @@ -1,4 +1,4 @@ -package com.songoda.epicenchants.utils; +package com.songoda.epicenchants.utils.single; import org.bukkit.entity.Player; diff --git a/core/src/main/java/com/songoda/epicenchants/utils/single/GeneralUtils.java b/core/src/main/java/com/songoda/epicenchants/utils/single/GeneralUtils.java new file mode 100644 index 0000000..d3eb996 --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/utils/single/GeneralUtils.java @@ -0,0 +1,52 @@ +package com.songoda.epicenchants.utils.single; + +import com.songoda.epicenchants.enums.EnchantResult; +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; + +public class GeneralUtils { + public static boolean chance(int chance) { + return chance((double) chance); + } + + public static boolean chance(double chance) { + return ThreadLocalRandom.current().nextDouble(101) < chance; + } + + public static String color(String input) { + return format(input, "", null); + } + + public static String format(String input, String placeholder, Object toReplace) { + return ChatColor.translateAlternateColorCodes('&', input).replaceAll(placeholder, toReplace == null ? "" : toReplace.toString()); + } + + public static String getMessageFromResult(EnchantResult result) { + return "enchant." + result.toString().toLowerCase().replace("_", ""); + } + + public static X getRandomElement(Set set) { + int item = ThreadLocalRandom.current().nextInt(set.size()); + int i = 0; + for (X obj : set) { + if (i == item) + return obj; + i++; + } + return null; + } + + public static int[] getSlots(String string) { + return Arrays.stream(string.split(",")).filter(StringUtils::isNumeric).mapToInt(Integer::parseInt).toArray(); + } + + public static List getSlotsList(String string) { + return Arrays.stream(string.split(",")).filter(StringUtils::isNumeric).mapToInt(Integer::parseInt).boxed().collect(Collectors.toList()); + } +} diff --git a/core/src/main/java/com/songoda/epicenchants/utils/single/RomanNumber.java b/core/src/main/java/com/songoda/epicenchants/utils/single/RomanNumber.java new file mode 100644 index 0000000..941ccaa --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/utils/single/RomanNumber.java @@ -0,0 +1,30 @@ +package com.songoda.epicenchants.utils.single; + +import java.util.TreeMap; + +public class RomanNumber { + private final static TreeMap map = new TreeMap() {{ + put(1000, "M"); + put(900, "CM"); + put(500, "D"); + put(400, "CD"); + put(100, "C"); + put(90, "XC"); + put(50, "L"); + put(40, "XL"); + put(10, "X"); + put(9, "IX"); + put(5, "V"); + put(4, "IV"); + put(1, "I"); + }}; + + public static String toRoman(int number) { + int l = map.floorKey(number); + if (number == l) { + return map.get(number); + } + return map.get(l) + toRoman(number - l); + } + +} diff --git a/core/src/main/java/com/songoda/epicenchants/utils/single/XMaterial.java b/core/src/main/java/com/songoda/epicenchants/utils/single/XMaterial.java new file mode 100644 index 0000000..537f80d --- /dev/null +++ b/core/src/main/java/com/songoda/epicenchants/utils/single/XMaterial.java @@ -0,0 +1,1018 @@ +package com.songoda.epicenchants.utils.single; + +/** + * The MIT License (MIT) + *

+ * Copyright (c) 2018 Hex_27 + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + **/ + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; + +public enum XMaterial { + ACACIA_BOAT(0, "BOAT_ACACIA"), + ACACIA_BUTTON(0, "WOOD_BUTTON"), + ACACIA_DOOR(0, "ACACIA_DOOR", "ACACIA_DOOR_ITEM"), + ACACIA_FENCE(0, "ACACIA_FENCE"), + ACACIA_FENCE_GATE(0, "ACACIA_FENCE_GATE"), + ACACIA_LEAVES(0, "LEAVES_2"), + ACACIA_LOG(0, "LOG_2"), + ACACIA_PLANKS(4, "WOOD"), + ACACIA_PRESSURE_PLATE(0, "WOOD_PLATE"), + ACACIA_SAPLING(4, "SAPLING"), + ACACIA_SLAB(4, "WOODEN_SLAB", "WOOD_STEP", "WOOD_DOUBLE_STEP"), + ACACIA_STAIRS(4, "ACACIA_STAIRS"), + ACACIA_TRAPDOOR(0, "TRAP_DOOR"), + ACACIA_WOOD(0, "LOG_2"), + ACTIVATOR_RAIL(0, "ACTIVATOR_RAIL"), + AIR(0, "AIR"), + ALLIUM(2, "RED_ROSE"), + ANDESITE(5, "STONE"), + ANVIL(0, "ANVIL"), + APPLE(0, "APPLE"), + ARMOR_STAND(0, "ARMOR_STAND"), + ARROW(0, "ARROW"), + ATTACHED_MELON_STEM(7, "MELON_STEM"), + ATTACHED_PUMPKIN_STEM(7, "PUMPKIN_STEM"), + AZURE_BLUET(3, "RED_ROSE"), + BAKED_POTATO(0, "BAKED_POTATO"), + BARRIER(0, "BARRIER"), + BAT_SPAWN_EGG(0, "MONSTER_EGG"), + BEACON(0, "BEACON"), + BEDROCK(0, "BEDROCK"), + BEEF(0, "RAW_BEEF"), + BEETROOT(0, "BEETROOT"), + BEETROOTS(0, "BEETROOT", "BEETROOT_BLOCK"), + BEETROOT_SEEDS(0, "BEETROOT_SEEDS"), + BEETROOT_SOUP(0, "BEETROOT_SOUP"), + BIRCH_BOAT(0, "BOAT_BIRCH"), + BIRCH_BUTTON(0, "WOOD_BUTTON"), + BIRCH_DOOR(0, "BIRCH_DOOR", "BIRCH_DOOR_ITEM"), + BIRCH_FENCE(0, "BIRCH_FENCE"), + BIRCH_FENCE_GATE(0, "BIRCH_FENCE_GATE"), + BIRCH_LEAVES(2, "LEAVES"), + BIRCH_LOG(2, "LOG"), + BIRCH_PLANKS(2, "WOOD"), + BIRCH_PRESSURE_PLATE(0, "WOOD_PLATE"), + BIRCH_SAPLING(2, "SAPLING"), + BIRCH_SLAB(2, "WOODEN_SLAB", "WOOD_STEP", "WOOD_DOUBLE_STEP"), + BIRCH_STAIRS(0, "BIRCH_WOOD_STAIRS"), + BIRCH_TRAPDOOR(0, "TRAP_DOOR"), + BIRCH_WOOD(2, "LOG"), + BLACK_BANNER(0, "BANNER", "STANDING_BANNER"), + BLACK_BED(15, "BED", "BED_BLOCK"), + BLACK_CARPET(15, "CARPET"), + BLACK_CONCRETE(15, "CONCRETE"), + BLACK_CONCRETE_POWDER(15, "CONCRETE_POWDER"), + BLACK_GLAZED_TERRACOTTA(0, "BLACK_GLAZED_TERRACOTTA"), + BLACK_SHULKER_BOX(0, "BLACK_SHULKER_BOX"), + BLACK_STAINED_GLASS(15, "STAINED_GLASS"), + BLACK_STAINED_GLASS_PANE(15, "STAINED_GLASS_PANE"), + BLACK_TERRACOTTA(15, "STAINED_CLAY"), + BLACK_WALL_BANNER(0, "WALL_BANNER"), + BLACK_WOOL(15, "WOOL"), + BLAZE_POWDER(0, "BLAZE_POWDER"), + BLAZE_ROD(0, "BLAZE_ROD"), + BLAZE_SPAWN_EGG(0, "MONSTER_EGG"), + BLUE_BANNER(11, "BANNER", "STANDING_BANNER"), + BLUE_BED(4, "BED", "BED_BLOCK"), + BLUE_CARPET(11, "CARPET"), + BLUE_CONCRETE(11, "CONCRETE"), + BLUE_CONCRETE_POWDER(11, "CONCRETE_POWDER"), + BLUE_GLAZED_TERRACOTTA(0, "BLUE_GLAZED_TERRACOTTA"), + BLUE_ICE(0, "PACKED_ICE"), + BLUE_ORCHID(1, "RED_ROSE"), + BLUE_SHULKER_BOX(0, "BLUE_SHULKER_BOX"), + BLUE_STAINED_GLASS(11, "STAINED_GLASS"), + BLUE_STAINED_GLASS_PANE(11, "STAINED_GLASS_PANE"), + BLUE_TERRACOTTA(11, "STAINED_CLAY"), + BLUE_WALL_BANNER(11, "WALL_BANNER"), + BLUE_WOOL(11, "WOOL"), + BONE(0, "BONE"), + BONE_BLOCK(0, "BONE_BLOCK"), + BONE_MEAL(15, "INK_SACK"), + BOOK(0, "BOOK"), + BOOKSHELF(0, "BOOKSHELF"), + BOW(0, "BOW"), + BOWL(0, "BOWL"), + BRAIN_CORAL(0, "STONE"), + BRAIN_CORAL_BLOCK(0, "STONE"), + BRAIN_CORAL_FAN(0, "STONE"), + BREAD(0, "BREAD"), + BREWING_STAND(0, "BREWING_STAND", "BREWING_STAND_ITEM"), + BRICK(0, "CLAY_BRICK"), + BRICKS(0, "BRICK"), + BRICK_SLAB(4, "STEP"), + BRICK_STAIRS(0, "BRICK_STAIRS"), + BROWN_BANNER(3, "BANNER", "STANDING_BANNER"), + BROWN_BED(12, "BED", "BED_BLOCK"), + BROWN_CARPET(12, "CARPET"), + BROWN_CONCRETE(12, "CONCRETE"), + BROWN_CONCRETE_POWDER(12, "CONCRETE_POWDER"), + BROWN_GLAZED_TERRACOTTA(0, "BROWN_GLAZED_TERRACOTTA"), + BROWN_MUSHROOM(0, "BROWN_MUSHROOM"), + BROWN_MUSHROOM_BLOCK(0, "BROWN_MUSHROOM", "HUGE_MUSHROOM_1"), + BROWN_SHULKER_BOX(0, "BROWN_SHULKER_BOX"), + BROWN_STAINED_GLASS(12, "STAINED_GLASS"), + BROWN_STAINED_GLASS_PANE(12, "STAINED_GLASS_PANE"), + BROWN_TERRACOTTA(12, "STAINED_CLAY"), + BROWN_WALL_BANNER(3, "WALL_BANNER"), + BROWN_WOOL(12, "WOOL"), + BUBBLE_COLUMN(0, "STONE"), + BUBBLE_CORAL(0, "STONE"), + BUBBLE_CORAL_BLOCK(0, "STONE"), + BUBBLE_CORAL_FAN(0, "STONE"), + BUCKET(0, "BUCKET"), + CACTUS(0, "CACTUS"), + CACTUS_GREEN(2, "INK_SACK"), + CAKE(0, "CAKE", "CAKE_BLOCK"), + CARROT(0, "CARROT_ITEM"), + CARROTS(0, "CARROT"), + CARROT_ON_A_STICK(0, "CARROT_STICK"), + CARVED_PUMPKIN(0, "PUMPKIN"), + CAULDRON(0, "CAULDRON", "CAULDRON_ITEM"), + CAVE_AIR(0, "AIR"), + CAVE_SPIDER_SPAWN_EGG(0, "MONSTER_EGG"), + CHAINMAIL_BOOTS(0, "CHAINMAIL_BOOTS"), + CHAINMAIL_CHESTPLATE(0, "CHAINMAIL_CHESTPLATE"), + CHAINMAIL_HELMET(0, "CHAINMAIL_HELMET"), + CHAINMAIL_LEGGINGS(0, "CHAINMAIL_LEGGINGS"), + CHAIN_COMMAND_BLOCK(0, "COMMAND_CHAIN"), + CHARCOAL(1, "COAL"), + CHEST(0, "CHEST", "LOCKED_CHEST"), + CHEST_MINECART(0, "STORAGE_MINECART"), + CHICKEN(0, "RAW_CHICKEN"), + CHICKEN_SPAWN_EGG(0, "MONSTER_EGG"), + CHIPPED_ANVIL(1, "ANVIL"), + CHISELED_QUARTZ_BLOCK(1, "QUARTZ_BLOCK"), + CHISELED_RED_SANDSTONE(1, "RED_SANDSTONE"), + CHISELED_SANDSTONE(1, "SANDSTONE"), + CHISELED_STONE_BRICKS(3, "SMOOTH_BRICK"), + CHORUS_FLOWER(0, "CHORUS_FLOWER"), + CHORUS_FRUIT(0, "CHORUS_FRUIT"), + CHORUS_PLANT(0, "CHORUS_PLANT"), + CLAY(0, "CLAY"), + CLAY_BALL(0, "CLAY_BALL"), + CLOCK(0, "WATCH"), + COAL(0, "COAL"), + COAL_BLOCK(0, "COAL_BLOCK"), + COAL_ORE(0, "COAL_ORE"), + COARSE_DIRT(1, "DIRT"), + COBBLESTONE(0, "COBBLESTONE"), + COBBLESTONE_SLAB(3, "STEP"), + COBBLESTONE_STAIRS(0, "COBBLESTONE_STAIRS"), + COBBLESTONE_WALL(0, "COBBLE_WALL"), + COBWEB(0, "WEB"), + COCOA(0, "COCOA"), + COCOA_BEANS(3, "INK_SACK"), + COD(0, "RAW_FISH"), + COD_BUCKET(0, "BUCKET"), + COD_SPAWN_EGG(0, "MONSTER_EGG"), + COMMAND_BLOCK(0, "COMMAND"), + COMMAND_BLOCK_MINECART(0, "COMMAND_MINECART"), + COMPARATOR(0, "REDSTONE_COMPARATOR", "REDSTONE_COMPARATOR_ON", "REDSTONE_COMPARATOR_OFF"), + COMPASS(0, "COMPASS"), + CONDUIT(0, "STONE"), + COOKED_BEEF(0, "COOKED_BEEF"), + COOKED_CHICKEN(0, "COOKED_CHICKEN"), + COOKED_COD(0, "COOKED_FISH"), + COOKED_MUTTON(0, "COOKED_MUTTON"), + COOKED_PORKCHOP(0, "GRILLED_PORK"), + COOKED_RABBIT(0, "COOKED_RABBIT"), + COOKED_SALMON(1, "COOKED_FISH"), + COOKIE(0, "COOKIE"), + COW_SPAWN_EGG(0, "MONSTER_EGG"), + CRACKED_STONE_BRICKS(2, "SMOOTH_BRICK"), + CRAFTING_TABLE(0, "WORKBENCH"), + CREEPER_HEAD(0, "SKULL", "SKULL_ITEM"), + CREEPER_SPAWN_EGG(0, "MONSTER_EGG"), + CREEPER_WALL_HEAD(0, "SKULL", "SKULL_ITEM"), + CUT_RED_SANDSTONE(0, "STONE"), + CUT_SANDSTONE(0, "STONE"), + CYAN_BANNER(6, "BANNER", "STANDING_BANNER"), + CYAN_BED(9, "BED", "BED_BLOCK"), + CYAN_CARPET(9, "CARPET"), + CYAN_CONCRETE(9, "CONCRETE"), + CYAN_CONCRETE_POWDER(9, "CONCRETE_POWDER"), + CYAN_DYE(6, "INK_SACK"), + CYAN_GLAZED_TERRACOTTA(0, "CYAN_GLAZED_TERRACOTTA"), + CYAN_SHULKER_BOX(0, "CYAN_SHULKER_BOX"), + CYAN_STAINED_GLASS(9, "STAINED_GLASS"), + CYAN_STAINED_GLASS_PANE(9, "STAINED_GLASS_PANE"), + CYAN_TERRACOTTA(9, "STAINED_CLAY"), + CYAN_WALL_BANNER(0, "WALL_BANNER"), + CYAN_WOOL(9, "WOOL"), + DAMAGED_ANVIL(2, "ANVIL"), + DANDELION(0, "YELLOW_FLOWER"), + DANDELION_YELLOW(11, "INK_SACK"), + DARK_OAK_BOAT(0, "BOAT_DARK_OAK"), + DARK_OAK_BUTTON(0, "WOOD_BUTTON"), + DARK_OAK_DOOR(0, "DARK_OAK_DOOR", "DARK_OAK_DOOR_ITEM"), + DARK_OAK_FENCE(0, "DARK_OAK_FENCE"), + DARK_OAK_FENCE_GATE(0, "DARK_OAK_FENCE_GATE"), + DARK_OAK_LEAVES(1, "LEAVES_2"), + DARK_OAK_LOG(1, "LOG_2"), + DARK_OAK_PLANKS(5, "WOOD"), + DARK_OAK_PRESSURE_PLATE(0, "WOOD_PLATE"), + DARK_OAK_SAPLING(5, "SAPLING"), + DARK_OAK_SLAB(0, "WOODEN_SLAB", "WOOD_STEP", "WOOD_DOUBLE_STEP"), + DARK_OAK_STAIRS(0, "DARK_OAK_STAIRS"), + DARK_OAK_TRAPDOOR(0, "TRAP_DOOR"), + DARK_OAK_WOOD(1, "LOG_2"), + DARK_PRISMARINE(2, "PRISMARINE"), + DARK_PRISMARINE_SLAB(0, "STONE"), + DARK_PRISMARINE_STAIRS(0, "STONE"), + DAYLIGHT_DETECTOR(0, "DAYLIGHT_DETECTOR", "DAYLIGHT_DETECTOR_INVERTED"), + DEAD_BRAIN_CORAL_BLOCK(0, "STONE"), + DEAD_BUBBLE_CORAL_BLOCK(0, "STONE"), + DEAD_BUSH(0, "DEAD_BUSH"), + DEAD_FIRE_CORAL_BLOCK(0, "STONE"), + DEAD_HORN_CORAL_BLOCK(0, "STONE"), + DEAD_TUBE_CORAL_BLOCK(0, "STONE"), + DEBUG_STICK(0, "STICK"), + DETECTOR_RAIL(0, "DETECTOR_RAIL"), + DIAMOND(0, "DIAMOND"), + DIAMOND_AXE(0, "DIAMOND_AXE"), + DIAMOND_BLOCK(0, "DIAMOND_BLOCK"), + DIAMOND_BOOTS(0, "DIAMOND_BOOTS"), + DIAMOND_CHESTPLATE(0, "DIAMOND_CHESTPLATE"), + DIAMOND_HELMET(0, "DIAMOND_HELMET"), + DIAMOND_HOE(0, "DIAMOND_HOE"), + DIAMOND_HORSE_ARMOR(0, "DIAMOND_BARDING"), + DIAMOND_LEGGINGS(0, "DIAMOND_LEGGINGS"), + DIAMOND_ORE(0, "DIAMOND_ORE"), + DIAMOND_PICKAXE(0, "DIAMOND_PICKAXE"), + DIAMOND_SHOVEL(0, "DIAMOND_SPADE"), + DIAMOND_SWORD(0, "DIAMOND_SWORD"), + DIORITE(3, "STONE"), + DIRT(0, "DIRT"), + DISPENSER(0, "DISPENSER"), + DOLPHIN_SPAWN_EGG(0, "MONSTER_EGG"), + DONKEY_SPAWN_EGG(0, "MONSTER_EGG"), + DRAGON_BREATH(0, "DRAGONS_BREATH"), + DRAGON_EGG(0, "DRAGON_EGG"), + DRAGON_HEAD(5, "SKULL", "SKULL_ITEM"), + DRAGON_WALL_HEAD(0, "SKULL", "SKULL_ITEM"), + DRIED_KELP(0, "STONE"), + DRIED_KELP_BLOCK(0, "STONE"), + DROPPER(0, "DROPPER"), + DROWNED_SPAWN_EGG(0, "MONSTER_EGG"), + EGG(0, "EGG"), + ELDER_GUARDIAN_SPAWN_EGG(0, "MONSTER_EGG"), + ELYTRA(0, "ELYTRA"), + EMERALD(0, "EMERALD"), + EMERALD_BLOCK(0, "EMERALD_BLOCK"), + EMERALD_ORE(0, "EMERALD_ORE"), + ENCHANTED_BOOK(0, "ENCHANTED_BOOK"), + ENCHANTED_GOLDEN_APPLE(1, "GOLDEN_APPLE"), + ENCHANTING_TABLE(0, "ENCHANTMENT_TABLE"), + ENDERMAN_SPAWN_EGG(0, "MONSTER_EGG"), + ENDERMITE_SPAWN_EGG(0, "MONSTER_EGG"), + ENDER_CHEST(0, "ENDER_CHEST"), + ENDER_EYE(0, "EYE_OF_ENDER"), + ENDER_PEARL(0, "ENDER_PEARL"), + END_CRYSTAL(0, "END_CRYSTAL"), + END_GATEWAY(0, "END_GATEWAY"), + END_PORTAL(0, "ENDER_PORTAL"), + END_PORTAL_FRAME(0, "ENDER_PORTAL_FRAME"), + END_ROD(0, "END_ROD"), + END_STONE(0, "ENDER_STONE"), + END_STONE_BRICKS(0, "END_BRICKS"), + EVOKER_SPAWN_EGG(0, "MONSTER_EGG"), + EXPERIENCE_BOTTLE(0, "EXP_BOTTLE"), + FARMLAND(0, "SOIL"), + FEATHER(0, "FEATHER"), + FERMENTED_SPIDER_EYE(0, "FERMENTED_SPIDER_EYE"), + FERN(2, "LONG_GRASS"), + FILLED_MAP(0, "MAP"), + FIRE(0, "FIRE"), + FIREWORK_ROCKET(0, "FIREWORK"), + FIREWORK_STAR(0, "FIREWORK_CHARGE"), + FIRE_CHARGE(0, "FIREBALL"), + FIRE_CORAL(0, "STONE"), + FIRE_CORAL_BLOCK(0, "STONE"), + FIRE_CORAL_FAN(0, "STONE"), + FISHING_ROD(0, "FISHING_ROD"), + FLINT(0, "FLINT"), + FLINT_AND_STEEL(0, "FLINT_AND_STEEL"), + FLOWER_POT(0, "FLOWER_POT", "FLOWER_POT_ITEM"), + FROSTED_ICE(0, "FROSTED_ICE"), + FURNACE(0, "FURNACE", "BURNING_FURNACE"), + FURNACE_MINECART(0, "POWERED_MINECART"), + GHAST_SPAWN_EGG(0, "MONSTER_EGG"), + GHAST_TEAR(0, "GHAST_TEAR"), + GLASS(0, "GLASS"), + GLASS_BOTTLE(0, "GLASS_BOTTLE"), + GLASS_PANE(0, "THIN_GLASS"), + GLISTERING_MELON_SLICE(0, "SPECKLED_MELON"), + GLOWSTONE(0, "GLOWSTONE"), + GLOWSTONE_DUST(0, "GLOWSTONE_DUST"), + GOLDEN_APPLE(0, "GOLDEN_APPLE"), + GOLDEN_AXE(0, "GOLD_AXE"), + GOLDEN_BOOTS(0, "GOLD_BOOTS"), + GOLDEN_CARROT(0, "GOLDEN_CARROT"), + GOLDEN_CHESTPLATE(0, "GOLD_CHESTPLATE"), + GOLDEN_HELMET(0, "GOLD_HELMET"), + GOLDEN_HOE(0, "GOLD_HOE"), + GOLDEN_HORSE_ARMOR(0, "GOLD_BARDING"), + GOLDEN_LEGGINGS(0, "GOLD_LEGGINGS"), + GOLDEN_PICKAXE(0, "GOLD_PICKAXE"), + GOLDEN_SHOVEL(0, "GOLD_SPADE"), + GOLDEN_SWORD(0, "GOLD_SWORD"), + GOLD_BLOCK(0, "GOLD_BLOCK"), + GOLD_INGOT(0, "GOLD_INGOT"), + GOLD_NUGGET(0, "GOLD_NUGGET"), + GOLD_ORE(0, "GOLD_ORE"), + GRANITE(1, "STONE"), + GRASS(0, "GRASS"), + GRASS_BLOCK(0, "GRASS"), + GRASS_PATH(0, "GRASS_PATH"), + GRAVEL(0, "GRAVEL"), + GRAY_BANNER(8, "BANNER", "STANDING_BANNER"), + GRAY_BED(7, "BED", "BED_BLOCK"), + GRAY_CARPET(7, "CARPET"), + GRAY_CONCRETE(7, "CONCRETE"), + GRAY_CONCRETE_POWDER(7, "CONCRETE_POWDER"), + GRAY_DYE(8, "INK_SACK"), + GRAY_GLAZED_TERRACOTTA(0, "GRAY_GLAZED_TERRACOTTA"), + GRAY_SHULKER_BOX(0, "GRAY_SHULKER_BOX"), + GRAY_STAINED_GLASS(7, "STAINED_GLASS"), + GRAY_STAINED_GLASS_PANE(7, "STAINED_GLASS_PANE"), + GRAY_TERRACOTTA(7, "STAINED_CLAY"), + GRAY_WALL_BANNER(0, "WALL_BANNER"), + GRAY_WOOL(7, "WOOL"), + GREEN_BANNER(2, "BANNER", "STANDING_BANNER"), + GREEN_BED(13, "BED", "BED_BLOCK"), + GREEN_CARPET(13, "CARPET"), + GREEN_CONCRETE(13, "CONCRETE"), + GREEN_CONCRETE_POWDER(13, "CONCRETE_POWDER"), + GREEN_GLAZED_TERRACOTTA(0, "GREEN_GLAZED_TERRACOTTA"), + GREEN_SHULKER_BOX(0, "GREEN_SHULKER_BOX"), + GREEN_STAINED_GLASS(13, "STAINED_GLASS"), + GREEN_STAINED_GLASS_PANE(13, "STAINED_GLASS_PANE"), + GREEN_TERRACOTTA(13, "STAINED_CLAY"), + GREEN_WALL_BANNER(0, "WALL_BANNER"), + GREEN_WOOL(13, "WOOL"), + GUARDIAN_SPAWN_EGG(0, "MONSTER_EGG"), + GUNPOWDER(0, "SULPHUR"), + HAY_BLOCK(0, "HAY_BLOCK"), + HEART_OF_THE_SEA(0, "STONE"), + HEAVY_WEIGHTED_PRESSURE_PLATE(0, "IRON_PLATE"), + HOPPER(0, "HOPPER"), + HOPPER_MINECART(0, "HOPPER_MINECART"), + HORN_CORAL(0, "STONE"), + HORN_CORAL_BLOCK(0, "STONE"), + HORN_CORAL_FAN(0, "STONE"), + HORSE_SPAWN_EGG(0, "MONSTER_EGG"), + HUSK_SPAWN_EGG(0, "MONSTER_EGG"), + ICE(0, "ICE"), + INFESTED_CHISELED_STONE_BRICKS(5, "MONSTER_EGGS"), + INFESTED_COBBLESTONE(1, "MONSTER_EGGS"), + INFESTED_CRACKED_STONE_BRICKS(4, "MONSTER_EGGS"), + INFESTED_MOSSY_STONE_BRICKS(3, "MONSTER_EGGS"), + INFESTED_STONE(0, "MONSTER_EGGS"), + INFESTED_STONE_BRICKS(2, "MONSTER_EGGS"), + INK_SAC(0, "INK_SACK"), + IRON_AXE(0, "IRON_AXE"), + IRON_BARS(0, "IRON_FENCE"), + IRON_BLOCK(0, "IRON_BLOCK"), + IRON_BOOTS(0, "IRON_BOOTS"), + IRON_CHESTPLATE(0, "IRON_CHESTPLATE"), + IRON_DOOR(0, "IRON_DOOR", "IRON_DOOR_BLOCK"), + IRON_HELMET(0, "IRON_HELMET"), + IRON_HOE(0, "IRON_HOE"), + IRON_HORSE_ARMOR(0, "IRON_BARDING"), + IRON_INGOT(0, "IRON_INGOT"), + IRON_LEGGINGS(0, "IRON_LEGGINGS"), + IRON_NUGGET(0, "IRON_NUGGET"), + IRON_ORE(0, "IRON_ORE"), + IRON_PICKAXE(0, "IRON_PICKAXE"), + IRON_SHOVEL(0, "IRON_SPADE"), + IRON_SWORD(0, "IRON_SWORD"), + IRON_TRAPDOOR(0, "IRON_TRAPDOOR"), + ITEM_FRAME(0, "ITEM_FRAME"), + JACK_O_LANTERN(0, "JACK_O_LANTERN"), + JUKEBOX(0, "JUKEBOX"), + JUNGLE_BOAT(0, "BOAT_JUNGLE"), + JUNGLE_BUTTON(0, "WOOD_BUTTON"), + JUNGLE_DOOR(0, "JUNGLE_DOOR", "JUNGLE_DOOR_ITEM"), + JUNGLE_FENCE(0, "JUNGLE_FENCE"), + JUNGLE_FENCE_GATE(0, "JUNGLE_FENCE_GATE"), + JUNGLE_LEAVES(3, "LEAVES"), + JUNGLE_LOG(3, "LOG"), + JUNGLE_PLANKS(3, "WOOD"), + JUNGLE_PRESSURE_PLATE(0, "WOOD_PLATE"), + JUNGLE_SAPLING(3, "SAPLING"), + JUNGLE_SLAB(3, "WOODEN_SLAB", "WOOD_STEP", "WOOD_DOUBLE_STEP"), + JUNGLE_STAIRS(0, "JUNGLE_WOOD_STAIRS"), + JUNGLE_TRAPDOOR(0, "TRAP_DOOR"), + JUNGLE_WOOD(3, "LOG"), + KELP(0, "STONE"), + KELP_PLANT(0, "STONE"), + KNOWLEDGE_BOOK(0, "KNOWLEDGE_BOOK"), + LADDER(0, "LADDER"), + LAPIS_BLOCK(0, "LAPIS_BLOCK"), + LAPIS_LAZULI(4, "INK_SACK"), + LAPIS_ORE(0, "LAPIS_ORE"), + LARGE_FERN(3, "DOUBLE_PLANT"), + LAVA(0, "LAVA", "STATIONARY_LAVA"), + LAVA_BUCKET(0, "LAVA_BUCKET"), + LEAD(0, "LEASH"), + LEATHER(0, "LEATHER"), + LEATHER_BOOTS(0, "LEATHER_BOOTS"), + LEATHER_CHESTPLATE(0, "LEATHER_CHESTPLATE"), + LEATHER_HELMET(0, "LEATHER_HELMET"), + LEATHER_LEGGINGS(0, "LEATHER_LEGGINGS"), + LEVER(0, "LEVER"), + LIGHT_BLUE_BANNER(12, "BANNER", "STANDING_BANNER"), + LIGHT_BLUE_BED(3, "BED", "BED_BLOCK"), + LIGHT_BLUE_CARPET(3, "CARPET"), + LIGHT_BLUE_CONCRETE(3, "CONCRETE"), + LIGHT_BLUE_CONCRETE_POWDER(3, "CONCRETE_POWDER"), + LIGHT_BLUE_DYE(12, "INK_SACK"), + LIGHT_BLUE_GLAZED_TERRACOTTA(0, "LIGHT_BLUE_GLAZED_TERRACOTTA"), + LIGHT_BLUE_SHULKER_BOX(0, "LIGHT_BLUE_SHULKER_BOX"), + LIGHT_BLUE_STAINED_GLASS(3, "STAINED_GLASS"), + LIGHT_BLUE_STAINED_GLASS_PANE(3, "STAINED_GLASS_PANE"), + LIGHT_BLUE_TERRACOTTA(3, "STAINED_CLAY"), + LIGHT_BLUE_WALL_BANNER(0, "BANNER", "STANDING_BANNER"), + LIGHT_BLUE_WOOL(3, "WOOL"), + LIGHT_GRAY_BANNER(7, "BANNER", "STANDING_BANNER"), + LIGHT_GRAY_BED(8, "BED", "BED_BLOCK"), + LIGHT_GRAY_CARPET(8, "CARPET"), + LIGHT_GRAY_CONCRETE(8, "CONCRETE"), + LIGHT_GRAY_CONCRETE_POWDER(8, "CONCRETE_POWDER"), + LIGHT_GRAY_DYE(7, "INK_SACK"), + LIGHT_GRAY_GLAZED_TERRACOTTA(0, "SILVER_GLAZED_TERRACOTTA"), + LIGHT_GRAY_SHULKER_BOX(0, "SILVER_SHULKER_BOX"), + LIGHT_GRAY_STAINED_GLASS(8, "STAINED_GLASS"), + LIGHT_GRAY_STAINED_GLASS_PANE(8, "STAINED_GLASS_PANE"), + LIGHT_GRAY_TERRACOTTA(8, "STAINED_CLAY"), + LIGHT_GRAY_WALL_BANNER(0, "WALL_BANNER"), + LIGHT_GRAY_WOOL(8, "WOOL"), + LIGHT_WEIGHTED_PRESSURE_PLATE(0, "GOLD_PLATE"), + LILAC(1, "DOUBLE_PLANT"), + LILY_PAD(0, "WATER_LILY"), + LIME_BANNER(10, "BANNER", "STANDING_BANNER"), + LIME_BED(5, "BED", "BED_BLOCK"), + LIME_CARPET(5, "CARPET"), + LIME_CONCRETE(5, "CONCRETE"), + LIME_CONCRETE_POWDER(5, "CONCRETE_POWDER"), + LIME_DYE(10, "INK_SACK"), + LIME_GLAZED_TERRACOTTA(0, "LIME_GLAZED_TERRACOTTA"), + LIME_SHULKER_BOX(0, "LIME_SHULKER_BOX"), + LIME_STAINED_GLASS(5, "STAINED_GLASS"), + LIME_STAINED_GLASS_PANE(5, "STAINED_GLASS_PANE"), + LIME_TERRACOTTA(5, "STAINED_CLAY"), + LIME_WALL_BANNER(0, "WALL_BANNER"), + LIME_WOOL(5, "WOOL"), + LINGERING_POTION(0, "LINGERING_POTION"), + LLAMA_SPAWN_EGG(0, "MONSTER_EGG"), + MAGENTA_BANNER(13, "BANNER", "STANDING_BANNER"), + MAGENTA_BED(2, "BED", "BED_BLOCK"), + MAGENTA_CARPET(2, "CARPET"), + MAGENTA_CONCRETE(2, "CONCRETE"), + MAGENTA_CONCRETE_POWDER(2, "CONCRETE_POWDER"), + MAGENTA_DYE(13, "INK_SACK"), + MAGENTA_GLAZED_TERRACOTTA(0, "MAGENTA_GLAZED_TERRACOTTA"), + MAGENTA_SHULKER_BOX(0, "MAGENTA_SHULKER_BOX"), + MAGENTA_STAINED_GLASS(2, "STAINED_GLASS"), + MAGENTA_STAINED_GLASS_PANE(2, "STAINED_GLASS_PANE"), + MAGENTA_TERRACOTTA(2, "STAINED_CLAY"), + MAGENTA_WALL_BANNER(0, "WALL_BANNER"), + MAGENTA_WOOL(2, "WOOL"), + MAGMA_BLOCK(0, "MAGMA"), + MAGMA_CREAM(0, "MAGMA_CREAM"), + MAGMA_CUBE_SPAWN_EGG(0, "MONSTER_EGG"), + MAP(0, "MAP", "EMPTY_MAP"), + MELON(0, "MELON_BLOCK"), + MELON_SEEDS(0, "MELON_SEEDS"), + MELON_SLICE(0, "MELON"), + MELON_STEM(0, "MELON_STEM"), + MILK_BUCKET(0, "MILK_BUCKET"), + MINECART(0, "MINECART"), + MOOSHROOM_SPAWN_EGG(0, "MONSTER_EGG"), + MOSSY_COBBLESTONE(0, "MOSSY_COBBLESTONE"), + MOSSY_COBBLESTONE_WALL(1, "COBBLE_WALL"), + MOSSY_STONE_BRICKS(1, "SMOOTH_BRICK"), + MOVING_PISTON(0, "PISTON_MOVING_PIECE"), + MULE_SPAWN_EGG(0, "MONSTER_EGG"), + MUSHROOM_STEM(0, "BROWN_MUSHROOM"), + MUSHROOM_STEW(0, "MUSHROOM_SOUP"), + MUSIC_DISC_11(0, "GOLD_RECORD"), + MUSIC_DISC_13(0, "GREEN_RECORD"), + MUSIC_DISC_BLOCKS(0, "RECORD_3"), + MUSIC_DISC_CAT(0, "RECORD_4"), + MUSIC_DISC_CHIRP(0, "RECORD_5"), + MUSIC_DISC_FAR(0, "RECORD_6"), + MUSIC_DISC_MALL(0, "RECORD_7"), + MUSIC_DISC_MELLOHI(0, "RECORD_8"), + MUSIC_DISC_STAL(0, "RECORD_9"), + MUSIC_DISC_STRAD(0, "RECORD_10"), + MUSIC_DISC_WAIT(0, "RECORD_11"), + MUSIC_DISC_WARD(0, "RECORD_12"), + MUTTON(0, "MUTTON"), + MYCELIUM(0, "MYCEL"), + NAME_TAG(0, "NAME_TAG"), + NAUTILUS_SHELL(0, "STONE"), + NETHERRACK(0, "NETHERRACK"), + NETHER_BRICK(0, "NETHER_BRICK"), + NETHER_BRICKS(0, "NETHER_BRICK"), + NETHER_BRICK_FENCE(0, "NETHER_FENCE"), + NETHER_BRICK_SLAB(6, "STEP"), + NETHER_BRICK_STAIRS(0, "NETHER_BRICK_STAIRS"), + NETHER_PORTAL(0, "PORTAL"), + NETHER_QUARTZ_ORE(0, "QUARTZ_ORE"), + NETHER_STAR(0, "NETHER_STAR"), + NETHER_WART(0, "NETHER_STALK"), + NETHER_WART_BLOCK(0, "NETHER_WART_BLOCK", "NETHER_WARTS"), + NOTE_BLOCK(0, "NOTE_BLOCK"), + OAK_BOAT(0, "BOAT"), + OAK_BUTTON(0, "WOOD_BUTTON"), + OAK_DOOR(0, "WOODEN_DOOR", "WOOD_DOOR"), + OAK_FENCE(0, "FENCE"), + OAK_FENCE_GATE(0, "FENCE_GATE"), + OAK_LEAVES(0, "LEAVES"), + OAK_LOG(0, "LOG"), + OAK_PLANKS(0, "WOOD"), + OAK_PRESSURE_PLATE(0, "WOOD_PLATE"), + OAK_SAPLING(0, "SAPLING"), + OAK_SLAB(0, "WOODEN_SLAB", "WOOD_STEP", "WOOD_DOUBLE_STEP"), + OAK_STAIRS(0, "WOOD_STAIRS"), + OAK_TRAPDOOR(0, "TRAP_DOOR"), + OAK_WOOD(0, "LOG"), + OBSERVER(0, "OBSERVER"), + OBSIDIAN(0, "OBSIDIAN"), + OCELOT_SPAWN_EGG(0, "RECORD_12"), + ORANGE_BANNER(14, "BANNER", "STANDING_BANNER"), + ORANGE_BED(1, "BED", "BED_BLOCK"), + ORANGE_CARPET(1, "CARPET"), + ORANGE_CONCRETE(1, "CONCRETE"), + ORANGE_CONCRETE_POWDER(1, "CONCRETE_POWDER"), + ORANGE_DYE(14, "INK_SACK"), + ORANGE_GLAZED_TERRACOTTA(0, "ORANGE_GLAZED_TERRACOTTA"), + ORANGE_SHULKER_BOX(0, "ORANGE_SHULKER_BOX"), + ORANGE_STAINED_GLASS(1, "STAINED_GLASS"), + ORANGE_STAINED_GLASS_PANE(1, "STAINED_GLASS_PANE"), + ORANGE_TERRACOTTA(1, "STAINED_CLAY"), + ORANGE_TULIP(5, "RED_ROSE"), + ORANGE_WALL_BANNER(0, "WALL_BANNER"), + ORANGE_WOOL(1, "WOOL"), + OXEYE_DAISY(8, "RED_ROSE"), + PACKED_ICE(0, "PACKED_ICE"), + PAINTING(0, "PAINTING"), + PAPER(0, "PAPER"), + PARROT_SPAWN_EGG(0, "MONSTER_EGG"), + PEONY(5, "DOUBLE_PLANT"), + PETRIFIED_OAK_SLAB(0, "STONE"), + PHANTOM_MEMBRANE(0, "STONE"), + PHANTOM_SPAWN_EGG(0, "MONSTER_EGG"), + PIG_SPAWN_EGG(0, "MONSTER_EGG"), + PINK_BANNER(9, "BANNER", "STANDING_BANNER"), + PINK_BED(6, "BED", "BED_BLOCK"), + PINK_CARPET(6, "CARPET"), + PINK_CONCRETE(6, "CONCRETE"), + PINK_CONCRETE_POWDER(6, "CONCRETE_POWDER"), + PINK_DYE(9, "INK_SACK"), + PINK_GLAZED_TERRACOTTA(0, "PINK_GLAZED_TERRACOTTA"), + PINK_SHULKER_BOX(0, "PINK_SHULKER_BOX"), + PINK_STAINED_GLASS(6, "STAINED_GLASS"), + PINK_STAINED_GLASS_PANE(6, "STAINED_GLASS_PANE"), + PINK_TERRACOTTA(6, "STAINED_CLAY"), + PINK_TULIP(7, "RED_ROSE"), + PINK_WALL_BANNER(0, "WALL_BANNER"), + PINK_WOOL(6, "WOOL"), + PISTON(0, "PISTON_BASE"), + PISTON_HEAD(0, "PISTON_EXTENSION"), + PLAYER_HEAD(0, "SKULL", "SKULL_ITEM"), + PLAYER_WALL_HEAD(0, "SKULL", "SKULL_ITEM"), + PODZOL(2, "DIRT"), + POISONOUS_POTATO(0, "POISONOUS_POTATO"), + POLAR_BEAR_SPAWN_EGG(0, "MONSTER_EGG"), + POLISHED_ANDESITE(6, "STONE"), + POLISHED_DIORITE(4, "STONE"), + POLISHED_GRANITE(2, "STONE"), + POPPED_CHORUS_FRUIT(0, "CHORUS_FRUIT_POPPED"), + POPPY(0, "RED_ROSE"), + PORKCHOP(0, "PORK"), + POTATO(0, "POTATO_ITEM"), + POTATOES(0, "POTATO"), + POTION(0, "POTION"), + POTTED_ACACIA_SAPLING(0, "FLOWER_POT"), + POTTED_ALLIUM(0, "FLOWER_POT"), + POTTED_AZURE_BLUET(0, "FLOWER_POT"), + POTTED_BIRCH_SAPLING(0, "FLOWER_POT"), + POTTED_BLUE_ORCHID(0, "FLOWER_POT"), + POTTED_BROWN_MUSHROOM(0, "FLOWER_POT"), + POTTED_CACTUS(0, "FLOWER_POT"), + POTTED_DANDELION(0, "FLOWER_POT"), + POTTED_DARK_OAK_SAPLING(0, "FLOWER_POT"), + POTTED_DEAD_BUSH(0, "FLOWER_POT"), + POTTED_FERN(0, "FLOWER_POT"), + POTTED_JUNGLE_SAPLING(0, "FLOWER_POT"), + POTTED_OAK_SAPLING(0, "FLOWER_POT"), + POTTED_ORANGE_TULIP(0, "FLOWER_POT"), + POTTED_OXEYE_DAISY(0, "FLOWER_POT"), + POTTED_PINK_TULIP(0, "FLOWER_POT"), + POTTED_POPPY(0, "FLOWER_POT"), + POTTED_RED_MUSHROOM(0, "FLOWER_POT"), + POTTED_RED_TULIP(0, "FLOWER_POT"), + POTTED_SPRUCE_SAPLING(0, "FLOWER_POT"), + POTTED_WHITE_TULIP(0, "FLOWER_POT"), + POWERED_RAIL(0, "POWERED_RAIL"), + PRISMARINE(0, "PRISMARINE"), + PRISMARINE_BRICKS(1, "PRISMARINE"), + PRISMARINE_BRICK_SLAB(0, "STONE"), + PRISMARINE_BRICK_STAIRS(0, "STONE"), + PRISMARINE_CRYSTALS(0, "PRISMARINE_CRYSTALS"), + PRISMARINE_SHARD(0, "PRISMARINE_SHARD"), + PRISMARINE_SLAB(0, "STONE"), + PRISMARINE_STAIRS(0, "STONE"), + PUFFERFISH(3, "RAW_FISH"), + PUFFERFISH_BUCKET(0, "STONE"), + PUFFERFISH_SPAWN_EGG(0, "MONSTER_EGG"), + PUMPKIN(0, "PUMPKIN"), + PUMPKIN_PIE(0, "PUMPKIN_PIE"), + PUMPKIN_SEEDS(0, "PUMPKIN_SEEDS"), + PUMPKIN_STEM(0, "PUMPKIN_STEM"), + PURPLE_BANNER(5, "BANNER", "STANDING_BANNER"), + PURPLE_BED(10, "BED", "BED_BLOCK"), + PURPLE_CARPET(10, "CARPET"), + PURPLE_CONCRETE(10, "CONCRETE"), + PURPLE_CONCRETE_POWDER(10, "CONCRETE_POWDER"), + PURPLE_DYE(5, "INK_SACK"), + PURPLE_GLAZED_TERRACOTTA(0, "PURPLE_GLAZED_TERRACOTTA"), + PURPLE_SHULKER_BOX(0, "PURPLE_SHULKER_BOX"), + PURPLE_STAINED_GLASS(10, "STAINED_GLASS"), + PURPLE_STAINED_GLASS_PANE(10, "STAINED_GLASS_PANE"), + PURPLE_TERRACOTTA(10, "STAINED_CLAY"), + PURPLE_WALL_BANNER(0, "WALL_BANNER"), + PURPLE_WOOL(10, "WOOL"), + PURPUR_BLOCK(0, "PURPUR_BLOCK"), + PURPUR_PILLAR(0, "PURPUR_PILLAR"), + PURPUR_SLAB(0, "PURPUR_SLAB", "PURPUR_DOUBLE_SLAB"), + PURPUR_STAIRS(0, "PURPUR_STAIRS"), + QUARTZ(0, "QUARTZ"), + QUARTZ_BLOCK(0, "QUARTZ_BLOCK"), + QUARTZ_PILLAR(2, "QUARTZ_BLOCK"), + QUARTZ_SLAB(7, "STEP"), + QUARTZ_STAIRS(0, "QUARTZ_STAIRS"), + RABBIT(0, "RABBIT"), + RABBIT_FOOT(0, "RABBIT_FOOT"), + RABBIT_HIDE(0, "RABBIT_HIDE"), + RABBIT_SPAWN_EGG(0, "MONSTER_EGG"), + RABBIT_STEW(0, "RABBIT_STEW"), + RAIL(0, "RAILS"), + REDSTONE(0, "REDSTONE"), + REDSTONE_BLOCK(0, "REDSTONE_BLOCK"), + REDSTONE_LAMP(0, "REDSTONE_LAMP_ON", "REDSTONE_LAMP_OFF"), + REDSTONE_ORE(0, "REDSTONE_ORE", "GLOWING_REDSTONE_ORE"), + REDSTONE_TORCH(0, "REDSTONE_TORCH_ON", "REDSTONE_TORCH_OFF"), + REDSTONE_WALL_TORCH(1, "REDSTONE_TORCH_ON", "REDSTONE_TORCH_OFF"), + REDSTONE_WIRE(0, "REDSTONE_WIRE"), + RED_BANNER(1, "BANNER", "STANDING_BANNER"), + RED_BED(14, "BED", "BED_BLOCK"), + RED_CARPET(14, "CARPET"), + RED_CONCRETE(14, "CONCRETE"), + RED_CONCRETE_POWDER(14, "CONCRETE_POWDER"), + RED_GLAZED_TERRACOTTA(0, "RED_GLAZED_TERRACOTTA"), + RED_MUSHROOM(0, "RED_MUSHROOM"), + RED_MUSHROOM_BLOCK(0, "RED_MUSHROOM", "HUGE_MUSHROOM_2"), + RED_NETHER_BRICKS(0, "RED_NETHER_BRICK"), + RED_SAND(1, "SAND"), + RED_SANDSTONE(0, "RED_SANDSTONE"), + RED_SANDSTONE_SLAB(0, "STONE_SLAB2", "DOUBLE_STONE_SLAB2"), + RED_SANDSTONE_STAIRS(0, "RED_SANDSTONE_STAIRS"), + RED_SHULKER_BOX(0, "RED_SHULKER_BOX"), + RED_STAINED_GLASS(14, "STAINED_GLASS"), + RED_STAINED_GLASS_PANE(14, "STAINED_GLASS_PANE"), + RED_TERRACOTTA(14, "STAINED_CLAY"), + RED_TULIP(4, "RED_ROSE"), + RED_WALL_BANNER(0, "WALL_BANNER"), + RED_WOOL(14, "WOOL"), + REPEATER(0, "DIODE", "DIODE_BLOCK_ON", "DIODE_BLOCK_OFF"), + REPEATING_COMMAND_BLOCK(0, "COMMAND_REPEATING"), + ROSE_BUSH(4, "DOUBLE_PLANT"), + ROSE_RED(1, "INK_SACK"), + ROTTEN_FLESH(0, "ROTTEN_FLESH"), + SADDLE(0, "SADDLE"), + SALMON(1, "RAW_FISH"), + SALMON_BUCKET(0, "BUCKET"), + SALMON_SPAWN_EGG(0, "MONSTER_EGG"), + SAND(0, "SAND"), + SANDSTONE(0, "SANDSTONE"), + SANDSTONE_SLAB(1, "STONE_SLAB", "STEP", "DOUBLE_STEP"), + SANDSTONE_STAIRS(0, "SANDSTONE_STAIRS"), + SCUTE(0, "STONE"), + SEAGRASS(0, "STONE"), + SEA_LANTERN(0, "SEA_LANTERN"), + SEA_PICKLE(0, "STONE"), + SHEARS(0, "SHEARS"), + SHEEP_SPAWN_EGG(0, "MONSTER_EGG"), + SHIELD(0, "SHIELD"), + SHULKER_BOX(0, "PURPLE_SHULKER_BOX"), + SHULKER_SHELL(0, "SHULKER_SHELL"), + SHULKER_SPAWN_EGG(0, "MONSTER_EGG"), + SIGN(0, "SIGN"), + SILVERFISH_SPAWN_EGG(0, "MONSTER_EGG"), + SKELETON_HORSE_SPAWN_EGG(0, "MONSTER_EGG"), + SKELETON_SKULL(0, "SKULL", "SKULL_ITEM"), + SKELETON_SPAWN_EGG(0, "MONSTER_EGG"), + SKELETON_WALL_SKULL(0, "SKULL", "SKULL_ITEM"), + SLIME_BALL(0, "SLIME_BALL"), + SLIME_BLOCK(0, "SLIME_BLOCK"), + SLIME_SPAWN_EGG(0, "MONSTER_EGG"), + SMOOTH_QUARTZ(0, "STONE"), + SMOOTH_RED_SANDSTONE(2, "RED_SANDSTONE"), + SMOOTH_SANDSTONE(2, "SANDSTONE"), + SMOOTH_STONE(0, "STEP"), + SNOW(0, "SNOW"), + SNOWBALL(0, "SNOW_BALL"), + SNOW_BLOCK(0, "SNOW_BLOCK"), + SOUL_SAND(0, "SOUL_SAND"), + SPAWNER(0, "MOB_SPAWNER"), + SPECTRAL_ARROW(0, "SPECTRAL_ARROW"), + SPIDER_EYE(0, "SPIDER_EYE"), + SPIDER_SPAWN_EGG(0, "MONSTER_EGG"), + SPLASH_POTION(0, "SPLASH_POTION"), + SPONGE(0, "SPONGE"), + SPRUCE_BOAT(0, "BOAT_SPRUCE"), + SPRUCE_BUTTON(0, "WOOD_BUTTON"), + SPRUCE_DOOR(0, "SPRUCE_DOOR", "SPRUCE_DOOR_ITEM"), + SPRUCE_FENCE(0, "SPRUCE_FENCE"), + SPRUCE_FENCE_GATE(0, "SPRUCE_FENCE_GATE"), + SPRUCE_LEAVES(1, "LEAVES"), + SPRUCE_LOG(1, "LOG"), + SPRUCE_PLANKS(1, "WOOD"), + SPRUCE_PRESSURE_PLATE(0, "WOOD_PLATE"), + SPRUCE_SAPLING(1, "SAPLING"), + SPRUCE_SLAB(1, "WOODEN_SLAB", "WOOD_STEP", "WOOD_DOUBLE_STEP"), + SPRUCE_STAIRS(0, "SPRUCE_WOOD_STAIRS"), + SPRUCE_TRAPDOOR(0, "TRAP_DOOR"), + SPRUCE_WOOD(1, "LOG"), + SQUID_SPAWN_EGG(0, "MONSTER_EGG"), + STICK(0, "STICK"), + STICKY_PISTON(0, "PISTON_STICKY_BASE"), + STONE(0, "STONE"), + STONE_AXE(0, "STONE_AXE"), + STONE_BRICKS(0, "SMOOTH_BRICK"), + STONE_BRICK_SLAB(5, "STONE_SLAB", "STEP", "DOUBLE_STEP"), + STONE_BRICK_STAIRS(0, "SMOOTH_STAIRS"), + STONE_BUTTON(0, "STONE_BUTTON"), + STONE_HOE(0, "STONE_HOE"), + STONE_PICKAXE(0, "STONE_PICKAXE"), + STONE_PRESSURE_PLATE(0, "STONE_PLATE"), + STONE_SHOVEL(0, "STONE_SPADE"), + STONE_SLAB(0, "STONE_SLAB", "STEP", "DOUBLE_STEP"), + STONE_SWORD(0, "STONE_SWORD"), + STRAY_SPAWN_EGG(0, "MONSTER_EGG"), + STRING(0, "STRING"), + STRIPPED_ACACIA_LOG(0, "STONE"), + STRIPPED_ACACIA_WOOD(0, "STONE"), + STRIPPED_BIRCH_LOG(0, "STONE"), + STRIPPED_BIRCH_WOOD(0, "STONE"), + STRIPPED_DARK_OAK_LOG(0, "STONE"), + STRIPPED_DARK_OAK_WOOD(0, "STONE"), + STRIPPED_JUNGLE_LOG(0, "STONE"), + STRIPPED_JUNGLE_WOOD(0, "STONE"), + STRIPPED_OAK_LOG(0, "STONE"), + STRIPPED_OAK_WOOD(0, "STONE"), + STRIPPED_SPRUCE_LOG(0, "STONE"), + STRIPPED_SPRUCE_WOOD(0, "STONE"), + STRUCTURE_BLOCK(0, "STRUCTURE_BLOCK"), + STRUCTURE_VOID(0, "STRUCTURE_VOID"), + SUGAR(0, "SUGAR"), + SUGAR_CANE(0, "SUGAR_CANE", "SUGAR_CANE_BLOCK"), + SUNFLOWER(0, "DOUBLE_PLANT"), + TALL_GRASS(2, "DOUBLE_PLANT"), + TALL_SEAGRASS(0, "STONE"), + TERRACOTTA(0, "HARD_CLAY"), + TIPPED_ARROW(0, "TIPPED_ARROW"), + TNT(0, "TNT"), + TNT_MINECART(0, "EXPLOSIVE_MINECART"), + TORCH(0, "TORCH"), + TOTEM_OF_UNDYING(0, "TOTEM"), + TRAPPED_CHEST(0, "TRAPPED_CHEST"), + TRIDENT(0, "STONE"), + TRIPWIRE(0, "TRIPWIRE"), + TRIPWIRE_HOOK(0, "TRIPWIRE_HOOK"), + TROPICAL_FISH(0, "RAW_FISH"), + TROPICAL_FISH_BUCKET(0, "BUCKET"), + TROPICAL_FISH_SPAWN_EGG(0, "MONSTER_EGG"), + TUBE_CORAL(0, "STONE"), + TUBE_CORAL_BLOCK(0, "STONE"), + TUBE_CORAL_FAN(0, "STONE"), + TURTLE_EGG(0, "MONSTER_EGG"), + TURTLE_HELMET(0, "STONE"), + TURTLE_SPAWN_EGG(0, "MONSTER_EGG"), + VEX_SPAWN_EGG(0, "MONSTER_EGG"), + VILLAGER_SPAWN_EGG(0, "MONSTER_EGG"), + VINDICATOR_SPAWN_EGG(0, "MONSTER_EGG"), + VINE(0, "VINE"), + VOID_AIR(0, "AIR"), + WALL_SIGN(0, "WALL_SIGN", "SIGN_POST"), + WALL_TORCH(1, "TORCH"), + WATER(0, "WATER", "STATIONARY_WATER"), + WATER_BUCKET(0, "WATER_BUCKET"), + WET_SPONGE(1, "SPONGE"), + WHEAT(0, "WHEAT", "CROPS"), + WHEAT_SEEDS(0, "WHEAT_SEEDS", "SEEDS"), + WHITE_BANNER(15, "BANNER", "STANDING_BANNER"), + WHITE_BED(0, "BED", "BED_BLOCK"), + WHITE_CARPET(0, "CARPET"), + WHITE_CONCRETE(0, "CONCRETE"), + WHITE_CONCRETE_POWDER(0, "CONCRETE_POWDER"), + WHITE_GLAZED_TERRACOTTA(0, "WHITE_GLAZED_TERRACOTTA"), + WHITE_SHULKER_BOX(0, "WHITE_SHULKER_BOX"), + WHITE_STAINED_GLASS(0, "STAINED_GLASS"), + WHITE_STAINED_GLASS_PANE(0, "STAINED_GLASS_PANE"), + WHITE_TERRACOTTA(0, "TERRACOTTA"), + WHITE_TULIP(6, "RED_ROSE"), + WHITE_WALL_BANNER(0, "WALL_BANNER"), + WHITE_WOOL(0, "WOOL"), + WITCH_SPAWN_EGG(0, "MONSTER_EGG"), + WITHER_SKELETON_SKULL(0, "SKULL", "SKULL_ITEM"), + WITHER_SKELETON_SPAWN_EGG(0, "MONSTER_EGG"), + WITHER_SKELETON_WALL_SKULL(0, "SKULL", "SKULL_ITEM"), + WOLF_SPAWN_EGG(0, "MONSTER_EGG"), + WOODEN_AXE(0, "WOOD_AXE"), + WOODEN_HOE(0, "WOOD_HOE"), + WOODEN_PICKAXE(0, "WOOD_PICKAXE"), + WOODEN_SHOVEL(0, "WOOD_SPADE"), + WOODEN_SWORD(0, "WOOD_SWORD"), + WRITABLE_BOOK(0, "BOOK_AND_QUILL"), + WRITTEN_BOOK(0, "WRITTEN_BOOK"), + YELLOW_BANNER(11, "BANNER", "STANDING_BANNER"), + YELLOW_BED(4, "BED", "BED_BLOCK"), + YELLOW_CARPET(4, "CARPET"), + YELLOW_CONCRETE(4, "CONCRETE"), + YELLOW_CONCRETE_POWDER(4, "CONCRETE_POWDER"), + YELLOW_GLAZED_TERRACOTTA(0, "YELLOW_GLAZED_TERRACOTTA"), + YELLOW_SHULKER_BOX(0, "YELLOW_SHULKER_BOX"), + YELLOW_STAINED_GLASS(4, "STAINED_GLASS"), + YELLOW_STAINED_GLASS_PANE(4, "STAINED_GLASS_PANE"), + YELLOW_TERRACOTTA(4, "STAINED_CLAY"), + YELLOW_WALL_BANNER(0, "WALL_BANNER"), + YELLOW_WOOL(4, "WOOL"), + ZOMBIE_HEAD(0, "SKULL", "SKULL_ITEM"), + ZOMBIE_HORSE_SPAWN_EGG(0, "MONSTER_EGG"), + ZOMBIE_PIGMAN_SPAWN_EGG(0, "MONSTER_EGG"), + ZOMBIE_SPAWN_EGG(0, "MONSTER_EGG"), + ZOMBIE_VILLAGER_SPAWN_EGG(0, "MONSTER_EGG"), + ZOMBIE_WALL_HEAD(0, "SKULL", "SKULL_ITEM"); + private static HashMap cachedSearch = new HashMap<>(); + String[] m; + int data; + + XMaterial(int data, String... m) { + this.m = m; + this.data = data; + } + + public static XMaterial requestXMaterial(String name, byte data) { + if (cachedSearch.containsKey(name.toUpperCase() + "," + data)) { + return cachedSearch.get(name.toUpperCase() + "," + data); + } + for (XMaterial mat : XMaterial.values()) { + for (String test : mat.m) { + if (name.toUpperCase().equals(test) && ((byte) mat.data) == data) { + cachedSearch.put(test + "," + data, mat); + return mat; + } + } + } + return null; + } + + public static XMaterial fromString(String key) { + XMaterial xmat; + try { + xmat = XMaterial.valueOf(key); + return xmat; + } catch (IllegalArgumentException e) { + String[] split = key.split(":"); + if (split.length == 1) { + xmat = requestXMaterial(key, (byte) 0); + } else { + xmat = requestXMaterial(split[0], (byte) Integer.parseInt(split[1])); + } + return xmat; + } + + } + + public ItemStack parseItem() { + Material mat = parseMaterial(); + if (isNewVersion()) { + return new ItemStack(mat); + } + return new ItemStack(mat, 1, (byte) data); + } + + public boolean isSameMaterial(ItemStack comp) { + if (isNewVersion()) { + return comp.getType() == this.parseMaterial(); + } + if (comp.getType() == this.parseMaterial() && + (int) comp.getData().getData() == (int) this.data) { + return true; + } + XMaterial xmat = fromMaterial(comp.getType()); + if (isDamageable(xmat)) { + if (this.parseMaterial() == comp.getType()) { + return true; + } + } + return false; + } + + public XMaterial fromMaterial(Material mat) { + try { + return XMaterial.valueOf(mat.toString()); + } catch (IllegalArgumentException e) { + for (XMaterial xmat : XMaterial.values()) { + for (String test : xmat.m) { + if (test.equalsIgnoreCase(mat.toString())) { + return xmat; + } + } + } + } + return null; + } + + public boolean isDamageable(XMaterial type) { + if (type == null) return false; + String[] split = type.toString().split("_"); + int length = split.length; + switch (split[length - 1]) { + case "HELMET": + return true; + case "CHESTPLATE": + return true; + case "LEGGINGS": + return true; + case "BOOTS": + return true; + case "SWORD": + return true; + case "AXE": + return true; + case "PICKAXE": + return true; + case "SHOVEL": + return true; + case "HOE": + return true; + case "ELYTRA": + return true; + case "TURTLE_HELMET": + return true; + case "TRIDENT": + return true; + case "HORSE_ARMOR": + return true; + case "SHEARS": + return true; + default: + return false; + } + } + + public Material parseMaterial() { + Material mat = Material.matchMaterial(this.toString()); + if (mat != null) { + return mat; + } + return Material.matchMaterial(m[0]); + } + + public static boolean isNewVersion() { + Material mat = Material.getMaterial("RED_WOOL"); + if (mat != null) { + return true; + } + return false; + } + +} diff --git a/core/src/main/java/com/songoda/epicenchants/wrappers/MobWrapper.java b/core/src/main/java/com/songoda/epicenchants/wrappers/MobWrapper.java index cfdbf0d..e939ad4 100644 --- a/core/src/main/java/com/songoda/epicenchants/wrappers/MobWrapper.java +++ b/core/src/main/java/com/songoda/epicenchants/wrappers/MobWrapper.java @@ -2,12 +2,9 @@ package com.songoda.epicenchants.wrappers; import com.songoda.epicenchants.enums.TriggerType; import com.songoda.epicenchants.objects.LeveledModifier; -import com.songoda.epicenchants.utils.GeneralUtils; -import com.songoda.epicenchants.utils.ItemBuilder; -import de.tr7zw.itemnbtapi.NBTEntity; -import de.tr7zw.itemnbtapi.NBTList; -import de.tr7zw.itemnbtapi.NBTListCompound; -import de.tr7zw.itemnbtapi.NBTType; +import com.songoda.epicenchants.utils.objects.ItemBuilder; +import com.songoda.epicenchants.utils.single.GeneralUtils; +import de.tr7zw.itemnbtapi.*; import lombok.Builder; import org.bukkit.Location; import org.bukkit.entity.*; diff --git a/core/src/main/resources/actions.yml b/core/src/main/resources/actions.yml new file mode 100644 index 0000000..25ad004 --- /dev/null +++ b/core/src/main/resources/actions.yml @@ -0,0 +1,37 @@ +general: + prefix: "&8[&6EpicEnchants&8]" + no-permission: "&cYou do not have permission to do that." + +command: + book: + received: "&7You have been given a &6{enchant} &7book." + gave: "&7You gave {player} a &6{enchant} &7book." + max-level: "&cThe max level for {enchant} is {max-level}." + + white-scroll: + received: "&7You have been given a whitescroll." + gave: "&7You gave {player} a whitescroll." + + reload: "&6Configuration files reload" + +enchanter: + cannot-afford: "&cYou cannot afford this purchase." + success: "&7Purchased {group_color}{group_name} &7book." + +tinkerer: + open: "&eTrading with the tinkerer." + cancelled: "&cCancelled." + accepted: "&aAccepted" + no-items: "&c&l(!) &r&cThe tinkerer is not interested in any of your items!" + deposited-all: "&a&l(!) &r&aDeposited {amount} items." + +enchants: + invalid-material: "&cYou can not apply &6{enchant} &cto that item." + broken-failure: "&6{enchant} &cfailed to apply and broke your item..." + success: "&aYou have success fully applied &6{enchant}." + conflict: "&cYou cannot apply this enchant as it conflicts with another enchant." + maxed-out: "&cYou already have that enchant maxed on this item." + already-applied: "&cYou already have that enchant with that level applied on this item." + protected: "&aYour book would have broken your item, luckily it was protected!" + + diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 7296020..8f25580 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -1 +1,13 @@ -language: "en_US" \ No newline at end of file +language: "en_US" + +roman-numbers: true + +rates: + black-scroll-min: 20 + black-scroll-max: 100 + + +commands: + enchanter: "enchanter" + alchemist: "alchemist" + tinkerer: "tinkerer" \ No newline at end of file diff --git a/core/src/main/resources/en_US.lang b/core/src/main/resources/en_US.lang deleted file mode 100644 index 9b8865c..0000000 --- a/core/src/main/resources/en_US.lang +++ /dev/null @@ -1,38 +0,0 @@ -#General -general.nametag.prefix= "&8[&6EpicEnchants&8]" - -#Command -command.book.received= "&7You have been given a &6{enchant} &7book." -command.book.gave= "&7You gave {player} a &6{enchant} &7book." -command.book.maxlevel= "&cThe max level for {enchant} is {max-level}." - -command.whitescroll;.received= "&7You have been given a whitescroll." -command.whitescroll.gave= "&7You gave {player} a whitescroll." - -command.blackscroll.received= "&7You have been given a blackscroll." -command.blackscroll.gave= "&7You gave {player} a blackscroll." - -command.reload= "&6Configuration files reload" -command.filereload.success= "&6{file-name} has been successfully reloaded." -command.filereload.failed= "&c{file-name} failed to be reloaded. &7Please check console for errors." - -#Event -event.general.nopermission= "&cYou do not have permission to do that." -event.purchase.noenchant= "&cThere is no enchant available for &6{group-name}&7." -event.purchase.cannotafford= "&cYou cannot afford this purchase." -event.purchase.success= "&7You successfully purchased a &6{group-name} &7Book." - -#Enchant -enchant.invalidmaterial= "&cYou can not apply &6{enchant} &cto that item." -enchant.failure= "&cYou failed to apply &6{enchant}." -enchant.brokenfailure= "&6{enchant} &cfailed to apply and broke your item..." -enchant.success= "&aYou have success fully applied &6{enchant}." -enchant.conflict= "&cYou cannot apply this enchant as it conflicts with another enchant." -enchant.maxedout= "&cYou already have that enchant maxed on this item." -enchant.alreadyapplied= "&cYou already have that enchant with that level applied on this item." - -#Item -whitescroll.applied="&aThis item is now protected." -whitescroll.alreadyapplied= "&cThis item is already protected." -blackscroll.success= "&aYou have successfully extracted an enchant from this item." -blackscroll.noenchants= "&cThis item has no enchants to extract" diff --git a/core/src/main/resources/groups.yml b/core/src/main/resources/groups.yml index 6e61350..a30d02d 100644 --- a/core/src/main/resources/groups.yml +++ b/core/src/main/resources/groups.yml @@ -1,8 +1,9 @@ groups: SIMPLE: - group-color: "&7" + group-color: "&f" group-name: "Simple" group-format: "{group_color} {enchant} {level}" + tinkerer-exp-per-level: 100 rates: destroy-min: 10 destroy-max: 100 @@ -10,15 +11,15 @@ groups: success-max: 80 book-item: material: BOOK - display-name: "&7{enchant} {level}" + display-name: "{group_color}{enchant} {level}" lore: - - "&7Drag on to item to enchant" - - "&7Destroy Rate &c{destroy_rate}" - - "&7Success Rate &a{success_rate}" + - "&a{success_rate}% Success Rate" + - "&c{destroy_rate}% Destroy Rate" UNIQUE: group-color: "&a" group-name: "Unique" group-format: "{group_color}{enchant} {level}" + tinkerer-exp-per-level: 200 rates: destroy-min: 10 destroy-max: 100 @@ -28,13 +29,13 @@ groups: material: BOOK display-name: "{group_color}{enchant} {level}" lore: - - "&7Drag on to item to enchant" - - "&7Destroy Rate &c{destroy_rate}" - - "&7Success Rate &a{success_rate}" + - "&a{success_rate}% Success Rate" + - "&c{destroy_rate}% Destroy Rate" ELITE: group-color: "&b" group-name: "Elite" group-format: "{group_color}{enchant} {level}" + tinkerer-exp-per-level: 300 rates: destroy-min: 10 destroy-max: 100 @@ -44,12 +45,12 @@ groups: material: BOOK display-name: "{group_color}{enchant} {level}" lore: - - "&7Drag on to item to enchant" - - "&7Destroy Rate &c{destroy_rate}" - - "&7Success Rate &a{success_rate}" + - "&a{success_rate}% Success Rate" + - "&c{destroy_rate}% Destroy Rate" ULTIMATE: group-color: "&e" group-name: "Ultimate" + tinkerer-exp-per-level: 600 group-format: "{group_color}{enchant} {level}" rates: destroy-min: 10 @@ -60,13 +61,13 @@ groups: material: BOOK display-name: "{group_color}{enchant} {level}" lore: - - "&7Drag on to item to enchant" - - "&cDestroy Rate {destroy_rate}" - - "&aSuccess Rate {success_rate}" + - "&a{success_rate}% Success Rate" + - "&c{destroy_rate}% Destroy Rate" LEGENDARY: group-color: "&6" group-name: "Legendary" group-format: "{group_color}{enchant} {level}" + tinkerer-exp-per-level: 1000 rates: destroy-min: 10 destroy-max: 100 @@ -76,6 +77,5 @@ groups: material: BOOK display-name: "{group_color}{enchant} {level}" lore: - - "&7Drag on to item to enchant" - - "&cDestroy Rate {destroy_rate}" - - "&aSuccess Rate {success_rate}" + - "&a{success_rate}% Success Rate" + - "&c{destroy_rate}% Destroy Rate" diff --git a/core/src/main/resources/items/dusts.yml b/core/src/main/resources/items/dusts.yml new file mode 100644 index 0000000..f0725a8 --- /dev/null +++ b/core/src/main/resources/items/dusts.yml @@ -0,0 +1,39 @@ +secret-dust: + material: FIREBALL + display-name: "{group-color}{group-name} Secret Dust &7(Right click)" + lore: + - "&aSuccess: +{min-rate}-{max-rate}%" + - "&7Contains &bMagic&7, &ePrimal&7 or &fMystery &7dust." + - "&7An unidentified satchel of dust." + +dusts: + mystery: + chance: 50 + material: SULPHUR + display-name: "&fMystery Dust" + lore: + - "&7The failed bi-product of" + - "&7Mystery and Primal dust." + + magic: + chance: 40 + material: SUGAR + display-name: "{group-color}{group-name} Magic Dust" + lore: + - "&a+{percentage}% success" + - "&7Apply to a &l{group-color}{group-name} Enchantment Book" + - "&7to increase its success rate by &l{group-color}{percentage}%" + - "" + - "&7Place dust on enchantment book." + primal: + chance: 10 + min-rate: 10 + max-rate: 30 + material: GLOWSTONE_DUST + display-name: "&l{group-color}{group-name} Primal Dust" + lore: + - "&a&l+{percentage}% SUCCESS" + - "&fApply to a &l{group-color}{group-name} Enchantment Book" + - "&fto increase its success rate by &l{group-color}{percentage}%" + - "" + - "&fPlace dust on enchantment book." \ No newline at end of file diff --git a/core/src/main/resources/items/special-items.yml b/core/src/main/resources/items/special-items.yml new file mode 100644 index 0000000..8c3bb7d --- /dev/null +++ b/core/src/main/resources/items/special-items.yml @@ -0,0 +1,24 @@ +white-scroll: + material: MAP + display-name: "&e&lWhite Scroll" + format: "&7&lPROTECTED" + lore: + - "&7Prevents an item from being destroyed" + - "&7due to a failed Enchantment Book." + - "&ePlace scroll on item to apply." + +black-scroll: + material: INK_SACK + display-name: "&f&lBlack Scroll" + lore: + - "&7Removes a random enchantment" + - "&7from an item and converts" + - "&7it into a {success-rate} success book." + - "&fPlace scroll on item to extract." + +mystery-book: + material: BOOK + display-name: "{group-color}{group-name} Enchantment &7(Right click)" + lore: + - "&7Examine to receive a random" + - "{group-color}{group-name} &7enchantment book." \ No newline at end of file diff --git a/core/src/main/resources/menus/enchanter-menu.yml b/core/src/main/resources/menus/enchanter-menu.yml index 26a4e9d..d625ce5 100644 --- a/core/src/main/resources/menus/enchanter-menu.yml +++ b/core/src/main/resources/menus/enchanter-menu.yml @@ -21,5 +21,4 @@ contents: group: SIMPLE exp-cost: 20 eco-cost: 2000 - row: 1 - column: 5 \ No newline at end of file + slot: 4 \ No newline at end of file diff --git a/core/src/main/resources/menus/tinkerer-menu.yml b/core/src/main/resources/menus/tinkerer-menu.yml new file mode 100644 index 0000000..d09f8b1 --- /dev/null +++ b/core/src/main/resources/menus/tinkerer-menu.yml @@ -0,0 +1,41 @@ +title: "Tinkerer" +rows: 6 + +player-slots: "1,2,3,9,10,11,12,18,19,20,21,27,28,29,30,36,37,38,39,45,46,47,48" + +tinkerer-slots: "5,6,7,14,15,16,17,23,24,25,26,32,33,34,35,41,42,43,44,50,51,52,53" + +slots: "(1,5) (2,6) (3,7) (9,14) +(10,15) (11,16) (12,17) (18,23) +(19,24) (20,25) (21,26) (27,32) +(28,33) (29,34) (30,35) (36,41) +(37,42) (38,43) (39,44) (45,50) +(46,51) (47,52) (48,53)" + +contents: + 1: + material: "STAINED_GLASS_PANE" + display-name: " " + slot: "4,13,22,31,40" + accept-left: + material: "STAINED_GLASS_PANE" + data: 4 + display-name: "&eClick to accept trade" + slot: 0 + accept-right: + material: "STAINED_GLASS_PANE" + data: 4 + display-name: "&eClick to accept trade" + slot: 8 + deposit-all: + material: "STAINED_GLASS_PANE" + data: 4 + display-name: "&l&eDeposit All" + lore: + - "&7Click to deposit all tinkerable items." + slot: "49" + +exp-table-per-level: + DEFAULT: 10 + DEPTH_STRIDER: 20 + ExampleEnchant: 50 \ No newline at end of file diff --git a/core/src/main/resources/plugin.yml b/core/src/main/resources/plugin.yml index 19424b3..0ce9cc3 100644 --- a/core/src/main/resources/plugin.yml +++ b/core/src/main/resources/plugin.yml @@ -4,4 +4,5 @@ main: com.songoda.epicenchants.EpicEnchants authors: [GB6] website: https://songoda.com/ depend: [Vault] +softdepend: [UltimateBottles] api-version: 1.13 \ No newline at end of file diff --git a/core/src/main/resources/special-items.yml b/core/src/main/resources/special-items.yml deleted file mode 100644 index 6ad4e6f..0000000 --- a/core/src/main/resources/special-items.yml +++ /dev/null @@ -1,16 +0,0 @@ -white-scroll: - material: EMPTY_MAP - display-name: "&e&lWhite Scroll" - lore: - - "&7Prevents an item from being destroyed" - - "&7due to a failed Enchantment Book." - - "&ePlace scroll on item to apply." - -black-scroll: - material: INK_SAC - display-name: "&f&lBlack Scroll" - lore: - - "&7Removes a random enchantment" - - "&7from an item and converts" - - "&7it into a {percentage} success book." - - "&fPlace scroll on item to extract." \ No newline at end of file diff --git a/hooks/FactionsUUID/pom.xml b/hooks/FactionsUUID/pom.xml new file mode 100644 index 0000000..58a8a2e --- /dev/null +++ b/hooks/FactionsUUID/pom.xml @@ -0,0 +1,15 @@ + + + + hooks + com.songoda + 1.0.3-ALPHA + + 4.0.0 + + FactionsUUID + + + \ No newline at end of file diff --git a/hooks/FactionsUUID/src/main/java/com/songoda/epicenchants/hooks/FactionsUUIDHook.java b/hooks/FactionsUUID/src/main/java/com/songoda/epicenchants/hooks/FactionsUUIDHook.java new file mode 100644 index 0000000..cf12e6b --- /dev/null +++ b/hooks/FactionsUUID/src/main/java/com/songoda/epicenchants/hooks/FactionsUUIDHook.java @@ -0,0 +1,4 @@ +package com.songoda.epicenchants.hooks; + +public class FactionsUUIDHook { +} diff --git a/hooks/pom.xml b/hooks/pom.xml new file mode 100644 index 0000000..5fcc9f7 --- /dev/null +++ b/hooks/pom.xml @@ -0,0 +1,21 @@ + + + + EpicEnchants-Parent + com.songoda + 1.0.3-ALPHA + + pom + + + FactionsUUID + + + 4.0.0 + + hooks + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5432709..352559c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,9 +7,10 @@ com.songoda EpicEnchants-Parent pom - 1.0.1-ALPHA + 1.0.3-ALPHA core + hooks