Fixes RevID Updates clearing stats granted by GemStones

Allows RevID Updater to update gemstones inserted in items, so they have the stats of the template, without having to take them out and put it back in again.
This commit is contained in:
Gunging 2023-02-15 14:03:28 -06:00
parent cf535747b0
commit 23ad7e7517
4 changed files with 149 additions and 56 deletions

View File

@ -46,7 +46,7 @@ public class ConfigManager implements Reloadable {
public String abilitySplitter;
public double soulboundBaseDamage, soulboundPerLvlDamage, levelSpread;
public NumericStatFormula defaultItemCapacity;
public ReforgeOptions revisionOptions, phatLootsOptions;
public ReforgeOptions revisionOptions, gemRevisionOptions, phatLootsOptions;
public final List<String> opStats = new ArrayList<>();
public ConfigManager() {
@ -181,8 +181,10 @@ 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");
ConfigurationSection gemKeepData = MMOItems.plugin.getConfig().getConfigurationSection("item-revision.keep-gem-data");
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);
gemRevisionOptions = gemKeepData != null ? new ReforgeOptions(gemKeepData) : 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);
List<String> exemptedPhatLoots = MMOItems.plugin.getConfig().getStringList("item-revision.disable-phat-loot");

View File

@ -153,7 +153,16 @@ public class GemstoneData {
*
* @param color Color of the slot this gem was inserted onto.
*/
public GemstoneData(@NotNull LiveMMOItem gemStoneMMOItem, @Nullable String color) {
public GemstoneData(@NotNull LiveMMOItem gemStoneMMOItem, @Nullable String color) { this(gemStoneMMOItem, color, UUID.randomUUID()); }
/**
* Create a GemStoneData from a GemStone MMOItem.
* <p></p>
* Basically extracts all the useable stats from the MMOItem, to have them ready to apply onto another MMOItem.
*
* @param color Color of the slot this gem was inserted onto.
*/
public GemstoneData(@NotNull LiveMMOItem gemStoneMMOItem, @Nullable String color, @NotNull UUID forcedHistoryUUID) {
// Get Name to Display
name = MMOUtils.getDisplayName(gemStoneMMOItem.getNBT().getItem());
@ -168,9 +177,8 @@ public class GemstoneData {
effects.addAll(((PotionEffectListData) gemStoneMMOItem.getData(ItemStats.PERM_EFFECTS)).getEffects());
}
// Generate own historic UUID
historicUUID = UUID.randomUUID();
historicUUID = forcedHistoryUUID;
mmoitemID = gemStoneMMOItem.getId();
mmoitemType = gemStoneMMOItem.getType().getId();
socketColor = color;

View File

@ -1,21 +1,25 @@
package net.Indyuce.mmoitems.listener.reforging;
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.event.MMOItemReforgeEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
import net.Indyuce.mmoitems.api.util.MMOItemReforger;
import net.Indyuce.mmoitems.stat.data.EnchantListData;
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
import net.Indyuce.mmoitems.stat.data.GemstoneData;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.type.GemStoneStat;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import java.util.ArrayList;
import java.util.UUID;
/**
* Prevents gems from being lost when reforging.
@ -32,107 +36,147 @@ public class RFGKeepGems implements Listener {
//RFG// MMOItems.log("§8Reforge §4EFG§7 Keeping Gems");
// Get those gems
GemSocketsData gems = (GemSocketsData) event.getOldMMOItem().getData(ItemStats.GEM_SOCKETS);
GemSocketsData oldGemstoneData = (GemSocketsData) event.getOldMMOItem().getData(ItemStats.GEM_SOCKETS);
// No gems? why are we here
if (gems == null) { return; }
if (oldGemstoneData == null) { return; }
// Get those gems
GemSocketsData current = (GemSocketsData) event.getNewMMOItem().getData(ItemStats.GEM_SOCKETS);
GemSocketsData newGemstoneData = (GemSocketsData) event.getNewMMOItem().getData(ItemStats.GEM_SOCKETS);
//RFG//MMOItems.log(" \u00a7a@ \u00a77Applying Gemstones");
ArrayList<GemstoneData> lostGems = new ArrayList<>();
// If has a upgrade template defined, just remember the level
if (current != null) {
// If it has an upgrade template defined, just remember the level
if (newGemstoneData != null) {
// Get current ig
//RFG//MMOItems.log(" \u00a7a* \u00a77Existing Data Detected\u00a7a " + current.toString());
//RFG//MMOItems.log(" \u00a7a* \u00a77Existing Data Detected\u00a7a " + oldGemstoneData.toString());
// Get those damn empty sockets
ArrayList<GemstoneData> putGems = new ArrayList<>();
ArrayList<String> availableSockets = new ArrayList<>(current.getEmptySlots());
ArrayList<GemstoneData> oldSockets = new ArrayList<>(gems.getGemstones());
ArrayList<GemstoneData> transferredGems = new ArrayList<>();
ArrayList<String> availableSockets = new ArrayList<>(newGemstoneData.getEmptySlots());
ArrayList<GemstoneData> oldSockets = new ArrayList<>(oldGemstoneData.getGemstones());
// Remaining
for (GemstoneData data : oldSockets) {
//RFG//MMOItems.log(" \u00a7a*\u00a7e* \u00a77Fitting \u00a7f" + data.getHistoricUUID().toString() + "\u00a77 '" + data.getName());
for (GemstoneData oldSocketedGem : oldSockets) {
//RFG//MMOItems.log(" \u00a7a*\u00a7e* \u00a77Fitting \u00a7f" + oldSocketedGem.getHistoricUUID().toString() + "\u00a77 '" + oldSocketedGem.getName() + "\u00a7'");
// No more if no more sockets left
if (availableSockets.size() <= 0) {
if (availableSockets.size() == 0) {
//RFG//MMOItems.log(" \u00a7a +\u00a7c+ \u00a77No More Sockets");
// This gemstone could not be inserted, it is thus lost
lostGems.add(data);
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Gemstone lost - \u00a7cno socket \u00a78" + data.getHistoricUUID());
lostGems.add(oldSocketedGem);
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Gemstone lost - \u00a7cno socket \u00a78" + oldSocketedGem.getHistoricUUID());
// Still some sockets to fill hMMM
} else {
// Get colour, uncolored if Unknown
String colour = data.getSocketColor();
String colour = oldSocketedGem.getSocketColor();
if (colour == null) { colour = GemSocketsData.getUncoloredGemSlot(); }
String remembrance = null;
String newColorToInsertInto = null;
// Does the gem data have an available socket?
for (String slot : availableSockets) { if (slot.equals(GemSocketsData.getUncoloredGemSlot()) || colour.equals(slot)) { remembrance = slot; } }
for (String slot : availableSockets) { if (slot.equals(GemSocketsData.getUncoloredGemSlot()) || colour.equals(slot)) { newColorToInsertInto = slot; } }
// Existed?
if (remembrance != null) {
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Gemstone fit - \u00a7e " + remembrance + " \u00a78" + data.getHistoricUUID());
if (newColorToInsertInto != null) {
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a77\u00a7e ----------------------- ");
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Gemstone fit - \u00a7e " + newColorToInsertInto + " \u00a78" + oldSocketedGem.getHistoricUUID());
// Remove
availableSockets.remove(remembrance);
// Get MMOItem
MMOItem restoredGem = event.getOldMMOItem().extractGemstone(oldSocketedGem);
if (restoredGem == null) {
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a7c Cannot rebuild gem Item Stack");
// And guess what... THAT is the colour of this gem! Fabulous huh?
data.setColour(remembrance);
// Include as lost gem
lostGems.add(oldSocketedGem);
continue; }
// Remember as a put gem
putGems.add(data);
// Reforge gemstone
MMOItemReforger gemReforge = new MMOItemReforger(restoredGem.newBuilder().build());
if (!gemReforge.canReforge()) {
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a7c Cannot reforge gem MMOItem");
// Scourge the old item's stat histories and transfer all stats related to this gem
for (StatHistory oldHist : event.getOldMMOItem().getStatHistories()) {
// Include as lost gem
lostGems.add(oldSocketedGem);
continue;
}
gemReforge.setPlayer(event.getPlayer());
if (!gemReforge.reforge(MMOItems.plugin.getLanguage().gemRevisionOptions)) {
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a7c Refoge event cancelled");
// For every gem
for (UUID oldHistGem : oldHist.getAllGemstones()) {
// Include as lost gem
lostGems.add(oldSocketedGem);
continue;
}
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Successfully\u00a7a applying gem");
//RFG// MMOItems.log("§8Reforge §4GEM§7 Gemstone of\u00a73 " + oldHist.getItemStat().getId() + "\u00a7e " + oldHistGem);
// Gems should not be dropping stuff but whatever
event.getReforger().getReforgingOutput().addAll(gemReforge.getReforgingOutput());
// Matches?
if (oldHistGem.equals(data.getHistoricUUID())) {
//RFG// MMOItems.log("§8Reforge §4GEM§7 Match!");
// Whatever
LiveMMOItem gemResult = new LiveMMOItem(gemReforge.getResult());
GemstoneData reforgedGemData = new GemstoneData(gemResult, newColorToInsertInto, oldSocketedGem.getHistoricUUID());
reforgedGemData.setLevel(oldSocketedGem.getLevel());
// Get the gem data
StatData sData = oldHist.getGemstoneData(oldHistGem);
// Remove, we have succeeded
availableSockets.remove(newColorToInsertInto);
if (!(sData instanceof Mergeable)) { continue; }
// Gem has been transferred (basically)
transferredGems.add(reforgedGemData);
// Put it there
StatHistory newHist = StatHistory.from(event.getNewMMOItem(), oldHist.getItemStat());
// Apply gemstone stats into the item
for (ItemStat stat : gemResult.getStats()) {
// Include yes
newHist.registerGemstoneData(oldHistGem, ((Mergeable) sData).cloneData());
// If it is not PROPER
if (!(stat instanceof GemStoneStat)) {
// Get the stat data
StatData data = gemResult.getData(stat);
// If the data is MERGEABLE
if (data instanceof Mergeable) {
// Just ignore that lol
if (data instanceof EnchantListData && ((Mergeable) data).isClear()) { continue; }
//RFG//MMOItems.log("\u00a79>>> \u00a77Gem-Merging \u00a7c" + stat.getNBTPath() + "\u00a7e" + data.toString() + "\u00a78 " + reforgedGemData.getHistoricUUID().toString());
/*
* The gem data is registered directly into the history (emphasis on not recalculating with purge)
*/
StatHistory hist = StatHistory.from(event.getNewMMOItem(), stat);
hist.registerGemstoneData(reforgedGemData.getHistoricUUID(), data);
//RFG//MMOItems.log("\u00a79>>> \u00a77 Stat history of this stat");
//RFG//hist.log();
}
}
}
// No space/valid socket hmm
} else {
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Gemstone lost - \u00a7cno color \u00a78" + data.getHistoricUUID());
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a77 Gemstone lost - \u00a7cno color \u00a78" + oldSocketedGem.getHistoricUUID());
// Include as lost gem
lostGems.add(data); }
lostGems.add(oldSocketedGem); }
}
}
// Create with select socket slots and gems
GemSocketsData primeGems = new GemSocketsData(availableSockets);
for (GemstoneData gem : putGems) { if (gem == null) { continue; } primeGems.add(gem); }
//RFG//MMOItems.log(" \u00a7a* \u00a77Operation Result\u00a7a " + primeGems.toString());
GemSocketsData reforgedGemstoneData = new GemSocketsData(availableSockets);
for (GemstoneData gem : transferredGems) { if (gem == null) { continue; } reforgedGemstoneData.add(gem); }
//RFG//MMOItems.log(" \u00a7a* \u00a77Operation Result\u00a7a " + reforgedGemstoneData.toString());
//RFG//for (String s : reforgedGemstoneData.getEmptySlots()) { MMOItems.log(" \u00a7a* \u00a77Empty\u00a7f " + s); }
//RFG//for (GemstoneData s : reforgedGemstoneData.getGemstones()) { MMOItems.log(" \u00a7a*\u00a7f " + s.getName() + "\u00a77 " + s.getHistoricUUID()); }
// That's the original data
StatHistory gemStory = StatHistory.from(event.getNewMMOItem(), ItemStats.GEM_SOCKETS);
gemStory.setOriginalData(primeGems);
gemStory.setOriginalData(reforgedGemstoneData);
event.getNewMMOItem().setData(ItemStats.GEM_SOCKETS, gemStory.recalculate(event.getNewMMOItem().getUpgradeLevel()));
//RFG//MMOItems.log(" \u00a7a* \u00a77History Final\u00a7a --------");
//RFG//gemStory.log();
@ -141,7 +185,7 @@ public class RFGKeepGems implements Listener {
//RFG//MMOItems.log("\u00a7c *\u00a7e*\u00a77 All gemstones were lost - \u00a7cno data");
// ALl were lost
lostGems.addAll(gems.getGemstones()); }
lostGems.addAll(oldGemstoneData.getGemstones()); }
// Config option enabled? Build the lost gem MMOItems!
if (ReforgeOptions.dropRestoredGems) {
@ -149,10 +193,32 @@ public class RFGKeepGems implements Listener {
// Get MMOItem
MMOItem restoredGem = event.getOldMMOItem().extractGemstone(lost);
if (restoredGem == null) { continue; }
if (restoredGem == null) {
// Success? Add that gem there
// Mention the loss
MMOItems.print(null, "$bGemstone $r{0} {1} $bno longer exists, it was$f deleted$b from $u{2}$b's {3}$b. ", "RevID", lost.getMMOItemType(), lost.getMMOItemID(), event.getPlayer() == null ? "null" : event.getPlayer().getName(), SilentNumbers.getItemName(event.getReforger().getStack(), false));
continue; }
// Reforge gemstone if it can be reforged
MMOItemReforger gemReforge = new MMOItemReforger(restoredGem.newBuilder().build());
if (gemReforge.canReforge()) {
// Reforge
gemReforge.setPlayer(event.getPlayer());
gemReforge.reforge(MMOItems.plugin.getLanguage().gemRevisionOptions);
// Gems should not be dropping stuff but whatever
event.getReforger().getReforgingOutput().addAll(gemReforge.getReforgingOutput());
// Success, Add that reforged gem
event.getReforger().addReforgingOutput(gemReforge.getResult());
// Cant reforge (uuuuuh) just add I guess
} else {
// Success? Add that gem (without reforging) there
event.getReforger().addReforgingOutput(restoredGem.newBuilder().build());
}
} }
}
}

View File

@ -319,6 +319,23 @@ item-revision:
# Third party plugin compatibility
advanced-enchantments: true
# Whether specific stats should be kept when gemstones
# within an item are updated to the latest revision.
keep-gem-data:
# Name of the item, usually renamed via anvil
display-name: true
# Enchantments put on the item by the player
enchantments: true
# Specific lore lines of the item...
# Warning, this prevents stats in the lore from updating visually!
lore: false
# Stats handled by RNG will be rerolled
reroll: false
phat-loots:
display-name: false
enchantments: false