From 9b09ec1d10234f1cc5d063da172ca697d75c0aa7 Mon Sep 17 00:00:00 2001 From: Gunging Date: Thu, 15 Apr 2021 21:40:44 -0500 Subject: [PATCH] Revision of items where gemstones are lost now supports giving those gems back to the player. Suppose the latest item has less gem slots / different colored gem slots, or you set keep-gems to FALSE. In all these scenarios, gems are 'lost' so that this config option (**true** by default!) gives them back to the player. Enable in your config: ``` # Options for the Item Revision System item-revision: # If an item is updated, and the new version does not # keep its gems, this will give the gems back to the # player so that they don't get lost forever. drop-extra-gems: true ``` --- pom.xml | 2 +- .../Indyuce/mmoitems/api/ReforgeOptions.java | 2 + .../crafting/recipe/CustomSmithingRecipe.java | 22 ++--- .../api/item/build/ItemStackBuilder.java | 8 +- .../mmoitems/api/item/mmoitem/MMOItem.java | 57 ++++++++++++ .../mmoitems/api/util/MMOItemReforger.java | 86 +++++++++++++------ .../mmoitems/listener/ItemListener.java | 42 ++++++++- .../mmoitems/manager/ConfigManager.java | 1 + .../mmoitems/stat/data/GemstoneData.java | 4 + .../mmoitems/stat/type/DoubleStat.java | 9 +- src/main/resources/config.yml | 5 ++ 11 files changed, 191 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index e8e96d00..f046a435 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 net.Indyuce MMOItems - 6.5.6-SNAPSHOT + 6.5.7 MMOItems A great item solution for your RPG server! diff --git a/src/main/java/net/Indyuce/mmoitems/api/ReforgeOptions.java b/src/main/java/net/Indyuce/mmoitems/api/ReforgeOptions.java index 7a1b83a3..4c4486ae 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/ReforgeOptions.java +++ b/src/main/java/net/Indyuce/mmoitems/api/ReforgeOptions.java @@ -4,6 +4,8 @@ import net.Indyuce.mmoitems.MMOItems; import org.bukkit.configuration.ConfigurationSection; public class ReforgeOptions { + public static boolean dropRestoredGems; + private final boolean keepName; private final boolean keepLore; diff --git a/src/main/java/net/Indyuce/mmoitems/api/crafting/recipe/CustomSmithingRecipe.java b/src/main/java/net/Indyuce/mmoitems/api/crafting/recipe/CustomSmithingRecipe.java index 0745a60d..6df5f47e 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/crafting/recipe/CustomSmithingRecipe.java +++ b/src/main/java/net/Indyuce/mmoitems/api/crafting/recipe/CustomSmithingRecipe.java @@ -19,6 +19,7 @@ import net.Indyuce.mmoitems.stat.data.EnchantListData; import net.Indyuce.mmoitems.stat.data.GemSocketsData; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Sound; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryAction; @@ -155,6 +156,7 @@ public class CustomSmithingRecipe extends MythicRecipeOutput { */ eventTrigger.setCancelled(true); if (!(eventTrigger.getWhoClicked() instanceof Player)) { return; } + Player player = (Player) eventTrigger.getWhoClicked(); // Get the two combinant items ItemStack item = otherInventories.getMainInventory().getFirst(); @@ -165,7 +167,7 @@ public class CustomSmithingRecipe extends MythicRecipeOutput { // Get the display Ref> droppedGemstones = new Ref<>(); - MMOItem display = fromCombinationWith(itemMMO, ingotMMO, (Player) eventTrigger.getWhoClicked(), droppedGemstones); + MMOItem display = fromCombinationWith(itemMMO, ingotMMO, player, droppedGemstones); // Result MythicRecipeInventory result = otherInventories.getResultInventory().clone(); @@ -259,7 +261,7 @@ public class CustomSmithingRecipe extends MythicRecipeOutput { // Build the result ArrayList outputItems = MRORecipe.toItemsList(result); HashMap modifiedInventory = null; - Inventory inven = eventTrigger.getWhoClicked().getInventory(); + Inventory inven = player.getInventory(); int trueTimes = 0; // For every time @@ -303,17 +305,17 @@ public class CustomSmithingRecipe extends MythicRecipeOutput { } // Drop? - if (isDropGemstones() && (droppedGemstones.getValue() != null) && (eventTrigger.getWhoClicked().getLocation().getWorld() != null)) { - Location l = eventTrigger.getWhoClicked().getLocation(); + if (isDropGemstones() && (droppedGemstones.getValue() != null) && (player.getLocation().getWorld() != null)) { - // Drop each yea - for (ItemStack gem : droppedGemstones.getValue()) { + // Give the gems back + for (ItemStack drop : player.getInventory().addItem( + droppedGemstones.getValue().toArray(new ItemStack[0])).values()) { - if (SilentNumbers.isAir(gem)) { continue; } + // Not air right + if (SilentNumbers.isAir(drop)) { continue; } - // God damn drop yo - l.getWorld().dropItemNaturally(l, gem); - } } + // Drop to the world + player.getWorld().dropItem(player.getLocation(), drop); } } // Consume ingredients consumeIngredients(otherInventories, cache, eventTrigger.getInventory(), map, times); diff --git a/src/main/java/net/Indyuce/mmoitems/api/item/build/ItemStackBuilder.java b/src/main/java/net/Indyuce/mmoitems/api/item/build/ItemStackBuilder.java index e2697533..03b7a100 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/item/build/ItemStackBuilder.java +++ b/src/main/java/net/Indyuce/mmoitems/api/item/build/ItemStackBuilder.java @@ -141,16 +141,16 @@ public class ItemStackBuilder { StatHistory s = builtMMOItem.getStatHistory(stat); int l = mmoitem.getUpgradeLevel(); // Found it? - if (s != null && (!s.isClear() || stat instanceof Enchants)) { + if (s != null) { //GEM//MMOItems.log("\u00a7a -+- \u00a77Recording History"); - // Add to NBT - addItemTag(new ItemTag(histroy_keyword + stat.getId(), s.toNBTString())); - // Recalculate //HSY//MMOItems.log(" \u00a73-\u00a7a- \u00a77ItemStack Building Recalculation \u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-"); builtMMOItem.setData(stat, s.recalculate(l)); + + // Add to NBT, if the gemstones were not purged + if ((!s.isClear() || stat instanceof Enchants)) { addItemTag(new ItemTag(histroy_keyword + stat.getId(), s.toNBTString())); } } if (forDisplay && stat instanceof Previewable) { diff --git a/src/main/java/net/Indyuce/mmoitems/api/item/mmoitem/MMOItem.java b/src/main/java/net/Indyuce/mmoitems/api/item/mmoitem/MMOItem.java index 8d1989bf..9aadee50 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/item/mmoitem/MMOItem.java +++ b/src/main/java/net/Indyuce/mmoitems/api/item/mmoitem/MMOItem.java @@ -9,6 +9,7 @@ import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder; import net.Indyuce.mmoitems.stat.Enchants; import net.Indyuce.mmoitems.stat.data.GemSocketsData; import net.Indyuce.mmoitems.stat.data.GemstoneData; +import net.Indyuce.mmoitems.stat.data.StringData; import net.Indyuce.mmoitems.stat.data.UpgradeData; import net.Indyuce.mmoitems.stat.data.type.Mergeable; import net.Indyuce.mmoitems.stat.data.type.StatData; @@ -388,6 +389,61 @@ public class MMOItem implements ItemReference { return new ArrayList<>(regeneratedGems.values()); } + /** + * Extracts a single gemstone. Note that this only builds the original Gemstone MMOItem, and if you + * wish to actually remove the GemStone, you must do so through {@link #removeGemStone(UUID, String)} + * + * @param gem Gemstone that you believe is in here + * + * @return The gemstone as it was when inserted, or null + * if such gemstone is not in here. + * + * @see #extractGemstones() More optimized method for extracting all gemstones at the same time. + */ + @Nullable public MMOItem extractGemstone(@NotNull GemstoneData gem) { + //XTC//MMOItems.log("\u00a7a *\u00a77 Extracting gem stone -\u00a7a " + gem.getMMOItemType() + " " + gem.getMMOItemID()); + + // Can we generate? + MMOItem restored = MMOItems.plugin.getMMOItem(MMOItems.plugin.getType(gem.getMMOItemType()), gem.getMMOItemID()); + + // Valid? neat-o + if (restored != null) { + //XTC//MMOItems.log("\u00a7a *\u00a73>\u00a77 Valid, regenerated \u00a7e" + restored.getData(ItemStats.NAME)); + + restored.asGemColor = gem.getSocketColor(); + restored.asGemUUID = gem.getHistoricUUID(); + //XTC//MMOItems.log("\u00a7a >\u00a77 Color \u00a7e" + restored.getAsGemColor()); + //XTC//MMOItems.log("\u00a7a >\u00a77 UUID \u00a7e" + restored.getAsGemUUID().toString()); + + // Cannot be removed + } else { + //XTC//MMOItems.log("\u00a7a *\u00a7c Gem too old / MMOItem missing"); + return null; } + + // Identify actual attributes + for (ItemStat stat : getStats()) { + + // Mergeable right + if (!(stat.getClearStatData() instanceof Mergeable)) { continue; } + + // Any stat affected by gems is sure to have a Stat History + StatHistory hist = getStatHistory(stat); + if (hist == null) { continue; } + //XTC//MMOItems.log("\u00a7a *\u00a7c>\u00a7a Found Stat History \u00a79" + stat.getId()); + + // History got gem registered? + StatData historicGemData = hist.getGemstoneData(gem.getHistoricUUID()); + if (historicGemData == null) { continue;} + //XTC//MMOItems.log("\u00a7a *\u00a77 Found data for gem \u00a7e" + gem.getHistoricUUID()); + + // This gemstone had this data... Override. + restored.setData(stat, historicGemData); } + + // That's it + //XTC//MMOItems.log("\u00a7a *\u00a77 Restored \u00a7e" + gem.getName() + "\u00a7a Successfully"); + return restored; + } + @Nullable String asGemColor; @NotNull UUID asGemUUID = UUID.randomUUID(); @@ -411,6 +467,7 @@ public class MMOItem implements ItemReference { * @param gemUUID UUID of gem to remove * @param color Color of the gem socket to restore. null to not restore socket. */ + @SuppressWarnings("ConstantConditions") public void removeGemStone(@NotNull UUID gemUUID, @Nullable String color) { // Get gemstone data 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 1250bf73..edc59aa2 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/util/MMOItemReforger.java +++ b/src/main/java/net/Indyuce/mmoitems/api/util/MMOItemReforger.java @@ -3,7 +3,6 @@ package net.Indyuce.mmoitems.api.util; import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.api.util.Ref; import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider; -import io.lumine.mythic.lib.api.util.ui.SilentNumbers; import net.Indyuce.mmoitems.ItemStats; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.ItemTier; @@ -182,7 +181,7 @@ public class MMOItemReforger { //UPDT//MMOItems.log("Determined Level: \u00a7e" + determinedItemLevel); // Restore stats - restorePreRNGStats(temporalDataHistory, options, template, determinedItemLevel); + restorePreRNGStats(temporalDataHistory, template, determinedItemLevel); return; } /* @@ -227,7 +226,7 @@ public class MMOItemReforger { //UPDT//MMOItems.log("Determined Level: \u00a7e" + determinedItemLevel); // Restore stats - restorePreRNGStats(temporalDataHistory, options, template, determinedItemLevel); + restorePreRNGStats(temporalDataHistory, template, determinedItemLevel); // Choose enchantments to keep if (options.shouldKeepEnchantments() && ambiguouslyOriginalEnchantmentCache != null) { ambiguouslyOriginalEnchantmentCache.identifyTrueOriginalEnchantments(mmoItem, cachedEnchantments);} @@ -261,7 +260,8 @@ public class MMOItemReforger { return ret; } - void restorePreRNGStats(@NotNull HashMap backup, @NotNull ReforgeOptions options, @NotNull MMOItemTemplate template, int determinedItemLevel) { + @SuppressWarnings("ConstantConditions") + void restorePreRNGStats(@NotNull HashMap backup, @NotNull MMOItemTemplate template, int determinedItemLevel) { /* * Extra step: Check every stat history @@ -815,6 +815,7 @@ public class MMOItemReforger { // Gem Stones if (cachedGemStones != null) { //UPDT//MMOItems.log(" \u00a7a@ \u00a77Applying Gemstones"); + ArrayList lostGems = new ArrayList<>(); // If has a upgrade template defined, just remember the level if (buildingMMOItem.hasData(ItemStats.GEM_SOCKETS)) { @@ -824,6 +825,7 @@ public class MMOItemReforger { GemSocketsData current = ((GemSocketsData) buildingMMOItem.getData(ItemStats.GEM_SOCKETS)); // Get those damn empty sockets + ArrayList putGems = new ArrayList<>(); ArrayList availableSockets = new ArrayList<>(current.getEmptySlots()); ArrayList oldSockets = new ArrayList<>(cachedGemStones.getGemstones()); @@ -835,44 +837,46 @@ public class MMOItemReforger { if (availableSockets.size() <= 0) { //UPDT//MMOItems.log(" \u00a7a +\u00a7c+ \u00a77No More Sockets"); - // They all will fit anyway - break; + // This gemstone could not be inserted, it is thus lost + lostGems.add(data); + //UPDT//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Gemstone lost - \u00a7cno socket \u00a78" + data.getHistoricUUID()); // Still some sockets to fill hMMM } else { - // Get colour + // Get colour, uncolored if Unknown String colour = data.getSocketColor(); - String remembrance; + if (colour == null) { colour = GemSocketsData.getUncoloredGemSlot(); } + String remembrance = null; - // Not null? - if (colour != null) { + // Does the gem data have an available socket? + for (String slot : availableSockets) { if (slot.equals(GemSocketsData.getUncoloredGemSlot()) || colour.equals(slot)) { remembrance = slot; } } - // Contained? Remove - remembrance = colour; + // Existed? + if (remembrance != null) { + //UPDT//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Gemstone fit - \u00a7e " + remembrance + " \u00a78" + data.getHistoricUUID()); - // No colour data, just remove a random slot ig + // Remove + availableSockets.remove(remembrance); + + // And guess what... THAT is the colour of this gem! Fabulous huh? + data.setColour(remembrance); + + // Remember as a put gem + putGems.add(data); + + // No space/valid socket hmm } else { + //UPDT//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Gemstone lost - \u00a7cno color \u00a78" + data.getHistoricUUID()); - // Get and remove - remembrance = availableSockets.get(0); - } - - // Remove - availableSockets.remove(remembrance); - - // And guess what... THAT is the colour of this gem! Fabulous huh? - data.setColour(remembrance); - //UPDT//MMOItems.log(" \u00a7a + \u00a77Fit into color \u00a7f" + remembrance); + // Include as lost gem + lostGems.add(data); } } } - // Update list of empty sockets - cachedGemStones.getEmptySlots().clear(); - // Create with select socket slots and gems GemSocketsData primeGems = new GemSocketsData(availableSockets); - for (GemstoneData gem : cachedGemStones.getGemstones()) { if (gem == null) { continue; } primeGems.add(gem); } + for (GemstoneData gem : putGems) { if (gem == null) { continue; } primeGems.add(gem); } // That's the original data StatHistory gemStory = StatHistory.from(buildingMMOItem, ItemStats.GEM_SOCKETS); @@ -880,9 +884,23 @@ public class MMOItemReforger { //HSY//MMOItems.log(" \u00a73-\u00a7a- \u00a77Restore Gemstones Recalculation \u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-"); buildingMMOItem.setData(ItemStats.GEM_SOCKETS, gemStory.recalculate(l)); - } // Could not fit any gems: No gem sockets! + } else { + //UPDT//MMOItems.log("\u00a7c *\u00a7e*\u00a77 All gemstones were lost - \u00a7cno data"); + + // ALl were lost + lostGems.addAll(cachedGemStones.getGemstones()); } + + // Config option enabled? Build the lost gem MMOItems! + if (ReforgeOptions.dropRestoredGems) { + for (GemstoneData lost : lostGems) { + + // Get MMOItem + MMOItem restoredGem = buildingMMOItem.extractGemstone(lost); + + // Success? + if (restoredGem != null) { destroyedGems.add(restoredGem); } } } } //GEM//MMOItems.log(" \u00a7a>\u00a7e2 \u00a77Regenerated Gem Sockets:\u00a7f " + buildingMMOItem.getData(ItemStats.GEM_SOCKETS)); //GEM//if (buildingMMOItem.getData(ItemStats.GEM_SOCKETS) instanceof GemSocketsData) for (String str : SilentNumbers.transcribeList(new ArrayList<>(((GemSocketsData) buildingMMOItem.getData(ItemStats.GEM_SOCKETS)).getGemstones()), (s) -> (s instanceof GemstoneData ? ((GemstoneData) s).getHistoricUUID() + "\u00a7f " + ((GemstoneData) s).getName() : "null"))) { MMOItems.log(" \u00a7a+>\u00a7e2 \u00a77Gem: \u00a7a" + str); } @@ -951,4 +969,16 @@ public class MMOItemReforger { if (mmoItem != null) { return;} mmoItem = new VolatileMMOItem(nbtItem); } + + @NotNull ArrayList destroyedGems = new ArrayList<>(); + + /** + * @return List of gems that have been destroyed from an item, presumably due + * to updating it without keeping gemstones, or they simply could not + * fit. + *
+ * Currently, it is only ever filled if the config option drop-gems + * for item revision is enabled. + */ + @NotNull public ArrayList getDestroyedGems() { return destroyedGems; } } diff --git a/src/main/java/net/Indyuce/mmoitems/listener/ItemListener.java b/src/main/java/net/Indyuce/mmoitems/listener/ItemListener.java index e15b5729..744aa64e 100644 --- a/src/main/java/net/Indyuce/mmoitems/listener/ItemListener.java +++ b/src/main/java/net/Indyuce/mmoitems/listener/ItemListener.java @@ -1,7 +1,10 @@ package net.Indyuce.mmoitems.listener; +import io.lumine.mythic.lib.api.util.ui.SilentNumbers; import net.Indyuce.mmoitems.ItemStats; import net.Indyuce.mmoitems.MMOItems; +import net.Indyuce.mmoitems.api.ReforgeOptions; +import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem; import net.Indyuce.mmoitems.api.util.MMOItemReforger; import io.lumine.mythic.lib.api.item.NBTItem; import org.bukkit.entity.EntityType; @@ -18,6 +21,8 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; + public class ItemListener implements Listener { @EventHandler(ignoreCancelled = true) private void itemPickup(EntityPickupItemEvent e) { @@ -93,8 +98,41 @@ public class ItemListener implements Listener { // Should this item be soulbound? if (shouldSoulbind(nbt, type)) { mod.applySoulbound(player); } - // Return either the changed one or null - return mod.hasChanges() ? mod.toStack() : null; + // L + if (!mod.hasChanges()) { return null; } + + // Perform all operations (including extracting lost gems) + ItemStack ret = mod.toStack(); + + // Give the gems to the player + if (ReforgeOptions.dropRestoredGems) { + //XTC//MMOItems.log("\u00a7a *\u00a7e*\u00a77 Dropping lost gemstones (\u00a73" + mod.getDestroyedGems().size() + "\u00a78)"); + + // Get Items + ArrayList items = new ArrayList<>(); + + // Build and drop every lost gemstone + for (MMOItem item : mod.getDestroyedGems()) { + + // Build + ItemStack built = item.newBuilder().build(); + //XTC//MMOItems.log("\u00a7e *\u00a77 Saved " + SilentNumbers.getItemName(built)); + + // Include + items.add(built); } + + // Drop those gems + for (ItemStack drop : player.getInventory().addItem( + items.toArray(new ItemStack[0])).values()) { + + // Not air right + if (SilentNumbers.isAir(drop)) { continue; } + + // Drop to the world + player.getWorld().dropItem(player.getLocation(), drop); } } + + // Return the modified version + return ret; } /* Checks whether or not an item should be automatically soulbound */ diff --git a/src/main/java/net/Indyuce/mmoitems/manager/ConfigManager.java b/src/main/java/net/Indyuce/mmoitems/manager/ConfigManager.java index 7545674d..e727303a 100644 --- a/src/main/java/net/Indyuce/mmoitems/manager/ConfigManager.java +++ b/src/main/java/net/Indyuce/mmoitems/manager/ConfigManager.java @@ -222,6 +222,7 @@ public class ConfigManager implements Reloadable { ConfigurationSection keepData = MMOItems.plugin.getConfig().getConfigurationSection("item-revision.keep-data"); ConfigurationSection phatLoots = MMOItems.plugin.getConfig().getConfigurationSection("item-revision.phat-loots"); + ReforgeOptions.dropRestoredGems = MMOItems.plugin.getConfig().getBoolean("item-revision.drop-extra-gems", true); revisionOptions = keepData != null ? new ReforgeOptions(keepData) : new ReforgeOptions(false, false, false, false, false, false, false, true); phatLootsOptions = phatLoots != null ? new ReforgeOptions(phatLoots) : new ReforgeOptions(false, false, false, false, false, false, false, true); diff --git a/src/main/java/net/Indyuce/mmoitems/stat/data/GemstoneData.java b/src/main/java/net/Indyuce/mmoitems/stat/data/GemstoneData.java index 2a91fc4f..49cf6ab5 100644 --- a/src/main/java/net/Indyuce/mmoitems/stat/data/GemstoneData.java +++ b/src/main/java/net/Indyuce/mmoitems/stat/data/GemstoneData.java @@ -6,8 +6,12 @@ import net.Indyuce.mmoitems.ItemStats; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.MMOUtils; import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem; +import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem; import net.Indyuce.mmoitems.stat.GemUpgradeScaling; +import net.Indyuce.mmoitems.stat.data.type.Mergeable; +import net.Indyuce.mmoitems.stat.data.type.StatData; import net.Indyuce.mmoitems.stat.type.ItemStat; +import net.Indyuce.mmoitems.stat.type.StatHistory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/net/Indyuce/mmoitems/stat/type/DoubleStat.java b/src/main/java/net/Indyuce/mmoitems/stat/type/DoubleStat.java index a7f2a112..e8e8edce 100644 --- a/src/main/java/net/Indyuce/mmoitems/stat/type/DoubleStat.java +++ b/src/main/java/net/Indyuce/mmoitems/stat/type/DoubleStat.java @@ -122,8 +122,13 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable { } } - // Add NBT Path - item.addItemTag(getAppliedNBT(data)); + /* + * Add NBT Data if it is not equal to ZERO, in which case it will just get removed. + * + * It is important that the tags are not excluded in getAppliedNBT() because the StatHistory does + * need that blanc tag information to remember when an Item did not initially have any of a stat. + */ + if (((DoubleData) data).getValue() != 0) { item.addItemTag(getAppliedNBT(data)); } } @NotNull public static String formatPath(@NotNull String format, boolean moreIsBetter, double value) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index bafd3d91..1167ec03 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -300,6 +300,11 @@ item-revision: # Please note, that this value has no effect if # ´reroll-when-updated´ is set to true. keep-tiers: true + + # If an item is updated, and the new version does not + # keep its gems, this will give the gems back to the + # player so that they don't get lost forever. + drop-extra-gems: true # Whether or not specific stats should be kept # when an item is updated to latest revision.