diff --git a/pom.xml b/pom.xml index 169b3baf..d2850fa1 100644 --- a/pom.xml +++ b/pom.xml @@ -17,15 +17,15 @@ - nexus - Lumine Releases - https://mvn.lumine.io/repository/maven-releases/ - - - nexus - Lumine Snapshots - https://mvn.lumine.io/repository/maven-snapshots/ - + nexus + Lumine Releases + https://mvn.lumine.io/repository/maven-releases/ + + + nexus + Lumine Snapshots + https://mvn.lumine.io/repository/maven-snapshots/ + @@ -88,14 +88,14 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - + - egg82-ninja - https://www.myget.org/F/egg82-java/maven/ - - - + egg82-ninja + https://www.myget.org/F/egg82-java/maven/ + + + codemc-repo https://repo.codemc.io/repository/maven-public/ @@ -132,7 +132,7 @@ net.Indyuce MMOCore - 1.8.0 + 1.8.1 provided @@ -227,13 +227,6 @@ provided - - com.Zrips.CMI - CMI - 8.6.5.0 - provided - - com.herocraftonline heroes diff --git a/src/main/java/net/Indyuce/mmoitems/MMOItems.java b/src/main/java/net/Indyuce/mmoitems/MMOItems.java index d816b98b..e73ac335 100644 --- a/src/main/java/net/Indyuce/mmoitems/MMOItems.java +++ b/src/main/java/net/Indyuce/mmoitems/MMOItems.java @@ -18,14 +18,23 @@ import net.Indyuce.mmoitems.api.util.MMOItemReforger; import net.Indyuce.mmoitems.api.util.NumericStatFormula; import net.Indyuce.mmoitems.api.util.message.FFPMMOItems; import net.Indyuce.mmoitems.command.MMOItemsCommandTreeRoot; -import net.Indyuce.mmoitems.comp.*; +import net.Indyuce.mmoitems.comp.MMOItemsMetrics; +import net.Indyuce.mmoitems.comp.MMOItemsRewardTypes; +import net.Indyuce.mmoitems.comp.McMMONonRPGHook; +import net.Indyuce.mmoitems.comp.PhatLootsHook; +import net.Indyuce.mmoitems.comp.RealDualWieldHook; +import net.Indyuce.mmoitems.comp.WorldEditSupport; import net.Indyuce.mmoitems.comp.denizen.DenizenHook; import net.Indyuce.mmoitems.comp.eco.VaultSupport; import net.Indyuce.mmoitems.comp.enchants.CrazyEnchantsStat; import net.Indyuce.mmoitems.comp.enchants.EnchantPlugin; import net.Indyuce.mmoitems.comp.enchants.MythicEnchantsSupport; import net.Indyuce.mmoitems.comp.enchants.advanced_enchants.AdvancedEnchantmentsHook; -import net.Indyuce.mmoitems.comp.inventory.*; +import net.Indyuce.mmoitems.comp.inventory.DefaultPlayerInventory; +import net.Indyuce.mmoitems.comp.inventory.OrnamentPlayerInventory; +import net.Indyuce.mmoitems.comp.inventory.PlayerInventory; +import net.Indyuce.mmoitems.comp.inventory.PlayerInventoryHandler; +import net.Indyuce.mmoitems.comp.inventory.RPGInventoryHook; import net.Indyuce.mmoitems.comp.itemglow.ItemGlowListener; import net.Indyuce.mmoitems.comp.itemglow.NoGlowListener; import net.Indyuce.mmoitems.comp.mmocore.MMOCoreMMOLoader; @@ -42,12 +51,39 @@ import net.Indyuce.mmoitems.comp.rpg.RPGHandler; import net.Indyuce.mmoitems.gui.PluginInventory; import net.Indyuce.mmoitems.gui.edition.recipe.RecipeBrowserGUI; import net.Indyuce.mmoitems.gui.listener.GuiListener; -import net.Indyuce.mmoitems.listener.*; -import net.Indyuce.mmoitems.manager.*; +import net.Indyuce.mmoitems.listener.CraftingListener; +import net.Indyuce.mmoitems.listener.CustomBlockListener; +import net.Indyuce.mmoitems.listener.CustomSoundListener; +import net.Indyuce.mmoitems.listener.DisableInteractions; +import net.Indyuce.mmoitems.listener.DurabilityListener; +import net.Indyuce.mmoitems.listener.ElementListener; +import net.Indyuce.mmoitems.listener.EquipListener; +import net.Indyuce.mmoitems.listener.ItemListener; +import net.Indyuce.mmoitems.listener.ItemUse; +import net.Indyuce.mmoitems.listener.PlayerListener; +import net.Indyuce.mmoitems.manager.AbilityManager; +import net.Indyuce.mmoitems.manager.BlockManager; +import net.Indyuce.mmoitems.manager.ConfigManager; +import net.Indyuce.mmoitems.manager.CraftingManager; +import net.Indyuce.mmoitems.manager.DropTableManager; +import net.Indyuce.mmoitems.manager.EntityManager; +import net.Indyuce.mmoitems.manager.ItemManager; +import net.Indyuce.mmoitems.manager.LayoutManager; +import net.Indyuce.mmoitems.manager.LoreFormatManager; +import net.Indyuce.mmoitems.manager.PluginUpdateManager; +import net.Indyuce.mmoitems.manager.RecipeManager; +import net.Indyuce.mmoitems.manager.SetManager; +import net.Indyuce.mmoitems.manager.StatManager; +import net.Indyuce.mmoitems.manager.TemplateManager; +import net.Indyuce.mmoitems.manager.TierManager; +import net.Indyuce.mmoitems.manager.TypeManager; +import net.Indyuce.mmoitems.manager.UpgradeManager; +import net.Indyuce.mmoitems.manager.WorldGenManager; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; @@ -62,797 +98,780 @@ import java.util.List; import java.util.logging.Level; public class MMOItems extends LuminePlugin { - public static MMOItems plugin; - - // Increment this when making breaking changes to items. - public static final int INTERNAL_REVISION_ID = 1; - - private final PluginUpdateManager pluginUpdateManager = new PluginUpdateManager(); - private final CraftingManager stationRecipeManager = new CraftingManager(); - private final LoreFormatManager formatManager = new LoreFormatManager(); - private final TemplateManager templateManager = new TemplateManager(); - private final AbilityManager abilityManager = new AbilityManager(); - private final EntityManager entityManager = new EntityManager(); - private final RecipeManager recipeManager = new RecipeManager(); - private final LayoutManager layoutManager = new LayoutManager(); - private final TypeManager typeManager = new TypeManager(); - private final ItemManager itemManager = new ItemManager(); - private final PlayerInventoryHandler inventory = new PlayerInventoryHandler(); - private final List stringInputParsers = new ArrayList<>(); - private final List enchantPlugins = new ArrayList<>(); - - private DropTableManager dropTableManager; - private WorldGenManager worldGenManager; - private UpgradeManager upgradeManager; - private ConfigManager configManager; - private BlockManager blockManager; - private TierManager tierManager; - private StatManager statManager; - private SetManager setManager; - private EquipListener equipListener; - - private PlaceholderParser placeholderParser = new DefaultPlaceholderParser(); - private VaultSupport vaultSupport; - private RPGHandler rpgPlugin; - - @Override - public void load() { - plugin = this; - - if (getServer().getPluginManager().getPlugin("WorldEdit") != null) - try { - new WorldEditSupport(); - getLogger().log(Level.INFO, "Hooked onto WorldEdit"); - } catch (Exception exception) { - getLogger().log(Level.WARNING, "Could not initialize support with WorldEdit 7: " + exception.getMessage()); - } - - saveDefaultConfig(); - - /* - * stat manager must be initialized before MMOCore compatibility - * initializes so that MMOCore can register its stats - */ - statManager = new StatManager(); - typeManager.reload(); - templateManager.preloadTemplates(); - - if (Bukkit.getPluginManager().getPlugin("MMOCore") != null) - new MMOCoreMMOLoader(); - - if (Bukkit.getPluginManager().getPlugin("mcMMO") != null) - //statManager.register(McMMOHook.MCMMO_SUPER_TOOL); - statManager.register(McMMOHook.disableMcMMORepair); - - if (Bukkit.getPluginManager().getPlugin("AdvancedEnchantments") != null) { - statManager.register(AdvancedEnchantmentsHook.ADVANCED_ENCHANTMENTS); - statManager.register(AdvancedEnchantmentsHook.DISABLE_ADVANCED_ENCHANTMENTS); - } - - if (Bukkit.getPluginManager().getPlugin("MythicEnchants") != null) - enchantPlugins.add(new MythicEnchantsSupport()); - - if (Bukkit.getPluginManager().getPlugin("Depenizen") != null) { - new DenizenHook(); - getLogger().log(Level.INFO, "Hooked onto Denizen"); - } - } - - @Override - public void enable() { - - new SpigotPlugin(39267, this).checkForUpdate(); - new MMOItemsMetrics(); - - RecipeBrowserGUI.registerNativeRecipes(); - abilityManager.loadPluginAbilities(); - configManager = new ConfigManager(); - - final int configVersion = getConfig().contains("config-version", true) ? getConfig().getInt("config-version") : -1; - final int defConfigVersion = getConfig().getDefaults().getInt("config-version"); - if (configVersion != defConfigVersion) { - getLogger().warning("You may be using an outdated config.yml!"); - getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')"); - } - - // registering here so the stats will load with the templates - if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) { - new MythicMobsLoader(); - if (getConfig().getBoolean("lootsplosion.enabled")) - Bukkit.getPluginManager().registerEvents(new LootsplosionListener(), this); - getLogger().log(Level.INFO, "Hooked onto MythicMobs"); - } - - if (Bukkit.getPluginManager().getPlugin("MMOInventory") != null) { - new MMOInventorySupport(); - getLogger().log(Level.INFO, "Hooked onto MMOInventory"); - } - - findRpgPlugin(); - - /* - * After tiers, sets and upgrade templates are loaded, MI template data - * can be fully loaded - */ - formatManager.reload(); - tierManager = new TierManager(); - setManager = new SetManager(); - upgradeManager = new UpgradeManager(); - templateManager.postloadTemplates(); - - dropTableManager = new DropTableManager(); - worldGenManager = new WorldGenManager(); - blockManager = new BlockManager(); - equipListener = new EquipListener(); - - if (Bukkit.getPluginManager().getPlugin("Vault") != null) - vaultSupport = new VaultSupport(); - - getLogger().log(Level.INFO, "Loading crafting stations, please wait.."); - layoutManager.reload(); - stationRecipeManager.reload(); - - // This ones are not implementing Reloadable - NumericStatFormula.reload(); - MMOItemReforger.reload(); - - Bukkit.getPluginManager().registerEvents(entityManager, this); - Bukkit.getPluginManager().registerEvents(dropTableManager, this); - Bukkit.getPluginManager().registerEvents(new ItemUse(), this); - Bukkit.getPluginManager().registerEvents(new ItemListener(), this); - Bukkit.getPluginManager().registerEvents(new PlayerListener(), this); - Bukkit.getPluginManager().registerEvents(new CustomSoundListener(), this); - Bukkit.getPluginManager().registerEvents(new DurabilityListener(), this); - Bukkit.getPluginManager().registerEvents(new DisableInteractions(), this); - Bukkit.getPluginManager().registerEvents(new GuiListener(), this); - Bukkit.getPluginManager().registerEvents(new ElementListener(), this); - Bukkit.getPluginManager().registerEvents(new CustomBlockListener(), this); - if (Bukkit.getPluginManager().getPlugin("PhatLoots") != null) { - Bukkit.getPluginManager().registerEvents(new PhatLootsHook(), this); - } - MMOItemUIFilter.register(); - - Bukkit.getScheduler().runTaskTimer(this, () -> Bukkit.getOnlinePlayers().forEach(player -> PlayerData.get(player).updateStats()), 100, 20); - - /* - * This tasks updates twice a second player inventories on the server. - * allows now to use a glitchy itemEquipEvent. Must be called after - * loading the config since it checks for a config option - */ - Bukkit.getScheduler().runTaskTimer(this, () -> { - for (Player player : Bukkit.getOnlinePlayers()) - PlayerData.get(player).getInventory().updateCheck(); - }, 100, getConfig().getInt("inventory-update-delay")); - - - if (Bukkit.getPluginManager().getPlugin("mcMMO") != null) - Bukkit.getPluginManager().registerEvents(new McMMONonRPGHook(), this); - - /* - * Registers Player Inventories. Each of these add locations of items to search for - * when doing inventory updates. - */ - getInventory().register(new DefaultPlayerInventory()); - if (Bukkit.getPluginManager().getPlugin("RPGInventory") != null) { - getInventory().register(new RPGInventoryHook()); - getLogger().log(Level.INFO, "Hooked onto RPGInventory"); - } - if (MMOItems.plugin.getConfig().getBoolean("iterate-whole-inventory")) - getInventory().register(new OrnamentPlayerInventory()); - - if (Bukkit.getPluginManager().getPlugin("CrazyEnchantments") != null) { - getStats().register(new CrazyEnchantsStat()); - getLogger().log(Level.INFO, "Hooked onto CrazyEnchantments"); - } - - if (Bukkit.getPluginManager().getPlugin("AdvancedEnchantments") != null) { - Bukkit.getPluginManager().registerEvents(new AdvancedEnchantmentsHook(), this); - getLogger().log(Level.INFO, "Hooked onto AdvancedEnchantments"); - } - - if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { - getLogger().log(Level.INFO, "Hooked onto PlaceholderAPI"); - placeholderParser = new PlaceholderAPIParser(); - } - - if (getConfig().getBoolean("item-glow")) { - if (Bukkit.getPluginManager().getPlugin("GlowAPI") != null && Bukkit.getPluginManager().getPlugin("PacketListenerApi") != null) { - Bukkit.getPluginManager().registerEvents(new ItemGlowListener(), this); - getLogger().log(Level.INFO, "Hooked onto GlowAPI (Item Glow)"); - } else - Bukkit.getPluginManager().registerEvents(new NoGlowListener(), this); - } - - if (Bukkit.getPluginManager().getPlugin("RealDualWield") != null) { - Bukkit.getPluginManager().registerEvents(new RealDualWieldHook(), this); - getLogger().log(Level.INFO, "Hooked onto RealDualWield"); - } - - if (Bukkit.getPluginManager().getPlugin("BossShopPro") != null) { - getLogger().log(Level.INFO, "Hooked onto BossShopPro"); - (new BukkitRunnable() { - public void run() { - //noinspection ProhibitedExceptionCaught - try { - new MMOItemsRewardTypes().register(); - } catch (NullPointerException ignored) { - getLogger().log(Level.INFO, "Could not Hook onto BossShopPro"); - } - } - }).runTaskLater(this, 1L); - } - - // compatibility with /reload - Bukkit.getScheduler().runTask(this, () -> Bukkit.getOnlinePlayers().forEach(PlayerData::load)); - - boolean book = getConfig().getBoolean("recipes.use-recipe-book"); - boolean amounts = getConfig().getBoolean("recipes.recipe-amounts"); - - if (book && amounts) { - getLogger().warning("Tried to enable recipe book while amounts are active!"); - getLogger().warning("Please use only ONE of these options!"); - getLogger().warning("Disabling both options for now..."); - book = false; - amounts = false; - } - - recipeManager.load(book, amounts); - if (amounts) - Bukkit.getPluginManager().registerEvents(new CraftingListener(), this); - - // amount and bukkit recipes - getLogger().log(Level.INFO, "Loading recipes, please wait..."); - recipeManager.loadRecipes(); - - // main command - MMOItemsCommandTreeRoot mmoitemsCommand = new MMOItemsCommandTreeRoot(); - getCommand("mmoitems").setExecutor(mmoitemsCommand); - getCommand("mmoitems").setTabCompleter(mmoitemsCommand); - - // update item command DISABLED - //getCommand("updateitem").setExecutor(new UpdateItemCommand()); - //getCommand("updateitem").setTabCompleter(new UpdateItemCompletion()); - } - - @Override - public void disable() { - - // save player data - PlayerData.getLoaded().forEach(PlayerData::save); - - // save item updater data - ConfigFile updater = new ConfigFile("/dynamic", "updater"); - updater.getConfig().getKeys(false).forEach(key -> updater.getConfig().set(key, null)); - updater.save(); - - // drop abandonned soulbound items - SoulboundInfo.getAbandonnedInfo().forEach(SoulboundInfo::dropItems); - - // close inventories - for (Player player : Bukkit.getOnlinePlayers()) - if (player.getOpenInventory() != null && player.getOpenInventory().getTopInventory().getHolder() instanceof PluginInventory) - player.closeInventory(); - } - - public String getPrefix() { - return ChatColor.DARK_GRAY + "[" + ChatColor.YELLOW + "MMOItems" + ChatColor.DARK_GRAY + "] " + ChatColor.GRAY; - } - - public File getJarFile() { - return plugin.getFile(); - } - - public CraftingManager getCrafting() { - return stationRecipeManager; - } - - public LayoutManager getLayouts() { - return layoutManager; - } - - public SetManager getSets() { - return setManager; - } - - public RPGHandler getRPG() { - return rpgPlugin; - } - - /** - * The RPGHandler interface lets MMOItems fetch and manipulate RPG data like - * player level, class, resources like mana and stamina for item or skill - * costs, item restrictions, etc. - * - * @param handler Your RPGHandler instance - */ - public void setRPG(RPGHandler handler) { - Validate.notNull(handler, "RPGHandler cannot be null"); - - // unregister events from current rpgPlugin instance - if (rpgPlugin != null && rpgPlugin instanceof Listener && isEnabled()) - HandlerList.unregisterAll((Listener) rpgPlugin); - - rpgPlugin = handler; - if (handler instanceof Listener && isEnabled()) - Bukkit.getPluginManager().registerEvents((Listener) handler, this); - } - - public PluginUpdateManager getUpdates() { - return pluginUpdateManager; - } - - public PlayerInventoryHandler getInventory() { - return inventory; - } - - /** - * The PlayerInventory interface lets MMOItems knows what items to look for - * in player inventories whe doing inventory updates. By default, it only - * checks held items + armor slots. However other plugins like MMOInv do - * implement custom slots and therefore must register a custom - * PlayerInventory instance that tells of additional items to look for. - */ - public void registerPlayerInventory(PlayerInventory value) { - - // Registers in the Inventory Handler - getInventory().register(value); - } - - /** - * The PlayerInventory interface lets MMOItems knows what items to look for - * in player inventories whe doing inventory updates. By default, it only - * checks held items + armor slots. However other plugins like MMOInv do - * implement custom slots and therefore must register a custom - * PlayerInventory instance. - *

