Modifiers now work with RevID increases.

This commit is contained in:
Gunging 2021-05-07 00:31:09 -04:00
parent 685431bec8
commit 370c2f8746
20 changed files with 1083 additions and 435 deletions

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>net.Indyuce</groupId>
<artifactId>MMOItems</artifactId>
<version>6.5.7</version>
<version>6.5.8</version>
<name>MMOItems</name>
<description>A great item solution for your RPG server!</description>

View File

@ -750,7 +750,9 @@ public class MMOItems extends LuminePlugin {
*/
public static void log(@Nullable String message) {
if (message == null) { message = "< null >"; }
plugin.getServer().getConsoleSender().sendMessage("\u00a78[" + ChatColor.YELLOW + "MMOItems\u00a78] \u00a77" + message);
//String prefix = "\u00a78[" + ChatColor.YELLOW + "MMOItems\u00a78] \u00a77";
String prefix = "";
plugin.getServer().getConsoleSender().sendMessage(prefix + message);
}
/**

View File

@ -1,7 +1,10 @@
package net.Indyuce.mmoitems.api;
import net.Indyuce.mmoitems.MMOItems;
import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ReforgeOptions {
public static boolean dropRestoredGems;
@ -21,6 +24,10 @@ public class ReforgeOptions {
private final boolean regenerate;
@NotNull String keepCase = ChatColor.GRAY.toString();
public void setKeepCase(@NotNull String kc) { keepCase = kc; }
@NotNull public String getKeepCase() { return keepCase; }
public ReforgeOptions(ConfigurationSection config) {
this.keepName = config.getBoolean("display-name");
this.keepLore = config.getBoolean("lore");
@ -28,6 +35,7 @@ public class ReforgeOptions {
this.keepUpgrades = config.getBoolean("upgrades");
this.keepGemStones = config.getBoolean("gemstones");
this.keepSoulbind = config.getBoolean("soulbound");
this.keepCase = config.getString("kept-lore-prefix", ChatColor.GRAY.toString());
this.keepExternalSH = config.getBoolean("external-sh", true);
this.regenerate = false;
}

View File

@ -117,10 +117,10 @@ public class GemStone extends UseItem {
// Check Gem gems are not supported >:l. Check the modifiers ig
boolean success = false;
if (gemStory.getModifiersBonus() != null) {
for (UUID uid : gemStory.getAllModifiers()) {
// Get that gem
GemSocketsData registeredGemData = (GemSocketsData) gemStory.getModifiersBonus();
GemSocketsData registeredGemData = (GemSocketsData) gemStory.getModifiersBonus(uid);
if (registeredGemData != null) {
if (registeredGemData.getEmptySocket(gemType) != null) {

View File

@ -22,6 +22,7 @@ import net.Indyuce.mmoitems.comp.flags.FlagPlugin.CustomFlag;
import net.Indyuce.mmoitems.stat.data.CommandData;
import net.Indyuce.mmoitems.stat.data.CommandListData;
import io.lumine.mythic.lib.api.item.NBTItem;
import org.jetbrains.annotations.NotNull;
public class UseItem {
protected final Player player;
@ -106,7 +107,7 @@ public class UseItem {
return getItem(player, item, Type.get(type));
}
public static UseItem getItem(Player player, NBTItem item, Type type) {
public static UseItem getItem(@NotNull Player player, @NotNull NBTItem item, @NotNull Type type) {
if (type.corresponds(Type.CONSUMABLE))
return new Consumable(player, item);
if (type.corresponds(Type.SKIN))

View File

@ -142,15 +142,18 @@ public class ItemStackBuilder {
// Found it?
if (s != null) {
//GEM//MMOItems.log("\u00a7a -+- \u00a77Recording History");
//GEM//MMOItems.log("\u00a7a -+- \u00a77History exists...");
//GEM//s.log();
// 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 ((!s.isClear() || stat instanceof Enchants)) {
//GEM//MMOItems.log("\u00a7a -+- \u00a77Recording History");
addItemTag(new ItemTag(histroy_keyword + stat.getId(), s.toNBTString())); }
}
if (forDisplay && stat instanceof Previewable) {

View File

@ -1,11 +1,6 @@
package net.Indyuce.mmoitems.api.item.build;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
@ -21,6 +16,7 @@ import net.Indyuce.mmoitems.stat.data.StringData;
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.NameData;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import org.jetbrains.annotations.NotNull;
@ -33,7 +29,7 @@ public class MMOItemBuilder {
* Name modifiers, prefixes or suffixes, with priorities. They are saved
* because they must be applied after the modifier selection process
*/
private final Set<NameModifier> nameModifiers = new HashSet<>();
private final HashMap<UUID, NameModifier> nameModifiers = new HashMap<>();
/**
* Instance which is created everytime an mmoitem is being randomly
@ -56,7 +52,7 @@ public class MMOItemBuilder {
* applied
*/
double capacity = (tier != null && tier.hasCapacity() ? tier.getModifierCapacity() : MMOItems.plugin.getLanguage().defaultItemCapacity).calculate(level);
this.mmoitem = new MMOItem(template.getType(), template.getId());
mmoitem = new MMOItem(template.getType(), template.getId());
// apply base item data
template.getBaseItemData().forEach((stat, random) -> applyData(stat, random.randomize(this)));
@ -73,11 +69,16 @@ public class MMOItemBuilder {
if (!modifier.rollChance() || modifier.getWeight() > capacity)
continue;
UUID modUUID = UUID.randomUUID();
capacity -= modifier.getWeight();
if (modifier.hasNameModifier()) { addModifier(modifier.getNameModifier()); }
if (modifier.hasNameModifier()) { addModifier(modifier.getNameModifier(), modUUID); }
for (ItemStat stat : modifier.getItemData().keySet()) {
addModifierData(stat, modifier.getItemData().get(stat).randomize(this));
applyModifierData(stat); } }
addModifierData(stat, modifier.getItemData().get(stat).randomize(this), modUUID);
}
}
}
public int getLevel() {
@ -98,15 +99,27 @@ public class MMOItemBuilder {
public MMOItem build() {
if (!nameModifiers.isEmpty()) {
StringBuilder displayName = new StringBuilder(mmoitem.hasData(ItemStats.NAME) ? mmoitem.getData(ItemStats.NAME).toString() : "Item");
for (NameModifier mod : nameModifiers) {
if (mod.getType() == ModifierType.PREFIX)
displayName.insert(0, mod.getFormat() + " ");
if (mod.getType() == ModifierType.SUFFIX)
displayName.append(" ").append(mod.getFormat());
// Get name data
StatHistory hist = StatHistory.from(mmoitem, ItemStats.NAME);
if (!mmoitem.hasData(ItemStats.NAME)) { mmoitem.setData(ItemStats.NAME, new NameData("Item")); }
for (UUID obs : nameModifiers.keySet()) {
// Create new Name Data
NameModifier mod = nameModifiers.get(obs);
NameData modName = new NameData("");
// Include modifier information
if (mod.getType() == ModifierType.PREFIX) { modName.addPrefix(mod.getFormat()); }
if (mod.getType() == ModifierType.SUFFIX) { modName.addSuffix(mod.getFormat()); }
// Register onto SH
hist.registerModifierBonus(obs, modName);
}
mmoitem.setData(ItemStats.NAME, new StringData(displayName.toString()));
// Recalculate name
mmoitem.setData(ItemStats.NAME, hist.recalculate(mmoitem.getUpgradeLevel()));
}
return mmoitem;
@ -127,6 +140,7 @@ public class MMOItemBuilder {
if (mmoitem.hasData(stat) && data instanceof Mergeable) {
((Mergeable) mmoitem.getData(stat)).merge(data);
} else {
// Set, there is no more.
@ -135,45 +149,22 @@ public class MMOItemBuilder {
}
/**
* Builds the Modifier StatData, which is in the end applied with
* {@link #applyModifierData(ItemStat)}
* Registers the modifier onto the item
*
* @param stat
* Stat owning the data
* @param data
* StatData to apply
*/
public void addModifierData(@NotNull ItemStat stat, @NotNull StatData data) {
// Is the data mergeable? Apply as External SH
if (mmoitem.hasData(stat) && data instanceof Mergeable) {
// Merge
if (modifierData == null) { modifierData = data; }
else {
try {
((Mergeable) modifierData).merge(data);
} catch (IllegalArgumentException ignored) {
MMOItems.print(null, "Could not merge $f{2}$b modifier data into $f{3}$b of $e{4}$b when generating $r{0} {1}$b. ", "Item Generation", mmoitem.getType().toString(), mmoitem.getId(), data.getClass().getSimpleName(), modifierData.getClass().getSimpleName(), stat.getId());
modifierData = data;
}
}
} else {
// Set, there is no more.
modifierData = data;
}
}
StatData modifierData;
public void applyModifierData(@NotNull ItemStat stat) {
public void addModifierData(@NotNull ItemStat stat, @NotNull StatData data, @NotNull UUID uuid) {
// Apply onto Stat History
StatHistory hist = StatHistory.from(mmoitem, stat);
//MOD//MMOItems.log("\u00a7c+---------->\u00a77 Modifying Item");
//MOD//hist.log();
// Apply
hist.setModifiersBonus(modifierData);
hist.registerModifierBonus(uuid, data);
}
/**
@ -183,15 +174,39 @@ public class MMOItemBuilder {
*
* @param modifier
* Name modifier which needs to be added
*
* @param mod
* UUID of storage into the Stat History of name
*/
public void addModifier(NameModifier modifier) {
public void addModifier(@NotNull NameModifier modifier, @NotNull UUID mod) {
for (NameModifier current : nameModifiers)
if (current.getType() == modifier.getType() && current.getPriority() > modifier.getPriority())
return;
// Might overwrite a modifier yes
ArrayList<UUID> removedObs = new ArrayList<>();
for (UUID cUID : nameModifiers.keySet()) {
nameModifiers.removeIf(current -> current.getType() == modifier.getType() && current.getPriority() < modifier.getPriority());
nameModifiers.add(modifier);
// Remove obs?
NameModifier obs = nameModifiers.get(cUID);
// Are they the same type?
if (obs.getType() == modifier.getType()) {
// Choose greater priority
if (obs.getPriority() > modifier.getPriority()) {
// Keep old one
return;
} else if (obs.getPriority() < modifier.getPriority()) {
// Remove old one and add new one
removedObs.add(cUID);
}
}
}
// Remove
for (UUID ro : removedObs) { nameModifiers.remove(ro); }
nameModifiers.put(mod, modifier);
}
/**

View File

@ -5,6 +5,7 @@ import java.util.logging.Level;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.stat.DisplayName;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import org.bukkit.ChatColor;
@ -47,13 +48,19 @@ public class LiveMMOItem extends ReadMMOItem {
// Will not do much if the stat is missing from the item
stat.whenLoaded(this);
// Also laod history :think ing:
ItemTag hisTag = ItemTag.getTagAtPath(ItemStackBuilder.histroy_keyword + stat.getId(), item, SupportedNBTTagValues.STRING);
if (hisTag != null) {
// History not prematurely loaded?
if (getStatHistory(stat) == null) {
// Aye
StatHistory hist = StatHistory.fromNBTString(this, (String) hisTag.getValue());
if (hist != null) { this.setStatHistory(stat, hist); }
// Also load history :think ing:
ItemTag hisTag = ItemTag.getTagAtPath(ItemStackBuilder.histroy_keyword + stat.getId(), getNBT(), SupportedNBTTagValues.STRING);
if (hisTag != null) {
// Aye
StatHistory hist = StatHistory.fromNBTString(this, (String) hisTag.getValue());
// History valid? Record
if (hist != null) { this.setStatHistory(stat, hist); }
}
}
// Some unknown error happened. L

View File

@ -465,7 +465,7 @@ public class MMOItem implements ItemReference {
* Deletes this UUID from all Stat Histories.
*
* @param gemUUID UUID of gem to remove
* @param color Color of the gem socket to restore. <code>null</code> to not restore socket.
* @param color Color of the gem socket to restore. {@code null} to not restore socket.
*/
@SuppressWarnings("ConstantConditions")
public void removeGemStone(@NotNull UUID gemUUID, @Nullable String color) {
@ -490,8 +490,8 @@ public class MMOItem implements ItemReference {
// Attempt externals
for (StatData externalData : gemStory.getExternalData()) { if (GemSocketsData.removeGemFrom(((GemSocketsData) externalData), gemUUID, color)) { return; } }
// Attempt externals
if (gemStory.getModifiersBonus() != null) { GemSocketsData.removeGemFrom(((GemSocketsData) gemStory.getModifiersBonus()), gemUUID, color); }
// Attempt gems
for (UUID gemDataUUID : gemStory.getAllModifiers()) { if (GemSocketsData.removeGemFrom(((GemSocketsData) gemStory.getModifiersBonus(gemDataUUID)), gemUUID, color)) { return; } }
}
//endregion
}

View File

@ -5,6 +5,7 @@ import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.stat.DisplayName;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.stat.type.StatHistory;
@ -47,13 +48,19 @@ public class VolatileMMOItem extends ReadMMOItem {
try {
stat.whenLoaded(this);
// Also laod history :think ing:
ItemTag hisTag = ItemTag.getTagAtPath(ItemStackBuilder.histroy_keyword + stat.getId(), getNBT(), SupportedNBTTagValues.STRING);
if (hisTag != null) {
// History not prematurely loaded?
if (getStatHistory(stat) == null) {
// Aye
StatHistory hist = StatHistory.fromNBTString(this, (String) hisTag.getValue());
if (hist != null) { this.setStatHistory(stat, hist); }
// Also load history :think ing:
ItemTag hisTag = ItemTag.getTagAtPath(ItemStackBuilder.histroy_keyword + stat.getId(), getNBT(), SupportedNBTTagValues.STRING);
if (hisTag != null) {
// Aye
StatHistory hist = StatHistory.fromNBTString(this, (String) hisTag.getValue());
// History valid? Record
if (hist != null) { this.setStatHistory(stat, hist); }
}
}
// Nope
@ -66,6 +73,7 @@ public class VolatileMMOItem extends ReadMMOItem {
+ ChatColor.RED + getId() + ChatColor.GRAY + "': "
+ ChatColor.YELLOW + exception.getMessage());
}
return super.hasData(stat);
}
}

View File

@ -3,6 +3,7 @@ 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;
@ -21,11 +22,13 @@ import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
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.NameData;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import org.apache.commons.lang.Validate;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -69,6 +72,7 @@ public class MMOItemReforger {
private final int amount;
// Not initialized at first for performance reasons
@Nullable
private MMOItem mmoItem;
// Data
@ -94,7 +98,7 @@ public class MMOItemReforger {
@Nullable UpgradeData cachedUpgradeLevel;
// Soulbound
private StatData cachedSoulbound;
@Nullable StatData cachedSoulbound;
//endregion
@ -105,7 +109,13 @@ public class MMOItemReforger {
public MMOItemReforger(@NotNull NBTItem nbt) {
this.nbtItem = nbt;
this.amount = nbt.getItem().getAmount();
VolatileMMOItem vol = new VolatileMMOItem(nbt);
if (vol.hasData(ItemStats.DURABILITY)) { cachedDurability = (DoubleData) vol.getData(ItemStats.DURABILITY); }
else if (nbt.getItem().getItemMeta() instanceof Damageable) { cachedDur = ((double) (((Damageable) nbt.getItem().getItemMeta()).getDamage())) / ((double) nbt.getItem().getType().getMaxDurability()); }
}
@Nullable DoubleData cachedDurability = null;
@Nullable Double cachedDur = null;
/**
* Apply a quick soulbound based on the config value <code>soulbound.auto-bind.level</code> (default = 1)
@ -113,7 +123,6 @@ public class MMOItemReforger {
public void applySoulbound(@NotNull Player p) {
applySoulbound(p, autoSoulboundLevel);
}
/**
* Apply a quick soulbound of this level
*/
@ -172,16 +181,16 @@ public class MMOItemReforger {
// Skip all this trash and just regenerate completely
if (options.isRegenerate()) {
// Store all the history of stat proceedings.
HashMap<ItemStat, StatHistory> temporalDataHistory = extractStatDataHistory(options);
HashMap<ItemStat, StatHistory> temporalDataHistory = extractStatDataHistory();
/*
* Generate fresh MMOItem, with stats that will be set if the chance is too low
*/
int determinedItemLevel = regenerate(player, template);
//UPDT//MMOItems.log("Determined Level: \u00a7e" + determinedItemLevel);
//UPGRD//MMOItems.log("Determined Level: \u00a7a" + determinedItemLevel + " \u00a78{ Regeneration }");
// Restore stats
restorePreRNGStats(temporalDataHistory, template, determinedItemLevel);
restorePreRNGStats(temporalDataHistory, template, determinedItemLevel, true);
return; }
/*
@ -201,74 +210,92 @@ public class MMOItemReforger {
if (options.shouldKeepName()) { keepName(meta); }
// Keep specific lore components
if (options.shouldKeepLore() && mmoItem.hasData(ItemStats.LORE)) { keepLore(); }
if (options.shouldKeepLore() && mmoItem.hasData(ItemStats.LORE)) { keepLore(options.getKeepCase()); }
EnchantListData ambiguouslyOriginalEnchantmentCache = null; //todo Corresponding to the block at the end of this method.
EnchantListData ambiguouslyOriginalEnchantmentCache = null;
// Choose enchantments to keep
if (options.shouldKeepEnchantments()) { Ref<EnchantListData> rf = new Ref<>(); keepEnchantments(rf); ambiguouslyOriginalEnchantmentCache = rf.getValue(); }
// Acquire old upgrade level
if (options.shouldKeepUpgrades() && mmoItem.hasData(ItemStats.UPGRADE)) { keepUpgrades(); }
// Gather Gemstones
// Gather Gemstones and ExSH in a Stat History clone.
if (options.shouldKeepGemStones() || options.shouldKeepExternalSH()) { cacheFullHistory(!options.shouldKeepGemStones(), !options.shouldKeepExternalSH()); }
// Soulbound transfer
if (options.shouldKeepSoulbind() && mmoItem.hasData(ItemStats.SOULBOUND)) { keepSoulbound(); }
// Store all the history of stat proceedings.
HashMap<ItemStat, StatHistory> temporalDataHistory = extractStatDataHistory(options);
// Store all the history of stat proceedings. This clears ExSH and Gems so they must already be remembered.
HashMap<ItemStat, StatHistory> temporalDataHistory = extractStatDataHistory();
/*
* Generate fresh MMOItem, with stats that will be set if the chance is too low
*/
int determinedItemLevel = regenerate(player, template);
//UPDT//MMOItems.log("Determined Level: \u00a7e" + determinedItemLevel);
//UPGRD//MMOItems.log("Determined Level: \u00a7e" + determinedItemLevel);
// Restore stats
restorePreRNGStats(temporalDataHistory, template, determinedItemLevel);
// Restore stats, handles Original Data and Modifiers.
restorePreRNGStats(temporalDataHistory, template, determinedItemLevel, false);
// Choose enchantments to keep
if (options.shouldKeepEnchantments() && ambiguouslyOriginalEnchantmentCache != null) { ambiguouslyOriginalEnchantmentCache.identifyTrueOriginalEnchantments(mmoItem, cachedEnchantments);}
}
@NotNull HashMap<ItemStat, StatHistory> extractStatDataHistory(@NotNull ReforgeOptions options) {
@NotNull HashMap<ItemStat, StatHistory> extractStatDataHistory() {
HashMap<ItemStat, StatHistory> ret = new HashMap<>();
//UPDT//MMOItems.log(" \u00a71*** \u00a77Remembering Stats");
//UPGRD//MMOItems.log(" \u00a71*** \u00a77Extracting History Data prior to RNG Reroll");
for (ItemStat stat : mmoItem.getStats()) {
//UPDT//MMOItems.log(" \u00a79 * \u00a77Stat \u00a7f" + stat.getNBTPath());
//UPGRD//MMOItems.log(" \u00a79 * \u00a77Stat \u00a7f" + stat.getNBTPath());
// Skip if it cant merge
if (!(stat.getClearStatData() instanceof Mergeable)) { continue; }
StatHistory hist = StatHistory.from(mmoItem, stat);
//UPDT//MMOItems.log(" \u00a73 * \u00a77History of \u00a7f" + hist.getItemStat().getNBTPath());
//UPGRD//MMOItems.log(" \u00a73 * \u00a77History of \u00a7f" + hist.getItemStat().getNBTPath());
// Clear externals
if (!options.shouldKeepExternalSH()) { hist.getExternalData().clear(); }
// Externals handled elsewhere
//UPGRD//MMOItems.log(" \u00a7c *\u00a71*\u00a78* \u00a77GEMS Handled Elsewhere, cleared them \u00a7f" + hist.getAllGemstones().size());
hist.clearGemstones();
// Externals handled elsewhere
//UPGRD//MMOItems.log(" \u00a73 *\u00a79*\u00a79* \u00a77EXSH Handled Elsewhere, cleared them \u00a7f" + hist.getExternalData().size());
hist.clearExternalData();
// Get and set
ret.put(hist.getItemStat(), hist);
//UPDT//MMOItems.log(" \u00a79 + \u00a77Storing for Update, History of \u00a7f" + hist.getItemStat().getNBTPath() + "\u00a77, Gx:\u00a7e" + hist.getAllGemstones().size() + "\u00a77, Ex:\u00a7e" + hist.getExternalData().size());
//GEM//MMOItems.log(" \u00a71 +-+ \u00a77Storing for Update, \u00a7bOG\u00a77: \u00a7f" + hist.getOriginalData().toString());
//GEM//for (String str : SilentNumbers.transcribeList(hist.getAllGemstones(), (s) -> (s instanceof UUID ? hist.getGemstoneData((UUID) s) + "\u00a73 (\u00a78" + s + "\u00a73)" : "null"))) { MMOItems.log(" \u00a71 +-+ \u00a77Storing for Update, \u00a7bGM\u00a77: \u00a7f" + str); }
//GEM//for (String str : SilentNumbers.transcribeList(hist.getExternalData(), (s) -> (s instanceof StatData ? s.toString() : "null"))) { MMOItems.log(" \u00a71 +-+ \u00a77Storing for Update, \u00a7bEX\u00a77: \u00a7f" + str); }
ret.put(hist.getItemStat(), hist.clone(mmoItem));
//UPGRD//MMOItems.log(" \u00a79 + \u00a77Storing for Update, History of \u00a7f" + hist.getItemStat().getNBTPath() + "\u00a77, Gx:\u00a7e" + hist.getAllGemstones().size() + "\u00a77, Ex:\u00a7e" + hist.getExternalData().size()+ "\u00a77, Md:\u00a7e" + hist.getAllModifiers().size());
//UPGRD//hist.log();
}
// Yes
return ret;
}
@SuppressWarnings("ConstantConditions")
void restorePreRNGStats(@NotNull HashMap<ItemStat, StatHistory> backup, @NotNull MMOItemTemplate template, int determinedItemLevel) {
void restorePreRNGStats(@NotNull HashMap<? extends ItemStat, ? extends StatHistory> backup, @NotNull MMOItemTemplate template, int determinedItemLevel, boolean cleanModifiers) {
// Clean older
if (!cleanModifiers) {
//UPGRD//MMOItems.log("\u00a73 Clearing RNG Modifiers\u00a77 -->\u00a78-------------------------------------\u00a77-\u00a73-");
for (ItemStat stat : mmoItem.getStats()) {
if (mmoItem.getData(stat) instanceof Mergeable) {
//UPGRD//MMOItems.log("\u00a77 --> \u00a73" + stat.getId() + "\u00a78-------\u00a7f " + mmoItem.getData(stat) + " \u00a78------\u00a77-\u00a73-");
// Clear modifiers
StatHistory clear = StatHistory.from(mmoItem, stat); //UPGRD//clear.log();
clear.clearModifiersBonus();
}
} }
/*
* Extra step: Check every stat history
*/
//UPGRD//MMOItems.log("\u00a7e Restore PreRNG Stats\u00a77 -->\u00a78-------------------------------------\u00a77-\u00a7e-");
int l = mmoItem.getUpgradeLevel();
for (ItemStat stat : backup.keySet()) {
//UPDT//MMOItems.log("\u00a7e @\u00a77 " + stat.getId());
//UPGRD//MMOItems.log("\u00a7e @\u00a77 " + stat.getId());
// Get history
StatHistory hist = backup.get(stat);
@ -276,87 +303,122 @@ public class MMOItemReforger {
// Alr what the template say
RandomStatData source = template.getBaseItemData().get(stat);
StatHistory clear;
StatData keptData = shouldRerollRegardless(stat, source, hist.getOriginalData(), determinedItemLevel);
StatHistory clear = StatHistory.from(mmoItem, stat);
if (keptData != null) { clear.setOriginalData(keptData); }
//MOD//MMOItems.log("\u00a77 --> \u00a7cPre-Modified History of this Stat:");
//MOD//clear.log();
//MOD//MMOItems.log("\u00a77 --> \u00a7cModifiers History of this Stat:");
//MOD//hist.log();
// Clean Modifiers = Forget old ones and generate new ones
if (cleanModifiers) {
//MOD//MMOItems.log("\u00a77 --* \u00a7cCleared cached modifiers");
hist.clearModifiersBonus();
// Unclean Modifiers - Keep old ones
} else {
//MOD//MMOItems.log("\u00a77 --* \u00a76Cleared newer modifiers");
// Remove any newly-generated modifiers
clear.clearModifiersBonus();
// Include old modifiers
for (UUID gem : hist.getAllModifiers()) {
//MOD//MMOItems.log("\u00a77 --* \u00a7bTransferred old \u00a78" + gem.toString() + " \u00a7e" + hist.getModifiersBonus(gem));
clear.registerModifierBonus(gem, hist.getModifiersBonus(gem)); }
}
// Store
StatHistory cachedGemsEX = itemDataHistory.get(stat);
if (cachedGemsEX != null) { clear.assimilate(cachedGemsEX); }
itemDataHistory.put(stat, clear);
mmoItem.setStatHistory(stat, clear);
//UPGRD//MMOItems.log("\u00a77 --> \u00a7aFinal History of this Stat:");
//UPGRD//clear.log();
}
}
/**
* @return The item is supposedly being updated, but that doesnt mean all its stats must remain the same.
*
* In contrast to reforging, in which it is expected its RNG to be rerolled, updating should not do it
* except in the most dire scenarios:
* + The mean/standard deviation changing significantly:
* If the chance of getting the same roll is ridiculously low (3.5SD) under the new settings, reroll.
*
* + The stat is no longer there, or a new stat was added
* The chance of getting a roll of 0 will be evaluated per the rule above.
*
*
*/
@Nullable StatData shouldRerollRegardless(@NotNull ItemStat stat, @NotNull RandomStatData source, @NotNull StatData original, int determinedItemLevel) {
/*
* Does the new item have it?
*
* If not, its gotten removed = we only keep extraneous
*/
if (source instanceof NumericStatFormula && original instanceof DoubleData) {
//UPGRD//MMOItems.log("\u00a7a +\u00a77 Valid for Double Data procedure\u00a78 {Original:\u00a77 " + ((DoubleData) original).getValue() + "\u00a78}");
// Very well, chance checking is only available for NumericStatFormula class so
double base = ((NumericStatFormula) source).getBase() + (((NumericStatFormula) source).getScale() * determinedItemLevel);
// Determine current
double current = ((DoubleData) original).getValue();
// What was the shift?
double shift = current - base;
// How many standard deviations away?
double sD = Math.abs(shift / ((NumericStatFormula) source).getSpread());
if (NumericStatFormula.useRelativeSpread) { sD = Math.abs(shift / (((NumericStatFormula) source).getSpread() * base)); }
//UPGRD//MMOItems.log("\u00a7b *\u00a77 Base: \u00a73" + base);
//UPGRD//MMOItems.log("\u00a7b *\u00a77 Curr: \u00a73" + current);
//UPGRD//MMOItems.log("\u00a7b *\u00a77 Shft: \u00a73" + shift);
//UPGRD//MMOItems.log("\u00a7b *\u00a77 SDev: \u00a73" + sD);
// Greater than max spread? Or heck, 0.1% Chance or less wth
if (sD > ((NumericStatFormula) source).getMaxSpread() || sD > 3.5) {
//UPGRD//MMOItems.log("\u00a7c -\u00a77 Ridiculous Range --- reroll");
// Adapt within reason
double reasonableShift = ((NumericStatFormula) source).getSpread() * Math.min(2, ((NumericStatFormula) source).getMaxSpread());
if (shift < 0) { reasonableShift *= -1;}
// That's the data we'll use
return new DoubleData(reasonableShift + base);
// Data arguably fine tbh, just use previous
} else {
//UPGRD//MMOItems.log("\u00a7a +\u00a77 Acceptable Range --- kept");
// Just clone I guess
return ((Mergeable) original).cloneData(); }
} else {
//UPGRD//MMOItems.log("\u00a7e +\u00a77 Not contained / unmerged --- reroll I suppose");
/*
* Does the new item have it?
*
* If not, its gotten removed = we only keep extraneous
* These stats are exempt from this 'keeping' operation.
* Probably because there is a ReforgeOption specifically
* designed for them that keeps them separately
*/
if (source instanceof NumericStatFormula && hist.getOriginalData() instanceof DoubleData) {
//UPDT//MMOItems.log("\u00a7a +\u00a77 Valid for Double Data procedure\u00a78 {Original:\u00a77 " + ((DoubleData) hist.getOriginalData()).getValue() + "\u00a78}");
// Very well, chance checking is only available for NumericStatFormula class so
double base = ((NumericStatFormula) source).getBase() + (((NumericStatFormula) source).getScale() * determinedItemLevel);
// Determine current
double current = ((DoubleData) hist.getOriginalData()).getValue();
// What was the shift?
double shift = current - base;
// How many standard deviations away?
double sD = Math.abs(shift / ((NumericStatFormula) source).getSpread());
if (NumericStatFormula.useRelativeSpread) { sD = Math.abs(shift / (((NumericStatFormula) source).getSpread() * base)); }
//UPDT//MMOItems.log("\u00a7b *\u00a77 Base: \u00a73" + base);
//UPDT//MMOItems.log("\u00a7b *\u00a77 Curr: \u00a73" + current);
//UPDT//MMOItems.log("\u00a7b *\u00a77 Shft: \u00a73" + shift);
//UPDT//MMOItems.log("\u00a7b *\u00a77 SDev: \u00a73" + sD);
// Greater than max spread? Or heck, 0.1% Chance or less wth
if (sD > ((NumericStatFormula) source).getMaxSpread() || sD > 3.5) {
//UPDT//MMOItems.log("\u00a7c -\u00a77 Ridiculous Range --- reroll");
// Adapt within reason
double reasonableShift = ((NumericStatFormula) source).getSpread() * Math.min(2, ((NumericStatFormula) source).getMaxSpread());
if (shift < 0) { reasonableShift *= -1;}
// That's the data we'll use
DoubleData finalData = new DoubleData(reasonableShift + base);
// Make a clear one
clear = new StatHistory(mmoItem, stat, finalData);
// Data arguably fine tbh, just use previous
} else {
//UPDT//MMOItems.log("\u00a7a +\u00a77 Acceptable Range --- kept");
// Just clone I guess
clear = new StatHistory(mmoItem, stat, ((DoubleData) hist.getOriginalData()).cloneData()); }
} else {
//UPDT//MMOItems.log("\u00a7e +\u00a77 Not contained / unmerged --- reroll I suppose");
/*
* These stats are exempt from this 'keeping' operation.
* Probably because there is a ReforgeOption specifically
* designed for them that keeps them separately
*/
if (ItemStats.LORE.equals(stat) ||
// Keep regenerated one
if (ItemStats.LORE.equals(stat) ||
ItemStats.NAME.equals(stat) ||
ItemStats.GEM_SOCKETS.equals(stat) ||
ItemStats.ABILITIES.equals(stat)) {
// Keep regenerated one
clear = new StatHistory(mmoItem, stat, mmoItem.getData(stat));
return null;
} else {
} else {
// Make a clear one
clear = new StatHistory(mmoItem, stat, hist.getOriginalData());
}
return original;
}
// Keep Gemstone and Extraneous data
for (UUID gem : hist.getAllGemstones()) { clear.registerGemstoneData(gem, hist.getGemstoneData(gem)); }
for (StatData ex : hist.getExternalData()) { clear.registerExternalData(ex); }
clear.setModifiersBonus(hist.getModifiersBonus());
// Store
itemDataHistory.put(stat, clear);
mmoItem.setStatHistory(stat, clear);
//HSY//MMOItems.log(" \u00a7b-\u00a7e- \u00a77Update Recalculation \u00a7b-\u00a7e-\u00a7b-\u00a7e-\u00a7b-\u00a7e-\u00a7b-\u00a7e-");
//todo EXPERIMENTAL no longer recalculate here mmoItem.setData(stat, clear.recalculate(false, l));
}
}
@ -371,7 +433,7 @@ public class MMOItemReforger {
if (template == null) { MMOItems.print(null, "Could not find template for $r{0} {1}$b. ", "MMOItems Reforger", mmoItem.getType().toString(), mmoItem.getId()); mmoItem = null; return; }
Validate.isTrue(meta != null, FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "Invalid item meta prevented $f{0}$b from updating.", template.getType().toString() + " " + template.getId()));
//UPDT//MMOItems.log("\u00a79*\u00a77 Regenerating... \u00a7d" + template.getId() + " " + template.getType());
//UPGRD//MMOItems.log("\u00a79*\u00a77 Regenerating... \u00a7d" + template.getId() + " " + template.getType());
if (p != null) {
@ -392,7 +454,7 @@ public class MMOItemReforger {
if (player == null) {
// Get default Item Level
final int iLevel = defaultItemLevel;
int iLevel = defaultItemLevel;
// What level with the regenerated item will be hmmmm.....
determinedItemLevel =
@ -451,6 +513,7 @@ public class MMOItemReforger {
if (p == null) { reforge((RPGPlayer) null, options); } else {
PlayerData dat = PlayerData.get(p);
if (dat == null) { reforge((RPGPlayer) null, options); } else { reforge(dat.getRPG(), options); } } }
/**
* Generates a new item of the same Type-ID and transfers the data
* from the old one following the options.
@ -476,9 +539,9 @@ public class MMOItemReforger {
if (options.shouldKeepName()) { keepName(meta);}
// Keep specific lore components
if (options.shouldKeepLore() && mmoItem.hasData(ItemStats.LORE)) { keepLore(); }
if (options.shouldKeepLore() && mmoItem.hasData(ItemStats.LORE)) { keepLore(options.getKeepCase()); }
EnchantListData ambiguouslyOriginalEnchantmentCache = null; //todo Corresponding to the block at the end of this method.
EnchantListData ambiguouslyOriginalEnchantmentCache = null;
// Choose enchantments to keep
if (options.shouldKeepEnchantments()) { Ref<EnchantListData> rf = new Ref<>(); keepEnchantments(rf); ambiguouslyOriginalEnchantmentCache = rf.getValue(); }
@ -509,7 +572,7 @@ public class MMOItemReforger {
if (mmoItem.hasData(ItemStats.NAME)) {
// Cache it
cachedName = mmoItem.getData(ItemStats.NAME).toString();
cachedName = ((NameData) mmoItem.getData(ItemStats.NAME)).getMainName();
// No name defined, use display name I guess (pretty unusual btw)
} else if (meta.hasDisplayName()) {
@ -522,28 +585,28 @@ public class MMOItemReforger {
* Examines the MMOItems Lore of the item being updated, and chooses which lore
* lines are desirable to keep (Those that start with §7)
*/
void keepLore() {
void keepLore(@NotNull String keepCase) {
if (!mmoItem.hasData(ItemStats.LORE)) { return; }
cachedLore = extractLore(((StringListData) mmoItem.getData(ItemStats.LORE)).getList());
cachedLore = extractLore(((StringListData) mmoItem.getData(ItemStats.LORE)).getList(), keepCase);
}
@NotNull ArrayList<String> extractLore(@NotNull List<String> lore) {
@NotNull ArrayList<String> extractLore(@NotNull List<String> lore, @NotNull String keepCase) {
//UPDT//MMOItems.log(" \u00a7d> \u00a77Keeping Lore");
//UPGRD//MMOItems.log(" \u00a7d> \u00a77Keeping Lore");
ArrayList<String> ret = new ArrayList<>();
// Examine every element
for (String str : lore) {
//UPDT//MMOItems.log(" \u00a7d>\u00a7c-\u00a7e- \u00a77Line:\u00a7f " + str);
//UPGRD//MMOItems.log(" \u00a7d>\u00a7c-\u00a7e- \u00a77Line:\u00a7f " + str);
// Does it start with the promised...?
if (str.startsWith("\u00a77")) {
//UPDT//MMOItems.log(" \u00a72>\u00a7a-\u00a7e- \u00a77Kept");
if (str.startsWith(keepCase)) {
//UPGRD//MMOItems.log(" \u00a72>\u00a7a-\u00a7e- \u00a77Kept");
ret.add(str); }
}
//UPDT//MMOItems.log(" \u00a7d> \u00a77Result");
//UPDT//for (String lr : cachedLore) { //UPDT//MMOItems.log(" \u00a7d + \u00a77" + lr); }
//UPGRD//MMOItems.log(" \u00a7d> \u00a77Result");
//UPGRD//for (String lr : cachedLore) { MMOItems.log(" \u00a7d + \u00a77" + lr); }
return ret;
}
@ -561,36 +624,36 @@ public class MMOItemReforger {
* which may not be original (and thus contain player enchantments)
*/
void keepEnchantments(@NotNull Ref<EnchantListData> ambiguouslyOriginalEnchantmentCache) {
//UPDT//MMOItems.log(" \u00a7b> \u00a77Keeping Enchantments");
//UPGRD//MMOItems.log(" \u00a7b> \u00a77Keeping Enchantments");
// Enchant list data
cachedEnchantments = new EnchantListData();
// Does it have MMOItems enchantment data?
if (!mmoItem.hasData(ItemStats.ENCHANTS)) {
//UPDT//MMOItems.log(" \u00a7b* \u00a77No Data, created blanc");
//UPGRD//MMOItems.log(" \u00a7b* \u00a77No Data, created blanc");
mmoItem.setData(ItemStats.ENCHANTS, new EnchantListData()); }
//UPDT//else { MMOItems.log(" \u00a7b* \u00a77Found Data"); }
//UPGRD//else { MMOItems.log(" \u00a7b* \u00a77Found Data"); }
// Make sure they are consolidated
Enchants.separateEnchantments(mmoItem);
// Gather
StatHistory hist = StatHistory.from(mmoItem, ItemStats.ENCHANTS);
ambiguouslyOriginalEnchantmentCache.setValue((EnchantListData) ((EnchantListData) hist.getOriginalData()).cloneData());
ambiguouslyOriginalEnchantmentCache.setValue((EnchantListData) ((Mergeable) hist.getOriginalData()).cloneData());
//UPDT//MMOItems.log(" \u00a7b:\u00a73:\u00a7: \u00a77Prime Arcane Report: \u00a7b-------------------------");
//UPDT//MMOItems.log(" \u00a73> \u00a77History:");
//UPDT//MMOItems.log(" \u00a73=\u00a7b> \u00a77Original:");
//UPDT//for (Enchantment e : ((EnchantListData) hist.getOriginalData()).getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getOriginalData()).getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73=\u00a7b> \u00a77Stones:");
//UPDT//for (UUID data : hist.getAllGemstones()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77" + data.toString()); for (Enchantment e : ((EnchantListData) hist.getGemstoneData(data)).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getGemstoneData(data)).getLevel(e)); } }
//UPDT//MMOItems.log(" \u00a73=\u00a7b> \u00a77Externals:");
//UPDT//for (StatData data : hist.getExternalData()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77 --------- "); for (Enchantment e : ((EnchantListData) data).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) data).getLevel(e)); } }
//UPDT//MMOItems.log(" \u00a73> \u00a77Cached:");
//UPDT//for (Enchantment e : cachedEnchantments.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + cachedEnchantments.getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73> \u00a77Ambiguous:");
//UPDT//for (Enchantment e : ambiguouslyOriginalEnchantmentCache.getValue().getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ambiguouslyOriginalEnchantmentCache.getValue().getLevel(e)); }
//UPGRD//MMOItems.log(" \u00a7b:\u00a73:\u00a7: \u00a77Prime Arcane Report: \u00a7b-------------------------");
//UPGRD//MMOItems.log(" \u00a73> \u00a77History:");
//UPGRD//MMOItems.log(" \u00a73=\u00a7b> \u00a77Original:");
//UPGRD//for (Enchantment e : ((EnchantListData) hist.getOriginalData()).getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getOriginalData()).getLevel(e)); }
//UPGRD//MMOItems.log(" \u00a73=\u00a7b> \u00a77Stones:");
//UPGRD//for (UUID data : hist.getAllGemstones()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77" + data.toString()); for (Enchantment e : ((EnchantListData) hist.getGemstoneData(data)).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getGemstoneData(data)).getLevel(e)); } }
//UPGRD//MMOItems.log(" \u00a73=\u00a7b> \u00a77Externals:");
//UPGRD//for (StatData data : hist.getExternalData()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77 --------- "); for (Enchantment e : ((EnchantListData) data).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) data).getLevel(e)); } }
//UPGRD//MMOItems.log(" \u00a73> \u00a77Cached:");
//UPGRD//for (Enchantment e : cachedEnchantments.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + cachedEnchantments.getLevel(e)); }
//UPGRD//MMOItems.log(" \u00a73> \u00a77Ambiguous:");
//UPGRD//for (Enchantment e : ambiguouslyOriginalEnchantmentCache.getValue().getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ambiguouslyOriginalEnchantmentCache.getValue().getLevel(e)); }
// Reap
for (StatData pEnchants : hist.getExternalData()) {
@ -599,7 +662,7 @@ public class MMOItemReforger {
if (pEnchants instanceof EnchantListData) {
// Merge bruh
((EnchantListData) pEnchants).merge(cachedEnchantments);
((Mergeable) pEnchants).merge(cachedEnchantments);
// For every stat
for (Enchantment e : ((EnchantListData) pEnchants).getEnchants()) {
@ -609,7 +672,7 @@ public class MMOItemReforger {
// Put
cachedEnchantments.addEnchant(e, calculated);
//UPDT//MMOItems.log(" \u00a7b + \u00a77" + e.getName() + " " + calculated);
//UPGRD//MMOItems.log(" \u00a7b + \u00a77" + e.getName() + " " + calculated);
}
}
}
@ -617,28 +680,28 @@ public class MMOItemReforger {
// The cache now stores the full extent of extraneous data. Separate from thy history. (As to not include it in this in the cached data later)
hist.getExternalData().clear();
//UPDT//MMOItems.log(" \u00a7b:\u00a73:\u00a7: \u00a77Arcane Report: \u00a7b-------------------------");
//UPDT//MMOItems.log(" \u00a73> \u00a77History:");
//UPDT//MMOItems.log(" \u00a73=\u00a7b> \u00a77Original:");
//UPDT//for (Enchantment e : ((EnchantListData) hist.getOriginalData()).getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getOriginalData()).getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73=\u00a7b> \u00a77Stones:");
//UPDT//for (UUID data : hist.getAllGemstones()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77" + data.toString()); for (Enchantment e : ((EnchantListData) hist.getGemstoneData(data)).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getGemstoneData(data)).getLevel(e)); } }
//UPDT//MMOItems.log(" \u00a73=\u00a7b> \u00a77Externals:");
//UPDT//for (StatData data : hist.getExternalData()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77 --------- "); for (Enchantment e : ((EnchantListData) data).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) data).getLevel(e)); } }
//UPDT//MMOItems.log(" \u00a73> \u00a77Cached:");
//UPDT//for (Enchantment e : cachedEnchantments.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + cachedEnchantments.getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73> \u00a77Ambiguous:");
//UPDT//for (Enchantment e : ambiguouslyOriginalEnchantmentCache.getValue().getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ambiguouslyOriginalEnchantmentCache.getValue().getLevel(e)); }
//UPGRD//MMOItems.log(" \u00a7b:\u00a73:\u00a7: \u00a77Arcane Report: \u00a7b-------------------------");
//UPGRD//MMOItems.log(" \u00a73> \u00a77History:");
//UPGRD//MMOItems.log(" \u00a73=\u00a7b> \u00a77Original:");
//UPGRD//for (Enchantment e : ((EnchantListData) hist.getOriginalData()).getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getOriginalData()).getLevel(e)); }
//UPGRD//MMOItems.log(" \u00a73=\u00a7b> \u00a77Stones:");
//UPGRD//for (UUID data : hist.getAllGemstones()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77" + data.toString()); for (Enchantment e : ((EnchantListData) hist.getGemstoneData(data)).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getGemstoneData(data)).getLevel(e)); } }
//UPGRD//MMOItems.log(" \u00a73=\u00a7b> \u00a77Externals:");
//UPGRD//for (StatData data : hist.getExternalData()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77 --------- "); for (Enchantment e : ((EnchantListData) data).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) data).getLevel(e)); } }
//UPGRD//MMOItems.log(" \u00a73> \u00a77Cached:");
//UPGRD//for (Enchantment e : cachedEnchantments.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + cachedEnchantments.getLevel(e)); }
//UPGRD//MMOItems.log(" \u00a73> \u00a77Ambiguous:");
//UPGRD//for (Enchantment e : ambiguouslyOriginalEnchantmentCache.getValue().getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ambiguouslyOriginalEnchantmentCache.getValue().getLevel(e)); }
}
/**
* Just copies the upgrade data, with info on the level of course.
*/
void keepUpgrades() {
//UPDT//MMOItems.log(" \u00a7e> \u00a77Keeping Upgrade Data");
//UPGRD//MMOItems.log(" \u00a7e> \u00a77Keeping Upgrade Data");
// Get Level
cachedUpgradeLevel = ((UpgradeData) mmoItem.getData(ItemStats.UPGRADE));
//UPDT//MMOItems.log(" \u00a7e>-- \u00a77Level: \u00a7b" + (cachedUpgradeLevel != null ? cachedUpgradeLevel.getLevel() : "0 \u00a78(null)"));
//UPGRD//MMOItems.log(" \u00a7e>-- \u00a77Level: \u00a7b" + (cachedUpgradeLevel != null ? cachedUpgradeLevel.getLevel() : "0 \u00a78(null)"));
}
/**
* Caches the full history of these items.
@ -652,8 +715,6 @@ public class MMOItemReforger {
if (mmoItem.hasData(ItemStats.GEM_SOCKETS) && !clearGems) {
//UPDT//MMOItems.log(" \u00a7a> \u00a77Keeping Gem Sockets Gx\u00a7b" + ((GemSocketsData) mmoItem.getData(ItemStats.GEM_SOCKETS)).getGemstones().size() + "\u00a77, Ex\u00a7b" + ((GemSocketsData) mmoItem.getData(ItemStats.GEM_SOCKETS)).getEmptySlots().size());
//GEM//for (String str : SilentNumbers.transcribeList(new ArrayList<>(((GemSocketsData) mmoItem.getData(ItemStats.GEM_SOCKETS)).getGemstones()), (s) -> (s instanceof GemstoneData ? ((GemstoneData) s).getHistoricUUID() + "\u00a7f " + ((GemstoneData) s).getName() : "null"))) { MMOItems.log(" \u00a7a+> \u00a77Gem: \u00a7a" + str); }
//GEM//for (String str : SilentNumbers.transcribeList(new ArrayList<>(((GemSocketsData) mmoItem.getData(ItemStats.GEM_SOCKETS)).getEmptySlots()), (s) -> s + "")) { MMOItems.log(" \u00a7a+> \u00a77Emp: \u00a76" + str); }
// Cache that gemstone data
cachedGemStones = (GemSocketsData) mmoItem.getData(ItemStats.GEM_SOCKETS); }
@ -661,26 +722,29 @@ public class MMOItemReforger {
//UPDT//MMOItems.log(" \u00a7a++ \u00a77Saving current histories (the information on current RNG rolls)");
// Store all the history of stat proceedings.
for (StatHistory hist : mmoItem.getStatHistories()) {
//UPDT//MMOItems.log(" \u00a7a + \u00a77History of \u00a7f" + hist.getItemStat().getNBTPath() + "\u00a77, Gx:\u00a7e" + hist.getAllGemstones().size() + "\u00a77, Ex:\u00a7e" + hist.getExternalData().size());
//UPDT//MMOItems.log(" \u00a7c + \u00a77Original History of \u00a7f" + hist.getItemStat().getNBTPath() + "\u00a77, Gx:\u00a7e" + hist.getAllGemstones().size() + "\u00a77, Ex:\u00a7e" + hist.getExternalData().size());
StatHistory cloned = hist.clone(mmoItem);
// Clear externals
if (clearExternalSH) {
//UPDT//MMOItems.log(" \u00a7a + \u00a77Clearing EXSH... \u00a7f");
hist.getExternalData().clear(); }
//UPDT//MMOItems.log(" \u00a7e + \u00a77Clearing \u00a73 " + cloned.getExternalData().size() + " \u00a77EXSH... \u00a7f");
cloned.clearExternalData(); }
// Modifiers handled elsewhere
//UPDT//MMOItems.log(" \u00a7e + \u00a77Clearing \u00a7c" + cloned.getAllModifiers().size() + " \u00a77Modifiers... \u00a7f");
cloned.clearModifiersBonus();
// Get and set
itemDataHistory.put(hist.getItemStat(), hist);
//UPDT//MMOItems.log(" \u00a7a + \u00a77History of \u00a7f" + hist.getItemStat().getNBTPath() + "\u00a77, Gx:\u00a7e" + hist.getAllGemstones().size() + "\u00a77, Ex:\u00a7e" + hist.getExternalData().size());
//GEM//MMOItems.log(" \u00a73 +-+ \u00a77OG: \u00a7f" + hist.getOriginalData().toString());
//GEM//for (String str : SilentNumbers.transcribeList(hist.getAllGemstones(), (s) -> (s instanceof UUID ? hist.getGemstoneData((UUID) s) + "\u00a73 (\u00a78" + s + "\u00a73)" : "null"))) { MMOItems.log(" \u00a73 +-+ \u00a77GM: \u00a7f" + str); }
//GEM//for (String str : SilentNumbers.transcribeList(hist.getExternalData(), (s) -> (s instanceof StatData ? s.toString() : "null"))) { MMOItems.log(" \u00a73 +-+ \u00a77EX: \u00a7f" + str); }
itemDataHistory.put(cloned.getItemStat(), cloned);
//UPDT//MMOItems.log(" \u00a7a +++ \u00a77Cloned History of \u00a7f" + cloned.getItemStat().getNBTPath() + "\u00a77, Gx:\u00a7e" + cloned.getAllGemstones().size() + "\u00a77, Ex:\u00a7e" + hist.getExternalData().size());
//UPDT//cloned.log();
}
}
/**
* Just copies the soulbound :B
*/
void keepSoulbound() {
//UPDT//MMOItems.log(" \u00a7c> \u00a77Keeping Soulbind");
//UPGRD//MMOItems.log(" \u00a7c> \u00a77Keeping Soulbind");
// Find data
cachedSoulbound = mmoItem.getData(ItemStats.SOULBOUND);
@ -717,11 +781,11 @@ public class MMOItemReforger {
*/
if (cachedUpgradeLevel != null) {
//UPDT//MMOItems.log(" \u00a7e@ \u00a77Applying Upgrade");
//UPGRD//MMOItems.log(" \u00a7e@ \u00a77Applying Upgrade");
// If has a upgrade template defined, just remember the level
if (buildingMMOItem.hasData(ItemStats.UPGRADE)) {
//UPDT//MMOItems.log(" \u00a7e* \u00a77Existing Upgrade Detected");
//UPGRD//MMOItems.log(" \u00a7e* \u00a77Existing Upgrade Detected");
// Get current ig
UpgradeData current = ((UpgradeData) buildingMMOItem.getData(ItemStats.UPGRADE));
@ -757,23 +821,25 @@ public class MMOItemReforger {
if (histOld == null) {
//UPDT//MMOItems.log(" \u00a72 *\u00a76* \u00a7cMissing");
continue; }
/*/ Is it completely clear?
if (histOld.isClear()) {
/UPDT//MMOItems.log(" \u00a72 *\u00a76* \u00a7cClear " + (histOld.getOriginalData() instanceof DoubleData ? "\u00a78 {Original:\u00a77 " + ((DoubleData) histOld.getOriginalData()).getValue() + "\u00a78}" : ""));
continue; }
/UPDT//MMOItems.log(" \u00a72 *\u00a76* \u00a7cNot clear: \u00a73Gems" + histOld.getAllGemstones().size() + " \u00a78|\u00a7b ExSH " + histOld.getExternalData().size() + (histOld.getOriginalData() instanceof DoubleData ? "\u00a78 {Original:\u00a77 " + ((DoubleData) histOld.getOriginalData()).getValue() + "\u00a78}" : ""));
//*/
//UPDT//MMOItems.log(" \u00a72 *\u00a76*\u00a7c->>>> \u00a77Cached History (histOLD)");
//UPDT//histOld.log();
// Regenerate the original data
StatHistory hist = StatHistory.from(buildingMMOItem, stat);
// Remember...
//UPDT//MMOItems.log(" \u00a72 *\u00a76*\u00a7c->>>> \u00a77Current History");
//UPDT//hist.log();
// Remember... (but the modifiers are already in there)
histOld.clearModifiersBonus();
hist.getExternalData().clear();
hist.assimilate(histOld);
// Recalculate
//HSY//MMOItems.log(" \u00a7b-\u00a7e- \u00a77Reforging Prep Recalculation \u00a7b-\u00a7e-\u00a7b-\u00a7e-\u00a7b-\u00a7e-\u00a7b-\u00a7e-");
buildingMMOItem.setData(hist.getItemStat(), hist.recalculate(false, l));
//UPDT//MMOItems.log(" \u00a72-\u00a76---> \u00a77Final \u00a76<---\u00a72-");
//UPDT//hist.log();
//LVL//MMOItems.log(" \u00a7d?\u00a77?\u00a76? \u00a77Lvl: \u00a7b" + buildingMMOItem.getUpgradeLevel());
}
@ -783,7 +849,7 @@ public class MMOItemReforger {
// Apply soulbound
if (cachedSoulbound != null) {
//UPDT//MMOItems.log(" \u00a7c@ \u00a77Applying Soulbind");
//UPGRD//MMOItems.log(" \u00a7c@ \u00a77Applying Soulbind");
// Apply
buildingMMOItem.setData(ItemStats.SOULBOUND, cachedSoulbound);
@ -791,22 +857,22 @@ public class MMOItemReforger {
// Contained enchantments huh
if (cachedEnchantments != null) {
//UPDT//MMOItems.log(" \u00a7b@ \u00a77Applying Enchantments");
//UPDT//for (Enchantment lr : cachedEnchantments.getEnchants()) { MMOItems.log(" \u00a7b + \u00a77" + lr.getName() + " \u00a7f" + cachedEnchantments.getLevel(lr)); }
//UPGRD//MMOItems.log(" \u00a7b@ \u00a77Applying Enchantments");
//UPGRD//for (Enchantment lr : cachedEnchantments.getEnchants()) { MMOItems.log(" \u00a7b + \u00a77" + lr.getName() + " \u00a7f" + cachedEnchantments.getLevel(lr)); }
// Register as extraneous obviously
StatHistory hist = StatHistory.from(buildingMMOItem, ItemStats.ENCHANTS);
hist.registerExternalData(cachedEnchantments.cloneData());
//UPDT//MMOItems.log(" \u00a7b:\u00a73:\u00a7: \u00a77Late Arcane Report: \u00a79-------------------------");
//UPDT//MMOItems.log(" \u00a73> \u00a77History:");
//UPDT//MMOItems.log(" \u00a73=\u00a7b> \u00a77Original:");
//UPDT//for (Enchantment e : ((EnchantListData) hist.getOriginalData()).getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getOriginalData()).getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73=\u00a7b> \u00a77Stones:");
//UPDT//for (UUID data : hist.getAllGemstones()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77" + data.toString()); for (Enchantment e : ((EnchantListData) hist.getGemstoneData(data)).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getGemstoneData(data)).getLevel(e)); } }
//UPDT//MMOItems.log(" \u00a73=\u00a7b> \u00a77Externals:");
//UPDT//for (StatData data : hist.getExternalData()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77 --------- "); for (Enchantment e : ((EnchantListData) data).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) data).getLevel(e)); } }
//UPGRD//MMOItems.log(" \u00a7b:\u00a73:\u00a7: \u00a77Late Arcane Report: \u00a79-------------------------");
//UPGRD//MMOItems.log(" \u00a73> \u00a77History:");
//UPGRD//MMOItems.log(" \u00a73=\u00a7b> \u00a77Original:");
//UPGRD//for (Enchantment e : ((EnchantListData) hist.getOriginalData()).getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getOriginalData()).getLevel(e)); }
//UPGRD//MMOItems.log(" \u00a73=\u00a7b> \u00a77Stones:");
//UPGRD//for (UUID data : hist.getAllGemstones()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77" + data.toString()); for (Enchantment e : ((EnchantListData) hist.getGemstoneData(data)).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) hist.getGemstoneData(data)).getLevel(e)); } }
//UPGRD//MMOItems.log(" \u00a73=\u00a7b> \u00a77Externals:");
//UPGRD//for (StatData data : hist.getExternalData()) { MMOItems.log(" \u00a7b==\u00a73> \u00a77 --------- "); for (Enchantment e : ((EnchantListData) data).getEnchants()) { MMOItems.log(" \u00a7b *\u00a73* \u00a77" + e.getName() + " \u00a7f" + ((EnchantListData) data).getLevel(e)); } }
// Recalculate and put
//HSY//MMOItems.log(" \u00a73-\u00a7a- \u00a77Reforge Enchantments Recalculation \u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-");
@ -909,11 +975,11 @@ public class MMOItemReforger {
// Lore
if (!cachedLore.isEmpty()) {
//UPDT//MMOItems.log(" \u00a7d@ \u00a77Applying Lore");
//UPGRD//MMOItems.log(" \u00a7d@ \u00a77Applying Lore");
// If it has lore, add I guess
if (buildingMMOItem.hasData(ItemStats.LORE)) {
//UPDT//MMOItems.log(" \u00a7d* \u00a77Inserting first");
//UPGRD//MMOItems.log(" \u00a7d* \u00a77Inserting first");
// Get current ig
StringListData current = ((StringListData) buildingMMOItem.getData(ItemStats.LORE));
@ -927,7 +993,7 @@ public class MMOItemReforger {
// Create stat
StringListData sData = new StringListData(cachedLore);
//UPDT//for (String lr : cachedLore) { MMOItems.log(" \u00a7d + \u00a77" + lr); }
//UPGRD//for (String lr : cachedLore) { MMOItems.log(" \u00a7d + \u00a77" + lr); }
// Set that as the lore
buildingMMOItem.setData(ItemStats.LORE, sData);
@ -935,17 +1001,29 @@ public class MMOItemReforger {
// Name
if (cachedName != null) {
//UPDT//MMOItems.log(" \u00a73@ \u00a77Applying Name \u00a7f" + cachedName);
//UPDT//MMOItems.log(" \u00a73@ \u00a77Restoring Name");
// Replace name completely
buildingMMOItem.setData(ItemStats.NAME, new StringData(cachedName));
// Find SH
StatHistory hist = StatHistory.from(buildingMMOItem, ItemStats.NAME);
// Overwrite whatever is the current name with the cached main name yea
((NameData) hist.getOriginalData()).setString(cachedName);
// Recalculate Name
buildingMMOItem.setData(ItemStats.NAME, hist.recalculate(buildingMMOItem.getUpgradeLevel()));
//UPDT//hist.log();
}
// Apply upgrades
if (buildingMMOItem.hasUpgradeTemplate()) {
//UPDT//MMOItems.log(" \u00a7f@ \u00a77Recalculating Upgrades");
//UPGRD//MMOItems.log(" \u00a7f@ \u00a77Recalculating Upgrades");
buildingMMOItem.getUpgradeTemplate().upgradeTo(buildingMMOItem, buildingMMOItem.getUpgradeLevel()); }
// Apply durability
if (cachedDurability != null) { mmoItem.setData(ItemStats.DURABILITY, cachedDurability); }
//GEM//MMOItems.log(" \u00a7a>3 \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+>3 \u00a77Gem: \u00a7a" + str); }
//GEM//if (buildingMMOItem.getData(ItemStats.GEM_SOCKETS) instanceof GemSocketsData) for (String str : SilentNumbers.transcribeList(new ArrayList<>(((GemSocketsData) buildingMMOItem.getData(ItemStats.GEM_SOCKETS)).getEmptySlots()), (s) -> s + "")) { MMOItems.log(" \u00a7a+>3 \u00a77Emp: \u00a76" + str); }
@ -953,6 +1031,9 @@ public class MMOItemReforger {
// Build and set amount
ItemStack stack = buildingMMOItem.newBuilder().build();
stack.setAmount(amount);
if (cachedDur != null && stack.getItemMeta() instanceof Damageable) { ((Damageable) stack.getItemMeta()).setDamage(SilentNumbers.floor(cachedDur * stack.getType().getMaxDurability())); }
return stack;
}

View File

@ -5,8 +5,11 @@ 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.item.mmoitem.VolatileMMOItem;
import net.Indyuce.mmoitems.api.util.MMOItemReforger;
import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmoitems.stat.data.DoubleData;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -18,6 +21,7 @@ import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

View File

@ -2,34 +2,45 @@ package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import io.lumine.mythic.lib.version.VersionMaterial;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.ItemTier;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
import net.Indyuce.mmoitems.stat.data.StringData;
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.type.GemStoneStat;
import net.Indyuce.mmoitems.stat.type.NameData;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import net.Indyuce.mmoitems.stat.type.StringStat;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.logging.Level;
public class DisplayName extends StringStat {
public class DisplayName extends StringStat implements GemStoneStat {
private final String[] cleanFilter = {ChatColor.BOLD.toString(), ChatColor.ITALIC.toString(), ChatColor.UNDERLINE.toString(), ChatColor.STRIKETHROUGH.toString(), ChatColor.MAGIC.toString()};
public DisplayName() {
super("NAME", VersionMaterial.OAK_SIGN.toMaterial(), "Display Name", new String[] { "The item display name." },
new String[] { "all" });
}
// TODO: 4/12/2021 WHAT THE FUCK IS HAPPENING HERE
@Override
public void whenApplied(@NotNull ItemStackBuilder item, @NotNull StatData data) {
String format = data.toString();
// Bake
String format;
if (data instanceof NameData) {
format = ((NameData) data).bake();
} else {
format = data.toString();
}
ItemTier tier = MMOItems.plugin.getTiers().findTier(item.getMMOItem());
format = format.replace("<tier-name>", tier != null ? ChatColor.stripColor(tier.getName()) : "");
@ -43,55 +54,63 @@ public class DisplayName extends StringStat {
}
// Is this upgradable?
if (item.getMMOItem().hasUpgradeTemplate()) {
int upgradeLevel = item.getMMOItem().getUpgradeLevel();
String suffix = MythicLib.plugin.parseColors(MMOItems.plugin.getConfig().getString("item-upgrading.name-suffix"));
format = cropUpgrade(format);
if (item.getMMOItem().hasUpgradeTemplate()) { format = appendUpgradeLevel(format, item.getMMOItem().getUpgradeLevel()); }
//MMOItems.getConsole().sendMessage("Level " + upgradeLevel);
//MMOItems.getConsole().sendMessage("Format " + format);
item.getMeta().setDisplayName(MythicLib.plugin.parseColors(format));
if (suffix != null) {
// Add NBT
item.addItemTag(getAppliedNBT(data));
}
// Crop lvl
int lvlOFFSET = suffix.indexOf("#lvl#");
String sB4 = suffix.substring(0, lvlOFFSET);
String aFt = suffix.substring(lvlOFFSET + "#lvl#".length());
String sB4_alt = sB4.replace("+", "-");
String aFt_alt = aFt.replace("+", "-");
@NotNull String cropUpgrade(@NotNull String format) {
String suffix = MythicLib.plugin.parseColors(MMOItems.plugin.getConfig().getString("item-upgrading.name-suffix"));
// Remove it
if (format.contains(sB4)) {
//MMOItems.getConsole().sendMessage("Level " + upgradeLevel);
//MMOItems.getConsole().sendMessage("Format " + format);
// Get offsets
int sB4_offset = format.indexOf(sB4);
int aFt_offset = format.lastIndexOf(aFt);
if (suffix != null) {
// No after = to completion
if (aFt_offset < 0) { aFt_offset = format.length(); } else { aFt_offset += aFt.length(); }
// Crop lvl
int lvlOFFSET = suffix.indexOf("#lvl#");
String sB4 = suffix.substring(0, lvlOFFSET);
String aFt = suffix.substring(lvlOFFSET + "#lvl#".length());
String sB4_alt = sB4.replace("+", "-");
String aFt_alt = aFt.replace("+", "-");
// Remove that
String beforePrefix = format.substring(0, sB4_offset);
String afterPrefix = format.substring(aFt_offset);
// Remove it
if (format.contains(sB4)) {
// Replace
format = beforePrefix + afterPrefix; }
// Get offsets
int sB4_offset = format.indexOf(sB4);
int aFt_offset = format.lastIndexOf(aFt);
// Remove it
if (format.contains(sB4_alt)) {
// No after = to completion
if (aFt_offset < 0) { aFt_offset = format.length(); } else { aFt_offset += aFt.length(); }
// Get offsets
int sB4_offset = format.indexOf(sB4_alt);
int aFt_offset = format.lastIndexOf(aFt_alt);
// Remove that
String beforePrefix = format.substring(0, sB4_offset);
String afterPrefix = format.substring(aFt_offset);
// No after = to completion
if (aFt_offset < 0) { aFt_offset = format.length(); } else { aFt_offset += aFt_alt.length(); }
// Replace
format = beforePrefix + afterPrefix; }
// Remove that
String beforePrefix = format.substring(0, sB4_offset);
String afterPrefix = format.substring(aFt_offset);
// Remove it
if (format.contains(sB4_alt)) {
// Replace
format = beforePrefix + afterPrefix; }
// Get offsets
int sB4_offset = format.indexOf(sB4_alt);
int aFt_offset = format.lastIndexOf(aFt_alt);
// No after = to completion
if (aFt_offset < 0) { aFt_offset = format.length(); } else { aFt_offset += aFt_alt.length(); }
// Remove that
String beforePrefix = format.substring(0, sB4_offset);
String afterPrefix = format.substring(aFt_offset);
// Replace
format = beforePrefix + afterPrefix; }
/*/ Bake old indices for removal
ArrayList<String> oldSuffixii = new ArrayList<>(); boolean negativity = false;
@ -111,23 +130,30 @@ public class DisplayName extends StringStat {
//MMOItems.getConsole().sendMessage("Edited " + format);
} //*/
// Add a prefix anew if the upgrade level worked
if (upgradeLevel != 0) {
// Get the current suffix
String actSuffix = levelPrefix(suffix, upgradeLevel);
//MMOItems.getConsole().sendMessage("Current " + actSuffix);
// Append it
format = format + actSuffix;
}
//MMOItems.getConsole().sendMessage("Final " + format);
}
//MMOItems.getConsole().sendMessage("Final " + format);
}
item.getMeta().setDisplayName(MythicLib.plugin.parseColors(format));
return format;
}
@NotNull String appendUpgradeLevel(@NotNull String format, int lvl) {
String suffix = MythicLib.plugin.parseColors(MMOItems.plugin.getConfig().getString("item-upgrading.name-suffix"));
//MMOItems.getConsole().sendMessage("Level " + upgradeLevel);
//MMOItems.getConsole().sendMessage("Format " + format);
if (suffix != null && lvl != 0) {
// Get the current suffix
String actSuffix = levelPrefix(suffix, lvl);
//MMOItems.getConsole().sendMessage("Current " + actSuffix);
// Append it
return format + actSuffix;
}
return format;
}
@ -151,6 +177,18 @@ public class DisplayName extends StringStat {
@Override
public ArrayList<ItemTag> getAppliedNBT(@NotNull StatData data) {
if (data instanceof NameData) {
ArrayList<ItemTag> tags = new ArrayList<>();
// Append those
tags.add(new ItemTag(getNBTPath(), ((NameData) data).getMainName()));
if (((NameData) data).hasPrefixes()) { tags.add(((NameData) data).compressPrefixes(getNBTPath() + "_PRE"));}
if (((NameData) data).hasSuffixes()) { tags.add(((NameData) data).compressSuffixes(getNBTPath() + "_SUF"));}
return tags;
}
// Thats it
return new ArrayList<>();
}
@ -158,23 +196,105 @@ public class DisplayName extends StringStat {
@Override
public void whenLoaded(@NotNull ReadMMOItem mmoitem) {
// No need to continue if the item has no display name
if (!mmoitem.getNBT().getItem().getItemMeta().hasDisplayName()) { return; }
// Get tags
ArrayList<ItemTag> relevantTags = new ArrayList<>();
ArrayList<ItemTag> relevantTags = new ArrayList<>(); boolean stored = false;
ItemTag mainName = ItemTag.getTagAtPath(getNBTPath(), mmoitem.getNBT(), SupportedNBTTagValues.STRING);
// Add sole tag
relevantTags.add(new ItemTag(getNBTPath(), mmoitem.getNBT().getItem().getItemMeta().getDisplayName()));
//NME//MMOItems.log("\u00a7b\u00a2\u00a2\u00a2\u00a77 Loading name of \u00a7b" + mmoitem.getType() + " " + mmoitem.getId());
if (mainName != null) {
// Ah yes
ItemTag prefixes = ItemTag.getTagAtPath(getNBTPath() + "_PRE", mmoitem.getNBT(), SupportedNBTTagValues.STRING);
ItemTag suffixes = ItemTag.getTagAtPath(getNBTPath() + "_SUF", mmoitem.getNBT(), SupportedNBTTagValues.STRING);
relevantTags.add(mainName);
relevantTags.add(prefixes);
relevantTags.add(suffixes);
// No need to evaluate anvil changes if the item has no display name
if (mmoitem.getNBT().getItem().getItemMeta().hasDisplayName()) { stored = true; }
} else {
// No need to continue if the item has no display name
if (!mmoitem.getNBT().getItem().getItemMeta().hasDisplayName()) { return; }
//NME//MMOItems.log("\u00a7a\u00a2\u00a2\u00a2\u00a77 Older item, decrypting as main name as:\u00a7f " + cropUpgrade(mmoitem.getNBT().getItem().getItemMeta().getDisplayName()));
// Add sole tag
relevantTags.add(new ItemTag(getNBTPath(), cropUpgrade(mmoitem.getNBT().getItem().getItemMeta().getDisplayName())));
}
// Use that
StringData bakedData = (StringData) getLoadedNBT(relevantTags);
NameData bakedData = (NameData) getLoadedNBT(relevantTags);
// Valid?
if (bakedData != null) {
//NME//MMOItems.log("\u00a7e\u00a2\u00a2\u00a2\u00a77 Built:\u00a7f " + bakedData.toString());
/*
* Suppose we expect an item name with prefixes and suffixes,
* well, removing those should leave the bare name, right?
*
* If the player has renamed their item, this bare name will be somewhat
* different, and this is where those changes are updated.
*/
@Nullable String itemName = null;
if (stored) {
// Could the player have renamed?
itemName = mmoitem.getNBT().getItem().getItemMeta().getDisplayName();
String colorless = ChatColor.stripColor(itemName);
//NME//MMOItems.log("\u00a7b\u00a2\u00a2\u00a2\u00a77 Comparing: " + itemName + " | " + colorless);
// By player
if (!itemName.equals(colorless)) {
//NME//MMOItems.log("\u00a7b\u00a2\u00a2\u00a2\u00a77 Not anvil");
itemName = null;
} else {
//NME//MMOItems.log("\u00a7b\u00a2\u00a2\u00a2\u00a77 Replaced main with \u00a7b " + itemName);
bakedData.setString(itemName);
}
}
// Set
mmoitem.setData(this, bakedData);
// Update in SH. Must happen after setting the data
if (stored && itemName != null) {
// History not prematurely loaded?
if (mmoitem.getStatHistory(this) == null) {
// Also load history :think ing:
ItemTag hisTag = ItemTag.getTagAtPath(ItemStackBuilder.histroy_keyword + getId(), mmoitem.getNBT(), SupportedNBTTagValues.STRING);
if (hisTag != null) {
// Aye
StatHistory hist = StatHistory.fromNBTString(mmoitem, (String) hisTag.getValue());
// History valid? Record
if (hist != null) {
// Original Data
NameData og = (NameData) hist.getOriginalData();
// Overwrite
og.setString(itemName);
// Load its stat history
mmoitem.setStatHistory(this, hist);
//NME//MMOItems.log("\u00a7b\u00a2\u00a2\u00a2\u00a77 Name History:");
//NME//hist.log();
}
}
}
}
}
}
@ -182,7 +302,7 @@ public class DisplayName extends StringStat {
@Override
public StatData getLoadedNBT(@NotNull ArrayList<ItemTag> storedTags) {
// You got a double righ
// You got a double right
ItemTag tg = ItemTag.getTagAtPath(getNBTPath(), storedTags);
// Found righ
@ -191,11 +311,27 @@ public class DisplayName extends StringStat {
// Get number
String value = (String) tg.getValue();
// Thats it
return new StringData(value);
// That's it
NameData nd = new NameData(value);
nd.readPrefixes(ItemTag.getTagAtPath(getNBTPath() + "_PRE", storedTags));
nd.readSuffixes(ItemTag.getTagAtPath(getNBTPath() + "_SUF", storedTags));
return nd;
}
// Fail
return null;
}
@NotNull
@Override
public StatData getClearStatData() {
return new NameData("");
}
@Override
public RandomStatData whenInitialized(Object object) {
return new NameData(object.toString());
}
}

View File

@ -16,4 +16,9 @@ public class KnockbackResistance extends AttributeStat {
"The chance of your item to block the", "knockback from explosions, creepers...", "1.0 corresponds to 100%, 0.7 to 70%..." },
Attribute.GENERIC_KNOCKBACK_RESISTANCE);
}
@Override
public double multiplyWhenDisplaying() {
return 100;
}
}

View File

@ -127,11 +127,8 @@ public class EnchantListData implements StatData, Mergeable {
clear();
//UPDT//MMOItems.log(" \u00a7b:\u00a73:\u00a7: \u00a77Trime Arcane Report: \u00a73-------------------------");
//UPDT//MMOItems.log(" \u00a73> \u00a77Cached:");
//UPDT//for (Enchantment e : cachedEnchantments.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + cachedEnchantments.getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73> \u00a77Ambiguous:");
//UPDT//for (Enchantment e : ambiguouslyOriginalEnchantmentCache.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ambiguouslyOriginalEnchantmentCache.getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73> \u00a77Output:");
//UPDT//for (Enchantment e : output.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + output.getLevel(e)); }
return;
}
@ -145,12 +142,8 @@ public class EnchantListData implements StatData, Mergeable {
output.merge(this);
//UPDT//MMOItems.log(" \u00a7b:\u00a73:\u00a7: \u00a77Trime Arcane Report: \u00a73-------------------------");
//UPDT//MMOItems.log(" \u00a73> \u00a77Cached:");
//UPDT//for (Enchantment e : cachedEnchantments.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + cachedEnchantments.getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73> \u00a77Ambiguous:");
//UPDT//for (Enchantment e : ambiguouslyOriginalEnchantmentCache.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + ambiguouslyOriginalEnchantmentCache.getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73> \u00a77Output:");
//UPDT//for (Enchantment e : output.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + output.getLevel(e)); }
return;
}
@ -192,8 +185,8 @@ public class EnchantListData implements StatData, Mergeable {
output.merge(processed);
//UPDT//MMOItems.log(" \u00a7b:\u00a73:\u00a7: \u00a77Trime Arcane Report: \u00a73-------------------------");
//UPDT//MMOItems.log(" \u00a73> \u00a77Cached:");
//UPDT//for (Enchantment e : cachedEnchantments.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + cachedEnchantments.getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73> \u00a77Output:");
//UPDT//for (Enchantment e : output.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + output.getLevel(e)); }
//UPDT//MMOItems.log(" \u00a73> \u00a77Processed:");
//UPDT//for (Enchantment e : processed.getEnchants()) { MMOItems.log(" \u00a7b * \u00a77" + e.getName() + " \u00a7f" + processed.getLevel(e)); }

View File

@ -14,6 +14,7 @@ public class StringData implements StatData, RandomStatData {
public void setString(String str) {
this.value = str;
}
public String getString() { return value; }
@Override
public String toString() {

View File

@ -59,8 +59,21 @@ public class StringListData implements StatData, RandomStatData, Mergeable {
}
@Override
public @NotNull StatData cloneData() { return new StringListData(getList()); }
@NotNull
public StatData cloneData() { return new StringListData(new ArrayList<>(getList())); }
@Override
public boolean isClear() { return getList().size() == 0; }
@Override
public String toString() {
StringBuilder b = new StringBuilder("\u00a77");
for (String str : getList()) {
if (b.length() > 0) { b.append("\u00a78;\u00a77 "); }
b.append(str);
}
return b.toString();
}
}

View File

@ -57,6 +57,13 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
return true;
}
/**
* @return For example knockback resistance, 0.01 = 1% so multiplies by 100 when displaying.
*/
public double multiplyWhenDisplaying() {
return 1;
}
/**
* Usually, a greater magnitude of stat benefits the player (more health, more attack damage).
* <p>However, its not impossible for a stat to be evil instead, who knows?
@ -110,15 +117,15 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
// Displaying upgrades?
if (upgradeShift != 0) {
item.getLore().insert(getPath(), formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter(), value)
item.getLore().insert(getPath(), formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter(), value * multiplyWhenDisplaying())
// Add upgrade format
+ MythicLib.plugin.parseColors(UpgradeTemplate.getUpgradeChangeSuffix(plus(upgradeShift) + (new StatFormat("##").format(upgradeShift)), !isGood(upgradeShift))));
+ MythicLib.plugin.parseColors(UpgradeTemplate.getUpgradeChangeSuffix(plus(upgradeShift * multiplyWhenDisplaying()) + (new StatFormat("##").format(upgradeShift * multiplyWhenDisplaying())), !isGood(upgradeShift * multiplyWhenDisplaying()))));
} else {
// Just display normally
item.getLore().insert(getPath(), formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter(), value));
item.getLore().insert(getPath(), formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter(), value * multiplyWhenDisplaying()));
} }
@ -181,10 +188,10 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
String builtRange;
if (SilentNumbers.round(techMinimum, 2) == SilentNumbers.round(techMaximum, 2)) {
builtRange = formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter(), techMaximum);
builtRange = formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter(), techMaximum * multiplyWhenDisplaying());
} else {
builtRange = formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter(), techMinimum, techMaximum); }
builtRange = formatPath(MMOItems.plugin.getLanguage().getStatFormat(getPath()), moreIsBetter(), techMinimum * multiplyWhenDisplaying(), techMaximum * multiplyWhenDisplaying()); }
// Just display normally
item.getLore().insert(getPath(), builtRange); }
@ -220,7 +227,8 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
}
@Override
public @NotNull ArrayList<ItemTag> getAppliedNBT(@NotNull StatData data) {
@NotNull
public ArrayList<ItemTag> getAppliedNBT(@NotNull StatData data) {
// Create Fresh
ArrayList<ItemTag> ret = new ArrayList<>();
@ -253,7 +261,8 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
}
}
@Override
public @Nullable StatData getLoadedNBT(@NotNull ArrayList<ItemTag> storedTags) {
@Nullable
public StatData getLoadedNBT(@NotNull ArrayList<ItemTag> storedTags) {
// You got a double righ
ItemTag tg = ItemTag.getTagAtPath(getNBTPath(), storedTags);
@ -261,11 +270,8 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
// Found righ
if (tg != null) {
// Get number
Double value = (Double) tg.getValue();
// Thats it
return new DoubleData(value);
return new DoubleData(SilentNumbers.round((Double) tg.getValue(), 4));
}
// Fail
@ -353,7 +359,7 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
}
@Override
public @NotNull StatData getClearStatData() {
@NotNull public StatData getClearStatData() {
return new DoubleData(0D);
}
@ -370,35 +376,36 @@ public class DoubleStat extends ItemStat implements Upgradable, Previewable {
public StatData apply(@NotNull StatData original, @NotNull UpgradeInfo info, int level) {
// Must be DoubleData
int i = level;
if (original instanceof DoubleData && info instanceof DoubleUpgradeInfo) {
// Get value
double value = ((DoubleData) original).getValue();
// If leveling up
if (level > 0) {
if (i > 0) {
// While still positive
while (level > 0) {
while (i > 0) {
// Apply PMP Operation Positively
value = ((DoubleUpgradeInfo) info).getPMP().apply(value);
// Decrease
level--;
i--;
}
// Degrading the item
} else if (level < 0) {
} else if (i < 0) {
// While still negative
while (level < 0) {
while (i < 0) {
// Apply PMP Operation Reversibly
value = ((DoubleUpgradeInfo) info).getPMP().reverse(value);
// Decrease
level++;
i++;
}
}

View File

@ -0,0 +1,147 @@
package net.Indyuce.mmoitems.stat.type;
import io.lumine.mythic.lib.api.item.ItemTag;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.stat.data.StringData;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
/**
* Data that stores what an item is originally named like and prefixes or whatever.
*/
public class NameData extends StringData implements Mergeable {
public NameData(@NotNull String str) {
super(str);
}
public void readPrefixes(@Nullable ItemTag tag) {
if (tag == null) { return; }
for (String str : ItemTag.getStringListFromTag(tag)) {
if (str == null) { continue; }
addPrefix(str);
}
}
@NotNull public String getMainName() { return getString(); }
public boolean hasPrefixes() { return prefixes.size() > 0; }
public boolean hasSuffixes() { return suffixes.size() > 0; }
/**
* @return The full, built name.
*/
@NotNull
public String bake() {
StringBuilder sb = new StringBuilder();
for (String prefix : getPrefixes()) { if (sb.length() > 0) { sb.append(" "); } sb.append(prefix); }
if (sb.length() > 0) { sb.append(" "); } sb.append(getMainName());
for (String suffix : getSuffixes()) { if (sb.length() > 0) { sb.append(" "); } sb.append(suffix); }
// Built
return sb.toString();
}
/**
* @return The built prefix
*/
@NotNull
public String bakePrefix() {
StringBuilder sb = new StringBuilder();
for (String prefix : getPrefixes()) { if (sb.length() > 0) { sb.append(" "); } sb.append(prefix); }
// Built
return sb.toString();
}
/**
* @return The full, built name.
*/
@NotNull
public String bakeSuffix() {
StringBuilder sb = new StringBuilder();
for (String suffix : getSuffixes()) { if (sb.length() > 0) { sb.append(" "); } sb.append(suffix); }
// Built
return sb.toString();
}
@Override
public String toString() {
return bake();
}
@NotNull public ItemTag compressPrefixes(@NotNull String path) {
return ItemTag.fromStringList(path, getPrefixes());
}
@NotNull public ItemTag compressSuffixes(@NotNull String path) {
return ItemTag.fromStringList(path, getSuffixes());
}
public void readSuffixes(@Nullable ItemTag tag) {
if (tag == null) { return; }
for (String str : ItemTag.getStringListFromTag(tag)) {
if (str == null) { continue; }
addSuffix(str);
}
}
@NotNull ArrayList<String> prefixes = new ArrayList<>();
public void addPrefix(@NotNull String str) { prefixes.add(str); }
public void clearPrefixes() { prefixes.clear(); }
@NotNull public ArrayList<String> getPrefixes() { return prefixes; }
@NotNull ArrayList<String> suffixes = new ArrayList<>();
public void addSuffix(@NotNull String str) { suffixes.add(str); }
public void clearSuffixes() { suffixes.clear(); }
@NotNull public ArrayList<String> getSuffixes() { return suffixes; }
@Override
public void merge(StatData data) {
// Assimilate
if (data instanceof NameData) {
// Replace name if not empty
if (!((NameData) data).getMainName().isEmpty()) { setString(((NameData) data).getMainName()); }
// Assimilate
for (String p : ((NameData) data).getPrefixes()) { addPrefix(p);}
for (String p : ((NameData) data).getSuffixes()) { addSuffix(p);}
} else if (data instanceof StringData) {
// Replace name if not empty
if (data.toString().isEmpty()) { return; }
setString(data.toString());
}
}
@NotNull
@Override
public StatData cloneData() {
NameData c = new NameData(getMainName());
for (String p : getPrefixes()) { c.addPrefix(p);}
for (String p : getSuffixes()) { c.addSuffix(p);}
return c;
}
@Override
public boolean isClear() {
return getMainName().isEmpty() && getPrefixes().size() == 0 && getSuffixes().size() == 0;
}
}

View File

@ -33,16 +33,20 @@ public class StatHistory {
/*
* Which stat is this the history of?
*/
@NotNull ItemStat itemStat;
@NotNull
ItemStat itemStat;
/**
* Which stat is this the history of?
*/
@NotNull public ItemStat getItemStat() { return itemStat; }
@NotNull
public ItemStat getItemStat() {
return itemStat;
}
/**
* @return Sure there is a Stat History and all but, does it
* actually have any information apart from the OG Data?
* actually have any information apart from the OG Data?
*/
public boolean isClear() {
@ -52,94 +56,152 @@ public class StatHistory {
* Its an important assumption in several methods
* like Enchants.separateEnchantments()
*/
if(getOriginalData() instanceof EnchantListData) {
if (getOriginalData() instanceof EnchantListData) {
if (((EnchantListData) getOriginalData()).getEnchants().size() != 0) {
//CLR//MMOItems.log("\u00a7a -+- \u00a77Found Enchantments, \u00a7cnot clear. \u00a78{\u00a77" + getItemStat().getId() + "\u00a78}");
return false;
} }
}
}
// Any gemstones or external SH? Then its NOT CLEAR
if (getAllGemstones().size() > 0 || getExternalData().size() > 0 || getModifiersBonus() != null) {
if (getAllGemstones().size() > 0 || getExternalData().size() > 0 || getAllModifiers().size() > 0) {
//CLR//MMOItems.log("\u00a7a -+- \u00a77Found Gemstones / ESH, \u00a7cnot clear. \u00a78{\u00a77" + getItemStat().getId() + "\u00a78}");
return false; }
return false;
}
// Is it clear?
if (((Mergeable) getOriginalData()).isClear() && (!isUpgradeable() || getMMOItem().getUpgradeLevel() == 0)) {
//CLR//MMOItems.log("\u00a7a -+- \u00a77Original data is clear & unupgraded, \u00a7aclear. \u00A73(\u00a78Upgradeable? \u00a7b" + isUpgradeable() + "\u00a78, Upgrade Level:\u00a7b " + getMMOItem().getUpgradeLevel() + "\u00a73) \u00a78{\u00a77" + getItemStat().getId() + "\u00a78}");
return true; }
return true;
}
// Exactly the same as the MMOItem? [This check should basically always be true though]
//CLR//if (getOriginalData().equals(getMMOItem().getData(getItemStat()))) { MMOItems.log("\u00a7a -+- \u00a77Original data has never been merged, \u00a7aclear. \u00a78{\u00a77" + getItemStat().getId() + "\u00a78}"); }
return getOriginalData().equals(getMMOItem().getData(getItemStat())); }
return getOriginalData().equals(getMMOItem().getData(getItemStat()));
}
/*
* What MMOItem is this StatHistory linked to?
*/
@NotNull MMOItem parent;
@NotNull
MMOItem parent;
/**
* What MMOItem is this StatHistory linked to?
*/
@NotNull public MMOItem getMMOItem() { return parent; }
@NotNull
public MMOItem getMMOItem() {
return parent;
}
/*
* The first value ever recorded of this stat, in this item.
* Presumably from when it was first generated.
*/
@NotNull StatData originalData;
@NotNull
StatData originalData;
/**
* The first value ever recorded of this stat, in this item.
* Presumably from when it was first generated.
*/
@NotNull public StatData getOriginalData() {
@NotNull
public StatData getOriginalData() {
//noinspection ConstantConditions
if (originalData == null) { setOriginalData(getItemStat().getClearStatData()); MMOItems.print(null, "Stat History for $e{0}$b in $u{1} {2}$b had null original data.", null, getItemStat().getId(), getMMOItem().getType().toString(), getMMOItem().getId()); }
return originalData; }
if (originalData == null) {
setOriginalData(getItemStat().getClearStatData());
MMOItems.print(null, "Stat History for $e{0}$b in $u{1} {2}$b had null original data.", null, getItemStat().getId(), getMMOItem().getType().toString(), getMMOItem().getId());
}
return originalData;
}
/**
* The first value ever recorded of this stat, in this item.
* Presumably from when it was first generated.
*/
public void setOriginalData(@NotNull StatData s) {
originalData = s;
}
/**
* The total bonus given by modifiers that
* were rolled when the item was first created.
*/
@Nullable StatData modifiersBonus;
/**
* @return The total bonus given by modifiers that
* were rolled when the item was first created.
*/
@Nullable public StatData getModifiersBonus() { return modifiersBonus; }
/**
* @param data The total bonus given by modifiers that
* were rolled when the item was first created.
*/
public void setModifiersBonus(@Nullable StatData data) { modifiersBonus = data; }
@NotNull
public HashMap<UUID, StatData> perModifierBonus = new HashMap<>();
/**
* The first value ever recorded of this stat, in this item.
* Presumably from when it was first generated.
* @return The total bonus given by modifiers that
* were rolled when the item was first created.
*/
public void setOriginalData(@NotNull StatData s) { originalData = s;}
@Contract("null -> null")
@Nullable
public StatData getModifiersBonus(@Nullable UUID of) {
if (of == null) {
return null;
}
return perModifierBonus.get(of);
}
/**
* @param of UUID to link this modifier to
* @param data The total bonus given by modifiers that
* were rolled when the item was first created.
*/
public void registerModifierBonus(@NotNull UUID of, @NotNull StatData data) {
perModifierBonus.put(of, data);
}
/**
* Removes the modifier of such UUID from those registered.
*
* @param of UUID of the modifier to remove.
*/
public void removeModifierBonus(@NotNull UUID of) {
perModifierBonus.remove(of);
}
/**
* All the Stat Datas provided by Modifiers
*/
@NotNull
public ArrayList<UUID> getAllModifiers() {
return new ArrayList<>(perModifierBonus.keySet());
}
/**
* Clears modifier data. No way to undo so be wary of using.
*/
public void clearModifiersBonus() { perModifierBonus.clear(); }
/*
* The final modifier being provided by each gemstone.
* GemStones may have scaled with upgrades, that will be accounted for.
*/
@NotNull public HashMap<UUID, StatData> perGemstoneData = new HashMap<>();
@NotNull
public HashMap<UUID, StatData> perGemstoneData = new HashMap<>();
/**
* The final modifier being provided by each gemstone.
* GemStones may have scaled with upgrades, that will be accounted for.
*/
@Contract("null -> null")
@Nullable public StatData getGemstoneData(@Nullable UUID of) { if (of == null) { return null; } return perGemstoneData.get(of); }
@Nullable
public StatData getGemstoneData(@Nullable UUID of) {
if (of == null) {
return null;
}
return perGemstoneData.get(of);
}
/**
* Removes the gem of such UUID from those registered.
*
* @param of UUID of the gem to remove.
*/
public void removeGemData(@NotNull UUID of) { perGemstoneData.remove(of); }
/**
* All the Stat Datas provided by GemStones
*/
@NotNull public ArrayList<UUID> getAllGemstones() { return new ArrayList<>(perGemstoneData.keySet()); }
@NotNull
public ArrayList<UUID> getAllGemstones() { return new ArrayList<>(perGemstoneData.keySet()); }
/**
* The final modifier being provided by each gemstone.
* GemStones may have scaled with upgrades, that will be accounted for.
@ -149,12 +211,17 @@ public class StatHistory {
* The value of this stat data will be <b><code>+5.5</code></b>
*/
public void registerGemstoneData(@NotNull UUID of, @NotNull StatData data) { perGemstoneData.put(of, data); }
/**
* Clears gemstone data. No way to undo so be wary of using.
*/
public void clearGemstones() { perGemstoneData.clear(); }
/*
* Modifiers of unknown origin.
* Presumably put here by external plugins I guess.
*/
@NotNull ArrayList<StatData> perExternalData = new ArrayList<>();
@NotNull
ArrayList<StatData> perExternalData = new ArrayList<>();
/**
* Modifiers of unknown origin.
@ -166,8 +233,28 @@ public class StatHistory {
* <p>They act as gem stones, adding together to produce the total of the item, but cannot be removed natively, since there is no way to tell them from each other.</p>
* Well, I guess whatever plugin is putting them here may remove them by editing the list directly with <code>StatHistory.getExternalData()</code>
*/
@NotNull public ArrayList<StatData> getExternalData() { return perExternalData; }
@NotNull
public ArrayList<StatData> getExternalData() { return perExternalData; }
/**
* Collapses all ExSH stat data into one.
*/
public void consolidateEXSH() {
// Create Clear
StatData theEXSH = getItemStat().getClearStatData();
// Merge All
for (StatData ex : getExternalData()) {
if (ex == null) {
continue;
}
((Mergeable) theEXSH).merge(ex);
}
// Clear and Register
getExternalData().clear();
registerExternalData(theEXSH);
}
/**
* Modifiers of unknown origin.
* Presumably put here by external plugins I guess.
@ -177,6 +264,10 @@ public class StatHistory {
* Well, I guess whatever plugin is putting them here may remove them by editing the list directly with <code>StatHistory.getExternalData()</code>
*/
public void registerExternalData(@NotNull StatData data) { perExternalData.add(data); }
/**
* Clears exsh data. No way to undo so be wary of using.
*/
public void clearExternalData() { perExternalData.clear(); }
/**
* Gets the stat history of this item. <b>The stat must be <code>Mergeable</code></b>
@ -213,6 +304,7 @@ public class StatHistory {
// Found? Thats it
if (hist != null) {
//UPGRD//MMOItems.log("Found Stat History of \u00a76" + ofStat.getNBTPath() + "\u00a77 in this \u00a7c" + ofItem.getType().getName() + " " + ofItem.getId());
//UPGRD//hist.log();
return hist; } }
// That is Mergeable right...
@ -229,7 +321,7 @@ public class StatHistory {
} else {
original = ((Mergeable) original).cloneData();
//UPGRD//MMOItems.log("\u00a7a +\u00a77 Found original data");
//UPGRD//MMOItems.log("\u00a7a +\u00a77 Found original data\u00a7f " + original);
}
//LVL//MMOItems.log(" \u00a7d*\u00a77-\u00a7a-\u00a763? \u00a77Lvl: \u00a7b" + ofItem.getUpgradeLevel() + "\u00a7d-\u00a77-\u00a7a-\u00a7d-\u00a77-\u00a7a-");
@ -403,12 +495,13 @@ public class StatHistory {
//DBL//if (ogCloned instanceof DoubleData) MMOItems.log("\u00a76 >\u00a77 Original Base: \u00a7e" + ((DoubleData) ogCloned).getValue() + "\u00a78 {Original:\u00a77 " + ((DoubleData) getOriginalData()).getValue() + "\u00a78}");
// Add Modifiers (who are affected by upgrades as if they was the base item data
if (getModifiersBonus() != null) {
for (UUID d : perModifierBonus.keySet()) {
//DBL//if (getModifiersBonus() instanceof DoubleData) MMOItems.log("\u00a76 >\u00a7c> \u00a77 Modifier Base: \u00a7e" + ((DoubleData) getModifiersBonus()).getValue());
// Just merge ig
((Mergeable) ogCloned).merge(((Mergeable) getModifiersBonus()).cloneData()); }
((Mergeable) ogCloned).merge(((Mergeable) getModifiersBonus(d)).cloneData());
}
// Level up
//RECALCULATE//MMOItems.log("\u00a76 ||\u00a77 Item Level: \u00a7e" + lvl);
StatData ret = ((Upgradable) getItemStat()).apply(ogCloned, inf, lvl);
@ -454,7 +547,7 @@ public class StatHistory {
//DBL//if (gRet instanceof DoubleData) MMOItems.log("\u00a76 \u00a7b|>\u00a77 Leveled Base: \u00a7e" + ((DoubleData) gRet).getValue());
// Merge
((Mergeable) ret).merge(gRet);
((Mergeable) ret).merge(((Mergeable) gRet).cloneData());
}
// Add up externals (who dont suffer upgrades
@ -488,21 +581,22 @@ public class StatHistory {
//DBL//if (ret instanceof DoubleData) MMOItems.log("\u00a73 > \u00a77 Original Base: \u00a7e" + ((DoubleData) ret).getValue());
// Add Modifiers
if (getModifiersBonus() != null) {
for (StatData d : perModifierBonus.values()) {
//DBL//if (getModifiersBonus() instanceof DoubleData) MMOItems.log("\u00a73 >\u00a7c> \u00a77 Modifier Base: \u00a7e" + ((DoubleData) getModifiersBonus()).getValue());
// Just merge ig
((Mergeable) ret).merge(((Mergeable) getModifiersBonus()).cloneData()); }
((Mergeable) ret).merge(((Mergeable) d).cloneData());
}
// Add up gemstones
for (StatData d : perGemstoneData.values()) {
//DBL//if (d instanceof DoubleData) MMOItems.log("\u00a73 >\u00a7b> \u00a77 Gemstone Base: \u00a7e" + ((DoubleData) d).getValue());
((Mergeable) ret).merge(d);
((Mergeable) ret).merge(((Mergeable) d).cloneData());
}
// Add up externals
for (StatData d : getExternalData()) {
//DBL//if (d instanceof DoubleData) MMOItems.log("\u00a73 >\u00a7c> \u00a77 Extraneous Base: \u00a7e" + ((DoubleData) d).getValue());
((Mergeable) ret).merge(d); }
((Mergeable) ret).merge(((Mergeable) d).cloneData()); }
// Return result
//DBL//if (ret instanceof DoubleData) MMOItems.log("\u00a73:::\u00a77 Result: \u00a7b" + ((DoubleData) ret).getValue());
@ -524,13 +618,13 @@ public class StatHistory {
object.addProperty(enc_Stat, getItemStat().getId());
// Original data
object.add(enc_OGS, ItemTag.compressTags(getItemStat().getAppliedNBT(getOriginalData())));
if (!((Mergeable) getOriginalData()).isClear()) { object.add(enc_OGS, ItemTag.compressTags(getItemStat().getAppliedNBT(getOriginalData()))); }
// Kompress Arrays
JsonArray gemz = new JsonArray();
// Compress I suppose
for (UUID gem : perGemstoneData.keySet()) {
for (UUID gem : getAllGemstones()) {
// As Json Object
JsonObject yes = new JsonObject();
@ -547,7 +641,8 @@ public class StatHistory {
}
// Include
object.add(enc_GSS, gemz);
if (gemz.size() > 0) { object.add(enc_GSS, gemz); }
// Kompress Arrays
JsonArray externals = new JsonArray();
@ -563,11 +658,31 @@ public class StatHistory {
}
// Include
object.add(enc_EXS, externals);
if (externals.size() > 0) { object.add(enc_EXS, externals); }
// Kompress Arrays
JsonArray modz = new JsonArray();
// Original data
if (getModifiersBonus() != null) {
object.add(enc_MOD, ItemTag.compressTags(getItemStat().getAppliedNBT(getModifiersBonus()))); }
for (UUID mod : getAllModifiers()) {
// As Json Object
JsonObject yes = new JsonObject();
// Compress tags
//noinspection ConstantConditions
JsonArray yesCompressed = ItemTag.compressTags(getItemStat().getAppliedNBT(getModifiersBonus(mod)));
// Put
yes.add(mod.toString(), yesCompressed);
// Actually Include
modz.add(yes);
}
// Include
if (modz.size() > 0) { object.add(enc_MOD, modz); }
return object;
}
@ -595,21 +710,21 @@ public class StatHistory {
// Get the stat we're searching for
JsonElement statEncode;
JsonElement ogStatsEncode;
JsonElement ogStatsEncode= null;
JsonElement gemsEncode = null;
JsonElement extEncode = null;
JsonElement modEncode = null;
// It has stat information right?
if (!json.has(enc_Stat)) { return null; } else { statEncode = json.get(enc_Stat); }
if (!json.has(enc_OGS)) { return null; } else { ogStatsEncode = json.get(enc_OGS); }
if (json.has(enc_Stat)) { statEncode = json.get(enc_Stat); } else { return null; }
if (json.has(enc_OGS)) { ogStatsEncode = json.get(enc_OGS); }
if (json.has(enc_GSS)) { gemsEncode = json.get(enc_GSS); }
if (json.has(enc_EXS)) { extEncode = json.get(enc_EXS); }
if (json.has(enc_MOD)) { modEncode = json.get(enc_MOD); }
// It is a primitive right
if (!statEncode.isJsonPrimitive()) { return null; }
if (!ogStatsEncode.isJsonArray()) { return null; }
if (ogStatsEncode != null && !ogStatsEncode.isJsonArray()) { return null; }
if (gemsEncode != null && !gemsEncode.isJsonArray()) { return null; }
if (extEncode != null && !extEncode.isJsonArray()) { return null; }
if (modEncode != null && !modEncode.isJsonArray()) { return null; }
@ -623,11 +738,20 @@ public class StatHistory {
// Nope
if (stat == null) { return null; }
// Decompress tags
ArrayList<ItemTag> ogDecoded = ItemTag.decompressTags(ogStatsEncode.getAsJsonArray());
// To know the stat it was
StatData sData = stat.getLoadedNBT(ogDecoded);
StatData sData;
if (ogStatsEncode != null) {
// Decompress tags
ArrayList<ItemTag> ogDecoded = ItemTag.decompressTags(ogStatsEncode.getAsJsonArray());
sData = stat.getLoadedNBT(ogDecoded);
// OG Not included (because its clear)
} else {
// Just generate as clear
sData = stat.getClearStatData();
}
// Validate non null
if (sData == null) { return null; }
@ -712,15 +836,51 @@ public class StatHistory {
//region Modifier History
if (modEncode != null) {
// Decompress tags
ArrayList<ItemTag> modDecoded = ItemTag.decompressTags(modEncode.getAsJsonArray());
// To know the stat it was
StatData modData = stat.getLoadedNBT(modDecoded);
// Set
sHistory.setModifiersBonus(modData); }
// Decompress gems
for (JsonElement elmnt : modEncode.getAsJsonArray()) {
// Must be an object
if (elmnt.isJsonObject()) {
// Get as Object
JsonObject element = elmnt.getAsJsonObject();
// Get map
Set<Map.Entry<String, JsonElement>> contained = element.entrySet();
// There should be exacly one but anyway;
for (Map.Entry<String, JsonElement> entry : contained) {
// Get path (Gemstone UUID)
String modUUID = entry.getKey();
// Attempt to parse gemuuid
UUID actualUUID = GemstoneData.UUIDFromString(modUUID);
// Get Stat compressed tag
JsonElement compressedTags = entry.getValue();
// Succeed?
if (compressedTags.isJsonArray() && actualUUID != null) {
// Continue...
ArrayList<ItemTag> tags = ItemTag.decompressTags(compressedTags.getAsJsonArray());
// Generate data
StatData modData = stat.getLoadedNBT(tags);
// Validated?
if (modData != null) {
// Add
sHistory.registerModifierBonus(actualUUID, modData);
}
}
}
}
}
}
//endregion
return sHistory;
@ -772,23 +932,31 @@ public class StatHistory {
//UPDT//MMOItems.log(" \u00a76:\u00a72: \u00a77Original Externals \u00a7f" + perExternalData.size());
// Register gemstones
for (UUID exUID : other.perGemstoneData.keySet()) {
for (UUID exUID : other.getAllGemstones()) {
//noinspection ConstantConditions
registerGemstoneData(exUID, other.getGemstoneData(exUID)); }
// Register externals
for (StatData ex : other.getExternalData()) { registerExternalData((ex)); }
// Modifier
setModifiersBonus(other.getModifiersBonus());
// Register modifiers
for (UUID exUID : other.getAllModifiers()) {
//noinspection ConstantConditions
registerModifierBonus(exUID, other.getModifiersBonus(exUID)); }
//UPDT//MMOItems.log(" \u00a76:\u00a72: \u00a77Final Gemstones \u00a7f" + perGemstoneData.size());
//UPDT//MMOItems.log(" \u00a76:\u00a72: \u00a77Final Externals \u00a7f" + perExternalData.size());
//ASS//MMOItems.log(" \u00a76:\u00a72: \u00a77Assimiliaton Result \u00a7f");
//ASS//log();
}
}
/**
* Clones this history but linked to another MMOItem
* Clones this history but linked to another MMOItem.
*
* It does not put it into the MMOItem, you must do that yourself.
*
* @see MMOItem#setStatHistory(ItemStat, StatHistory)
*
* @param clonedMMOItem Usually this is called when you are cloning the MMOItem itself,
* this is a reference to the new one.
@ -806,15 +974,27 @@ public class StatHistory {
if (!(gem instanceof Mergeable)) { continue; }
// Clone
res.registerGemstoneData(uid, ((Mergeable) gem).cloneData()); }
res.registerGemstoneData(uid, ((Mergeable) gem).cloneData());
}
// Add all
for (StatData ex : getExternalData()) {
if (!(ex instanceof Mergeable)) { continue; }
// Clone
res.registerExternalData(((Mergeable) ex).cloneData()); }
// Clone
if (getModifiersBonus() != null) { res.setModifiersBonus(((Mergeable) getModifiersBonus()).cloneData());}
for (UUID uid : getAllModifiers()) {
if (uid == null) { continue; }
StatData mod = getModifiersBonus(uid);
if (!(mod instanceof Mergeable)) { continue; }
// Clone
res.registerModifierBonus(uid, ((Mergeable) mod).cloneData());
}
// Thats it
return res;
@ -825,4 +1005,41 @@ public class StatHistory {
static final String enc_GSS = "Gemstory";
static final String enc_EXS = "Exstory";
static final String enc_MOD = "Mod";
/**
* Logs into the console. Dev Mehtod
*/
public void log() {
MMOItems.print(null, "\u00a76SH of \u00a7e" + getItemStat().getId() + "\u00a77, \u00a7b" + getMMOItem().getType() + " " + getMMOItem().getId(), null);
if (getOriginalData() instanceof StringListData) {
MMOItems.print(null, "\u00a7a++ Original", null);
for (String str : ((StringListData) getOriginalData()).getList()) { MMOItems.print(null, "\u00a7a ++\u00a77 " + str, null); }
MMOItems.print(null, "\u00a7e++ Gemstones", null);
for (UUID ui : getAllGemstones()) { StatData sd = getGemstoneData(ui); if (!(sd instanceof StringListData)) { continue; } for (String str : ((StringListData) sd).getList()) { MMOItems.print(null, "\u00a7e ++\u00a77 " + str, null); } }
MMOItems.print(null, "\u00a7c++ ExSH", null);
for (StatData sd : getExternalData()) { if (!(sd instanceof StringListData)) { continue; } for (String str : ((StringListData) sd).getList()) { MMOItems.print(null, "\u00a7e ++\u00a77 " + str, null); } }
MMOItems.print(null, "\u00a7d++ Modifiers", null);
for (UUID ui : getAllModifiers()) { StatData sd = getModifiersBonus(ui); if (!(sd instanceof StringListData)) { continue; } for (String str : ((StringListData) sd).getList()) { MMOItems.print(null, "\u00a7d ++\u00a77 " + str, null); } }
} else {
MMOItems.print(null, "\u00a7a-- Original", null);
MMOItems.print(null, "\u00a7a ++\u00a77 " + getOriginalData(), null);
MMOItems.print(null, "\u00a7e-- Gemstones", null);
for (UUID ui : getAllGemstones()) { StatData sd = getGemstoneData(ui); if (sd == null) { continue; } MMOItems.print(null, "\u00a7e ++\u00a77 " + sd, null);}
MMOItems.print(null, "\u00a7c-- ExSH", null);
for (StatData sd : getExternalData()) { if (sd == null) { continue; } MMOItems.print(null, "\u00a7e ++\u00a77 " + sd, null); }
MMOItems.print(null, "\u00a7d-- Modifiers", null);
for (UUID ui : getAllModifiers()) { StatData sd = getModifiersBonus(ui); if (sd == null) { continue; } MMOItems.print(null, "\u00a7d ++\u00a77 " + sd, null);}
}
}
}