mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2024-12-23 04:47:34 +01:00
Fixed abilities not transfering from gems
This commit is contained in:
parent
09b34d2123
commit
c1ecc198e3
@ -18,6 +18,7 @@ import net.Indyuce.mmoitems.api.interaction.GemStone;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
|
||||
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
|
||||
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
|
||||
import net.Indyuce.mmoitems.stat.Enchants;
|
||||
import net.Indyuce.mmoitems.stat.data.EnchantListData;
|
||||
@ -601,7 +602,7 @@ public class CustomSmithingRecipe extends MythicRecipeOutput {
|
||||
continue; }
|
||||
|
||||
// Ok proceed
|
||||
GemStone asGem = new GemStone(p, m.newBuilder().buildNBT());
|
||||
GemStone asGem = new GemStone(PlayerData.get(p), m.newBuilder().buildNBT());
|
||||
|
||||
// Put
|
||||
GemStone.ApplyResult res = asGem.applyOntoItem(gen, gen.getType(), "", false, true);
|
||||
|
@ -45,8 +45,7 @@ public class GemStone extends UseItem {
|
||||
* Entirely loads the MMOItem and checks if
|
||||
* it has the required empty socket for the gem
|
||||
*/
|
||||
MMOItem targetMMO = new LiveMMOItem(target);
|
||||
return applyOntoItem(targetMMO, targetType, MMOUtils.getDisplayName(target.getItem()), true, false);
|
||||
return applyOntoItem(new LiveMMOItem(target), targetType, MMOUtils.getDisplayName(target.getItem()), true, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@ -64,7 +63,7 @@ public class GemStone extends UseItem {
|
||||
|
||||
// Checks if the gem supports the item type, or the item set, or a weapon
|
||||
String appliableTypes = getNBTItem().getString(ItemStats.ITEM_TYPE_RESTRICTION.getNBTPath());
|
||||
if (!appliableTypes.equals("") && (!targetType.isWeapon() || !appliableTypes.contains("WEAPON"))
|
||||
if (!appliableTypes.isEmpty() && (!targetType.isWeapon() || !appliableTypes.contains("WEAPON"))
|
||||
&& !appliableTypes.contains(targetType.getId()))
|
||||
return new ApplyResult(ResultType.NONE);
|
||||
|
||||
@ -89,79 +88,29 @@ public class GemStone extends UseItem {
|
||||
return new ApplyResult(ResultType.FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* To not clear enchantments put by players
|
||||
*/
|
||||
// To not clear enchantments put by players
|
||||
Enchants.separateEnchantments(targetMMO);
|
||||
|
||||
/*
|
||||
* Gem stone can be successfully applied. apply stats then abilities and
|
||||
* permanent effects. also REGISTER gem stone in the item gem stone list.
|
||||
* Gemstone can be successfully applied. Apply stats then abilities and
|
||||
* permanent effects. also REGISTER gemstone in the item gemstone list.
|
||||
*/
|
||||
LiveMMOItem gemMMOItem = new LiveMMOItem(getNBTItem());
|
||||
GemstoneData gemData = new GemstoneData(gemMMOItem, foundSocketColor);
|
||||
|
||||
/*
|
||||
* Now must apply the gem sockets data to the Stat History and then recalculate.
|
||||
*
|
||||
* Gotta, however, find the correct StatData to which apply it to. Damn this can
|
||||
* be pretty complicated!
|
||||
* Gotta, however, find the correct StatData to which apply it to.
|
||||
*/
|
||||
StatHistory gemStory = StatHistory.from(targetMMO, ItemStats.GEM_SOCKETS);
|
||||
|
||||
// Original?
|
||||
if (((GemSocketsData) gemStory.getOriginalData()).getEmptySocket(gemType) != null) {
|
||||
//UPGRD//MMOItems.log("\u00a77Applied Gemstone @\u00a76Original\u00a77: \u00a73" + foundSocketColor);
|
||||
|
||||
// Charmer
|
||||
((GemSocketsData) gemStory.getOriginalData()).apply(gemType, gemData);
|
||||
|
||||
} else {
|
||||
|
||||
// Check Gem gems are not supported >:l. Check the modifiers ig
|
||||
boolean success = false;
|
||||
for (UUID uid : gemStory.getAllModifiers()) {
|
||||
|
||||
// Get that gem
|
||||
GemSocketsData registeredGemData = (GemSocketsData) gemStory.getModifiersBonus(uid);
|
||||
if (registeredGemData != null && registeredGemData.getEmptySocket(gemType) != null) {
|
||||
//UPGRD//MMOItems.log("\u00a77Applied Gemstone @\u00a76Gemstone\u00a77: \u00a73" + foundSocketColor);
|
||||
|
||||
// Charmer
|
||||
success = true;
|
||||
registeredGemData.apply(gemType, gemData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
|
||||
for (StatData extraneousGem : gemStory.getExternalData()) {
|
||||
|
||||
// Get that gem
|
||||
GemSocketsData registeredGemData = (GemSocketsData) extraneousGem;
|
||||
if (registeredGemData != null && registeredGemData.getEmptySocket(gemType) != null) {
|
||||
//UPGRD//MMOItems.log("\u00a77Applied Gemstone @\u00a76External\u00a77: \u00a73" + foundSocketColor);
|
||||
|
||||
// Charmer
|
||||
registeredGemData.apply(gemType, gemData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculate
|
||||
//HSY//MMOItems.log(" \u00a73-\u00a7a- \u00a77Gem Application Recalculation \u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-");
|
||||
findEmptySocket(gemStory, gemType, gemData);
|
||||
targetMMO.setData(ItemStats.GEM_SOCKETS, gemStory.recalculate(targetMMO.getUpgradeLevel()));
|
||||
//UPGRD//MMOItems.log("Applied Gemstone: \u00a73" + foundSocketColor);
|
||||
|
||||
/*
|
||||
* Get the item's level, important for the GemScalingStat
|
||||
*/
|
||||
Integer levelIdentified = null;
|
||||
final String scaling = gemMMOItem.hasData(ItemStats.GEM_UPGRADE_SCALING) ? gemMMOItem.getData(ItemStats.GEM_UPGRADE_SCALING).toString() : GemUpgradeScaling.defaultValue;
|
||||
//UPGRD//MMOItems.log("Scaling Identified: \u00a73" + scaling);
|
||||
switch (scaling) {
|
||||
case "HISTORIC":
|
||||
levelIdentified = 0;
|
||||
@ -169,32 +118,18 @@ public class GemStone extends UseItem {
|
||||
case "SUBSEQUENT":
|
||||
levelIdentified = targetMMO.getUpgradeLevel();
|
||||
break;
|
||||
case "NEVER":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gemData.setLevel(levelIdentified);
|
||||
//UPGRD//MMOItems.log("Set Level: \u00a7b" + gemData.getLevel());
|
||||
/*
|
||||
* Only applies NON PROPER and MERGEABLE item stats
|
||||
*/
|
||||
|
||||
// Only applies NON PROPER and MERGEABLE item stats
|
||||
for (ItemStat stat : gemMMOItem.getStats()) {
|
||||
if (stat instanceof GemStoneStat) continue;
|
||||
|
||||
// If it is not PROPER
|
||||
if (!(stat instanceof GemStoneStat)) {
|
||||
|
||||
// Get the stat data
|
||||
StatData data = gemMMOItem.getData(stat);
|
||||
|
||||
// If the data is MERGEABLE
|
||||
if (data instanceof Mergeable) {
|
||||
//UPGRD//MMOItems.log("\u00a79>>> \u00a77Gem-Merging \u00a7c" + stat.getNBTPath());
|
||||
|
||||
// Merge into it
|
||||
targetMMO.mergeData(stat, data, gemData.getHistoricUUID());
|
||||
}
|
||||
}
|
||||
final StatData data = gemMMOItem.getData(stat);
|
||||
if (data instanceof Mergeable)
|
||||
targetMMO.mergeData(stat, data, gemData.getHistoricUUID());
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
@ -204,11 +139,37 @@ public class GemStone extends UseItem {
|
||||
|
||||
if (buildStack)
|
||||
return new ApplyResult(targetMMO.newBuilder().build());
|
||||
|
||||
else
|
||||
return new ApplyResult(targetMMO, ResultType.SUCCESS);
|
||||
}
|
||||
|
||||
private void findEmptySocket(StatHistory socketHistory, String gemType, GemstoneData gemstone) {
|
||||
|
||||
// Og data
|
||||
GemSocketsData data = ((GemSocketsData) socketHistory.getOriginalData());
|
||||
if (data.apply(gemType, gemstone)) return;
|
||||
|
||||
// Modifiers
|
||||
for (UUID modifierId : socketHistory.getAllModifiers()) {
|
||||
data = (GemSocketsData) socketHistory.getModifiersBonus(modifierId);
|
||||
if (data.apply(gemType, gemstone)) return;
|
||||
}
|
||||
|
||||
// External
|
||||
for (StatData untypedData : socketHistory.getExternalData()) {
|
||||
data = (GemSocketsData) untypedData;
|
||||
if (data.apply(gemType, gemstone)) return;
|
||||
}
|
||||
|
||||
// Gems
|
||||
for (UUID gemId : socketHistory.getAllGemstones()) {
|
||||
data = (GemSocketsData) socketHistory.getGemstoneData(gemId);
|
||||
if (data.apply(gemType, gemstone)) return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("MMOItem contains available socket but not its socket stat history");
|
||||
}
|
||||
|
||||
public static class ApplyResult {
|
||||
@NotNull
|
||||
private final ResultType type;
|
||||
|
@ -168,7 +168,7 @@ public class ItemStackBuilder {
|
||||
builtMMOItem.setData(stat, s.recalculate(l));
|
||||
|
||||
// Add to NBT, if the gemstones were not purged
|
||||
if (!s.isClear()) {
|
||||
if (!s.isEmpty()) {
|
||||
|
||||
//GEM//MMOItems.log("\u00a7a -+- \u00a77Recording History");
|
||||
addItemTag(new ItemTag(history_keyword + stat.getId(), s.toNBTString()));
|
||||
|
@ -145,7 +145,7 @@ public class MMOItemBuilder extends Buildable<MMOItem> {
|
||||
*/
|
||||
public void applyData(@NotNull ItemStat stat, @NotNull StatData data) {
|
||||
final StatData found = mmoitem.getData(stat);
|
||||
if (found != null && found instanceof Mergeable) ((Mergeable) found).mergeWith(data);
|
||||
if (found != null && found instanceof Mergeable) ((Mergeable) found).mergeWith((Mergeable) data);
|
||||
else mmoitem.setData(stat, data);
|
||||
}
|
||||
|
||||
|
@ -27,204 +27,188 @@ import java.util.*;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class MMOItem implements ItemReference {
|
||||
private final Type type;
|
||||
private final String id;
|
||||
private final Type type;
|
||||
private final String id;
|
||||
|
||||
/**
|
||||
* Where data about all the item stats is stored. When the item is
|
||||
* generated, this map is read and all the stats are applied. The order in
|
||||
* which stats are added is not very important anymore
|
||||
*/
|
||||
@NotNull
|
||||
private final Map<ItemStat, StatData> stats = new HashMap<>();
|
||||
/**
|
||||
* Where data about all the item stats is stored. When the item is
|
||||
* generated, this map is read and all the stats are applied. The order in
|
||||
* which stats are added is not very important anymore
|
||||
*/
|
||||
@NotNull
|
||||
private final Map<ItemStat, StatData> stats = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructor used to generate an ItemStack based on some stat data
|
||||
*
|
||||
* @param type
|
||||
* The type of the item you want to create
|
||||
* @param id
|
||||
* The id of the item, make sure it is different from other
|
||||
* existing items not to interfere with MI features like the
|
||||
* dynamic item updater
|
||||
*/
|
||||
public MMOItem(Type type, String id) {
|
||||
this.type = type;
|
||||
this.id = id;
|
||||
}
|
||||
/**
|
||||
* Constructor used to generate an ItemStack based on some stat data
|
||||
*
|
||||
* @param type The type of the item you want to create
|
||||
* @param id The id of the item, make sure it is different from other
|
||||
* existing items not to interfere with MI features like the
|
||||
* dynamic item updater
|
||||
*/
|
||||
public MMOItem(Type type, String id) {
|
||||
this.type = type;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() { return type; }
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() { return id; }
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will merge that data into this item:
|
||||
* <p></p>
|
||||
* If the item does not have this stat yet, it will be set with <code>MMOItem.setData()</code>
|
||||
* <p>If this data is not <code>Mergeable</code>, it will also be set</p>
|
||||
* <p></p>
|
||||
* Otherwise, the data will be merged with the previous. If an UUID is provided, it will also be
|
||||
* stored as a GemStone in the history, allowing to be removed from the item with that same UUID.
|
||||
*/
|
||||
public void mergeData(@NotNull ItemStat stat, @NotNull StatData data, @Nullable UUID associatedGemStone) {
|
||||
//GEM//MMOItems.log("Merging stone stat \u00a76" + stat.getNBTPath() + "\u00a77 into \u00a7c" + getType().getName() + " " + getId());
|
||||
/**
|
||||
* Will merge that data into this item:
|
||||
* <p></p>
|
||||
* If the item does not have this stat yet, it will be set with <code>MMOItem.setData()</code>
|
||||
* <p>If this data is not <code>Mergeable</code>, it will also be set</p>
|
||||
* <p></p>
|
||||
* Otherwise, the data will be merged with the previous. If an UUID is provided, it will also be
|
||||
* stored as a GemStone in the history, allowing to be removed from the item with that same UUID.
|
||||
*/
|
||||
public void mergeData(@NotNull ItemStat stat, @NotNull StatData data, @Nullable UUID associatedGemStone) {
|
||||
boolean bc = stat.equals(ItemStats.ABILITIES);
|
||||
|
||||
// Do we already have the data?
|
||||
if (data instanceof Mergeable) {
|
||||
//GEM//MMOItems.log("\u00a7a + \u00a77Mergeable");
|
||||
// Merge if possible, otherwise write over
|
||||
if (data instanceof Mergeable) {
|
||||
|
||||
// Prepare to merge: Gather History (Also initializes the ORIGINAL stats)
|
||||
StatHistory sHistory = StatHistory.from(this, stat);
|
||||
// Prepare to merge, gather history
|
||||
StatHistory sHistory = StatHistory.from(this, stat);
|
||||
if (associatedGemStone != null) sHistory.registerGemstoneData(associatedGemStone, data);
|
||||
else sHistory.registerExternalData(data);
|
||||
setData(stat, sHistory.recalculate(getUpgradeLevel()));
|
||||
} else
|
||||
setData(stat, data);
|
||||
}
|
||||
|
||||
// As GemStone or as External?
|
||||
if (associatedGemStone != null) {
|
||||
//GEM//MMOItems.log(" \u00a79++\u00a77 As Gemstone \u00a7b" + associatedGemStone.toString());
|
||||
public void setData(@NotNull ItemStat stat, @NotNull StatData data) {
|
||||
stats.put(stat, data);
|
||||
}
|
||||
|
||||
// As GemStone
|
||||
sHistory.registerGemstoneData(associatedGemStone, data);
|
||||
public void replaceData(@NotNull ItemStat stat, @NotNull StatData data) {
|
||||
stats.replace(stat, data);
|
||||
}
|
||||
|
||||
// As External
|
||||
} else {
|
||||
//GEM//MMOItems.log(" \u00a7c++\u00a77 As External");
|
||||
public void removeData(@NotNull ItemStat stat) {
|
||||
stats.remove(stat);
|
||||
}
|
||||
|
||||
// As External, UUIDless modifier
|
||||
sHistory.registerExternalData(data);
|
||||
}
|
||||
public StatData getData(@NotNull ItemStat stat) {
|
||||
return stats.get(stat);
|
||||
}
|
||||
|
||||
// Recalculate
|
||||
//GEM//MMOItems.log(" \u00a76+++\u00a77 Recalculating...");
|
||||
//HSY//MMOItems.log(" \u00a73-\u00a7a- \u00a77Gem Application Recalculation \u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-\u00a73-\u00a7a-");
|
||||
setData(stat, sHistory.recalculate(getUpgradeLevel()));
|
||||
public boolean hasData(@NotNull ItemStat stat) {
|
||||
return (stats.get(stat) != null);
|
||||
}
|
||||
|
||||
// Merging means replacing if it cannot be merged
|
||||
} else {
|
||||
/**
|
||||
* @return Collection of all item stats which have some data on this mmoitem
|
||||
*/
|
||||
@NotNull
|
||||
public Set<ItemStat> getStats() {
|
||||
return stats.keySet();
|
||||
}
|
||||
//endregion
|
||||
|
||||
// Override Completely
|
||||
setData(stat, data);
|
||||
}
|
||||
}
|
||||
//region Building
|
||||
|
||||
public void setData(@NotNull ItemStat stat, @NotNull StatData data) {
|
||||
stats.put(stat, data);
|
||||
}
|
||||
/**
|
||||
* @return A class which lets you build this mmoitem into an ItemStack
|
||||
*/
|
||||
@NotNull
|
||||
public ItemStackBuilder newBuilder() {
|
||||
return new ItemStackBuilder(this);
|
||||
}
|
||||
|
||||
public void replaceData(@NotNull ItemStat stat, @NotNull StatData data) {
|
||||
stats.replace(stat, data);
|
||||
}
|
||||
/***
|
||||
* @return A cloned instance of this mmoitem. This does NOT clone the
|
||||
* StatData instances! If you edit these statDatas, the previous
|
||||
* mmoitem will be edited as well.
|
||||
*/
|
||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||
@Override
|
||||
public MMOItem clone() {
|
||||
MMOItem clone = new MMOItem(type, id);
|
||||
|
||||
public void removeData(@NotNull ItemStat stat) {
|
||||
stats.remove(stat);
|
||||
}
|
||||
// Clone them stats and histories
|
||||
for (ItemStat stat : stats.keySet()) {
|
||||
|
||||
public StatData getData(@NotNull ItemStat stat) {
|
||||
return stats.get(stat);
|
||||
}
|
||||
// Copy Stat Datas themselves
|
||||
clone.stats.put(stat, stats.get(stat));
|
||||
|
||||
public boolean hasData(@NotNull ItemStat stat) { return (stats.get(stat) != null); }
|
||||
// Copy Histories
|
||||
StatHistory hist = getStatHistory(stat);
|
||||
if (hist != null) {
|
||||
final StatHistory histClone = hist.clone();
|
||||
histClone.setParent(clone);
|
||||
clone.setStatHistory(stat, histClone);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection of all item stats which have some data on this mmoitem
|
||||
*/
|
||||
@NotNull public Set<ItemStat> getStats() {
|
||||
return stats.keySet();
|
||||
}
|
||||
//endregion
|
||||
// Thats it
|
||||
return clone;
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region Building and such
|
||||
/**
|
||||
* @return A class which lets you build this mmoitem into an ItemStack
|
||||
*/
|
||||
@NotNull public ItemStackBuilder newBuilder() {
|
||||
return new ItemStackBuilder(this);
|
||||
}
|
||||
//region Stat History Stuff
|
||||
/*
|
||||
* When merging stats (like applying a gemstone), the item must remember which were
|
||||
* its original stats, and from which gem stone came each stat, in order to allow
|
||||
* removal of gem stones in the future. This is where that is remembered.
|
||||
*/
|
||||
@NotNull
|
||||
private final Map<ItemStat, StatHistory> mergeableStatHistory = new HashMap<>();
|
||||
|
||||
/***
|
||||
* @return A cloned instance of this mmoitem. This does NOT clone the
|
||||
* StatData instances! If you edit these statDatas, the previous
|
||||
* mmoitem will be edited as well.
|
||||
*/
|
||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||
@Override
|
||||
public MMOItem clone() {
|
||||
MMOItem clone = new MMOItem(type, id);
|
||||
/**
|
||||
* Gets the history associated to this stat, if there is any
|
||||
* <p></p>
|
||||
* A stat history is basically the memory of its original stats,
|
||||
* from when it was created, its gemstone stats,
|
||||
* those added by which gem, and its upgrade bonuses.
|
||||
*/
|
||||
@Nullable
|
||||
public StatHistory getStatHistory(@NotNull ItemStat stat) {
|
||||
|
||||
// Clone them stats and histories
|
||||
for (ItemStat stat : stats.keySet()) {
|
||||
/*
|
||||
* As an assumption for several enchantment recognition operations,
|
||||
* Enchantment data must never be clear and lack history. This is
|
||||
* the basis for when an item is 'old'
|
||||
*/
|
||||
if (stat instanceof Enchants)
|
||||
return mergeableStatHistory.getOrDefault(stat, StatHistory.from(this, stat, true));
|
||||
|
||||
// Copy Stat Datas themselves
|
||||
clone.stats.put(stat, stats.get(stat));
|
||||
/*
|
||||
* Normal stat, just fetch.
|
||||
*/
|
||||
try {
|
||||
|
||||
// Copy Histories
|
||||
StatHistory hist = getStatHistory(stat);
|
||||
if (hist != null) {
|
||||
final StatHistory histClone = hist.clone();
|
||||
histClone.setParent(clone);
|
||||
clone.setStatHistory(stat, histClone);
|
||||
}
|
||||
}
|
||||
// Well that REALLY should work
|
||||
return mergeableStatHistory.get(stat);
|
||||
|
||||
// Thats it
|
||||
return clone;
|
||||
}
|
||||
//endregion
|
||||
} catch (ClassCastException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//region Stat History Stuff
|
||||
/*
|
||||
* When merging stats (like applying a gemstone), the item must remember which were
|
||||
* its original stats, and from which gem stone came each stat, in order to allow
|
||||
* removal of gem stones in the future. This is where that is remembered.
|
||||
*/
|
||||
@NotNull
|
||||
private final Map<ItemStat, StatHistory> mergeableStatHistory = new HashMap<>();
|
||||
@NotNull
|
||||
public ArrayList<StatHistory> getStatHistories() {
|
||||
return new ArrayList<>(mergeableStatHistory.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the history associated to this stat, if there is any
|
||||
* <p></p>
|
||||
* A stat history is basically the memmory of its original stats,
|
||||
* from when it was created, its gem stone stats,
|
||||
* those added by which gem, and its upgrade bonuses.
|
||||
*/
|
||||
@Nullable
|
||||
public StatHistory getStatHistory(@NotNull ItemStat stat) {
|
||||
|
||||
/*
|
||||
* As an assumption for several enchantment recognition operations,
|
||||
* Enchantment data must never be clear and lack history. This is
|
||||
* the basis for when an item is 'old'
|
||||
*/
|
||||
if (stat instanceof Enchants)
|
||||
return mergeableStatHistory.getOrDefault(stat, StatHistory.from(this, stat, true));
|
||||
|
||||
/*
|
||||
* Normal stat, just fetch.
|
||||
*/
|
||||
try {
|
||||
|
||||
// Well that REALLY should work
|
||||
return mergeableStatHistory.get(stat);
|
||||
|
||||
} catch (ClassCastException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ArrayList<StatHistory> getStatHistories() {
|
||||
return new ArrayList<>(mergeableStatHistory.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the history associated to this stat.
|
||||
* <p></p>
|
||||
* A stat history is basically the memory of its original stats,
|
||||
* from when it was created, its gemstone stats, those
|
||||
* added by which gem, and its upgrade bonuses.
|
||||
*/
|
||||
public void setStatHistory(@NotNull ItemStat stat, @NotNull StatHistory hist) {
|
||||
mergeableStatHistory.put(stat, hist);
|
||||
}
|
||||
/**
|
||||
* Sets the history associated to this stat.
|
||||
* <p></p>
|
||||
* A stat history is basically the memory of its original stats,
|
||||
* from when it was created, its gemstone stats, those
|
||||
* added by which gem, and its upgrade bonuses.
|
||||
*/
|
||||
public void setStatHistory(@NotNull ItemStat stat, @NotNull StatHistory hist) {
|
||||
mergeableStatHistory.put(stat, hist);
|
||||
}
|
||||
|
||||
//region Other API
|
||||
|
||||
@ -246,272 +230,265 @@ public class MMOItem implements ItemReference {
|
||||
return found != null ? MMOItems.plugin.getLore().getTooltip(found.toString()) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A MMOItem from the template only has damage
|
||||
* from the ITEM_DAMAGE stat
|
||||
*
|
||||
* @return The damage suffered by this item
|
||||
*/
|
||||
@Deprecated
|
||||
public int getDamage() {
|
||||
/**
|
||||
* A MMOItem from the template only has damage
|
||||
* from the ITEM_DAMAGE stat
|
||||
*
|
||||
* @return The damage suffered by this item
|
||||
*/
|
||||
@Deprecated
|
||||
public int getDamage() {
|
||||
|
||||
// Does it use MMO Durability?
|
||||
int maxDurability = hasData(ItemStats.MAX_DURABILITY) ? SilentNumbers.round(((DoubleData) getData(ItemStats.MAX_DURABILITY)).getValue()) : -1;
|
||||
// Does it use MMO Durability?
|
||||
int maxDurability = hasData(ItemStats.MAX_DURABILITY) ? SilentNumbers.round(((DoubleData) getData(ItemStats.MAX_DURABILITY)).getValue()) : -1;
|
||||
|
||||
if (maxDurability > 0) {
|
||||
if (maxDurability > 0) {
|
||||
|
||||
// Apparently we must do this
|
||||
NBTItem nbtItem = newBuilder().buildNBT();
|
||||
// Apparently we must do this
|
||||
NBTItem nbtItem = newBuilder().buildNBT();
|
||||
|
||||
// Durability
|
||||
int durability = hasData(ItemStats.CUSTOM_DURABILITY) ? SilentNumbers.round(((DoubleData) getData(ItemStats.CUSTOM_DURABILITY)).getValue()) : maxDurability;
|
||||
// Durability
|
||||
int durability = hasData(ItemStats.CUSTOM_DURABILITY) ? SilentNumbers.round(((DoubleData) getData(ItemStats.CUSTOM_DURABILITY)).getValue()) : maxDurability;
|
||||
|
||||
// Damage is the difference between max and current durability
|
||||
return maxDurability - durability;
|
||||
// Damage is the difference between max and current durability
|
||||
return maxDurability - durability;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
// Use vanilla durability
|
||||
return hasData(ItemStats.ITEM_DAMAGE) ? SilentNumbers.round(((DoubleData) getData(ItemStats.ITEM_DAMAGE)).getValue()) : 0;
|
||||
}
|
||||
}
|
||||
// Use vanilla durability
|
||||
return hasData(ItemStats.ITEM_DAMAGE) ? SilentNumbers.round(((DoubleData) getData(ItemStats.ITEM_DAMAGE)).getValue()) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A MMOItem from the template only has damage
|
||||
* from the ITEM_DAMAGE stat
|
||||
*
|
||||
* @param damage The damage suffered by this item
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDamage(int damage) {
|
||||
/**
|
||||
* A MMOItem from the template only has damage
|
||||
* from the ITEM_DAMAGE stat
|
||||
*
|
||||
* @param damage The damage suffered by this item
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDamage(int damage) {
|
||||
|
||||
// Too powerful
|
||||
if (hasData(ItemStats.UNBREAKABLE)) { return; }
|
||||
// Too powerful
|
||||
if (hasData(ItemStats.UNBREAKABLE)) return;
|
||||
|
||||
// Does it use MMO Durability?
|
||||
int maxDurability = hasData(ItemStats.MAX_DURABILITY) ? SilentNumbers.round(((DoubleData) getData(ItemStats.MAX_DURABILITY)).getValue()) : -1;
|
||||
// Does it use MMO Durability?
|
||||
int maxDurability = hasData(ItemStats.MAX_DURABILITY) ? SilentNumbers.round(((DoubleData) getData(ItemStats.MAX_DURABILITY)).getValue()) : -1;
|
||||
|
||||
if (maxDurability > 0) {
|
||||
if (maxDurability > 0) {
|
||||
|
||||
// Apparently we must do this
|
||||
NBTItem nbtItem = newBuilder().buildNBT();
|
||||
// Apparently we must do this
|
||||
NBTItem nbtItem = newBuilder().buildNBT();
|
||||
|
||||
// Durability
|
||||
setData(ItemStats.CUSTOM_DURABILITY, new DoubleData(maxDurability - damage));
|
||||
// Durability
|
||||
setData(ItemStats.CUSTOM_DURABILITY, new DoubleData(maxDurability - damage));
|
||||
|
||||
// Scale damage
|
||||
Material mat = hasData(ItemStats.MATERIAL) ? ((MaterialData) getData(ItemStats.MATERIAL)).getMaterial() : Material.GOLD_INGOT;
|
||||
double multiplier = ((double) damage) * ((double) mat.getMaxDurability()) / ((double) maxDurability);
|
||||
if (multiplier == 0) { return; }
|
||||
// Scale damage
|
||||
Material mat = hasData(ItemStats.MATERIAL) ? ((MaterialData) getData(ItemStats.MATERIAL)).getMaterial() : Material.GOLD_INGOT;
|
||||
double multiplier = ((double) damage) * ((double) mat.getMaxDurability()) / ((double) maxDurability);
|
||||
if (multiplier == 0) return;
|
||||
|
||||
// Set to some decent amount of damage
|
||||
setData(ItemStats.ITEM_DAMAGE, new DoubleData(multiplier));
|
||||
// Set to some decent amount of damage
|
||||
setData(ItemStats.ITEM_DAMAGE, new DoubleData(multiplier));
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
// Use vanilla durability
|
||||
setData(ItemStats.ITEM_DAMAGE, new DoubleData(damage));
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
// Use vanilla durability
|
||||
setData(ItemStats.ITEM_DAMAGE, new DoubleData(damage));
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region Upgrading API
|
||||
//region Upgrading API
|
||||
|
||||
/**
|
||||
* Upgrades this MMOItem one level.
|
||||
* <p></p>
|
||||
* <b>Make sure to check {@link #hasUpgradeTemplate()} before calling.</b>
|
||||
*/
|
||||
public void upgrade() {
|
||||
/**
|
||||
* Upgrades this MMOItem one level.
|
||||
* <p></p>
|
||||
* <b>Make sure to check {@link #hasUpgradeTemplate()} before calling.</b>
|
||||
*/
|
||||
public void upgrade() {
|
||||
|
||||
// Upgrade through the template's API
|
||||
getUpgradeTemplate().upgrade(this);
|
||||
}
|
||||
// Upgrade through the template's API
|
||||
getUpgradeTemplate().upgrade(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this item has all the information
|
||||
* required to call
|
||||
*/
|
||||
public boolean hasUpgradeTemplate() {
|
||||
return hasData(ItemStats.UPGRADE) && ((UpgradeData) getData(ItemStats.UPGRADE)).getTemplate() != null;
|
||||
}
|
||||
/**
|
||||
* Whether or not this item has all the information
|
||||
* required to call
|
||||
*/
|
||||
public boolean hasUpgradeTemplate() {
|
||||
return hasData(ItemStats.UPGRADE) && ((UpgradeData) getData(ItemStats.UPGRADE)).getTemplate() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The upgrade level, or 0 if there is none.
|
||||
*/
|
||||
public int getUpgradeLevel() {
|
||||
return hasData(ItemStats.UPGRADE) ? ((UpgradeData) getData(ItemStats.UPGRADE)).getLevel() : 0;
|
||||
}
|
||||
/**
|
||||
* @return The upgrade level, or 0 if there is none.
|
||||
*/
|
||||
public int getUpgradeLevel() {
|
||||
return hasData(ItemStats.UPGRADE) ? ((UpgradeData) getData(ItemStats.UPGRADE)).getLevel() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The upgrade level, or 0 if there is none.
|
||||
*/
|
||||
public int getMaxUpgradeLevel() {
|
||||
/**
|
||||
* @return The upgrade level, or 0 if there is none.
|
||||
*/
|
||||
public int getMaxUpgradeLevel() {
|
||||
|
||||
// Does it have Upgrade Data?
|
||||
if (hasData(ItemStats.UPGRADE)) {
|
||||
// Does it have Upgrade Data?
|
||||
if (hasData(ItemStats.UPGRADE)) {
|
||||
|
||||
// Return the registered level.
|
||||
return ((UpgradeData) getData(ItemStats.UPGRADE)).getMax();
|
||||
}
|
||||
// Return the registered level.
|
||||
return ((UpgradeData) getData(ItemStats.UPGRADE)).getMax();
|
||||
}
|
||||
|
||||
// Nope? Well its level 0 I guess.
|
||||
return 0;
|
||||
}
|
||||
// Nope? Well its level 0 I guess.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Make sure to check {@link #hasUpgradeTemplate()} before calling.</b>
|
||||
* <p></p>
|
||||
* This will fail and throw an exception if the MMOItem has no upgrade template.
|
||||
* @return The upgrade template by which the MMOItem would upgrade normally.
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull public UpgradeTemplate getUpgradeTemplate() {
|
||||
Validate.isTrue(hasUpgradeTemplate(), "Item has no upgrade information");
|
||||
/**
|
||||
* <b>Make sure to check {@link #hasUpgradeTemplate()} before calling.</b>
|
||||
* <p></p>
|
||||
* This will fail and throw an exception if the MMOItem has no upgrade template.
|
||||
*
|
||||
* @return The upgrade template by which the MMOItem would upgrade normally.
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@NotNull
|
||||
public UpgradeTemplate getUpgradeTemplate() {
|
||||
Validate.isTrue(hasUpgradeTemplate(), "Item has no upgrade information");
|
||||
|
||||
// All Right
|
||||
UpgradeData data = (UpgradeData) getData(ItemStats.UPGRADE);
|
||||
// All Right
|
||||
UpgradeData data = (UpgradeData) getData(ItemStats.UPGRADE);
|
||||
|
||||
// That's the template
|
||||
return data.getTemplate();
|
||||
}
|
||||
// That's the template
|
||||
return data.getTemplate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of GemStones inserted into this item
|
||||
*/
|
||||
@NotNull
|
||||
public Set<GemstoneData> getGemStones() {
|
||||
@NotNull
|
||||
public List<GemstoneData> getGemstones() {
|
||||
final StatData data = getData(ItemStats.GEM_SOCKETS);
|
||||
return data == null ? new ArrayList<>() : ((GemSocketsData) data).getGems();
|
||||
}
|
||||
|
||||
// Got gem sockets?
|
||||
if (hasData(ItemStats.GEM_SOCKETS)) {
|
||||
/**
|
||||
* @see #getGemstones()
|
||||
*/
|
||||
@Deprecated
|
||||
public Set<GemstoneData> getGemStones() {
|
||||
return new HashSet<>(getGemstones());
|
||||
}
|
||||
//endregion
|
||||
|
||||
// Get Data
|
||||
GemSocketsData data = (GemSocketsData) getData(ItemStats.GEM_SOCKETS);
|
||||
//region Gem Sockets API
|
||||
|
||||
// Thats it
|
||||
return data.getGemstones();
|
||||
/**
|
||||
* It is not 100% fool-proof, since some GemStones just don't have
|
||||
* enough information to be extracted (legacy gemstones).
|
||||
* <p></p>
|
||||
* Note that this is somewhat an expensive operation, restrain
|
||||
* from calling it much because it completely loads all the stats
|
||||
* of every Gem Stone.
|
||||
*
|
||||
* @return The list of GemStones contained here.
|
||||
*/
|
||||
@NotNull
|
||||
public List<Pair<GemstoneData, MMOItem>> extractGemstones() {
|
||||
|
||||
// Has no gem sockets
|
||||
} else {
|
||||
// Found?
|
||||
final @Nullable GemSocketsData thisSocketsData = (GemSocketsData) getData(ItemStats.GEM_SOCKETS);
|
||||
if (thisSocketsData == null)
|
||||
return new ArrayList<>();
|
||||
|
||||
// Empty Set
|
||||
return new HashSet<>();
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
// Find restored items
|
||||
final List<Pair<GemstoneData, MMOItem>> pairs = new ArrayList<>();
|
||||
for (GemstoneData gem : thisSocketsData.getGemstones()) {
|
||||
final MMOItem restored = MMOItems.plugin.getMMOItem(MMOItems.plugin.getTypes().get(gem.getMMOItemType()), gem.getMMOItemID());
|
||||
if (restored != null)
|
||||
pairs.add(Pair.of(gem, restored));
|
||||
}
|
||||
|
||||
//region Gem Sockets API
|
||||
// If RevID updating, no need to identify stats
|
||||
if (MMOItemReforger.gemstonesRevIDWhenUnsocket)
|
||||
return pairs;
|
||||
|
||||
/**
|
||||
* It is not 100% fool proof, since some GemStones just don't have
|
||||
* enough information to be extracted (legacy gemstones).
|
||||
* <p></p>
|
||||
* Note that this is somewhat an expensive operation, restrain
|
||||
* from calling it much because it completely loads all the stats
|
||||
* of every Gem Stone.
|
||||
*
|
||||
* @return The list of GemStones contained here.
|
||||
*/
|
||||
@NotNull
|
||||
public List<Pair<GemstoneData, MMOItem>> extractGemstones() {
|
||||
// Identify actual stats
|
||||
for (StatHistory hist : mergeableStatHistory.values())
|
||||
for (Pair<GemstoneData, MMOItem> gem : pairs) {
|
||||
final StatData historicGemData = hist.getGemstoneData(gem.getKey().getHistoricUUID());
|
||||
if (historicGemData != null)
|
||||
gem.getValue().setData(hist.getItemStat(), historicGemData);
|
||||
}
|
||||
|
||||
// Found?
|
||||
final @Nullable GemSocketsData thisSocketsData = (GemSocketsData) getData(ItemStats.GEM_SOCKETS);
|
||||
if (thisSocketsData == null)
|
||||
return new ArrayList<>();
|
||||
return pairs;
|
||||
}
|
||||
|
||||
// Find restored items
|
||||
final List<Pair<GemstoneData, MMOItem>> pairs = new ArrayList<>();
|
||||
for (GemstoneData gem : thisSocketsData.getGemstones()) {
|
||||
final MMOItem restored = MMOItems.plugin.getMMOItem(MMOItems.plugin.getTypes().get(gem.getMMOItemType()), gem.getMMOItemID());
|
||||
if (restored != null)
|
||||
pairs.add(Pair.of(gem, restored));
|
||||
}
|
||||
/**
|
||||
* Extracts a single gemstone. Note that this only builds the original Gemstone MMOItem, and if you
|
||||
* wish to actually remove the GemStone, you must do so through {@link #removeGemStone(UUID, String)}
|
||||
*
|
||||
* @param gem Gemstone that you believe is in here
|
||||
* @return The gemstone as it was when inserted, or <code>null</code>
|
||||
* if such gemstone is not in here.
|
||||
* @see #extractGemstones() More optimized method for extracting all gemstones at the same time.
|
||||
*/
|
||||
@Nullable
|
||||
public MMOItem extractGemstone(@NotNull GemstoneData gem) {
|
||||
|
||||
// If RevID updating, no need to identify stats
|
||||
if (MMOItemReforger.gemstonesRevIDWhenUnsocket)
|
||||
return pairs;
|
||||
final MMOItem restored = MMOItems.plugin.getMMOItem(MMOItems.plugin.getTypes().get(gem.getMMOItemType()), gem.getMMOItemID());
|
||||
if (restored == null)
|
||||
return null;
|
||||
|
||||
// Identify actual stats
|
||||
for (StatHistory hist : mergeableStatHistory.values())
|
||||
for (Pair<GemstoneData, MMOItem> gem : pairs) {
|
||||
final StatData historicGemData = hist.getGemstoneData(gem.getKey().getHistoricUUID());
|
||||
if (historicGemData != null)
|
||||
gem.getValue().setData(hist.getItemStat(), historicGemData);
|
||||
}
|
||||
// If RevID updating, no need to identify stats
|
||||
if (MMOItemReforger.gemstonesRevIDWhenUnsocket)
|
||||
return restored;
|
||||
|
||||
return pairs;
|
||||
}
|
||||
// Identify actual stats
|
||||
for (StatHistory hist : mergeableStatHistory.values()) {
|
||||
final StatData historicGemData = hist.getGemstoneData(gem.getHistoricUUID());
|
||||
if (historicGemData != null)
|
||||
restored.setData(hist.getItemStat(), historicGemData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a single gemstone. Note that this only builds the original Gemstone MMOItem, and if you
|
||||
* wish to actually remove the GemStone, you must do so through {@link #removeGemStone(UUID, String)}
|
||||
*
|
||||
* @param gem Gemstone that you believe is in here
|
||||
* @return The gemstone as it was when inserted, or <code>null</code>
|
||||
* if such gemstone is not in here.
|
||||
* @see #extractGemstones() More optimized method for extracting all gemstones at the same time.
|
||||
*/
|
||||
@Nullable
|
||||
public MMOItem extractGemstone(@NotNull GemstoneData gem) {
|
||||
return restored;
|
||||
}
|
||||
|
||||
final MMOItem restored = MMOItems.plugin.getMMOItem(MMOItems.plugin.getTypes().get(gem.getMMOItemType()), gem.getMMOItemID());
|
||||
if (restored == null)
|
||||
return null;
|
||||
/**
|
||||
* 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} to not restore socket.
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void removeGemStone(@NotNull UUID gemUUID, @Nullable String color) {
|
||||
|
||||
// If RevID updating, no need to identify stats
|
||||
if (MMOItemReforger.gemstonesRevIDWhenUnsocket)
|
||||
return restored;
|
||||
// Get gemstone data
|
||||
if (!hasData(ItemStats.GEM_SOCKETS))
|
||||
return;
|
||||
|
||||
// Identify actual stats
|
||||
for (StatHistory hist : mergeableStatHistory.values()) {
|
||||
final StatData historicGemData = hist.getGemstoneData(gem.getHistoricUUID());
|
||||
if (historicGemData != null)
|
||||
restored.setData(hist.getItemStat(), historicGemData);
|
||||
}
|
||||
//GEM//MMOItems.log("\u00a7b-\u00a78-\u00a79-\u00a77 Extracting \u00a7e" + gemUUID.toString());
|
||||
StatHistory gemStory = StatHistory.from(this, ItemStats.GEM_SOCKETS);
|
||||
|
||||
return restored;
|
||||
}
|
||||
/*
|
||||
* We must only find the StatData where this gem resides,
|
||||
* and eventually the StatHistories of the affected stats
|
||||
* will purge themselves from extraneous gems (that are
|
||||
* no longer registered onto the GEM_SOCKETS history).
|
||||
*/
|
||||
if (((GemSocketsData) gemStory.getOriginalData()).removeGem(gemUUID, color))
|
||||
return;
|
||||
|
||||
/**
|
||||
* 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} to not restore socket.
|
||||
*/
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void removeGemStone(@NotNull UUID gemUUID, @Nullable String color) {
|
||||
// Attempt gems
|
||||
for (UUID gemDataUUID : gemStory.getAllGemstones())
|
||||
if (((GemSocketsData) gemStory.getGemstoneData(gemDataUUID)).removeGem(gemUUID, color))
|
||||
return;
|
||||
|
||||
// Get gemstone data
|
||||
if (!hasData(ItemStats.GEM_SOCKETS))
|
||||
return;
|
||||
// Attempt externals
|
||||
for (StatData externalData : gemStory.getExternalData())
|
||||
if (((GemSocketsData) externalData).removeGem(gemUUID, color))
|
||||
return;
|
||||
|
||||
//GEM//MMOItems.log("\u00a7b-\u00a78-\u00a79-\u00a77 Extracting \u00a7e" + gemUUID.toString());
|
||||
StatHistory gemStory = StatHistory.from(this, ItemStats.GEM_SOCKETS);
|
||||
|
||||
/*
|
||||
* We must only find the StatData where this gem resides,
|
||||
* and eventually the StatHistories of the affected stats
|
||||
* will purge themselves from extraneous gems (that are
|
||||
* no longer registered onto the GEM_SOCKETS history).
|
||||
*/
|
||||
if (((GemSocketsData) gemStory.getOriginalData()).removeGem(gemUUID, color))
|
||||
return;
|
||||
|
||||
// Attempt gems
|
||||
for (UUID gemDataUUID : gemStory.getAllGemstones())
|
||||
if (((GemSocketsData) gemStory.getGemstoneData(gemDataUUID)).removeGem(gemUUID, color))
|
||||
return;
|
||||
|
||||
// Attempt externals
|
||||
for (StatData externalData : gemStory.getExternalData())
|
||||
if (((GemSocketsData) externalData).removeGem(gemUUID, color))
|
||||
return;
|
||||
|
||||
// Attempt gems
|
||||
for (UUID gemDataUUID : gemStory.getAllModifiers())
|
||||
if (((GemSocketsData) gemStory.getModifiersBonus(gemDataUUID)).removeGem(gemUUID, color))
|
||||
return;
|
||||
}
|
||||
//endregion
|
||||
// Attempt gems
|
||||
for (UUID gemDataUUID : gemStory.getAllModifiers())
|
||||
if (((GemSocketsData) gemStory.getModifiersBonus(gemDataUUID)).removeGem(gemUUID, color))
|
||||
return;
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
@ -168,6 +168,14 @@ public class AbilityData extends Skill {
|
||||
return ability.equals(that.ability) && getTrigger().equals(that.getTrigger()) && modifiers.equals(that.modifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AbilityData{" +
|
||||
"ability=" + ability +
|
||||
", modifiers=" + modifiers +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(ability, modifiers);
|
||||
|
@ -38,7 +38,9 @@ public class AbilityListData implements StatData, Mergeable<AbilityListData> {
|
||||
@NotNull
|
||||
@Override
|
||||
public AbilityListData clone() {
|
||||
return new AbilityListData();
|
||||
final AbilityListData clone = new AbilityListData();
|
||||
clone.abilities.addAll(this.abilities);
|
||||
return clone;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -76,6 +78,13 @@ public class AbilityListData implements StatData, Mergeable<AbilityListData> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AbilityListData{" +
|
||||
"abilities=" + abilities +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return abilities.isEmpty();
|
||||
|
@ -23,7 +23,7 @@ import java.util.*;
|
||||
*/
|
||||
public class GemSocketsData implements StatData, Mergeable<GemSocketsData>, RandomStatData<GemSocketsData> {
|
||||
@NotNull
|
||||
private final Set<GemstoneData> gems = new LinkedHashSet<>();
|
||||
private final List<GemstoneData> gems = new ArrayList<>();
|
||||
@NotNull
|
||||
private final List<String> emptySlots;
|
||||
|
||||
@ -55,7 +55,7 @@ public class GemSocketsData implements StatData, Mergeable<GemSocketsData>, Rand
|
||||
@Nullable
|
||||
public String getEmptySocket(@NotNull String gem) {
|
||||
for (String slot : emptySlots)
|
||||
if (gem.equals("") || slot.equals(getUncoloredGemSlot()) || gem.equals(slot))
|
||||
if (gem.isEmpty() || slot.equals(getUncoloredGemSlot()) || gem.equals(slot))
|
||||
return slot;
|
||||
return null;
|
||||
}
|
||||
@ -70,9 +70,12 @@ public class GemSocketsData implements StatData, Mergeable<GemSocketsData>, Rand
|
||||
gems.add(gem);
|
||||
}
|
||||
|
||||
public void apply(String gem, GemstoneData gemstone) {
|
||||
emptySlots.remove(getEmptySocket(gem));
|
||||
public boolean apply(String gem, GemstoneData gemstone) {
|
||||
final String matchingSocket = getEmptySocket(gem);
|
||||
if (matchingSocket == null) return false;
|
||||
emptySlots.remove(matchingSocket);
|
||||
gems.add(gemstone);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addEmptySlot(@NotNull String slot) {
|
||||
@ -84,8 +87,18 @@ public class GemSocketsData implements StatData, Mergeable<GemSocketsData>, Rand
|
||||
return emptySlots;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/**
|
||||
* @see #getGems()
|
||||
* @deprecated Gems are stored inside a list
|
||||
* rather than inside a linked hash set.
|
||||
*/
|
||||
@Deprecated
|
||||
public Set<GemstoneData> getGemstones() {
|
||||
return new HashSet<>(gems);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<GemstoneData> getGems() {
|
||||
return gems;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
* <b>Strongly encouraged to override the <code>equals</code> method
|
||||
* to something fitting here as Mergeable stats should support comparisons.</b>
|
||||
*/
|
||||
public interface Mergeable<S extends StatData> extends StatData {
|
||||
public interface Mergeable<S extends Mergeable<S>> extends StatData {
|
||||
|
||||
/**
|
||||
* Merging two stat datas is required when an item benefits from
|
||||
|
@ -354,46 +354,14 @@ public class DoubleStat extends ItemStat<NumericStatFormula, DoubleData> impleme
|
||||
@NotNull
|
||||
@Override
|
||||
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
|
||||
int i = level;
|
||||
double value = ((DoubleData) original).getValue();
|
||||
|
||||
// If leveling up
|
||||
if (i > 0) {
|
||||
|
||||
// While still positive
|
||||
while (i > 0) {
|
||||
|
||||
// Apply PMP Operation Positively
|
||||
value = ((DoubleUpgradeInfo) info).getPMP().apply(value);
|
||||
|
||||
// Decrease
|
||||
i--;
|
||||
}
|
||||
|
||||
// Degrading the item
|
||||
} else if (i < 0) {
|
||||
|
||||
// While still negative
|
||||
while (i < 0) {
|
||||
|
||||
// Apply PMP Operation Reversibly
|
||||
value = ((DoubleUpgradeInfo) info).getPMP().reverse(value);
|
||||
|
||||
// Decrease
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Update
|
||||
while (i-- > 0) value = ((DoubleUpgradeInfo) info).getPMP().apply(value);
|
||||
while (i++ < 0) value = ((DoubleUpgradeInfo) info).getPMP().reverse(value);
|
||||
((DoubleData) original).setValue(value);
|
||||
}
|
||||
|
||||
// Upgraded
|
||||
return original;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@ import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
|
||||
import net.Indyuce.mmoitems.stat.data.EnchantListData;
|
||||
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
|
||||
import net.Indyuce.mmoitems.stat.data.GemstoneData;
|
||||
import net.Indyuce.mmoitems.stat.data.StringListData;
|
||||
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
|
||||
import net.Indyuce.mmoitems.stat.data.type.StatData;
|
||||
import net.Indyuce.mmoitems.stat.data.type.UpgradeInfo;
|
||||
@ -43,10 +42,10 @@ public class StatHistory {
|
||||
private ArrayList<StatData> perExternalData = new ArrayList<>();
|
||||
private HashMap<UUID, StatData> perGemstoneData = new HashMap<>();
|
||||
|
||||
private StatHistory(@NotNull MMOItem ofItem, @NotNull ItemStat ofStat, @NotNull StatData ogData) {
|
||||
itemStat = ofStat;
|
||||
originalData = ogData;
|
||||
parent = ofItem;
|
||||
private StatHistory(@NotNull MMOItem parentItem, @NotNull ItemStat parentStat, @NotNull StatData parentData) {
|
||||
itemStat = parentStat;
|
||||
originalData = parentData;
|
||||
parent = parentItem;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -78,36 +77,20 @@ public class StatHistory {
|
||||
* @return Sure there is a Stat History and all but, does it
|
||||
* actually have any information apart from the OG Data?
|
||||
*/
|
||||
public boolean isClear() {
|
||||
public boolean isEmpty() {
|
||||
|
||||
/*
|
||||
* Enchant list data is not clear even if redundant.
|
||||
*
|
||||
* Its an important assumption in several methods
|
||||
* like Enchants.separateEnchantments()
|
||||
* like Enchants#separateEnchantments()
|
||||
*/
|
||||
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 || getAllModifiers().size() > 0) {
|
||||
//CLR//MMOItems.log("\u00a7a -+- \u00a77Found Gemstones / ESH, \u00a7cnot clear. \u00a78{\u00a77" + getItemStat().getId() + "\u00a78}");
|
||||
if (getOriginalData() instanceof EnchantListData && ((EnchantListData) getOriginalData()).getEnchants().size() != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is it clear?
|
||||
if (getOriginalData().isEmpty() && (!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;
|
||||
}
|
||||
// Any gemstones, external or modifier data?
|
||||
if (getAllGemstones().size() > 0 || getExternalData().size() > 0 || getAllModifiers().size() > 0) return false;
|
||||
|
||||
// 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 true;
|
||||
}
|
||||
|
||||
public void setParent(@NotNull MMOItem parent) {
|
||||
@ -119,7 +102,8 @@ public class StatHistory {
|
||||
* Presumably from when it was first generated.
|
||||
*/
|
||||
public void setOriginalData(@NotNull StatData s) {
|
||||
originalData = Objects.requireNonNull(s, "Original data cannot be null");
|
||||
Validate.notNull(s, "Original data cannot be null");
|
||||
originalData = s;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,6 +121,8 @@ public class StatHistory {
|
||||
* were rolled when the item was first created.
|
||||
*/
|
||||
public void registerModifierBonus(@NotNull UUID of, @NotNull StatData data) {
|
||||
Validate.notNull(of, "Modifier UUID cannot be null");
|
||||
Validate.notNull(data, "Stat data cannot be null");
|
||||
perModifierBonus.put(of, data);
|
||||
}
|
||||
|
||||
@ -199,6 +185,8 @@ 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) {
|
||||
Validate.notNull(of, "Gemstone ID cannot be null");
|
||||
Validate.notNull(data, "Stat data cannot be null");
|
||||
perGemstoneData.put(of, data);
|
||||
}
|
||||
|
||||
@ -224,20 +212,15 @@ public class StatHistory {
|
||||
return perExternalData;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void consolidateEXSH() {
|
||||
collapseExternalData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapses all external stat datas
|
||||
* of unknown source into only one.
|
||||
* Merges all external stat datas of unknown
|
||||
* origin into one stat data instance.
|
||||
*/
|
||||
public void collapseExternalData() {
|
||||
public void fuseExternalData() {
|
||||
|
||||
// Create Clear
|
||||
StatData theEXSH = getItemStat().getClearStatData();
|
||||
for (StatData ex : getExternalData()) if (ex != null) ((Mergeable) theEXSH).mergeWith(ex);
|
||||
for (StatData ex : getExternalData()) ((Mergeable) theEXSH).mergeWith((Mergeable) ex);
|
||||
|
||||
// Clear and Register
|
||||
getExternalData().clear();
|
||||
@ -253,6 +236,7 @@ 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) {
|
||||
Validate.notNull(data, "Stat data cannot be null");
|
||||
perExternalData.add(data);
|
||||
}
|
||||
|
||||
@ -323,86 +307,33 @@ public class StatHistory {
|
||||
original = ((Mergeable) original).clone();
|
||||
//UPGRD//MMOItems.log("\u00a7a +\u00a77 Found original data\u00a7f " + original);
|
||||
}
|
||||
//LVL//MMOItems.log(" \u00a7d*\u00a77-\u00a7a-\u00a763? \u00a77Lvl: \u00a7b" + parentItem.getUpgradeLevel() + "\u00a7d-\u00a77-\u00a7a-\u00a7d-\u00a77-\u00a7a-");
|
||||
|
||||
// Create new
|
||||
// Create and register new
|
||||
hist = new StatHistory(parentItem, stat, original);
|
||||
|
||||
//LVL//MMOItems.log(" \u00a7d*\u00a77-\u00a7a-\u00a764? \u00a77Lvl: \u00a7b" + parentItem.getUpgradeLevel() + "\u00a7d-\u00a77-\u00a7a-\u00a7d-\u00a77-\u00a7a-");
|
||||
// Append to the item
|
||||
parentItem.setStatHistory(stat, hist);
|
||||
|
||||
//LVL//MMOItems.log(" \u00a7d*\u00a77-\u00a7a-\u00a765? \u00a77Lvl: \u00a7b" + parentItem.getUpgradeLevel() + "\u00a7d-\u00a77-\u00a7a-\u00a7d-\u00a77-\u00a7a-");
|
||||
|
||||
//LVL//MMOItems.log(" \u00a7d*\u00a77*\u00a7a*\u00a766? \u00a77Lvl: \u00a7b" + hist.getMMOItem().getUpgradeLevel() + "\u00a7d-\u00a77-\u00a7a-\u00a7d-\u00a77-\u00a7a-");
|
||||
// Thats it
|
||||
return hist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the item and makes sure that the UUIDs attributed to gemstones
|
||||
* link to existing gem stones. Removes them if no such gemstone exists.
|
||||
* link to existing gemstones. Removes them if no such gemstone exists.
|
||||
*/
|
||||
public void purgeGemstones() {
|
||||
|
||||
// Which will get purged...
|
||||
ArrayList<UUID> extraneous = new ArrayList<>();
|
||||
// No socket history can be found => clear all gems
|
||||
GemSocketsData data = (GemSocketsData) getMMOItem().getData(ItemStats.GEM_SOCKETS);
|
||||
if (data == null) {
|
||||
data = new GemSocketsData(new ArrayList<>());
|
||||
perGemstoneData.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// For each UUID
|
||||
for (UUID gem : perGemstoneData.keySet()) {
|
||||
|
||||
// Check Gemstones
|
||||
boolean success = false;
|
||||
for (GemstoneData indiv : data.getGemstones()) {
|
||||
|
||||
// Not null
|
||||
if (indiv != null) {
|
||||
|
||||
// Equal in UUID
|
||||
if (gem.equals(indiv.getHistoricUUID())) {
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No success?
|
||||
if (!success) {
|
||||
|
||||
// No gemstone matched
|
||||
extraneous.add(gem);
|
||||
}
|
||||
// Pb: intersecting between List and HashTable
|
||||
HashMap<UUID, StatData> newPerGemstoneData = new HashMap<>();
|
||||
for (GemstoneData gemData : data.getGemstones()) {
|
||||
final StatData found = perGemstoneData.get(gemData.getHistoricUUID());
|
||||
if (found != null) newPerGemstoneData.put(gemData.getHistoricUUID(), found);
|
||||
}
|
||||
|
||||
// Unregister
|
||||
for (UUID ext : extraneous) {
|
||||
//RECALCULATE//MMOItems.log("\u00a76 ||\u00a77 Purged Stone: \u00a7e" + ext.toString() + "\u00a78 (\u00a73" + getItemStat().getId() + "\u00a78)");
|
||||
|
||||
// Remove
|
||||
removeGemData(ext);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If this stat changes when the MMOItem is upgraded.
|
||||
*/
|
||||
public boolean isUpgradeable() {
|
||||
|
||||
// No upgrades no possible
|
||||
if (!getMMOItem().hasUpgradeTemplate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get Upgrade Info?
|
||||
UpgradeInfo inf = getMMOItem().getUpgradeTemplate().getUpgradeInfo(getItemStat());
|
||||
|
||||
// No Upgrade Information? Looks like you're calculating as a normal merge stat
|
||||
return inf != null;
|
||||
perGemstoneData = newPerGemstoneData;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -416,70 +347,21 @@ public class StatHistory {
|
||||
return recalculate(true, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* This recalculates final value of the stats of the item.
|
||||
* <p></p>
|
||||
* This will not apply the changes, it will just give you the final
|
||||
* <code>StatData</code> that shall be applied (used when upgrading).
|
||||
*
|
||||
* @param withPurge Check if the gemstones UUIDs are valid.
|
||||
* Leave <code>true</code> unless you know
|
||||
* what you're doing.
|
||||
*/
|
||||
@NotNull
|
||||
public StatData recalculate(boolean withPurge, int level) {
|
||||
//RECALCULATE//MMOItems.log("\u00a7d|||\u00a77 Recalculating \u00a7f" + getItemStat().getNBTPath() + "\u00a77, Purge? \u00a7e" + withPurge);
|
||||
|
||||
if (withPurge) {
|
||||
purgeGemstones();
|
||||
}
|
||||
|
||||
// If its upgradeable and not level ZERO, it must apply upgrades
|
||||
//UPGRD//MMOItems.log("\u00a7d|\u00a79|\u00a76|\u00a77 Upgradeable Requirements: ");
|
||||
//UPGRD//MMOItems.log(" \u00a76|\u00a77 Upgrade Level: \u00a7e" + level);
|
||||
//UPGRD//MMOItems.log(" \u00a76|\u00a77 Upgradeable Stat: \u00a7e" + (getItemStat() instanceof Upgradable));
|
||||
//UPGRD//MMOItems.log(" \u00a76|\u00a77 Template Exists: \u00a7e" + (getMMOItem().hasUpgradeTemplate()));
|
||||
if ((level != 0) &&
|
||||
(getItemStat() instanceof Upgradable) &&
|
||||
(getMMOItem().hasUpgradeTemplate())) {
|
||||
|
||||
// Recalculate upgrading
|
||||
return recalculateUpgradeable(level);
|
||||
}
|
||||
|
||||
// Merge Normally
|
||||
return recalculateMergeable();
|
||||
}
|
||||
|
||||
/**
|
||||
* This recalculates values accounting only for gemstones and external data.
|
||||
* <p></p>
|
||||
* In case someone was wondered the contribution of upgrading the item, just
|
||||
* substract it from {@link #recalculate(int)}
|
||||
* subtract it from {@link #recalculate(int)}.
|
||||
*/
|
||||
@NotNull
|
||||
public StatData recalculateUnupgraded() {
|
||||
return recalculateUnupgraded(true);
|
||||
return recalculate(true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This recalculates values accounting only for gemstones and external data.
|
||||
* <p></p>
|
||||
* In case someone was wondered the contribution of upgrading the item, just
|
||||
* substract it from {@link #recalculate(int)}
|
||||
*
|
||||
* @param withPurge Check if the gemstones UUIDs are valid.
|
||||
* Leave <code>true</code> unless you know
|
||||
* what you're doing.
|
||||
*/
|
||||
@NotNull
|
||||
public StatData recalculateUnupgraded(boolean withPurge) {
|
||||
if (withPurge) {
|
||||
purgeGemstones();
|
||||
}
|
||||
|
||||
// Merge Normally
|
||||
return recalculateMergeable();
|
||||
private int findLevel(int upgradeLevel, UUID gemstoneId) {
|
||||
for (GemstoneData gemstone : getMMOItem().getGemstones())
|
||||
if (gemstone.getHistoricUUID().equals(gemstoneId))
|
||||
return gemstone.isScaling() ? gemstone.getLevel() : upgradeLevel;
|
||||
throw new IllegalArgumentException("Could not find level of gem " + gemstoneId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -492,131 +374,39 @@ public class StatHistory {
|
||||
* </p>4: Sums Gem Stone Data (which should be scaled accordingly [Upgrades are entirely merged into their data])
|
||||
* <p>5: Sums external data (modifiers that are not linked to an ID, I suppose by external plugins).
|
||||
*/
|
||||
private StatData recalculateUpgradeable(int lvl) {
|
||||
//RECALCULATE//MMOItems.log("\u00a76|||\u00a77 Calculating \u00a7f" + getItemStat().getNBTPath() + "\u00a77 as Upgradeable");
|
||||
@NotNull
|
||||
public StatData recalculate(boolean purgeFirst, @Nullable Integer upgradeLevel) {
|
||||
if (purgeFirst) purgeGemstones();
|
||||
|
||||
// Get Upgrade Info?
|
||||
UpgradeInfo inf = getMMOItem().getUpgradeTemplate().getUpgradeInfo(getItemStat());
|
||||
|
||||
// No Upgrade Information? Looks like you're calculating as a normal merge stat
|
||||
if (inf == null) {
|
||||
return recalculateMergeable();
|
||||
}
|
||||
final UpgradeInfo upgradeInfo = upgradeLevel != null &&
|
||||
upgradeLevel != 0 &&
|
||||
getItemStat() instanceof Upgradable ?
|
||||
getMMOItem().getUpgradeTemplate().getUpgradeInfo(getItemStat()) : null;
|
||||
|
||||
// Clone original
|
||||
StatData ogCloned = ((Mergeable) originalData).clone();
|
||||
//DBL//if (ogCloned instanceof DoubleData) MMOItems.log("\u00a76 >\u00a77 Original Base: \u00a7e" + ((DoubleData) ogCloned).getValue() + "\u00a78 {Original:\u00a77 " + ((DoubleData) getOriginalData()).getValue() + "\u00a78}");
|
||||
Mergeable finalData = ((Mergeable) originalData).clone();
|
||||
|
||||
// Add Modifiers (who are affected by upgrades as if they was the base item data
|
||||
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).mergeWith(((Mergeable) getModifiersBonus(d)).clone());
|
||||
}
|
||||
// Add modifiers (affected by upgrades as if they were base item data)
|
||||
for (UUID modifierId : perModifierBonus.keySet()) finalData.mergeWith((Mergeable) getModifiersBonus(modifierId));
|
||||
|
||||
// Level up
|
||||
//RECALCULATE//MMOItems.log("\u00a76 ||\u00a77 Item Level: \u00a7e" + lvl);
|
||||
StatData ret = ((Upgradable) getItemStat()).apply(ogCloned, inf, lvl);
|
||||
//DBL//if (ret instanceof DoubleData) MMOItems.log("\u00a76 >\u00a77 Leveled Base: \u00a7e" + ((DoubleData) ret).getValue() + "\u00a78 {Original:\u00a77 " + ((DoubleData) getOriginalData()).getValue() + "\u00a78}");
|
||||
if (upgradeInfo != null)
|
||||
finalData = (Mergeable) ((Upgradable) getItemStat()).apply(finalData, upgradeInfo, upgradeLevel);
|
||||
|
||||
// Add up gemstones
|
||||
for (UUID d : perGemstoneData.keySet()) {
|
||||
|
||||
// Identify insertion level (When was the gemstone put into the item?
|
||||
int level = 0;
|
||||
|
||||
// Whats this gemstone's upgrade level?
|
||||
for (GemstoneData gData : getMMOItem().getGemStones()) {
|
||||
if (gData == null) {
|
||||
continue;
|
||||
}
|
||||
//RECALCULATE//MMOItems.log("\u00a76 -\u00a7b-\u00a76-\u00a77 Gemstone " + gData.getName() + "\u00a77 " + gData.getHistoricUUID().toString());
|
||||
|
||||
// Find that one of matching UUID
|
||||
if (gData.getHistoricUUID().equals(d)) {
|
||||
|
||||
if (gData.isScaling()) {
|
||||
|
||||
// Ok
|
||||
level = gData.getLevel();
|
||||
//RECALCULATE//MMOItems.log("\u00a76 -\u00a7b-\u00a76-\u00a7a- Found:\u00a77" + level);
|
||||
|
||||
} else {
|
||||
|
||||
// No scaling
|
||||
level = lvl;
|
||||
//RECALCULATE//MMOItems.log("\u00a76 -\u00a7b-\u00a76-\u00a7a- Found,\u00a77 Unscaling");
|
||||
}
|
||||
}
|
||||
for (UUID gemstoneId : perGemstoneData.keySet()) {
|
||||
Mergeable gsData = (Mergeable) getGemstoneData(gemstoneId);
|
||||
if (upgradeInfo != null) {
|
||||
int levelDifference = upgradeLevel - findLevel(upgradeLevel, gemstoneId);
|
||||
gsData = (Mergeable) ((Upgradable) getItemStat()).apply(gsData.clone(), upgradeInfo, levelDifference);
|
||||
}
|
||||
|
||||
// Calculate level difference
|
||||
int gLevel = lvl - level;
|
||||
//RECALCULATE//MMOItems.log("\u00a76 |\u00a7b|\u00a76>\u00a77 Gemstone Level: \u00a7e" + gLevel + "\u00a77 (Put at \u00a7b" + level + "\u00a77)");
|
||||
|
||||
//DBL//if (getGemstoneData(d) instanceof DoubleData) MMOItems.log("\u00a76 \u00a7b|>\u00a77 Gemstone Base: \u00a7e" + ((DoubleData) getGemstoneData(d)).getValue());
|
||||
// Apply upgrades
|
||||
//noinspection ConstantConditions
|
||||
StatData gRet = ((Upgradable) getItemStat()).apply(((Mergeable) getGemstoneData(d)).clone(), inf, gLevel);
|
||||
//DBL//if (gRet instanceof DoubleData) MMOItems.log("\u00a76 \u00a7b|>\u00a77 Leveled Base: \u00a7e" + ((DoubleData) gRet).getValue());
|
||||
|
||||
// Merge
|
||||
((Mergeable) ret).mergeWith(((Mergeable) gRet).clone());
|
||||
finalData.mergeWith(gsData);
|
||||
}
|
||||
|
||||
// Add up externals (who dont suffer upgrades
|
||||
for (StatData d : getExternalData()) {
|
||||
// Add up externals (who don't suffer upgrades)
|
||||
for (StatData externalData : getExternalData()) finalData.mergeWith((Mergeable) externalData);
|
||||
|
||||
//DBL//if (d instanceof DoubleData) MMOItems.log("\u00a76 >\u00a7c> \u00a77 Extraneous Base: \u00a7e" + ((DoubleData) d).getValue());
|
||||
// Just merge ig
|
||||
((Mergeable) ret).mergeWith(((Mergeable) d).clone());
|
||||
}
|
||||
|
||||
// Return result
|
||||
//DBL//if (ret instanceof DoubleData) MMOItems.log("\u00a76:::\u00a77 Result: \u00a7e" + ((DoubleData) ret).getValue() + "\u00a78 {Original:\u00a77 " + ((DoubleData) getOriginalData()).getValue() + "\u00a78}");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* This recalculates final value of the stats of the item.
|
||||
* <p></p>
|
||||
* That is, it (in this order):
|
||||
* <p>1: Starts out with a fresh (empty) data
|
||||
* </p>2: Sums the original values
|
||||
* </p>3: Sums Gem Stone Data (which should be scaled accordingly [Upgrades are entirely merged into their data])
|
||||
* <p>4: Sums external data (modifiers that are not linked to an ID, I suppose by external plugins).
|
||||
*/
|
||||
private StatData recalculateMergeable() {
|
||||
//RECALCULATE//MMOItems.log("\u00a73|||\u00a77 Calculating \u00a7f" + getItemStat().getNBTPath() + "\u00a77 as Mergeable");
|
||||
|
||||
// Just clone bro
|
||||
StatData ret = ((Mergeable) getOriginalData()).clone();
|
||||
|
||||
//DBL//if (ret instanceof DoubleData) MMOItems.log("\u00a73 > \u00a77 Original Base: \u00a7e" + ((DoubleData) ret).getValue());
|
||||
|
||||
// Add Modifiers
|
||||
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).mergeWith(((Mergeable) d).clone());
|
||||
}
|
||||
|
||||
// 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).mergeWith(((Mergeable) d).clone());
|
||||
}
|
||||
|
||||
// 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).mergeWith(((Mergeable) d).clone());
|
||||
}
|
||||
|
||||
// Return result
|
||||
//DBL//if (ret instanceof DoubleData) MMOItems.log("\u00a73:::\u00a77 Result: \u00a7b" + ((DoubleData) ret).getValue());
|
||||
return ret;
|
||||
return finalData;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -632,7 +422,7 @@ public class StatHistory {
|
||||
JsonObject object = new JsonObject();
|
||||
|
||||
// To know the stat it was
|
||||
object.addProperty(enc_Stat, getItemStat().getId());
|
||||
object.addProperty(ENC_STAT, getItemStat().getId());
|
||||
|
||||
/*
|
||||
* Save the original data. It is redundant to save if it is clear though.
|
||||
@ -646,7 +436,7 @@ public class StatHistory {
|
||||
* StatHistory of these items.
|
||||
*/
|
||||
if (!getOriginalData().isEmpty() || getItemStat() == ItemStats.ENCHANTS) {
|
||||
object.add(enc_OGS, ItemTag.compressTags(getItemStat().getAppliedNBT(getOriginalData())));
|
||||
object.add(ENC_OGS, ItemTag.compressTags(getItemStat().getAppliedNBT(getOriginalData())));
|
||||
}
|
||||
|
||||
// Kompress Arrays
|
||||
@ -671,7 +461,7 @@ public class StatHistory {
|
||||
|
||||
// Include
|
||||
if (gemz.size() > 0) {
|
||||
object.add(enc_GSS, gemz);
|
||||
object.add(ENC_GSS, gemz);
|
||||
}
|
||||
|
||||
|
||||
@ -692,7 +482,7 @@ public class StatHistory {
|
||||
|
||||
// Include
|
||||
if (externals.size() > 0) {
|
||||
object.add(enc_EXS, externals);
|
||||
object.add(ENC_EXS, externals);
|
||||
}
|
||||
|
||||
// Kompress Arrays
|
||||
@ -717,7 +507,7 @@ public class StatHistory {
|
||||
|
||||
// Include
|
||||
if (modz.size() > 0) {
|
||||
object.add(enc_MOD, modz);
|
||||
object.add(ENC_MOD, modz);
|
||||
}
|
||||
|
||||
|
||||
@ -756,22 +546,22 @@ public class StatHistory {
|
||||
JsonElement modEncode = null;
|
||||
|
||||
// It has stat information right?
|
||||
if (json.has(enc_Stat)) {
|
||||
statEncode = json.get(enc_Stat);
|
||||
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_OGS)) {
|
||||
ogStatsEncode = json.get(ENC_OGS);
|
||||
}
|
||||
if (json.has(enc_GSS)) {
|
||||
gemsEncode = json.get(enc_GSS);
|
||||
if (json.has(ENC_GSS)) {
|
||||
gemsEncode = json.get(ENC_GSS);
|
||||
}
|
||||
if (json.has(enc_EXS)) {
|
||||
extEncode = json.get(enc_EXS);
|
||||
if (json.has(ENC_EXS)) {
|
||||
extEncode = json.get(ENC_EXS);
|
||||
}
|
||||
if (json.has(enc_MOD)) {
|
||||
modEncode = json.get(enc_MOD);
|
||||
if (json.has(ENC_MOD)) {
|
||||
modEncode = json.get(ENC_MOD);
|
||||
}
|
||||
|
||||
// It is a primitive right
|
||||
@ -960,21 +750,12 @@ public class StatHistory {
|
||||
@Nullable
|
||||
public static StatHistory fromNBTString(@NotNull MMOItem iSource, @NotNull String codedJson) {
|
||||
|
||||
// Attempt
|
||||
try {
|
||||
|
||||
// Make JSON Parser
|
||||
JsonParser pJSON = new JsonParser();
|
||||
|
||||
// Parse as array
|
||||
JsonObject oJSON = pJSON.parse(codedJson).getAsJsonObject();
|
||||
|
||||
// Bake
|
||||
return fromJson(iSource, oJSON);
|
||||
|
||||
} catch (Throwable e) {
|
||||
|
||||
// Feedbacc
|
||||
FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FFPMMOItems.get());
|
||||
ffp.activatePrefix(true, "Stat History");
|
||||
ffp.log(FriendlyFeedbackCategory.ERROR, "Could not get stat history: $f{0}$b at $f{1}", e.getMessage(), e.getStackTrace()[0].toString());
|
||||
@ -983,53 +764,6 @@ public class StatHistory {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all gemstone and extraneous data from this other, while
|
||||
* keeping the current ones as well as <u>these</u> original bases.
|
||||
* <p></p>
|
||||
* Fails if the stats are not the same one.
|
||||
*/
|
||||
@Deprecated
|
||||
public void assimilate(@NotNull StatHistory other) {
|
||||
|
||||
// Stat must be the same
|
||||
if (other.getItemStat().getNBTPath().equals(getItemStat().getNBTPath())) {
|
||||
//UPDT//MMOItems.log(" \u00a72>\u00a76> \u00a77History Stat Matches");
|
||||
|
||||
//UPDT//MMOItems.log(" \u00a76:\u00a72: \u00a77Original Gemstones \u00a7f" + perGemstoneData.size());
|
||||
//UPDT//MMOItems.log(" \u00a76:\u00a72: \u00a77Original Externals \u00a7f" + perExternalData.size());
|
||||
|
||||
// Register gemstones
|
||||
for (UUID exUID : other.getAllGemstones()) {
|
||||
//noinspection ConstantConditions
|
||||
registerGemstoneData(exUID, other.getGemstoneData(exUID));
|
||||
}
|
||||
|
||||
// Register externals
|
||||
for (StatData ex : other.getExternalData()) {
|
||||
registerExternalData((ex));
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public StatHistory clone(@NotNull MMOItem newParent) {
|
||||
final StatHistory his = clone();
|
||||
his.setParent(newParent);
|
||||
return his;
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||
@NotNull
|
||||
public StatHistory clone() {
|
||||
@ -1042,88 +776,51 @@ public class StatHistory {
|
||||
return res;
|
||||
}
|
||||
|
||||
static final String enc_Stat = "Stat";
|
||||
static final String enc_OGS = "OGStory";
|
||||
static final String enc_GSS = "Gemstory";
|
||||
static final String enc_EXS = "Exstory";
|
||||
static final String enc_MOD = "Mod";
|
||||
private static final String ENC_STAT = "Stat", ENC_OGS = "OGStory", ENC_GSS = "Gemstory", ENC_EXS = "Exstory", ENC_MOD = "Mod";
|
||||
|
||||
/**
|
||||
* Logs into the console. Dev Method
|
||||
*/
|
||||
@Deprecated
|
||||
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);
|
||||
}
|
||||
//region Methods not used
|
||||
public void assimilate(@NotNull StatHistory other) {
|
||||
if (other.getItemStat().getNBTPath().equals(getItemStat().getNBTPath())) {
|
||||
for (UUID exUID : other.getAllGemstones()) registerGemstoneData(exUID, other.getGemstoneData(exUID));
|
||||
for (StatData ex : other.getExternalData()) registerExternalData((ex));
|
||||
for (UUID exUID : other.getAllModifiers()) registerModifierBonus(exUID, other.getModifiersBonus(exUID));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #clone()} followed by {@link #setParent(MMOItem)}
|
||||
*/
|
||||
@Deprecated
|
||||
public StatHistory clone(@NotNull MMOItem newParent) {
|
||||
final StatHistory his = clone();
|
||||
his.setParent(newParent);
|
||||
return his;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public StatData recalculateUnupgraded(boolean withPurge) {
|
||||
return recalculate(withPurge, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #isEmpty()
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isClear() {
|
||||
return isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #fuseExternalData()
|
||||
*/
|
||||
@Deprecated
|
||||
public void consolidateEXSH() {
|
||||
fuseExternalData();
|
||||
}
|
||||
|
||||
public boolean isUpgradeable() {
|
||||
return getMMOItem().hasUpgradeTemplate() && getMMOItem().getUpgradeTemplate().getUpgradeInfo(getItemStat()) != null;
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user