- * Default instance is DefaultPlayerInventory in comp.inventory - * - * @param value The player inventory subclass - * @deprecated Rather than setting this to the only inventory MMOItems will - * search equipment within, you must add your inventory to the - * handler with getInventory().register(). This method - * will clear all other PlayerInventories for now, as to keep - * backwards compatibility. - */ - @Deprecated - public void setPlayerInventory(PlayerInventory value) { - - // Unregisters those previously registered - getInventory().unregisterAll(); - - // Registers this as the only - getInventory().register(value); - } - - /** - * Plugins like MythicEnchants which utilize the Bukkit - * class Enchantment by extending it don't use any ItemStat - * to store their enchants and therefore need to be called - * to update the item lore when any item is built. - * - * @param enchantPlugin Enchantment plugin - */ - public void registerEnchantPlugin(EnchantPlugin enchantPlugin) { - Validate.notNull(enchantPlugin, "Enchant plugin cannot be null"); - enchantPlugins.add(enchantPlugin); - } - - public StatManager getStats() { - return statManager; - } - - public TierManager getTiers() { - return tierManager; - } - - public EntityManager getEntities() { - return entityManager; - } - - public DropTableManager getDropTables() { - return dropTableManager; - } - - public AbilityManager getAbilities() { - return abilityManager; - } - - public BlockManager getCustomBlocks() { - return blockManager; - } - - public WorldGenManager getWorldGen() { - return worldGenManager; - } - - public RecipeManager getRecipes() { - return recipeManager; - } - - public ConfigManager getLanguage() { - return configManager; - } - - public TypeManager getTypes() { - return typeManager; - } - - public UpgradeManager getUpgrades() { - return upgradeManager; - } - - public PlaceholderParser getPlaceholderParser() { - return placeholderParser; - } - - public EquipListener getEquipListener() { - return equipListener; - } - - public TemplateManager getTemplates() { - return templateManager; - } - - public LoreFormatManager getFormats() { - return formatManager; - } - - @Deprecated - public ItemManager getItems() { - return itemManager; - } - - /* - * External API's - */ - public boolean hasPermissions() { - return vaultSupport != null && vaultSupport.getPermissions() != null; - } - - public List getEnchantPlugins() { - return enchantPlugins; - } - - public boolean hasEconomy() { - return vaultSupport != null && vaultSupport.getEconomy() != null; - } - - public VaultSupport getVault() { - return vaultSupport; - } - - public List getStringInputParsers() { - return stringInputParsers; - } - - //region Easy-Access API - - /** - * Decide by which system will the RPG Requirements of the player will be checked. - *

- * For example, required level, is that vanilla XP levels, MMOCore levels, McMMO Leves or what? - */ - public void findRpgPlugin() { - if (rpgPlugin != null) - return; - - String preferred = plugin.getConfig().getString("preferred-rpg-provider", null); - if (preferred != null) { - - try { - RPGHandler.PluginEnum preferredRPG = RPGHandler.PluginEnum.valueOf(preferred.toUpperCase()); - // Found the plugin? - if (Bukkit.getPluginManager().getPlugin(preferredRPG.getName()) != null) { - - // Load that one - setRPG(preferredRPG.load()); - - // Mention it - print(null, "Using $s{0}$b as RPGPlayer provider", "RPG Provider", preferredRPG.getName()); - return; - } else - - print(null, "Preferred RPGPlayer provider $r{0}$b is not installed!", "RPG Provider", preferred); - - } catch (IllegalArgumentException ignored) { - - // Log error - FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FFPMMOItems.get()); - ffp.activatePrefix(true, "RPG Provider"); - ffp.log(FriendlyFeedbackCategory.ERROR, "Invalid RPG Provider '$u{0}$b' --- These are the supported ones:", preferred); - for (RPGHandler.PluginEnum pgrep : RPGHandler.PluginEnum.values()) { - ffp.log(FriendlyFeedbackCategory.ERROR, " $r+ $b{0}", pgrep.getName()); - } - ffp.sendTo(FriendlyFeedbackCategory.ERROR, getConsole()); - } - } - - // For each supported plugin - for (RPGHandler.PluginEnum pluginEnum : RPGHandler.PluginEnum.values()) { - - // Found the plugin? - if (Bukkit.getPluginManager().getPlugin(pluginEnum.getName()) != null) { - - // Load that one - setRPG(pluginEnum.load()); - - // Mention it - print(null, "Using $s{0}$b as RPGPlayer provider", "RPG Provider", pluginEnum.getName()); - return; - } - } - - // Just use the default - setRPG(new DefaultHook()); - } - - /** - * @return Generates an item given an item template. The item level will - * scale according to the player RPG level if the template has the - * 'level-item' option. The item will pick a random tier if the - * template has the 'tiered' option - */ - @Nullable - public MMOItem getMMOItem(@Nullable Type type, @Nullable String id, @Nullable PlayerData player) { - - // Valid template? - MMOItemTemplate found = getTemplates().getTemplate(type, id); - if (found == null) - return null; - - // Build if found - return found.newBuilder(player).build(); - } - - /** - * @return Generates an item given an item template. The item level will - * scale according to the player RPG level if the template has the - * 'level-item' option. The item will pick a random tier if the - * template has the 'tiered' option - */ - @Nullable - public ItemStack getItem(@NotNull Type type, @NotNull String id, @NotNull PlayerData player) { - Validate.notNull(type, "Type cannot be null"); - Validate.notNull(id, "ID cannot be null"); - - // Valid MMOItem? - MMOItem m = getMMOItem(type, id, player); - if (m == null) - return null; - - // Build if found - return m.newBuilder().build(); - } - - /** - * @param itemLevel The desired item level - * @param itemTier The desired item tier, can be null - * @return Generates an item given an item template with a - * specific item level and item tier - */ - @Nullable - public MMOItem getMMOItem(@NotNull Type type, @NotNull String id, int itemLevel, @Nullable ItemTier itemTier) { - Validate.notNull(type, "Type cannot be null"); - Validate.notNull(id, "ID cannot be null"); - - // Valid template? - MMOItemTemplate found = getTemplates().getTemplate(type, id); - if (found == null) - return null; - - // Build if found - return found.newBuilder(itemLevel, itemTier).build(); - } - - /** - * @param itemLevel The desired item level - * @param itemTier The desired item tier, can be null - * @return Generates an item given an item template with a - * specific item level and item tier - */ - @Nullable - public ItemStack getItem(@NotNull Type type, @NotNull String id, int itemLevel, @Nullable ItemTier itemTier) { - Validate.notNull(type, "Type cannot be null"); - Validate.notNull(id, "ID cannot be null"); - - // Valid MMOItem? - MMOItem m = getMMOItem(type, id, itemLevel, itemTier); - if (m == null) - return null; - - // Build if found - return m.newBuilder().build(); - } - - /** - * @return Generates an item given an item template. The item level will be - * 0 and the item will have no item tier unless one is specified in - * the base item data. - *

- * Will return null if such MMOItem does not exist. - */ - @Nullable - public MMOItem getMMOItem(@NotNull Type type, @NotNull String id) { - Validate.notNull(type, "Type cannot be null"); - Validate.notNull(id, "ID cannot be null"); - - // Valid template? - MMOItemTemplate found = getTemplates().getTemplate(type, id); - if (found == null) return null; - - // Build if found - return found.newBuilder(0, null).build(); - } - - /** - * @return Generates an item given an item template. The item level will be - * 0 and the item will have no item tier unless one is specified in - * the base item data. - *

- * Will return null if such MMOItem does not exist. - */ - - @Nullable - public ItemStack getItem(@Nullable String type, @Nullable String id) { - if (type == null || id == null) { - return null; - } - return getItem(getTypes().get(type), id); - } - - /** - * @return Generates an item given an item template. The item level will be - * 0 and the item will have no item tier unless one is specified in - * the base item data. - *

- * Will return null if such MMOItem does not exist. - */ - @Nullable - public ItemStack getItem(@Nullable Type type, @Nullable String id) { - if (type == null || id == null) { - return null; - } - - // Valid MMOItem? - MMOItem m = getMMOItem(type, id); - if (m == null) { - return null; - } - - // Build if found - return m.newBuilder().build(); - } - - //region Reading MMOItems from ItemStacks - - /** - * @param stack The stack you trying to read - * @return The MMOItems type of this stack, if it has one - * @see #getType(NBTItem) - */ - @Nullable - public static Type getType(@Nullable ItemStack stack) { - - // Get from nbt - return getType(NBTItem.get(stack)); - } - - /** - * @param nbt The NBTItem you trying to read - * @return The MMOItems type of this nbt, if it has one - */ - @Nullable - public static Type getType(@Nullable NBTItem nbt) { - - // That's it - return plugin.getTypes().get(getTypeName(nbt)); - } - - /** - * @param stack The stack you trying to read - * @return The MMOItems type of this stack, if it has one - * @see #getTypeName(NBTItem) - */ - @Nullable - public static String getTypeName(@Nullable ItemStack stack) { - - // Get from nbt - return getTypeName(NBTItem.get(stack)); - } - - /** - * @param nbt The NBTItem you trying to read - * @return The MMOItems type of this nbt, if it has one - */ - @Nullable - public static String getTypeName(@Nullable NBTItem nbt) { - - // Straight up no - if (nbt == null) { - return null; - } - - // Get from nbt - if (!nbt.hasType()) { - return null; - } - - // That's it - return nbt.getType(); - } - - /** - * @param nbt The ItemStack you trying to read - * @return The MMOItems ID of this stack, if it has one - * @see #getID(NBTItem) - */ - @Nullable - public static String getID(@Nullable ItemStack nbt) { - - // That's it - return getID(NBTItem.get(nbt)); - } - - /** - * @param nbt The NBTItem you trying to read - * @return The MMOItems ID of this nbt, if it has one - */ - @Nullable - public static String getID(@Nullable NBTItem nbt) { - - // Straight up no - if (nbt == null) { - return null; - } - - // That's it - return nbt.getString("MMOITEMS_ITEM_ID"); - } - //endregion - - /** - * Logs something into the console with a cool [MMOItems] prefix :) - *

- * Parses color codes. Mostly for DEV testing. these may removed any release. - * - * @author Gunging - */ - public static void log(@Nullable String message) { - if (message == null) { - message = "< null >"; - } - //String prefix = "\u00a78[" + ChatColor.YELLOW + "MMOItems\u00a78] \u00a77"; - String prefix = ""; - plugin.getServer().getConsoleSender().sendMessage(prefix + message); - } - - /** - * Easily log something using the FriendlyFeedbackProvider, nice! - *

- * Use a null level to use the normal console sender. - * - * @author Gunging - */ - public static void print(@Nullable Level level, @Nullable String message, @Nullable String prefix, @NotNull String... replaces) { - if (message == null) { - message = "< null >"; - } - if (level != null) { - plugin.getLogger().log(level, FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), message, replaces)); - } else { - FriendlyFeedbackMessage p = new FriendlyFeedbackMessage("", prefix); - FriendlyFeedbackMessage r = FriendlyFeedbackProvider.generateMessage(p, message, replaces); - getConsole().sendMessage(r.forConsole(FFPMMOItems.get())); - } - } - - /** - * @return The server's console sender. - * @author Gunging - */ - @NotNull - public static ConsoleCommandSender getConsole() { - return plugin.getServer().getConsoleSender(); - } - //endregion + public static MMOItems plugin; + + // Increment this when making breaking changes to items. + public static final int INTERNAL_REVISION_ID = 1; + + private final PluginUpdateManager pluginUpdateManager = new PluginUpdateManager(); + private final CraftingManager stationRecipeManager = new CraftingManager(); + private final LoreFormatManager formatManager = new LoreFormatManager(); + private final TemplateManager templateManager = new TemplateManager(); + private final AbilityManager abilityManager = new AbilityManager(); + private final EntityManager entityManager = new EntityManager(); + private final RecipeManager recipeManager = new RecipeManager(); + private final LayoutManager layoutManager = new LayoutManager(); + private final TypeManager typeManager = new TypeManager(); + private final ItemManager itemManager = new ItemManager(); + private final PlayerInventoryHandler inventory = new PlayerInventoryHandler(); + private final List stringInputParsers = new ArrayList<>(); + private final List> enchantPlugins = new ArrayList<>(); + + private DropTableManager dropTableManager; + private WorldGenManager worldGenManager; + private UpgradeManager upgradeManager; + private ConfigManager configManager; + private BlockManager blockManager; + private TierManager tierManager; + private StatManager statManager; + private SetManager setManager; + private EquipListener equipListener; + + private PlaceholderParser placeholderParser = new DefaultPlaceholderParser(); + private VaultSupport vaultSupport; + private RPGHandler rpgPlugin; + + @Override + public void load() { + plugin = this; + + if (getServer().getPluginManager().getPlugin("WorldEdit") != null) try { + new WorldEditSupport(); + getLogger().log(Level.INFO, "Hooked onto WorldEdit"); + } catch (Exception exception) { + getLogger().log(Level.WARNING, "Could not initialize support with WorldEdit 7: " + exception.getMessage()); + } + + saveDefaultConfig(); + + /* + * stat manager must be initialized before MMOCore compatibility + * initializes so that MMOCore can register its stats + */ + statManager = new StatManager(); + typeManager.reload(); + templateManager.preloadTemplates(); + + if (Bukkit.getPluginManager().getPlugin("MMOCore") != null) new MMOCoreMMOLoader(); + + if (Bukkit.getPluginManager().getPlugin("mcMMO") != null) + //statManager.register(McMMOHook.MCMMO_SUPER_TOOL); + statManager.register(McMMOHook.disableMcMMORepair); + + if (Bukkit.getPluginManager().getPlugin("AdvancedEnchantments") != null) { + statManager.register(AdvancedEnchantmentsHook.ADVANCED_ENCHANTMENTS); + statManager.register(AdvancedEnchantmentsHook.DISABLE_ADVANCED_ENCHANTMENTS); + } + + if (Bukkit.getPluginManager().getPlugin("MythicEnchants") != null) enchantPlugins.add(new MythicEnchantsSupport()); + } + + @Override + public void enable() { + new SpigotPlugin(39267, this).checkForUpdate(); + new MMOItemsMetrics(); + + RecipeBrowserGUI.registerNativeRecipes(); + abilityManager.loadPluginAbilities(); + configManager = new ConfigManager(); + + final int configVersion = getConfig().contains("config-version", true) ? getConfig().getInt("config-version") : -1; + final int defConfigVersion = getConfig().getDefaults().getInt("config-version"); + if (configVersion != defConfigVersion) { + getLogger().warning("You may be using an outdated config.yml!"); + getLogger().warning("(Your config version: '" + configVersion + "' | Expected config version: '" + defConfigVersion + "')"); + } + + // registering here so the stats will load with the templates + if (Bukkit.getPluginManager().getPlugin("MythicMobs") != null) { + new MythicMobsLoader(); + if (getConfig().getBoolean("lootsplosion.enabled")) Bukkit.getPluginManager().registerEvents(new LootsplosionListener(), this); + getLogger().log(Level.INFO, "Hooked onto MythicMobs"); + } + + if (Bukkit.getPluginManager().getPlugin("MMOInventory") != null) { + new MMOInventorySupport(); + getLogger().log(Level.INFO, "Hooked onto MMOInventory"); + } + + findRpgPlugin(); + + /* + * After tiers, sets and upgrade templates are loaded, MI template data + * can be fully loaded + */ + formatManager.reload(); + tierManager = new TierManager(); + setManager = new SetManager(); + upgradeManager = new UpgradeManager(); + templateManager.postloadTemplates(); + + dropTableManager = new DropTableManager(); + worldGenManager = new WorldGenManager(); + blockManager = new BlockManager(); + equipListener = new EquipListener(); + + if (Bukkit.getPluginManager().getPlugin("Vault") != null) vaultSupport = new VaultSupport(); + + getLogger().log(Level.INFO, "Loading crafting stations, please wait.."); + layoutManager.reload(); + stationRecipeManager.reload(); + + // This ones are not implementing Reloadable + NumericStatFormula.reload(); + MMOItemReforger.reload(); + + Bukkit.getPluginManager().registerEvents(entityManager, this); + Bukkit.getPluginManager().registerEvents(dropTableManager, this); + Bukkit.getPluginManager().registerEvents(new ItemUse(), this); + Bukkit.getPluginManager().registerEvents(new ItemListener(), this); + Bukkit.getPluginManager().registerEvents(new PlayerListener(), this); + Bukkit.getPluginManager().registerEvents(new CustomSoundListener(), this); + Bukkit.getPluginManager().registerEvents(new DurabilityListener(), this); + Bukkit.getPluginManager().registerEvents(new DisableInteractions(), this); + Bukkit.getPluginManager().registerEvents(new GuiListener(), this); + Bukkit.getPluginManager().registerEvents(new ElementListener(), this); + Bukkit.getPluginManager().registerEvents(new CustomBlockListener(), this); + if (Bukkit.getPluginManager().getPlugin("PhatLoots") != null) { + Bukkit.getPluginManager().registerEvents(new PhatLootsHook(), this); + } + MMOItemUIFilter.register(); + + Bukkit.getScheduler().runTaskTimer(this, () -> Bukkit.getOnlinePlayers().forEach(player -> PlayerData.get(player).updateStats()), 100, 20); + + /* + * This tasks updates twice a second player inventories on the server. + * allows now to use a glitchy itemEquipEvent. Must be called after + * loading the config since it checks for a config option + */ + Bukkit.getScheduler().runTaskTimer(this, () -> { + for (Player player : Bukkit.getOnlinePlayers()) + PlayerData.get(player).getInventory().updateCheck(); + }, 100, getConfig().getInt("inventory-update-delay")); + + + if (Bukkit.getPluginManager().getPlugin("mcMMO") != null) Bukkit.getPluginManager().registerEvents(new McMMONonRPGHook(), this); + + /* + * Registers Player Inventories. Each of these add locations of items to search for + * when doing inventory updates. + */ + getInventory().register(new DefaultPlayerInventory()); + if (Bukkit.getPluginManager().getPlugin("RPGInventory") != null) { + getInventory().register(new RPGInventoryHook()); + getLogger().log(Level.INFO, "Hooked onto RPGInventory"); + } + if (MMOItems.plugin.getConfig().getBoolean("iterate-whole-inventory")) getInventory().register(new OrnamentPlayerInventory()); + + if (Bukkit.getPluginManager().getPlugin("CrazyEnchantments") != null) { + getStats().register(new CrazyEnchantsStat()); + getLogger().log(Level.INFO, "Hooked onto CrazyEnchantments"); + } + + if (Bukkit.getPluginManager().getPlugin("AdvancedEnchantments") != null) { + Bukkit.getPluginManager().registerEvents(new AdvancedEnchantmentsHook(), this); + getLogger().log(Level.INFO, "Hooked onto AdvancedEnchantments"); + } + + if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { + getLogger().log(Level.INFO, "Hooked onto PlaceholderAPI"); + placeholderParser = new PlaceholderAPIParser(); + } + + if (getConfig().getBoolean("item-glow")) { + if (Bukkit.getPluginManager().getPlugin("GlowAPI") != null && Bukkit.getPluginManager().getPlugin("PacketListenerApi") != null) { + Bukkit.getPluginManager().registerEvents(new ItemGlowListener(), this); + getLogger().log(Level.INFO, "Hooked onto GlowAPI (Item Glow)"); + } else Bukkit.getPluginManager().registerEvents(new NoGlowListener(), this); + } + + if (Bukkit.getPluginManager().getPlugin("RealDualWield") != null) { + Bukkit.getPluginManager().registerEvents(new RealDualWieldHook(), this); + getLogger().log(Level.INFO, "Hooked onto RealDualWield"); + } + + if (Bukkit.getPluginManager().getPlugin("BossShopPro") != null) { + getLogger().log(Level.INFO, "Hooked onto BossShopPro"); + (new BukkitRunnable() { + public void run() { + //noinspection ProhibitedExceptionCaught + try { + new MMOItemsRewardTypes().register(); + } catch (NullPointerException ignored) { + getLogger().log(Level.INFO, "Could not Hook onto BossShopPro"); + } + } + }).runTaskLater(this, 1L); + } + + /*if (Bukkit.getPluginManager().getPlugin("Denizen") != null) { + new DenizenHook(); + getLogger().log(Level.INFO, "Hooked onto Denizen"); + }*/ + + // compatibility with /reload + Bukkit.getScheduler().runTask(this, () -> Bukkit.getOnlinePlayers().forEach(PlayerData::load)); + + boolean book = getConfig().getBoolean("recipes.use-recipe-book"); + boolean amounts = getConfig().getBoolean("recipes.recipe-amounts"); + + if (book && amounts) { + getLogger().warning("Tried to enable recipe book while amounts are active!"); + getLogger().warning("Please use only ONE of these options!"); + getLogger().warning("Disabling both options for now..."); + book = false; + amounts = false; + } + + recipeManager.load(book, amounts); + if (amounts) Bukkit.getPluginManager().registerEvents(new CraftingListener(), this); + + // amount and bukkit recipes + getLogger().log(Level.INFO, "Loading recipes, please wait..."); + recipeManager.loadRecipes(); + + // main command + MMOItemsCommandTreeRoot mmoitemsCommand = new MMOItemsCommandTreeRoot(); + getCommand("mmoitems").setExecutor(mmoitemsCommand); + getCommand("mmoitems").setTabCompleter(mmoitemsCommand); + + // update item command DISABLED + //getCommand("updateitem").setExecutor(new UpdateItemCommand()); + //getCommand("updateitem").setTabCompleter(new UpdateItemCompletion()); + } + + @Override + public void disable() { + + // save player data + PlayerData.getLoaded().forEach(PlayerData::save); + + // save item updater data + ConfigFile updater = new ConfigFile("/dynamic", "updater"); + updater.getConfig().getKeys(false).forEach(key -> updater.getConfig().set(key, null)); + updater.save(); + + // drop abandonned soulbound items + SoulboundInfo.getAbandonnedInfo().forEach(SoulboundInfo::dropItems); + + // close inventories + for (Player player : Bukkit.getOnlinePlayers()) + if (player.getOpenInventory() != null && player.getOpenInventory().getTopInventory().getHolder() instanceof PluginInventory) + player.closeInventory(); + } + + public String getPrefix() { + return ChatColor.DARK_GRAY + "[" + ChatColor.YELLOW + "MMOItems" + ChatColor.DARK_GRAY + "] " + ChatColor.GRAY; + } + + public File getJarFile() { + return plugin.getFile(); + } + + public CraftingManager getCrafting() { + return stationRecipeManager; + } + + public LayoutManager getLayouts() { + return layoutManager; + } + + public SetManager getSets() { + return setManager; + } + + public RPGHandler getRPG() { + return rpgPlugin; + } + + /** + * The RPGHandler interface lets MMOItems fetch and manipulate RPG data like + * player level, class, resources like mana and stamina for item or skill + * costs, item restrictions, etc. + * + * @param handler Your RPGHandler instance + */ + public void setRPG(RPGHandler handler) { + Validate.notNull(handler, "RPGHandler cannot be null"); + + // unregister events from current rpgPlugin instance + if (rpgPlugin != null && rpgPlugin instanceof Listener && isEnabled()) HandlerList.unregisterAll((Listener) rpgPlugin); + + rpgPlugin = handler; + if (handler instanceof Listener && isEnabled()) Bukkit.getPluginManager().registerEvents((Listener) handler, this); + } + + public PluginUpdateManager getUpdates() { + return pluginUpdateManager; + } + + public PlayerInventoryHandler getInventory() { + return inventory; + } + + /** + * The PlayerInventory interface lets MMOItems knows what items to look for + * in player inventories whe doing inventory updates. By default, it only + * checks held items + armor slots. However other plugins like MMOInv do + * implement custom slots and therefore must register a custom + * PlayerInventory instance that tells of additional items to look for. + */ + public void registerPlayerInventory(PlayerInventory value) { + + // Registers in the Inventory Handler + getInventory().register(value); + } + + /** + * The PlayerInventory interface lets MMOItems knows what items to look for + * in player inventories whe doing inventory updates. By default, it only + * checks held items + armor slots. However other plugins like MMOInv do + * implement custom slots and therefore must register a custom + * PlayerInventory instance. + *

+ * Default instance is DefaultPlayerInventory in comp.inventory + * + * @param value The player inventory subclass + * @deprecated Rather than setting this to the only inventory MMOItems will + * search equipment within, you must add your inventory to the + * handler with getInventory().register(). This method + * will clear all other PlayerInventories for now, as to keep + * backwards compatibility. + */ + @Deprecated + public void setPlayerInventory(PlayerInventory value) { + + // Unregisters those previously registered + getInventory().unregisterAll(); + + // Registers this as the only + getInventory().register(value); + } + + /** + * Plugins like MythicEnchants which utilize the Bukkit + * class Enchantment by extending it don't use any ItemStat + * to store their enchants and therefore need to be called + * to update the item lore when any item is built. + * + * @param enchantPlugin Enchantment plugin + */ + public void registerEnchantPlugin(EnchantPlugin enchantPlugin) { + Validate.notNull(enchantPlugin, "Enchant plugin cannot be null"); + enchantPlugins.add(enchantPlugin); + } + + public StatManager getStats() { + return statManager; + } + + public TierManager getTiers() { + return tierManager; + } + + public EntityManager getEntities() { + return entityManager; + } + + public DropTableManager getDropTables() { + return dropTableManager; + } + + public AbilityManager getAbilities() { + return abilityManager; + } + + public BlockManager getCustomBlocks() { + return blockManager; + } + + public WorldGenManager getWorldGen() { + return worldGenManager; + } + + public RecipeManager getRecipes() { + return recipeManager; + } + + public ConfigManager getLanguage() { + return configManager; + } + + public TypeManager getTypes() { + return typeManager; + } + + public UpgradeManager getUpgrades() { + return upgradeManager; + } + + public PlaceholderParser getPlaceholderParser() { + return placeholderParser; + } + + public EquipListener getEquipListener() { + return equipListener; + } + + public TemplateManager getTemplates() { + return templateManager; + } + + public LoreFormatManager getFormats() { + return formatManager; + } + + @Deprecated + public ItemManager getItems() { + return itemManager; + } + + /* + * External API's + */ + public boolean hasPermissions() { + return vaultSupport != null && vaultSupport.getPermissions() != null; + } + + public List> getEnchantPlugins() { + return enchantPlugins; + } + + public boolean hasEconomy() { + return vaultSupport != null && vaultSupport.getEconomy() != null; + } + + public VaultSupport getVault() { + return vaultSupport; + } + + public List getStringInputParsers() { + return stringInputParsers; + } + + //region Easy-Access API + + /** + * Decide by which system will the RPG Requirements of the player will be checked. + *

+ * For example, required level, is that vanilla XP levels, MMOCore levels, McMMO Leves or what? + */ + public void findRpgPlugin() { + if (rpgPlugin != null) return; + + String preferred = plugin.getConfig().getString("preferred-rpg-provider", null); + if (preferred != null) { + + try { + RPGHandler.PluginEnum preferredRPG = RPGHandler.PluginEnum.valueOf(preferred.toUpperCase()); + // Found the plugin? + if (Bukkit.getPluginManager().getPlugin(preferredRPG.getName()) != null) { + + // Load that one + setRPG(preferredRPG.load()); + + // Mention it + print(null, "Using $s{0}$b as RPGPlayer provider", "RPG Provider", preferredRPG.getName()); + return; + } else + + print(null, "Preferred RPGPlayer provider $r{0}$b is not installed!", "RPG Provider", preferred); + + } catch (IllegalArgumentException ignored) { + + // Log error + FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FFPMMOItems.get()); + ffp.activatePrefix(true, "RPG Provider"); + ffp.log(FriendlyFeedbackCategory.ERROR, "Invalid RPG Provider '$u{0}$b' --- These are the supported ones:", preferred); + for (RPGHandler.PluginEnum pgrep : RPGHandler.PluginEnum.values()) { + ffp.log(FriendlyFeedbackCategory.ERROR, " $r+ $b{0}", pgrep.getName()); + } + ffp.sendTo(FriendlyFeedbackCategory.ERROR, getConsole()); + } + } + + // For each supported plugin + for (RPGHandler.PluginEnum pluginEnum : RPGHandler.PluginEnum.values()) { + + // Found the plugin? + if (Bukkit.getPluginManager().getPlugin(pluginEnum.getName()) != null) { + + // Load that one + setRPG(pluginEnum.load()); + + // Mention it + print(null, "Using $s{0}$b as RPGPlayer provider", "RPG Provider", pluginEnum.getName()); + return; + } + } + + // Just use the default + setRPG(new DefaultHook()); + } + + /** + * @return Generates an item given an item template. The item level will + * scale according to the player RPG level if the template has the + * 'level-item' option. The item will pick a random tier if the + * template has the 'tiered' option + */ + @Nullable + public MMOItem getMMOItem(@Nullable Type type, @Nullable String id, @Nullable PlayerData player) { + + // Valid template? + MMOItemTemplate found = getTemplates().getTemplate(type, id); + if (found == null) return null; + + // Build if found + return found.newBuilder(player).build(); + } + + /** + * @return Generates an item given an item template. The item level will + * scale according to the player RPG level if the template has the + * 'level-item' option. The item will pick a random tier if the + * template has the 'tiered' option + */ + @Nullable + public ItemStack getItem(@NotNull Type type, @NotNull String id, @NotNull PlayerData player) { + Validate.notNull(type, "Type cannot be null"); + Validate.notNull(id, "ID cannot be null"); + + // Valid MMOItem? + MMOItem m = getMMOItem(type, id, player); + if (m == null) return null; + + // Build if found + return m.newBuilder().build(); + } + + /** + * @param itemLevel The desired item level + * @param itemTier The desired item tier, can be null + * @return Generates an item given an item template with a + * specific item level and item tier + */ + @Nullable + public MMOItem getMMOItem(@NotNull Type type, @NotNull String id, int itemLevel, @Nullable ItemTier itemTier) { + Validate.notNull(type, "Type cannot be null"); + Validate.notNull(id, "ID cannot be null"); + + // Valid template? + MMOItemTemplate found = getTemplates().getTemplate(type, id); + if (found == null) return null; + + // Build if found + return found.newBuilder(itemLevel, itemTier).build(); + } + + /** + * @param itemLevel The desired item level + * @param itemTier The desired item tier, can be null + * @return Generates an item given an item template with a + * specific item level and item tier + */ + @Nullable + public ItemStack getItem(@NotNull Type type, @NotNull String id, int itemLevel, @Nullable ItemTier itemTier) { + Validate.notNull(type, "Type cannot be null"); + Validate.notNull(id, "ID cannot be null"); + + // Valid MMOItem? + MMOItem m = getMMOItem(type, id, itemLevel, itemTier); + if (m == null) return null; + + // Build if found + return m.newBuilder().build(); + } + + /** + * @return Generates an item given an item template. The item level will be + * 0 and the item will have no item tier unless one is specified in + * the base item data. + *

+ * Will return null if such MMOItem does not exist. + */ + @Nullable + public MMOItem getMMOItem(@NotNull Type type, @NotNull String id) { + Validate.notNull(type, "Type cannot be null"); + Validate.notNull(id, "ID cannot be null"); + + // Valid template? + MMOItemTemplate found = getTemplates().getTemplate(type, id); + if (found == null) return null; + + // Build if found + return found.newBuilder(0, null).build(); + } + + /** + * @return Generates an item given an item template. The item level will be + * 0 and the item will have no item tier unless one is specified in + * the base item data. + *

+ * Will return null if such MMOItem does not exist. + */ + + @Nullable + public ItemStack getItem(@Nullable String type, @Nullable String id) { + if (type == null || id == null) { + return null; + } + return getItem(getTypes().get(type), id); + } + + /** + * @return Generates an item given an item template. The item level will be + * 0 and the item will have no item tier unless one is specified in + * the base item data. + *

+ * Will return null if such MMOItem does not exist. + */ + @Nullable + public ItemStack getItem(@Nullable Type type, @Nullable String id) { + if (type == null || id == null) { + return null; + } + + // Valid MMOItem? + MMOItem m = getMMOItem(type, id); + if (m == null) { + return null; + } + + // Build if found + return m.newBuilder().build(); + } + + //region Reading MMOItems from ItemStacks + + /** + * @param stack The stack you trying to read + * @return The MMOItems type of this stack, if it has one + * @see #getType(NBTItem) + */ + @Nullable + public static Type getType(@Nullable ItemStack stack) { + + // Get from nbt + return getType(NBTItem.get(stack)); + } + + /** + * @param nbt The NBTItem you trying to read + * @return The MMOItems type of this nbt, if it has one + */ + @Nullable + public static Type getType(@Nullable NBTItem nbt) { + + // That's it + return plugin.getTypes().get(getTypeName(nbt)); + } + + /** + * @param stack The stack you trying to read + * @return The MMOItems type of this stack, if it has one + * @see #getTypeName(NBTItem) + */ + @Nullable + public static String getTypeName(@Nullable ItemStack stack) { + + // Get from nbt + return getTypeName(NBTItem.get(stack)); + } + + /** + * @param nbt The NBTItem you trying to read + * @return The MMOItems type of this nbt, if it has one + */ + @Nullable + public static String getTypeName(@Nullable NBTItem nbt) { + + // Straight up no + if (nbt == null) { + return null; + } + + // Get from nbt + if (!nbt.hasType()) { + return null; + } + + // That's it + return nbt.getType(); + } + + /** + * @param nbt The ItemStack you trying to read + * @return The MMOItems ID of this stack, if it has one + * @see #getID(NBTItem) + */ + @Nullable + public static String getID(@Nullable ItemStack nbt) { + + // That's it + return getID(NBTItem.get(nbt)); + } + + /** + * @param nbt The NBTItem you trying to read + * @return The MMOItems ID of this nbt, if it has one + */ + @Nullable + public static String getID(@Nullable NBTItem nbt) { + + // Straight up no + if (nbt == null) { + return null; + } + + // That's it + return nbt.getString("MMOITEMS_ITEM_ID"); + } + //endregion + + /** + * Logs something into the console with a cool [MMOItems] prefix :) + *

+ * Parses color codes. Mostly for DEV testing. these may removed any release. + * + * @author Gunging + */ + public static void log(@Nullable String message) { + if (message == null) { + message = "< null >"; + } + //String prefix = "\u00a78[" + ChatColor.YELLOW + "MMOItems\u00a78] \u00a77"; + String prefix = ""; + plugin.getServer().getConsoleSender().sendMessage(prefix + message); + } + + /** + * Easily log something using the FriendlyFeedbackProvider, nice! + *

+ * Use a null level to use the normal console sender. + * + * @author Gunging + */ + public static void print(@Nullable Level level, @Nullable String message, @Nullable String prefix, @NotNull String... replaces) { + if (message == null) { + message = "< null >"; + } + if (level != null) { + plugin.getLogger().log(level, FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), message, replaces)); + } else { + FriendlyFeedbackMessage p = new FriendlyFeedbackMessage("", prefix); + FriendlyFeedbackMessage r = FriendlyFeedbackProvider.generateMessage(p, message, replaces); + getConsole().sendMessage(r.forConsole(FFPMMOItems.get())); + } + } + + /** + * @return The server's console sender. + * @author Gunging + */ + @NotNull + public static ConsoleCommandSender getConsole() { + return plugin.getServer().getConsoleSender(); + } + //endregion } \ No newline at end of file diff --git a/src/main/java/net/Indyuce/mmoitems/ability/Ability.java b/src/main/java/net/Indyuce/mmoitems/ability/Ability.java index 61a792af..e65943b2 100644 --- a/src/main/java/net/Indyuce/mmoitems/ability/Ability.java +++ b/src/main/java/net/Indyuce/mmoitems/ability/Ability.java @@ -139,7 +139,12 @@ public abstract class Ability implements CooldownObje /** * Performing a right click while sneaking */ - SHIFT_RIGHT_CLICK; + SHIFT_RIGHT_CLICK, + + /** + * When player Sneaks + */ + SNEAK; private final boolean message; diff --git a/src/main/java/net/Indyuce/mmoitems/api/Type.java b/src/main/java/net/Indyuce/mmoitems/api/Type.java index d0829649..0365702b 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/Type.java +++ b/src/main/java/net/Indyuce/mmoitems/api/Type.java @@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.api; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.api.player.EquipmentSlot; +import io.lumine.mythic.lib.api.util.ui.SilentNumbers; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.item.util.identify.UnidentifiedItem; import net.Indyuce.mmoitems.manager.TypeManager; @@ -46,7 +47,7 @@ public class Type { public static final Type ORNAMENT = new Type(TypeSet.EXTRA, "ORNAMENT", false, EquipmentSlot.ANY); // extra - public static final Type ARMOR = new Type(TypeSet.EXTRA, "ARMOR", false, EquipmentSlot.ARMOR); + public static final Type ARMOR = new Type(TypeSet.EXTRA, "ARMOR", false, EquipmentSlot.ARMOR, true); public static final Type TOOL = new Type(TypeSet.EXTRA, "TOOL", false, EquipmentSlot.MAIN_HAND); public static final Type CONSUMABLE = new Type(TypeSet.EXTRA, "CONSUMABLE", false, EquipmentSlot.MAIN_HAND); public static final Type MISCELLANEOUS = new Type(TypeSet.EXTRA, "MISCELLANEOUS", false, EquipmentSlot.MAIN_HAND); @@ -59,6 +60,12 @@ public class Type { private String name; private final TypeSet set; + public boolean isFourGUIMode() { + return fourGUIMode; + } + + private final boolean fourGUIMode; + /** * Used for item type restrictions for gem stones to easily check if the * item is a weapon. @@ -89,10 +96,13 @@ public class Type { private final List available = new ArrayList<>(); public Type(TypeSet set, String id, boolean weapon, EquipmentSlot equipType) { + this(set, id, weapon, equipType, false); + } + public Type(TypeSet set, String id, boolean weapon, EquipmentSlot equipType, boolean fourGUI) { this.set = set; this.id = id.toUpperCase().replace("-", "_").replace(" ", "_"); this.equipType = equipType; - + this.fourGUIMode = fourGUI; this.weapon = weapon; } @@ -103,6 +113,7 @@ public class Type { set = parent.set; weapon = parent.weapon; equipType = parent.equipType; + this.fourGUIMode = config.getBoolean("AlternateGUIMode", parent.fourGUIMode); } public void load(ConfigurationSection config) { diff --git a/src/main/java/net/Indyuce/mmoitems/api/crafting/condition/PlaceholderCondition.java b/src/main/java/net/Indyuce/mmoitems/api/crafting/condition/PlaceholderCondition.java index e12deb62..00e46132 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/crafting/condition/PlaceholderCondition.java +++ b/src/main/java/net/Indyuce/mmoitems/api/crafting/condition/PlaceholderCondition.java @@ -27,16 +27,16 @@ public class PlaceholderCondition extends Condition { switch (comparator) { case "<": return Double.valueOf(placeholders) < Double.valueOf(compareTo); - case "<=": + case "<+": return Double.valueOf(placeholders) <= Double.valueOf(compareTo); case ">": return Double.valueOf(placeholders) > Double.valueOf(compareTo); - case ">=": + case ">+": return Double.valueOf(placeholders) >= Double.valueOf(compareTo); - case "==": - case "=": + case "++": + case "+": return Double.valueOf(placeholders) == Double.valueOf(compareTo); - case "!=": + case "!+": return Double.valueOf(placeholders) != Double.valueOf(compareTo); case "equals": return placeholders.equals(compareTo); diff --git a/src/main/java/net/Indyuce/mmoitems/api/interaction/GemStone.java b/src/main/java/net/Indyuce/mmoitems/api/interaction/GemStone.java index 94a87cbd..d5d93646 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/interaction/GemStone.java +++ b/src/main/java/net/Indyuce/mmoitems/api/interaction/GemStone.java @@ -69,6 +69,9 @@ public class GemStone extends UseItem { // Check for success rate double successRate = getNBTItem().getStat(ItemStats.SUCCESS_RATE.getId()); + if (successRate == 0.0) + successRate = 100; + // Call the Bukkit event ApplyGemStoneEvent called = new ApplyGemStoneEvent(playerData, mmoitem, targetMMO, RANDOM.nextDouble() > successRate / 100 ? ResultType.FAILURE : ResultType.SUCCESS); diff --git a/src/main/java/net/Indyuce/mmoitems/api/interaction/ItemSkin.java b/src/main/java/net/Indyuce/mmoitems/api/interaction/ItemSkin.java index f506eac9..d6ec5409 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/interaction/ItemSkin.java +++ b/src/main/java/net/Indyuce/mmoitems/api/interaction/ItemSkin.java @@ -34,7 +34,7 @@ public class ItemSkin extends UseItem { return new ApplyResult(ResultType.NONE); if (MMOItems.plugin.getConfig().getBoolean("locked-skins") && target.getBoolean("MMOITEMS_HAS_SKIN")) { - player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 2); + player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1); Message.SKIN_REJECTED.format(ChatColor.RED, "#item#", MMOUtils.getDisplayName(target.getItem())) .send(player); return new ApplyResult(ResultType.NONE); diff --git a/src/main/java/net/Indyuce/mmoitems/api/util/MMOItemReforger.java b/src/main/java/net/Indyuce/mmoitems/api/util/MMOItemReforger.java index 7dd371b2..cb47dc0a 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/util/MMOItemReforger.java +++ b/src/main/java/net/Indyuce/mmoitems/api/util/MMOItemReforger.java @@ -369,7 +369,7 @@ public class MMOItemReforger { * * @param options Additional options to pass onto the modules. * - * @return If reforged successfully ~ true unless cancelled. + * @return If reforged successfully. Basically true, unless cancelled. */ public boolean reforge(@NotNull ReforgeOptions options) { //RFG//MMOItems.log("§8Reforge §4RFG§7 Reforging " + SilentNumbers.getItemName(getStack())); diff --git a/src/main/java/net/Indyuce/mmoitems/command/mmoitems/ReloadCommandTreeNode.java b/src/main/java/net/Indyuce/mmoitems/command/mmoitems/ReloadCommandTreeNode.java index 911cc7dd..407e4a16 100644 --- a/src/main/java/net/Indyuce/mmoitems/command/mmoitems/ReloadCommandTreeNode.java +++ b/src/main/java/net/Indyuce/mmoitems/command/mmoitems/ReloadCommandTreeNode.java @@ -79,6 +79,7 @@ public class ReloadCommandTreeNode extends CommandTreeNode { sender.sendMessage(MMOItems.plugin.getPrefix() + "- " + ChatColor.RED + (MMOItems.plugin.getRecipes().getLoadedLegacyRecipes().size() + MMOItems.plugin.getRecipes().getLegacyCustomRecipes().size() + + MMOItems.plugin.getRecipes().getBooklessRecipes().size() + MMOItems.plugin.getRecipes().getCustomRecipes().size()) + ChatColor.GRAY + " Recipes"); } diff --git a/src/main/java/net/Indyuce/mmoitems/comp/denizen/DenizenBridge.java b/src/main/java/net/Indyuce/mmoitems/comp/denizen/DenizenBridge.java deleted file mode 100644 index 9b5ed404..00000000 --- a/src/main/java/net/Indyuce/mmoitems/comp/denizen/DenizenBridge.java +++ /dev/null @@ -1,74 +0,0 @@ -package net.Indyuce.mmoitems.comp.denizen; - -import com.denizenscript.denizen.objects.ItemTag; -import com.denizenscript.denizencore.objects.ObjectFetcher; -import com.denizenscript.denizencore.objects.ObjectTag; -import com.denizenscript.denizencore.objects.core.MapTag; -import com.denizenscript.denizencore.objects.properties.PropertyParser; -import com.denizenscript.denizencore.tags.TagManager; -import com.denizenscript.depenizen.bukkit.Bridge; -import net.Indyuce.mmoitems.MMOItems; -import net.Indyuce.mmoitems.api.Type; - -/** - * Basic integration with Denizen - */ -public class DenizenBridge extends Bridge { - - @Override - public void init() { - - /* - * This registers sub tags in the custom coded denizen tags - */ - /* ObjectFetcher.registerWithObjectFetcher(MMOItemTag.class, MMOItemTag.tagProcessor);*/ - ObjectFetcher.registerWithObjectFetcher(MMOItemTemplateTag.class, MMOItemTemplateTag.tagProcessor); - - /* - * Implement some properties to the already existing ItemTag - */ - PropertyParser.registerProperty(MMOItemsItemProperty.class, ItemTag.class); - - /* - * This implements a way to retrieve an MMOItem as itemStack. - * - * Usage: - * - */ - TagManager.registerTagHandler("mmoitem_template", attribute -> { - if (!attribute.hasContext(1)) { - attribute.echoError("Please provide an item type and ID."); - return null; - } - - MapTag map = attribute.contextAsType(1, MapTag.class); - if (map == null) { - attribute.echoError("Invalid MapTag input"); - return null; - } - - ObjectTag type = map.getObject("type"); - ObjectTag id = map.getObject("id"); - if (type == null || id == null) { - attribute.echoError("Invalid MapTag input - missing 'type' or 'id'"); - return null; - } - - String typeName = type.toString().replace("-", "_").toUpperCase(); - Type parsedType = MMOItems.plugin.getTypes().get(typeName); - if (parsedType == null) { - attribute.echoError("Invalid type - cannot find type with name '" + typeName + "'"); - return null; - } - - // Format ID and return item - String formattedId = id.toString().replace("-", "_").toUpperCase(); - if (!MMOItems.plugin.getTemplates().hasTemplate(parsedType, formattedId)) { - attribute.echoError("Invalid template ID - cannot find template with name '" + formattedId + "'"); - return null; - } - - return new MMOItemTemplateTag(parsedType, formattedId); - }); - } -} diff --git a/src/main/java/net/Indyuce/mmoitems/comp/denizen/DenizenHook.java b/src/main/java/net/Indyuce/mmoitems/comp/denizen/DenizenHook.java index 6a14a475..b4cca618 100644 --- a/src/main/java/net/Indyuce/mmoitems/comp/denizen/DenizenHook.java +++ b/src/main/java/net/Indyuce/mmoitems/comp/denizen/DenizenHook.java @@ -1,18 +1,72 @@ package net.Indyuce.mmoitems.comp.denizen; -import com.denizenscript.depenizen.bukkit.Depenizen; +import com.denizenscript.denizen.objects.ItemTag; +import com.denizenscript.denizencore.objects.ObjectFetcher; +import com.denizenscript.denizencore.objects.ObjectTag; +import com.denizenscript.denizencore.objects.core.MapTag; +import com.denizenscript.denizencore.objects.properties.PropertyParser; +import com.denizenscript.denizencore.tags.TagManager; import net.Indyuce.mmoitems.MMOItems; -import org.bukkit.Bukkit; +import net.Indyuce.mmoitems.api.Type; public class DenizenHook { + /** + * Putting this here so that the Depenizen import does not + * appear in the main MMOItems class which would cause an issue + * for all servers without Denizen + */ + public DenizenHook() { + /* + * This registers sub tags in the custom coded denizen tags + */ + /* ObjectFetcher.registerWithObjectFetcher(MMOItemTag.class, MMOItemTag.tagProcessor);*/ + ObjectFetcher.registerWithObjectFetcher(MMOItemTemplateTag.class, MMOItemTemplateTag.tagProcessor); - /** - * Putting this here so that the Depenizen import does not - * appear in the main MMOItems class which would cause an issue - * for all servers without Denizen - */ - public DenizenHook() { - Depenizen depenizen = (Depenizen) Bukkit.getPluginManager().getPlugin("Depenizen"); - depenizen.registerBridge(MMOItems.plugin.getName(), () -> new DenizenBridge()); - } + /* + * Implement some properties to the already existing ItemTag + */ + PropertyParser.registerProperty(MMOItemsItemProperty.class, ItemTag.class); + + /* + * This implements a way to retrieve an MMOItem as itemStack. + * + * Usage: + * + */ + TagManager.registerTagHandler("mmoitem_template", attribute -> { + if (!attribute.hasContext(1)) { + attribute.echoError("Please provide an item type and ID."); + return null; + } + + MapTag map = attribute.contextAsType(1, MapTag.class); + if (map == null) { + attribute.echoError("Invalid MapTag input"); + return null; + } + + ObjectTag type = map.getObject("type"); + ObjectTag id = map.getObject("id"); + if (type == null || id == null) { + attribute.echoError("Invalid MapTag input - missing 'type' or 'id'"); + return null; + } + + String typeName = type.toString().replace("-", "_").toUpperCase(); + Type parsedType = MMOItems.plugin.getTypes().get(typeName); + if (parsedType == null) { + attribute.echoError("Invalid type - cannot find type with name '" + typeName + "'"); + return null; + } + + // Format ID and return item + String formattedId = id.toString().replace("-", "_").toUpperCase(); + if (!MMOItems.plugin.getTemplates().hasTemplate(parsedType, formattedId)) { + attribute.echoError("Invalid template ID - cannot find template with name '" + formattedId + "'"); + return null; + } + + return new MMOItemTemplateTag(parsedType, formattedId); + }); + } } diff --git a/src/main/java/net/Indyuce/mmoitems/comp/denizen/MMOItemTemplateTag.java b/src/main/java/net/Indyuce/mmoitems/comp/denizen/MMOItemTemplateTag.java index b2c4cb2a..ab27b309 100644 --- a/src/main/java/net/Indyuce/mmoitems/comp/denizen/MMOItemTemplateTag.java +++ b/src/main/java/net/Indyuce/mmoitems/comp/denizen/MMOItemTemplateTag.java @@ -13,138 +13,133 @@ import net.Indyuce.mmoitems.api.ItemTier; import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate; import net.Indyuce.mmoitems.api.player.PlayerData; -import org.bukkit.inventory.ItemStack; import java.util.Random; public class MMOItemTemplateTag extends SimpleTag { - private final Type type; - private final String id; + private final Type type; + private final String id; - private static final Random random = new Random(); + private static final Random random = new Random(); - public MMOItemTemplateTag(Type type, String id) { - this.type = type; - this.id = id; - } + public MMOItemTemplateTag(Type type, String id) { + this.type = type; + this.id = id; + } - public MMOItemTemplate getTemplate() { - return MMOItems.plugin.getTemplates().getTemplate(type, id); - } + public MMOItemTemplate getTemplate() { + return MMOItems.plugin.getTemplates().getTemplate(type, id); + } - @Override - public boolean isUnique() { - return true; - } + @Override + public boolean isUnique() { + return true; + } - @Override - public String getObjectType() { - return "MMOItemTemplate"; - } + @Override + public String getObjectType() { + return "MMOItemTemplate"; + } - @Override - public String identify() { - return "mmoitem_template@" + type.getId() + "." + id; - } + @Override + public String identify() { + return "mmoitem_template@" + type.getId() + "." + id; + } - @Override - public String identifySimple() { - return identify(); - } + @Override + public String identifySimple() { + return identify(); + } - public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>(); + public static ObjectTagProcessor tagProcessor = new ObjectTagProcessor<>(); - @Override - public ObjectTag getObjectAttribute(Attribute attribute) { - return tagProcessor.getObjectAttribute(this, attribute); - } + @Override + public ObjectTag getObjectAttribute(Attribute attribute) { + return tagProcessor.getObjectAttribute(this, attribute); + } - public static void registerTags() { + public static void registerTags() { - // Display template type name - tagProcessor.registerTag("item_type", ((attribute, object) -> new ElementTag(object.type.getName()))); + // Display template type name + tagProcessor.registerTag("item_type", ((attribute, object) -> new ElementTag(object.type.getName()))); - // Display template id - tagProcessor.registerTag("item_id", ((attribute, object) -> new ElementTag(object.id))); + // Display template id + tagProcessor.registerTag("item_id", ((attribute, object) -> new ElementTag(object.id))); - /* - * Used to generate an item with custom tier and level. - * - * Usage: - * { - if (!attribute.hasContext(1)) - return new ItemTag(object.getTemplate().newBuilder().build().newBuilder().build()); + /* + * Used to generate an item with custom tier and level. + * + * Usage: + * { + if (!attribute.hasContext(1)) return new ItemTag(object.getTemplate().newBuilder().build().newBuilder().build()); - MapTag map = attribute.contextAsType(1, MapTag.class); - if (map == null) { - attribute.echoError("Invalid MapTag input"); - return null; - } + MapTag map = attribute.contextAsType(1, MapTag.class); + if (map == null) { + attribute.echoError("Invalid MapTag input"); + return null; + } - ObjectTag playerTag = map.getObject("player"); - if (playerTag != null && !(playerTag instanceof PlayerTag)) { - attribute.echoError("Bad player input type"); - return null; - } + ObjectTag playerTag = map.getObject("player"); + if (playerTag != null && !(playerTag instanceof PlayerTag)) { + attribute.echoError("Bad player input type"); + return null; + } - // Specified level - ObjectTag levelTag = map.getObject("level"); - int level = -1; - if (levelTag != null) - try { - level = Integer.valueOf(levelTag.toString()); - } catch (IllegalArgumentException exception) { - attribute.echoError("Bad level input: " + levelTag.toString() + " is not a valid integer"); - return null; - } + // Specified level + ObjectTag levelTag = map.getObject("level"); + int level = -1; + if (levelTag != null) try { + level = Integer.parseInt(levelTag.toString()); + } catch (IllegalArgumentException exception) { + attribute.echoError("Bad level input: " + levelTag + " is not a valid integer"); + return null; + } - // Match level - ObjectTag matchLevelTag = map.getObject("match-level"); - boolean matchLevel = matchLevelTag != null && Boolean.valueOf(matchLevelTag.toString()); + // Match level + ObjectTag matchLevelTag = map.getObject("match-level"); + boolean matchLevel = matchLevelTag != null && Boolean.parseBoolean(matchLevelTag.toString()); - // Item tier param - ObjectTag tierTag = map.getObject("tier"); - ItemTier tier = null; - if (tierTag != null) - try { - tier = MMOItems.plugin.getTiers().getOrThrow(tierTag.toString().toUpperCase().replace("-", "_")); - } catch (IllegalArgumentException exception) { - attribute.echoError(exception.getMessage()); - } + // Item tier param + ObjectTag tierTag = map.getObject("tier"); + ItemTier tier = null; + if (tierTag != null) try { + tier = MMOItems.plugin.getTiers().getOrThrow(tierTag.toString().toUpperCase().replace("-", "_")); + } catch (IllegalArgumentException exception) { + attribute.echoError(exception.getMessage()); + } - // Find item level - int itemLevel = level >= 0 ? level : (matchLevel && playerTag != null ? - MMOItems.plugin.getTemplates().rollLevel(PlayerData.get(((PlayerTag) playerTag).getPlayerEntity()).getRPG().getLevel()) : 1 + random.nextInt(100)); + // Find item level + int itemLevel = level >= 0 ? level : (matchLevel && playerTag != null ? MMOItems.plugin.getTemplates() + .rollLevel(PlayerData.get(((PlayerTag) playerTag).getPlayerEntity()).getRPG().getLevel()) : 1 + random.nextInt(100)); - // Find item tier - ItemTier itemTier = tier != null ? tier : MMOItems.plugin.getTemplates().rollTier(); + // Find item tier + ItemTier itemTier = tier != null ? tier : MMOItems.plugin.getTemplates().rollTier(); - // Build item - return new ItemTag(object.getTemplate().newBuilder(itemLevel, itemTier).build().newBuilder().build()); - }); - } + // Build item + return new ItemTag(object.getTemplate().newBuilder(itemLevel, itemTier).build().newBuilder().build()); + }); + } - public static MMOItemTemplateTag valueOf(String string, TagContext context) { - if (string == null) - return null; + public static MMOItemTemplateTag valueOf(String string, TagContext context) { + if (string == null) return null; - try { - String[] split = string.substring("mmoitem_template@".length()).split("\\."); - String typeId = split[0]; - String itemId = split[1]; + try { + String[] split = string.substring("mmoitem_template@".length()).split("\\."); + String typeId = split[0]; + String itemId = split[1]; - Type type = MMOItems.plugin.getTypes().getOrThrow(typeId); - MMOItems.plugin.getTemplates().getTemplateOrThrow(type, itemId); + Type type = MMOItems.plugin.getTypes().getOrThrow(typeId); + MMOItems.plugin.getTemplates().getTemplateOrThrow(type, itemId); - return new MMOItemTemplateTag(type, itemId); - } catch (Exception exception) { - return null; - } - } + return new MMOItemTemplateTag(type, itemId); + } catch (Exception exception) { + return null; + } + } } diff --git a/src/main/java/net/Indyuce/mmoitems/comp/mythicmobs/skill/MythicMobsAbility.java b/src/main/java/net/Indyuce/mmoitems/comp/mythicmobs/skill/MythicMobsAbility.java index e271f889..1251aa53 100644 --- a/src/main/java/net/Indyuce/mmoitems/comp/mythicmobs/skill/MythicMobsAbility.java +++ b/src/main/java/net/Indyuce/mmoitems/comp/mythicmobs/skill/MythicMobsAbility.java @@ -23,7 +23,7 @@ public class MythicMobsAbility extends Ability { private final Skill skill; public MythicMobsAbility(String id, FileConfiguration config) { - super(id, config.getString("name"), CastingMode.ON_HIT, CastingMode.WHEN_HIT, CastingMode.LEFT_CLICK, CastingMode.RIGHT_CLICK, CastingMode.SHIFT_LEFT_CLICK, CastingMode.SHIFT_RIGHT_CLICK); + super(id, config.getString("name"), CastingMode.ON_HIT, CastingMode.WHEN_HIT, CastingMode.LEFT_CLICK, CastingMode.RIGHT_CLICK, CastingMode.SHIFT_LEFT_CLICK, CastingMode.SHIFT_RIGHT_CLICK, CastingMode.SNEAK); String skillName = config.getString("mythicmobs-skill-id"); Validate.notNull(skillName, "Could not find MM skill name"); diff --git a/src/main/java/net/Indyuce/mmoitems/gui/ItemBrowser.java b/src/main/java/net/Indyuce/mmoitems/gui/ItemBrowser.java index 858d40c9..fadc907c 100644 --- a/src/main/java/net/Indyuce/mmoitems/gui/ItemBrowser.java +++ b/src/main/java/net/Indyuce/mmoitems/gui/ItemBrowser.java @@ -24,6 +24,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; @@ -38,6 +39,8 @@ public class ItemBrowser extends PluginInventory { private boolean deleteMode; private static final int[] slots = { 10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, 32, 33, 34 }; + //private static final int[] slotsAlt = { 10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43 }; + private static final int[] slotsAlt = { 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, 32, 33, 34 }; public ItemBrowser(Player player) { this(player, null); @@ -48,11 +51,14 @@ public class ItemBrowser extends PluginInventory { this.type = type; } + + int[] getUsedSlots(@Nullable Type forType) { return forType == null ? slots : forType.isFourGUIMode() ? slotsAlt : slots; } @Override public Inventory getInventory() { - int min = (page - 1) * slots.length; - int max = page * slots.length; + int[] usedSlots = getUsedSlots(type); + int min = (page - 1) * usedSlots.length; + int max = page * usedSlots.length; int n = 0; /* @@ -125,7 +131,7 @@ public class ItemBrowser extends PluginInventory { ItemStack item = template.newBuilder(playerData.getRPG()).build().newBuilder().build(); if (item == null || item.getType() == Material.AIR) { cached.put(template.getId(), error); - inv.setItem(slots[n++], error); + inv.setItem(usedSlots[n++], error); continue; } NBTItem nbtItem = NBTItem.get(item); @@ -148,7 +154,7 @@ public class ItemBrowser extends PluginInventory { cached.put(template.getId(), nbtItem.toItem()); - inv.setItem(slots[n++], cached.get(template.getId())); + inv.setItem(usedSlots[n++], cached.get(template.getId())); } ItemStack noItem = VersionMaterial.GRAY_STAINED_GLASS_PANE.toItem(); @@ -192,8 +198,8 @@ public class ItemBrowser extends PluginInventory { inv.setItem(45, downloadPack); } - while (n < slots.length) - inv.setItem(slots[n++], noItem); + while (n < usedSlots.length) + inv.setItem(usedSlots[n++], noItem); if (!deleteMode) inv.setItem(51, create); inv.setItem(47, delete); diff --git a/src/main/java/net/Indyuce/mmoitems/gui/edition/recipe/registry/RMGRR_Shapeless.java b/src/main/java/net/Indyuce/mmoitems/gui/edition/recipe/registry/RMGRR_Shapeless.java index 0c3a855e..3cc7c52f 100644 --- a/src/main/java/net/Indyuce/mmoitems/gui/edition/recipe/registry/RMGRR_Shapeless.java +++ b/src/main/java/net/Indyuce/mmoitems/gui/edition/recipe/registry/RMGRR_Shapeless.java @@ -63,6 +63,11 @@ public class RMGRR_Shapeless implements RecipeRegistry { // Add ProvidedUIFilter p = RecipeMakerGUI.readIngredientFrom(str, ffp); + + // Not air right + if (p.isAir()) { continue; } + + // Ok snooze nonAirFound = true; poofs.add(new MythicRecipeIngredient(p)); } diff --git a/src/main/java/net/Indyuce/mmoitems/gui/edition/recipe/registry/RMGRR_Smithing.java b/src/main/java/net/Indyuce/mmoitems/gui/edition/recipe/registry/RMGRR_Smithing.java index bef3c761..5bbedc92 100644 --- a/src/main/java/net/Indyuce/mmoitems/gui/edition/recipe/registry/RMGRR_Smithing.java +++ b/src/main/java/net/Indyuce/mmoitems/gui/edition/recipe/registry/RMGRR_Smithing.java @@ -9,6 +9,7 @@ import io.lumine.mythic.lib.api.crafting.recipes.ShapelessRecipe; import io.lumine.mythic.lib.api.crafting.uimanager.ProvidedUIFilter; import io.lumine.mythic.lib.api.util.Ref; import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider; +import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.crafting.recipe.CustomSmithingRecipe; import net.Indyuce.mmoitems.api.crafting.recipe.SmithingCombinationType; import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate; @@ -86,8 +87,8 @@ public class RMGRR_Smithing implements RecipeRegistry { // Read the options and output int outputAmount = recipeSection.getInt(RBA_AmountOutput.AMOUNT_INGREDIENTS, 1); boolean dropGems = recipeSection.getBoolean(RBA_DropGems.SMITH_GEMS, false); - SmithingCombinationType upgradeEffect = readSCT(recipeSection.getString(RBA_SmithingEnchantments.SMITH_ENCHANTS)); - SmithingCombinationType enchantEffect = readSCT(recipeSection.getString(RBA_SmithingUpgrades.SMITH_UPGRADES)); + SmithingCombinationType enchantEffect = readSCT(recipeSection.getString(RBA_SmithingEnchantments.SMITH_ENCHANTS)); + SmithingCombinationType upgradeEffect = readSCT(recipeSection.getString(RBA_SmithingUpgrades.SMITH_UPGRADES)); // Build Output CustomSmithingRecipe outputRecipe = new CustomSmithingRecipe(template, dropGems, enchantEffect, upgradeEffect, outputAmount); diff --git a/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java b/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java index a5f1d9ca..6fe35f76 100644 --- a/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java +++ b/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java @@ -277,8 +277,11 @@ public class ItemUse implements Listener { return; NBTItem item = NBTItem.get(event.getBow()); + if (!item.hasType()) + return; Type type = Type.get(item.getType()); + PlayerData playerData = PlayerData.get((Player) event.getEntity()); if (type != null) { Weapon weapon = new Weapon(playerData, item); diff --git a/src/main/java/net/Indyuce/mmoitems/listener/PlayerListener.java b/src/main/java/net/Indyuce/mmoitems/listener/PlayerListener.java index 6d368c93..fe12571e 100644 --- a/src/main/java/net/Indyuce/mmoitems/listener/PlayerListener.java +++ b/src/main/java/net/Indyuce/mmoitems/listener/PlayerListener.java @@ -60,6 +60,12 @@ public class PlayerListener implements Listener { PlayerData.get(player).castAbilities(damager, CastingMode.WHEN_HIT); } + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void castWhenSneakAbilities(PlayerToggleSneakEvent event) { + Player player = event.getPlayer(); + PlayerData.get(player).castAbilities(null, CastingMode.SNEAK); + } + @EventHandler(priority = EventPriority.LOW) public void castClickAbilities(PlayerInteractEvent event) { if (event.getAction() == Action.PHYSICAL) @@ -148,6 +154,9 @@ public class PlayerListener implements Listener { return; NBTItem nbtItem = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item.getItem()); + if (!nbtItem.hasType()) + return; + Type type = Type.get(nbtItem.getType()); PlayerData playerData = PlayerData.get((Player) event.getEntity().getShooter()); diff --git a/src/main/java/net/Indyuce/mmoitems/manager/RecipeManager.java b/src/main/java/net/Indyuce/mmoitems/manager/RecipeManager.java index 6dda910b..56e60825 100644 --- a/src/main/java/net/Indyuce/mmoitems/manager/RecipeManager.java +++ b/src/main/java/net/Indyuce/mmoitems/manager/RecipeManager.java @@ -214,6 +214,7 @@ public class RecipeManager implements Reloadable { return legacyCraftingRecipes; } public HashMap getCustomRecipes() { return customRecipes; } + public ArrayList getBooklessRecipes() { return booklessRecipes; } @Nullable ArrayList generatedNKs;