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;