some code cleanup

This commit is contained in:
Indyuce 2021-12-20 11:47:15 +01:00
parent f2bb73e2b7
commit 23b9590cf1
8 changed files with 676 additions and 524 deletions

View File

@ -486,7 +486,8 @@ public class MMOItem implements ItemReference {
public void removeGemStone(@NotNull UUID gemUUID, @Nullable String color) {
// Get gemstone data
if (!hasData(ItemStats.GEM_SOCKETS)) { return; }
if (!hasData(ItemStats.GEM_SOCKETS))
return;
//GEM//MMOItems.log("\u00a7b-\u00a78-\u00a79-\u00a77 Extracting \u00a7e" + gemUUID.toString());
StatHistory gemStory = StatHistory.from(this, ItemStats.GEM_SOCKETS);
@ -497,16 +498,23 @@ public class MMOItem implements ItemReference {
* will purge themselves from extraneous gems (that are
* no longer registered onto the GEM_SOCKETS history).
*/
if (GemSocketsData.removeGemFrom(((GemSocketsData) gemStory.getOriginalData()), gemUUID, color)) { return; }
if (((GemSocketsData) gemStory.getOriginalData()).removeGem(gemUUID, color))
return;
// Attempt gems
for (UUID gemDataUUID : gemStory.getAllGemstones()) { if (GemSocketsData.removeGemFrom(((GemSocketsData) gemStory.getGemstoneData(gemDataUUID)), gemUUID, color)) { return; } }
for (UUID gemDataUUID : gemStory.getAllGemstones())
if (((GemSocketsData) gemStory.getGemstoneData(gemDataUUID)).removeGem(gemUUID, color))
return;
// Attempt externals
for (StatData externalData : gemStory.getExternalData()) { if (GemSocketsData.removeGemFrom(((GemSocketsData) externalData), gemUUID, color)) { return; } }
for (StatData externalData : gemStory.getExternalData())
if (((GemSocketsData) externalData).removeGem(gemUUID, color))
return;
// Attempt gems
for (UUID gemDataUUID : gemStory.getAllModifiers()) { if (GemSocketsData.removeGemFrom(((GemSocketsData) gemStory.getModifiersBonus(gemDataUUID)), gemUUID, color)) { return; } }
for (UUID gemDataUUID : gemStory.getAllModifiers())
if (((GemSocketsData) gemStory.getModifiersBonus(gemDataUUID)).removeGem(gemUUID, color))
return;
}
//endregion
}

View File

@ -2,8 +2,9 @@ package net.Indyuce.mmoitems.api.player;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
import io.lumine.mythic.lib.api.player.EquipmentSlot;
import io.lumine.mythic.lib.api.player.MMOPlayerData;
import io.lumine.mythic.lib.api.stat.modifier.ModifierSource;
import io.lumine.mythic.lib.damage.AttackMetadata;
import io.lumine.mythic.lib.skill.trigger.PassiveSkill;
import net.Indyuce.mmoitems.ItemStats;
@ -36,7 +37,6 @@ import org.bukkit.scheduler.BukkitRunnable;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.logging.Level;
public class PlayerData {
private static final Map<UUID, PlayerData> data = new HashMap<>();
@ -234,10 +234,12 @@ public class PlayerData {
/*
* Apply abilities
*/
if (item.hasData(ItemStats.ABILITIES) && (MMOItems.plugin.getConfig().getBoolean("abilities-bypass-encumbering", false) || !fullHands))
if (item.hasData(ItemStats.ABILITIES) && (MMOItems.plugin.getConfig().getBoolean("abilities-bypass-encumbering") || !fullHands))
if (equipped.getSlot() != EquipmentSlot.OFF_HAND || !MMOItems.plugin.getConfig().getBoolean("disable-abilities-in-offhand"))
for (AbilityData abilityData : ((AbilityListData) item.getData(ItemStats.ABILITIES)).getAbilities())
mmoData.registerSkillTrigger(new PassiveSkill("MMOItemsItem", abilityData.getTriggerType(), abilityData));
for (AbilityData abilityData : ((AbilityListData) item.getData(ItemStats.ABILITIES)).getAbilities()) {
ModifierSource modSource = equipped.getItem().getType() == null ? ModifierSource.OTHER : equipped.getItem().getType().getItemSet().getModifierSource();
mmoData.registerSkillTrigger(new PassiveSkill("MMOItemsItem", abilityData.getTriggerType(), abilityData, equipped.getSlot(), modSource));
}
/*
* Apply permissions if vault exists
@ -314,7 +316,7 @@ public class PlayerData {
return;
// perm effects
permanentEffects.keySet().forEach(effect -> getPlayer().addPotionEffect(permanentEffects.get(effect)));
permanentEffects.values().forEach(effect -> getPlayer().addPotionEffect(effect));
// two handed
if (fullHands)
@ -451,7 +453,9 @@ public class PlayerData {
// Might not be null, after all
PlayerData observedData = data.get(uuid);
if (observedData != null) { return observedData; }
if (observedData != null) {
return observedData;
}
// Attempt to load
load(uuid);

View File

@ -127,9 +127,9 @@ public class GemSockets extends ItemStat {
if (gTag != null) {
try {
// INterpret as Json Object
// Interpret as Json Object
JsonObject object = new JsonParser().parse((String) gTag.getValue()).getAsJsonObject();
GemSocketsData sockets = new GemSocketsData(toList(object.getAsJsonArray("EmptySlots")));
GemSocketsData sockets = new GemSocketsData(object.getAsJsonArray("EmptySlots"));
JsonArray array = object.getAsJsonArray("Gemstones");
array.forEach(element -> sockets.add(new GemstoneData(element.getAsJsonObject())));
@ -148,12 +148,6 @@ public class GemSockets extends ItemStat {
return null;
}
private List<String> toList(JsonArray array) {
List<String> list = new ArrayList<>();
array.forEach(str -> list.add(str.getAsString()));
return list;
}
@Override
public void whenClicked(@NotNull EditionInventory inv, @NotNull InventoryClickEvent event) {
if (event.getAction() == InventoryAction.PICKUP_ALL)

View File

@ -1,192 +1,204 @@
package net.Indyuce.mmoitems.stat.data;
import java.util.*;
import io.lumine.mythic.lib.api.util.Ref;
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
import net.Indyuce.mmoitems.api.interaction.GemStone;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import org.apache.commons.lang.Validate;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
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 org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class GemSocketsData implements StatData, Mergeable, RandomStatData {
@NotNull private final Set<GemstoneData> gems = new HashSet<>();
@NotNull private final List<String> emptySlots;
import java.util.*;
public GemSocketsData(@NotNull List<String> emptySlots) {
this.emptySlots = emptySlots;
}
/**
* A class containing all the information about gemstones on
* an MMOItem. This contains the information of all the item modifiers
* applied by a gem stone as well as the empty gem sockets.
* <p>
* When used as a {@link RandomStatData}, the 'gems' set is useless
* because items do not come with gems applied to it when generated.
*/
public class GemSocketsData implements Mergeable, RandomStatData {
@NotNull
private final Set<GemstoneData> gems = new HashSet<>();
@NotNull
private final List<String> emptySlots;
@Override
public boolean equals(Object obj) {
if (!(obj instanceof GemSocketsData)) { return false; }
if (((GemSocketsData) obj).getEmptySlots().size() != getEmptySlots().size()) { return false; }
if (((GemSocketsData) obj).getGemstones().size() != getGemstones().size()) { return false; }
if (!SilentNumbers.hasAll(((GemSocketsData) obj).getEmptySlots(), getEmptySlots())) { return false; }
public GemSocketsData(@NotNull List<String> emptySlots) {
this.emptySlots = emptySlots;
}
for (GemstoneData objGem : ((GemSocketsData) obj).getGemstones()) {
public GemSocketsData(@NotNull JsonArray emptySlots) {
this.emptySlots = new ArrayList<>();
if (objGem == null) { continue; }
emptySlots.forEach(el -> this.emptySlots.add(el.getAsString()));
}
// Validate with ours
boolean unmatched = true;
for (GemstoneData thisGem : getGemstones()) {
/**
* Attempts to find a slot of the same color of this gem within the item.
* <p></p>
* To know the color of the socket pass the same argument to {@link #getEmptySocket(String)}
* which checks in the same order as this method for the first success.
*/
public boolean canReceive(@NotNull String gem) {
return getEmptySocket(gem) != null;
}
// Test match
if (objGem.equals(thisGem)) {
unmatched = false;
break; }
}
if (unmatched) { return false; } }
/**
* Get the first empty gem socket that matches this color.
*
* @return <code>null</code> if none matched.
*/
@Nullable
public String getEmptySocket(@NotNull String gem) {
for (String slot : emptySlots)
if (gem.equals("") || slot.equals(getUncoloredGemSlot()) || gem.equals(slot))
return slot;
return null;
}
// All equal
return true;
}
@NotNull
public static String getUncoloredGemSlot() {
String s = MMOItems.plugin.getConfig().getString("gem-sockets.uncolored");
return s == null ? "Uncolored" : s;
}
/**
* Attempts to find a slot of the same color of this gem within the item.
* <p></p>
* To know the color of the socket pass the same argument to {@link #getEmptySocket(String)}
* which checks in the same order as this method for the first success.
*/
public boolean canReceive(@NotNull String gem) {
return getEmptySocket(gem) != null;
}
public void add(GemstoneData gem) {
gems.add(gem);
}
/**
* Get the first emtpty gem socket that matches this color
* @return <code>null</code> if none matched.
*/
@Nullable public String getEmptySocket(@NotNull String gem) {
for (String slot : emptySlots)
if (gem.equals("") || slot.equals(getUncoloredGemSlot()) || gem.equals(slot))
return slot;
return null;
}
public void apply(String gem, GemstoneData gemstone) {
emptySlots.remove(getEmptySocket(gem));
gems.add(gemstone);
}
@NotNull public static String getUncoloredGemSlot() { String s = MMOItems.plugin.getConfig().getString("gem-sockets.uncolored"); return s == null ? "Uncolored" : s; }
public void addEmptySlot(@NotNull String slot) {
emptySlots.add(slot);
}
public void add(GemstoneData gem) {
gems.add(gem);
}
@NotNull
public List<String> getEmptySlots() {
return emptySlots;
}
public void apply(String gem, GemstoneData gemstone) { emptySlots.remove(getEmptySocket(gem)); gems.add(gemstone); }
@NotNull
public Set<GemstoneData> getGemstones() {
return gems;
}
public void addEmptySlot(@NotNull String slot) {
emptySlots.add(slot);
}
/**
* Removes such gem from this GemSocketsData, if it exists and
* registers again an empty gem socket if required
*
* @param gemId The unique ID of the gem to remove
* @param socket The socket color to replace the gem with, <code>null</code> for no socket.
* @return Whether a gem was removed from the data.
*/
public boolean removeGem(@NotNull UUID gemId, @Nullable String socket) {
for (GemstoneData data : getGemstones())
if (data.getHistoricUUID().equals(gemId)) {
if (socket != null)
addEmptySlot(socket);
gems.remove(data);
return true;
}
@NotNull public List<String> getEmptySlots() {
return emptySlots;
}
return false;
}
@NotNull public Set<GemstoneData> getGemstones() {
return gems;
}
public JsonObject toJson() {
JsonObject object = new JsonObject();
public void removeGem(@NotNull UUID gem) {
JsonArray empty = new JsonArray();
getEmptySlots().forEach(empty::add);
object.add("EmptySlots", empty);
// Find
GemstoneData d = null;
for (GemstoneData data : getGemstones()) {
if (data.getHistoricUUID().equals(gem)) {
//GEM//MMOItems.log("\u00a7b*\u00a77 Found gem to unregister: \u00a7a" + data.getName());
d = data; break; }}
JsonArray array = new JsonArray();
gems.forEach(gem -> array.add(gem.toJson()));
object.add("Gemstones", array);
// Remove
gems.remove(d);
}
return object;
}
/**
* Removes such gem from this GemSocketsData, if it exists.
*
* @param data The Data from which to remove the gem
* @param gemUUID The Gem to remove
* @param socket The socket color to replace the gem with, <code>null</code> for no socket.
* @return Whether a gem was removed from the data.
*/
public static boolean removeGemFrom(@NotNull GemSocketsData data, @NotNull UUID gemUUID, @Nullable String socket) {
@Override
public void merge(StatData data) {
Validate.isTrue(data instanceof GemSocketsData, "Cannot merge two different stat data types");
boolean removal = false;
for (GemstoneData gem : data.getGemstones()) {
// Combine both actual gems, and empty slots
emptySlots.addAll(((GemSocketsData) data).emptySlots);
gems.addAll(((GemSocketsData) data).getGemstones());
}
// Is it the one we are searching for?
if (gem.getHistoricUUID().equals(gemUUID)) {
@Override
public @NotNull
StatData cloneData() {
// Found it, restore the socket and we're done.
if (socket != null) { data.addEmptySlot(socket); }
// Clone empty slots
GemSocketsData ret = new GemSocketsData(new ArrayList<>(emptySlots));
// Remove
removal = true; break; } }
// Clone gems
for (GemstoneData gem : getGemstones())
ret.add(gem.cloneGem());
// Its time.
if (removal) { data.removeGem(gemUUID); }
return ret;
}
return removal;
}
@Override
public boolean isClear() {
return getGemstones().size() == 0 && getEmptySlots().size() == 0;
}
public JsonObject toJson() {
JsonObject object = new JsonObject();
@Override
public StatData randomize(MMOItemBuilder builder) {
return new GemSocketsData(new ArrayList<>(emptySlots));
}
JsonArray empty = new JsonArray();
getEmptySlots().forEach(empty::add);
object.add("EmptySlots", empty);
@Override
public String toString() {
return "Empty:\u00a7b " + getEmptySlots().size() + "\u00a77, Gems:\u00a7b " + getGemstones().size();
}
JsonArray array = new JsonArray();
gems.forEach(gem -> array.add(gem.toJson()));
object.add("Gemstones", array);
@Override
public boolean equals(Object obj) {
if (!(obj instanceof GemSocketsData)) {
return false;
}
if (((GemSocketsData) obj).getEmptySlots().size() != getEmptySlots().size()) {
return false;
}
if (((GemSocketsData) obj).getGemstones().size() != getGemstones().size()) {
return false;
}
if (!SilentNumbers.hasAll(((GemSocketsData) obj).getEmptySlots(), getEmptySlots())) {
return false;
}
return object;
}
for (GemstoneData objGem : ((GemSocketsData) obj).getGemstones()) {
@Override
public void merge(StatData data) {
Validate.isTrue(data instanceof GemSocketsData, "Cannot merge two different stat data types");
if (objGem == null) {
continue;
}
//MRG//MMOItems.log("\u00a73||| \u00a77Merging slots; Original:");
//MRG//for (String str : SilentNumbers.transcribeList(emptySlots, (s) -> "\u00a73|+ \u00a77" + ((String) s))) { MMOItems.log(str); }
//MRG//MMOItems.log("\u00a73||| \u00a77Including");
//MRG//for (String str : SilentNumbers.transcribeList(((GemSocketsData) data).emptySlots, (s) -> "\u00a73|+ \u00a77" + ((String) s))) { MMOItems.log(str); }
// Validate with ours
boolean unmatched = true;
for (GemstoneData thisGem : getGemstones()) {
// Combine both actual gems, and empty slots
emptySlots.addAll(((GemSocketsData) data).emptySlots);
gems.addAll(((GemSocketsData) data).getGemstones());
// Test match
if (objGem.equals(thisGem)) {
unmatched = false;
break;
}
}
if (unmatched) {
return false;
}
}
//MRG//MMOItems.log("\u00a73||| \u00a7aResult");
//MRG//for (String str : SilentNumbers.transcribeList(emptySlots, (s) -> "\u00a73|+ \u00a77" + ((String) s))) { MMOItems.log(str); }
//MRG//MMOItems.log("\u00a73||| \u00a7a---------------------------------------");
}
@Override
public @NotNull StatData cloneData() {
// Start Fresh
GemSocketsData ret = new GemSocketsData(new ArrayList<>(emptySlots));
// Add Gems
for (GemstoneData g : getGemstones()) { ret.add(g.cloneGem()); }
return ret;
}
@Override
public boolean isClear() { return getGemstones().size() == 0 && getEmptySlots().size() == 0; }
@Override
public StatData randomize(MMOItemBuilder builder) {
return new GemSocketsData(new ArrayList<>(emptySlots));
}
@Override
public String toString() { return "Empty:\u00a7b " + getEmptySlots().size() + "\u00a77, Gems:\u00a7b " + getGemstones().size(); }
// All equal
return true;
}
}

View File

@ -3,15 +3,10 @@ package net.Indyuce.mmoitems.stat.data;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.stat.GemUpgradeScaling;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -19,247 +14,309 @@ import java.util.*;
@SuppressWarnings("unused")
public class GemstoneData {
@NotNull private final Set<AbilityData> abilities = new HashSet<>();
@NotNull private final List<PotionEffectData> effects = new ArrayList<>();
@NotNull private final Map<ItemStat, Double> stats = new HashMap<>();
@NotNull private final String name;
@Nullable Integer levelPut;
@NotNull final UUID historicUUID;
@Nullable final String mmoitemType;
@Nullable final String mmoitemID;
@Nullable String socketColor;
private final Set<AbilityData> abilities = new HashSet<>();
private final List<PotionEffectData> effects = new ArrayList<>();
private final Map<ItemStat, Double> stats = new HashMap<>();
private final String name;
@NotNull
private final UUID historicUUID;
@Nullable
private final String mmoitemType;
@Nullable
private final String mmoitemID;
public GemstoneData cloneGem() {
@Nullable
private String socketColor;
@Nullable
private Integer levelPut;
GemstoneData ret = new GemstoneData(getName(), getMMOItemType(), getMMOItemID(), getSocketColor(), getHistoricUUID());
for (AbilityData d : abilities) { ret.addAbility(d); }
for (PotionEffectData d : effects) { ret.addPermanentEffect(d); }
for (ItemStat d : stats.keySet()) { ret.setStat(d, stats.get(d)); }
ret.setLevel(getLevel());
public GemstoneData cloneGem() {
return ret;
}
GemstoneData ret = new GemstoneData(getName(), getMMOItemType(), getMMOItemID(), getSocketColor(), getHistoricUUID());
for (AbilityData d : abilities)
ret.addAbility(d);
for (PotionEffectData d : effects)
ret.addPermanentEffect(d);
for (ItemStat d : stats.keySet())
ret.setStat(d, stats.get(d));
ret.setLevel(getLevel());
/**
* Gemstone equals method is for practical purposes and only checks that
* this other thing is both a GemstoneData and has the same UUID.
*
* @param obj Object to compare with
* @return <code>true</code> if they have the same {@link #getHistoricUUID()}
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof GemstoneData)) { return false; }
return ret;
}
return ((GemstoneData) obj).getHistoricUUID().equals(getHistoricUUID());
}
/**
* Gemstone equals method is for practical purposes and only checks that
* this other thing is both a GemstoneData and has the same UUID.
*
* @param obj Object to compare with
* @return <code>true</code> if they have the same {@link #getHistoricUUID()}
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof GemstoneData)) {
return false;
}
@Nullable
public String getMMOItemType() {
return mmoitemType;
}
return ((GemstoneData) obj).getHistoricUUID().equals(getHistoricUUID());
}
@Nullable
public String getMMOItemID() {
return mmoitemID;
}
@Nullable
public String getMMOItemType() {
return mmoitemType;
}
/**
* If known, the socket colour this gem was put into
*/
@Nullable
public String getSocketColor() {
return socketColor;
}
@Nullable
public String getMMOItemID() {
return mmoitemID;
}
/**
* This constructor is not really performance friendly. It should only be
* used when applying gem stones to keep max performance.
*/
public GemstoneData(@NotNull JsonObject object) {
/**
* If known, the socket colour this gem was put into
*/
@Nullable
public String getSocketColor() {
return socketColor;
}
// GEt Name
name = object.get("Name").getAsString();
/**
* This constructor is not really performance friendly. It should only be
* used when applying gem stones to keep max performance.
*/
public GemstoneData(@NotNull JsonObject object) {
// Get Stats
//object.getAsJsonObject("Stats").entrySet() .forEach(entry -> this.stats.put(MMOItems.plugin.getStats().get(entry.getKey()), entry.getValue().getAsDouble()));
// GEt Name
name = object.get("Name").getAsString();
// Get Abilities
//object.getAsJsonArray("Abilities").forEach(element -> this.abilities.add(new AbilityData(element.getAsJsonObject())));
// Get Stats
//object.getAsJsonObject("Stats").entrySet() .forEach(entry -> this.stats.put(MMOItems.plugin.getStats().get(entry.getKey()), entry.getValue().getAsDouble()));
// Get Permanent Potion Effects
//object.getAsJsonObject("Effects").entrySet().forEach(entry -> this.effects.add(new PotionEffectData(PotionEffectType.getByName(entry.getKey()), entry.getValue().getAsInt())));
// Get Abilities
//object.getAsJsonArray("Abilities").forEach(element -> this.abilities.add(new AbilityData(element.getAsJsonObject())));
// Get assigned HUUID, Assign new if its an olden item without it :>
JsonElement uuid = object.get("History");
if (uuid != null) {
// Get Permanent Potion Effects
//object.getAsJsonObject("Effects").entrySet().forEach(entry -> this.effects.add(new PotionEffectData(PotionEffectType.getByName(entry.getKey()), entry.getValue().getAsInt())));
// Its of this gen of gemstones...
String hUUID = uuid.getAsString();
UUID hisUUID = MMOUtils.UUIDFromString(hUUID);
if (hisUUID != null) { historicUUID = hisUUID; }
else { historicUUID = UUID.randomUUID(); }
// Get assigned HUUID, Assign new if its an olden item without it :>
JsonElement uuid = object.get("History");
if (uuid != null) {
// Get Type and IDs
JsonElement gType = object.get("Type");
JsonElement gID = object.get("Id");
if (gType != null) { mmoitemType = gType.getAsString(); } else { mmoitemType = null; }
if (gID != null) { mmoitemID = gID.getAsString(); } else { mmoitemID = null; }
// Its of this gen of gemstones...
String hUUID = uuid.getAsString();
UUID hisUUID = MMOUtils.UUIDFromString(hUUID);
if (hisUUID != null) {
historicUUID = hisUUID;
} else {
historicUUID = UUID.randomUUID();
}
JsonElement level = object.get("Level");
if (level != null && level.isJsonPrimitive()) { levelPut = level.getAsJsonPrimitive().getAsInt(); } else { levelPut = null; }
//LVL//MMOItems.log("\u00a73 -\u00a7b-\u00a73-\u00a77 Read Level: \u00a7b" + levelPut);
// Get Type and IDs
JsonElement gType = object.get("Type");
JsonElement gID = object.get("Id");
if (gType != null) {
mmoitemType = gType.getAsString();
} else {
mmoitemType = null;
}
if (gID != null) {
mmoitemID = gID.getAsString();
} else {
mmoitemID = null;
}
JsonElement color = object.get("Color");
if (color != null && color.isJsonPrimitive()) { socketColor = color.getAsJsonPrimitive().getAsString(); } else { socketColor = null; }
JsonElement level = object.get("Level");
if (level != null && level.isJsonPrimitive()) {
levelPut = level.getAsJsonPrimitive().getAsInt();
} else {
levelPut = null;
}
//LVL//MMOItems.log("\u00a73 -\u00a7b-\u00a73-\u00a77 Read Level: \u00a7b" + levelPut);
} else { historicUUID = UUID.randomUUID(); mmoitemID = null; mmoitemType = null; socketColor = null; }
}
JsonElement color = object.get("Color");
if (color != null && color.isJsonPrimitive()) {
socketColor = color.getAsJsonPrimitive().getAsString();
} else {
socketColor = null;
}
/**
* Create a GemStoneData from a GemStone MMOItem.
* <p></p>
* Basically extracts all the useable stats from the MMOItem, to have them ready to apply onto another MMOItem.
* @param color Color of the slot this gem was inserted onto.
*/
public GemstoneData(@NotNull LiveMMOItem gemStoneMMOItem, @Nullable String color) {
} else {
historicUUID = UUID.randomUUID();
mmoitemID = null;
mmoitemType = null;
socketColor = null;
}
}
// Get Name to Display
name = MMOUtils.getDisplayName(gemStoneMMOItem.getNBT().getItem());
/**
* Create a GemStoneData from a GemStone MMOItem.
* <p></p>
* Basically extracts all the useable stats from the MMOItem, to have them ready to apply onto another MMOItem.
*
* @param color Color of the slot this gem was inserted onto.
*/
public GemstoneData(@NotNull LiveMMOItem gemStoneMMOItem, @Nullable String color) {
// Extract abilities from the Gem Stone MMOItem into a more accessible form
if (gemStoneMMOItem.hasData(ItemStats.ABILITIES)) { abilities.addAll(((AbilityListData) gemStoneMMOItem.getData(ItemStats.ABILITIES)).getAbilities()); }
// Get Name to Display
name = MMOUtils.getDisplayName(gemStoneMMOItem.getNBT().getItem());
// Extract permenent effects from the Gem Stone MMOItem into a more accessible form
if (gemStoneMMOItem.hasData(ItemStats.PERM_EFFECTS)) { effects.addAll(((PotionEffectListData) gemStoneMMOItem.getData(ItemStats.PERM_EFFECTS)).getEffects()); }
// Extract abilities from the Gem Stone MMOItem into a more accessible form
if (gemStoneMMOItem.hasData(ItemStats.ABILITIES)) {
abilities.addAll(((AbilityListData) gemStoneMMOItem.getData(ItemStats.ABILITIES)).getAbilities());
}
// Extract permenent effects from the Gem Stone MMOItem into a more accessible form
if (gemStoneMMOItem.hasData(ItemStats.PERM_EFFECTS)) {
effects.addAll(((PotionEffectListData) gemStoneMMOItem.getData(ItemStats.PERM_EFFECTS)).getEffects());
}
// Generate own historic UUID
historicUUID = UUID.randomUUID();
mmoitemID = gemStoneMMOItem.getId();
mmoitemType = gemStoneMMOItem.getType().getId();
socketColor = color;
}
// Generate own historic UUID
historicUUID = UUID.randomUUID();
mmoitemID = gemStoneMMOItem.getId();
mmoitemType = gemStoneMMOItem.getType().getId();
socketColor = color;
}
/**
* This is a completely empty builder.
* <p></p>
* You may add whatever you want with <code>addAbility()</code>,<code>addPermamentEffect</code>, or most widely usedly, <code>setStat()</code>.
* <p></p>
* @deprecated This gem stone will not have a type/id and will cause problems when trying to remove it from items with a consumable.
* @param name Name to display in the lore of the item when you put the gemstone into it.
*/
public GemstoneData(@NotNull String name) {
this.name = name;
mmoitemID = null;
mmoitemType = null;
socketColor = null;
historicUUID = UUID.randomUUID();
}
/**
* This is a completely empty builder.
* <p></p>
* You may add whatever you want with <code>addAbility()</code>,<code>addPermamentEffect</code>, or most widely usedly, <code>setStat()</code>.
* <p></p>
*
* @param name Name to display in the lore of the item when you put the gemstone into it.
* @deprecated This gem stone will not have a type/id and will cause problems when trying to remove it from items with a consumable.
*/
public GemstoneData(@NotNull String name) {
this.name = name;
mmoitemID = null;
mmoitemType = null;
socketColor = null;
historicUUID = UUID.randomUUID();
}
/**
* This is at which level (of the item) the gemstone was placed onto the item.
* <p>A null level means this gem does not scale.</p>
* <p></p>
* For scaling purposes of stat {@link GemUpgradeScaling}
*/
public void setLevel(@Nullable Integer l) {
//LVL//MMOItems.log("\u00a73 -\u00a7b-\u00a73-\u00a77 Set Level: \u00a7b" + l);
levelPut = l; }
/**
* This is at which level (of the item) the gemstone was placed onto the item.
* <p>A null level means this gem does not scale.</p>
* <p></p>
* For scaling purposes of stat {@link GemUpgradeScaling}
*/
@Nullable public Integer getLevel() { return levelPut; }
/**
* This is at which level (of the item) the gemstone was placed onto the item.
* <p>A null level means this gem does not scale.</p>
* <p></p>
* For scaling purposes of stat {@link GemUpgradeScaling}
*/
public void setLevel(@Nullable Integer l) {
//LVL//MMOItems.log("\u00a73 -\u00a7b-\u00a73-\u00a77 Set Level: \u00a7b" + l);
levelPut = l;
}
/**
* Does this gem scale with item upgrades?
*/
public boolean isScaling() { return levelPut != null; }
/**
* This is at which level (of the item) the gemstone was placed onto the item.
* <p>A null level means this gem does not scale.</p>
* <p></p>
* For scaling purposes of stat {@link GemUpgradeScaling}
*/
@Nullable
public Integer getLevel() {
return levelPut;
}
/**
* This is a completely empty builder.
* <p></p>
* You may add whatever you want with <code>addAbility()</code>,<code>addPermamentEffect</code>, or most widely usedly, <code>setStat()</code>.
* @param name Name to display in the lore of the item when you put the gemstone into it.
* @param color Color of the socket this gem is inserted onto
*/
public GemstoneData(@NotNull String name, @Nullable String type, @Nullable String id, @Nullable String color) {
this.name = name;
mmoitemID = id;
mmoitemType = type;
socketColor = color;
historicUUID = UUID.randomUUID(); }
/**
* Does this gem scale with item upgrades?
*/
public boolean isScaling() {
return levelPut != null;
}
/**
* This is a completely empty builder.
* <p></p>
* You may add whatever you want with <code>addAbility()</code>,<code>addPermamentEffect</code>, or most widely usedly, <code>setStat()</code>.
* @param name Name to display in the lore of the item when you put the gemstone into it.
* @param color Color of the socket this gem is inserted onto
*/
public GemstoneData(@NotNull String name, @Nullable String type, @Nullable String id, @Nullable String color, @NotNull UUID uiid) {
this.name = name;
mmoitemID = id;
mmoitemType = type;
socketColor = color;
historicUUID = uiid; }
/**
* This is a completely empty builder.
* <p></p>
* You may add whatever you want with <code>addAbility()</code>,<code>addPermamentEffect</code>, or most widely usedly, <code>setStat()</code>.
*
* @param name Name to display in the lore of the item when you put the gemstone into it.
* @param color Color of the socket this gem is inserted onto
*/
public GemstoneData(@NotNull String name, @Nullable String type, @Nullable String id, @Nullable String color) {
this.name = name;
mmoitemID = id;
mmoitemType = type;
socketColor = color;
historicUUID = UUID.randomUUID();
}
/**
* Add an ability to this Gem Stone
*/
public void addAbility(@NotNull AbilityData ability) {
abilities.add(ability);
}
/**
* This is a completely empty builder.
* <p></p>
* You may add whatever you want with <code>addAbility()</code>,<code>addPermamentEffect</code>, or most widely usedly, <code>setStat()</code>.
*
* @param name Name to display in the lore of the item when you put the gemstone into it.
* @param color Color of the socket this gem is inserted onto
*/
public GemstoneData(@NotNull String name, @Nullable String type, @Nullable String id, @Nullable String color, @NotNull UUID uiid) {
this.name = name;
mmoitemID = id;
mmoitemType = type;
socketColor = color;
historicUUID = uiid;
}
/**
* Add a permanent potion effect to this Gem Stone
*/
public void addPermanentEffect(@NotNull PotionEffectData effect) {
effects.add(effect);
}
/**
* Add an ability to this Gem Stone
*/
public void addAbility(@NotNull AbilityData ability) {
abilities.add(ability);
}
/**
* Add an ItemStat to this gemstone
*/
public void setStat(@NotNull ItemStat stat, double value) {
stats.put(stat, value);
}
/**
* Add a permanent potion effect to this Gem Stone
*/
public void addPermanentEffect(@NotNull PotionEffectData effect) {
effects.add(effect);
}
/**
* Get the display text for when this is put into lore.
*/
@NotNull public String getName() {
return name;
}
/**
* Add an ItemStat to this gemstone
*/
public void setStat(@NotNull ItemStat stat, double value) {
stats.put(stat, value);
}
/**
* If known, the socket colour this gem was put into
*/
public void setColour(@Nullable String color) { socketColor = color; }
/**
* Get the display text for when this is put into lore.
*/
@NotNull
public String getName() {
return name;
}
/**
* Want to know which stats were given to the item by this gemstone (after applying upgrade scaling and such)? Use this!
*/
@NotNull public UUID getHistoricUUID() {
return historicUUID;
}
/**
* If known, the socket colour this gem was put into
*/
public void setColour(@Nullable String color) {
socketColor = color;
}
/**
* To store onto the NBT of the item.
*/
@NotNull public JsonObject toJson() {
JsonObject object = new JsonObject();
object.addProperty("Name", name);
object.addProperty("History", historicUUID.toString());
if (mmoitemID != null) { object.addProperty("Id", mmoitemID); }
if (mmoitemType != null) { object.addProperty("Type", mmoitemType); }
if (levelPut != null) {
//LVL//MMOItems.log("\u00a73 -\u00a7b-\u00a73-\u00a77 Saving Level: \u00a7b" + levelPut);
object.addProperty("Level", levelPut); }
object.addProperty("Color", socketColor);
/**
* Want to know which stats were given to the item by this gemstone (after applying upgrade scaling and such)? Use this!
*/
@NotNull
public UUID getHistoricUUID() {
return historicUUID;
}
/**
* To store onto the NBT of the item.
*/
@NotNull
public JsonObject toJson() {
JsonObject object = new JsonObject();
object.addProperty("Name", name);
object.addProperty("History", historicUUID.toString());
if (mmoitemID != null) {
object.addProperty("Id", mmoitemID);
}
if (mmoitemType != null) {
object.addProperty("Type", mmoitemType);
}
if (levelPut != null) {
//LVL//MMOItems.log("\u00a73 -\u00a7b-\u00a73-\u00a77 Saving Level: \u00a7b" + levelPut);
object.addProperty("Level", levelPut);
}
object.addProperty("Color", socketColor);
/*
* These seem obsolete. Abilities, effects, and stats, are merged into the
@ -281,6 +338,6 @@ public class GemstoneData {
object.add("Effects", effects);
*/
return object;
}
return object;
}
}

View File

@ -4,7 +4,6 @@ import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* When updating items with the RevID system, an interesting case is when
@ -12,6 +11,9 @@ import org.jetbrains.annotations.Nullable;
* roll in a player's item... unless this roll was unobtainable now, perhaps
* the reason the item is getting updated is to fix that roll being too good...
*
* Example of unobtainable data: the current numeric stat value is now out
* of the numeric formula bounds (defined by max-spread).
*
* This interface will tell the {@link net.Indyuce.mmoitems.api.util.MMOItemReforger}
* if the current roll may be kept, or it is too extreme (under the updated metrics)
* to be considered 'obtainable' and thus must be removed.

View File

@ -13,7 +13,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 {
public interface Mergeable extends StatData {
/**
* Merging two stat data is used when either applying a gem stone to an item

View File

@ -1,6 +1,9 @@
package net.Indyuce.mmoitems.stat.type;
import com.google.gson.*;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackCategory;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
@ -9,7 +12,9 @@ import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
import net.Indyuce.mmoitems.stat.data.*;
import net.Indyuce.mmoitems.stat.data.EnchantListData;
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
import net.Indyuce.mmoitems.stat.data.GemstoneData;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.data.type.UpgradeInfo;
@ -30,12 +35,29 @@ import java.util.*;
*/
@SuppressWarnings({"unused", "SpellCheckingInspection"})
public class StatHistory {
/*
* Which stat is this the history of?
*/
@NotNull
private final ItemStat itemStat;
private final MMOItem parent;
/**
* The final modifier being provided by each gemstone.
* GemStones may have scaled with upgrades, that will be accounted for.
* <p>
* Gem stones all have a UUID bound to them so that MI knows
* what modifiers to take away when removing gem stones.
*/
public final HashMap<UUID, StatData> perGemstoneData = new HashMap<>();
/**
* The total bonus given by modifiers that
* were rolled when the item was first created.
*/
public final HashMap<UUID, StatData> perModifierBonus = new HashMap<>();
private static final String enc_Stat = "Stat";
private static final String enc_OGS = "OGStory";
private static final String enc_GSS = "Gemstory";
private static final String enc_EXS = "Exstory";
private static final String enc_MOD = "Mod";
/**
* Which stat is this the history of?
@ -47,7 +69,7 @@ public class StatHistory {
/**
* @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() {
@ -81,11 +103,6 @@ public class StatHistory {
return getOriginalData().equals(getMMOItem().getData(getItemStat()));
}
/*
* What MMOItem is this StatHistory linked to?
*/
@NotNull
MMOItem parent;
/**
* What MMOItem is this StatHistory linked to?
@ -124,16 +141,9 @@ public class StatHistory {
originalData = s;
}
/**
* The total bonus given by modifiers that
* were rolled when the item was first created.
*/
@NotNull
public HashMap<UUID, StatData> perModifierBonus = new HashMap<>();
/**
* @return The total bonus given by modifiers that
* were rolled when the item was first created.
* were rolled when the item was first created.
*/
@Contract("null -> null")
@Nullable
@ -169,17 +179,14 @@ public class StatHistory {
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(); }
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<>();
/**
* The final modifier being provided by each gemstone.
* GemStones may have scaled with upgrades, that will be accounted for.
@ -192,17 +199,24 @@ public class StatHistory {
}
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); }
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()); }
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.
@ -211,11 +225,16 @@ public class StatHistory {
* <p>originally <code>+5</code>, now at level 2, with <code>+0.25</code> per level</p>
* 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); }
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(); }
public void clearGemstones() {
perGemstoneData.clear();
}
/*
* Modifiers of unknown origin.
@ -235,7 +254,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>
*/
@NotNull
public ArrayList<StatData> getExternalData() { return perExternalData; }
public ArrayList<StatData> getExternalData() {
return perExternalData;
}
/**
* Collapses all ExSH stat data into one.
*/
@ -256,6 +278,7 @@ public class StatHistory {
getExternalData().clear();
registerExternalData(theEXSH);
}
/**
* Modifiers of unknown origin.
* Presumably put here by external plugins I guess.
@ -264,11 +287,16 @@ public class StatHistory {
* <p>They act as gem stones, adding together to produce the total of the item, but cannot be removed, 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>
*/
public void registerExternalData(@NotNull StatData data) { perExternalData.add(data); }
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(); }
public void clearExternalData() {
perExternalData.clear();
}
/**
* Gets the stat history of this item. <b>The stat must be <code>Mergeable</code></b>
@ -281,7 +309,11 @@ public class StatHistory {
* @param ofItem MMOItem to extract stat history from
* @param ofStat Stat of which to make history
*/
@NotNull public static StatHistory from(@NotNull MMOItem ofItem, @NotNull ItemStat ofStat) { return from(ofItem, ofStat, false); }
@NotNull
public static StatHistory from(@NotNull MMOItem ofItem, @NotNull ItemStat ofStat) {
return from(ofItem, ofStat, false);
}
/**
* Gets the stat history of this item. <b>The stat must be <code>Mergeable</code></b>
* <p></p>
@ -290,8 +322,8 @@ public class StatHistory {
* <p></p>
* <b>Make sure the item has the stat present</b>
*
* @param ofItem MMOItem to extract stat history from
* @param ofStat Stat of which to make history
* @param ofItem MMOItem to extract stat history from
* @param ofStat Stat of which to make history
* @param forceNew <b>Only if you know what you are doing</b>, set to true to not check if the item already has stat history of this stat.
*/
@NotNull
@ -306,7 +338,9 @@ public class StatHistory {
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; } }
return hist;
}
}
// That is Mergeable right...
//UPGRD//MMOItems.log("\u00a7aCreated Hisotry of \u00a76" + ofStat.getNBTPath() + "\u00a7a of this \u00a7c" + ofItem.getType().getName() + " " + ofItem.getId());
@ -325,7 +359,7 @@ public class StatHistory {
//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-");
// Create new
hist = new StatHistory(ofItem, ofStat, original);
@ -345,7 +379,11 @@ public class StatHistory {
* <p></p>
* Use <code>StatHistory.From()</code> to get the stat history associated to an item.
*/
public StatHistory(@NotNull MMOItem ofItem, @NotNull ItemStat ofStat, @NotNull StatData ogData) { itemStat = ofStat; originalData = ogData; parent = ofItem; }
public StatHistory(@NotNull MMOItem ofItem, @NotNull ItemStat ofStat, @NotNull StatData ogData) {
itemStat = ofStat;
originalData = ogData;
parent = ofItem;
}
/**
* Checks the item and makes sure that the UUIDs
@ -357,7 +395,9 @@ public class StatHistory {
// Which will get purged...
ArrayList<UUID> extraneous = new ArrayList<>();
GemSocketsData data = (GemSocketsData) getMMOItem().getData(ItemStats.GEM_SOCKETS);
if (data == null) { data = new GemSocketsData(new ArrayList<>()); }
if (data == null) {
data = new GemSocketsData(new ArrayList<>());
}
// For each UUID
for (UUID gem : perGemstoneData.keySet()) {
@ -401,7 +441,9 @@ public class StatHistory {
public boolean isUpgradeable() {
// No upgrades no possible
if (!getMMOItem().hasUpgradeTemplate()) { return false; }
if (!getMMOItem().hasUpgradeTemplate()) {
return false;
}
// Get Upgrade Info?
UpgradeInfo inf = getMMOItem().getUpgradeTemplate().getUpgradeInfo(getItemStat());
@ -416,34 +458,42 @@ public class StatHistory {
* This will not apply the changes, it will just give you the final
* <code>StatData</code> that shall be applied (used when upgrading).
*/
@NotNull public StatData recalculate(int level) { return recalculate(true, level); }
@NotNull
public StatData recalculate(int level) {
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) {
@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 (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())) {
if ((level != 0) &&
(getItemStat() instanceof Upgradable) &&
(getMMOItem().hasUpgradeTemplate())) {
// Recalculate upgrading
return recalculateUpgradeable(level);
}
}
// Merge Normally
return recalculateMergeable();
}
@ -454,19 +504,26 @@ public class StatHistory {
* In case someone was wondered the contribution of upgrading the item, just
* substract it from {@link #recalculate(int)}
*/
@NotNull public StatData recalculateUnupgraded() { return recalculateUnupgraded(true); }
@NotNull
public StatData recalculateUnupgraded() {
return recalculateUnupgraded(true);
}
/**
* 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(); }
@NotNull
public StatData recalculateUnupgraded(boolean withPurge) {
if (withPurge) {
purgeGemstones();
}
// Merge Normally
return recalculateMergeable();
@ -489,7 +546,9 @@ public class StatHistory {
UpgradeInfo inf = getMMOItem().getUpgradeTemplate().getUpgradeInfo(getItemStat());
// No Upgrade Information? Looks like you're calculating as a normal merge stat
if (inf == null) { return recalculateMergeable(); }
if (inf == null) {
return recalculateMergeable();
}
// Clone original
StatData ogCloned = ((Mergeable) originalData).cloneData();
@ -516,7 +575,9 @@ public class StatHistory {
// Whats this gemstone's upgrade level?
for (GemstoneData gData : getMMOItem().getGemStones()) {
if (gData == null) { continue; }
if (gData == null) {
continue;
}
//RECALCULATE//MMOItems.log("\u00a76 -\u00a7b-\u00a76-\u00a77 Gemstone " + gData.getName() + "\u00a77 " + gData.getHistoricUUID().toString());
// Find that one of matching UUID
@ -577,10 +638,10 @@ public class StatHistory {
//RECALCULATE//MMOItems.log("\u00a73|||\u00a77 Calculating \u00a7f" + getItemStat().getNBTPath() + "\u00a77 as Mergeable");
// Just clone bro
StatData ret = ((Mergeable) getOriginalData()).cloneData();
StatData ret = ((Mergeable) getOriginalData()).cloneData();
//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());
@ -597,7 +658,8 @@ public class StatHistory {
// 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(((Mergeable) d).cloneData()); }
((Mergeable) ret).merge(((Mergeable) d).cloneData());
}
// Return result
//DBL//if (ret instanceof DoubleData) MMOItems.log("\u00a73:::\u00a77 Result: \u00a7b" + ((DoubleData) ret).getValue());
@ -612,14 +674,17 @@ public class StatHistory {
* <p></p>
* Still don't abuse calls to this. Try to do so only when necessary
*/
@NotNull public JsonObject toJson() {
@NotNull
public JsonObject toJson() {
JsonObject object = new JsonObject();
// To know the stat it was
object.addProperty(enc_Stat, getItemStat().getId());
// Original data
if (!((Mergeable) getOriginalData()).isClear()) { 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();
@ -642,7 +707,9 @@ public class StatHistory {
}
// Include
if (gemz.size() > 0) { object.add(enc_GSS, gemz); }
if (gemz.size() > 0) {
object.add(enc_GSS, gemz);
}
// Kompress Arrays
@ -652,14 +719,18 @@ public class StatHistory {
for (StatData ex : getExternalData()) {
// Skip clear
if (((Mergeable) ex).isClear()) { continue; }
if (((Mergeable) ex).isClear()) {
continue;
}
// Put
externals.add(ItemTag.compressTags(getItemStat().getAppliedNBT(ex)));
}
// Include
if (externals.size() > 0) { object.add(enc_EXS, externals); }
if (externals.size() > 0) {
object.add(enc_EXS, externals);
}
// Kompress Arrays
JsonArray modz = new JsonArray();
@ -682,7 +753,9 @@ public class StatHistory {
}
// Include
if (modz.size() > 0) { object.add(enc_MOD, modz); }
if (modz.size() > 0) {
object.add(enc_MOD, modz);
}
return object;
@ -696,7 +769,8 @@ public class StatHistory {
* <p></p>
* Still don't abuse calls to this. Try to do so only when necessary
*/
@NotNull public String toNBTString() {
@NotNull
public String toNBTString() {
// Just convert to string :thinking:
return toJson().toString();
@ -705,30 +779,54 @@ public class StatHistory {
/**
* To read from NBT data. This undoes {@link #toJson()} basically.
* <p></p>
*
* @param iSource The MMOItem you are trying to read the NBT of
*/
@Nullable public static StatHistory fromJson(@NotNull MMOItem iSource, @NotNull JsonObject json) {
@Nullable
public static StatHistory fromJson(@NotNull MMOItem iSource, @NotNull JsonObject json) {
// Get the stat we're searching for
JsonElement statEncode;
JsonElement ogStatsEncode= null;
JsonElement ogStatsEncode = null;
JsonElement gemsEncode = null;
JsonElement extEncode = null;
JsonElement modEncode = null;
// It has stat information right?
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); }
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 != 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; }
if (!statEncode.isJsonPrimitive()) {
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;
}
// Get string
String statInternalName = statEncode.getAsJsonPrimitive().getAsString();
@ -737,7 +835,9 @@ public class StatHistory {
ItemStat stat = MMOItems.plugin.getStats().get(statInternalName);
// Nope
if (stat == null) { return null; }
if (stat == null) {
return null;
}
// To know the stat it was
StatData sData;
@ -747,7 +847,7 @@ public class StatHistory {
ArrayList<ItemTag> ogDecoded = ItemTag.decompressTags(ogStatsEncode.getAsJsonArray());
sData = stat.getLoadedNBT(ogDecoded);
// OG Not included (because its clear)
// OG Not included (because its clear)
} else {
// Just generate as clear
@ -755,7 +855,9 @@ public class StatHistory {
}
// Validate non null
if (sData == null) { return null; }
if (sData == null) {
return null;
}
// Can now generate stat history
StatHistory sHistory = new StatHistory(iSource, stat, sData);
@ -834,7 +936,7 @@ public class StatHistory {
}
}
//endregion
//region Modifier History
if (modEncode != null) {
@ -892,7 +994,8 @@ public class StatHistory {
* <p></p>
* Will be null if some error happens
*/
@Nullable public static StatHistory fromNBTString(@NotNull MMOItem iSource, @NotNull String codedJson) {
@Nullable
public static StatHistory fromNBTString(@NotNull MMOItem iSource, @NotNull String codedJson) {
// Attempt
try {
@ -927,40 +1030,43 @@ public class StatHistory {
// Stat must be the same
if (other.getItemStat().getNBTPath().equals(getItemStat().getNBTPath())) {
//UPDT//MMOItems.log(" \u00a72>\u00a76> \u00a77History Stat Matches");
//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());
//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)); }
registerGemstoneData(exUID, other.getGemstoneData(exUID));
}
// Register externals
for (StatData ex : other.getExternalData()) { registerExternalData((ex)); }
for (StatData ex : other.getExternalData()) {
registerExternalData((ex));
}
// Register modifiers
for (UUID exUID : other.getAllModifiers()) {
//noinspection ConstantConditions
registerModifierBonus(exUID, other.getModifiersBonus(exUID)); }
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();
//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.
*
* <p>
* 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.
* @see MMOItem#setStatHistory(ItemStat, StatHistory)
*/
public StatHistory clone(@NotNull MMOItem clonedMMOItem) {
@ -969,10 +1075,14 @@ public class StatHistory {
// Add all
for (UUID uid : getAllGemstones()) {
if (uid == null) { continue; }
if (uid == null) {
continue;
}
StatData gem = getGemstoneData(uid);
if (!(gem instanceof Mergeable)) { continue; }
if (!(gem instanceof Mergeable)) {
continue;
}
// Clone
res.registerGemstoneData(uid, ((Mergeable) gem).cloneData());
@ -980,18 +1090,25 @@ public class StatHistory {
// Add all
for (StatData ex : getExternalData()) {
if (!(ex instanceof Mergeable)) { continue; }
if (!(ex instanceof Mergeable)) {
continue;
}
// Clone
res.registerExternalData(((Mergeable) ex).cloneData()); }
res.registerExternalData(((Mergeable) ex).cloneData());
}
// Clone
for (UUID uid : getAllModifiers()) {
if (uid == null) { continue; }
if (uid == null) {
continue;
}
StatData mod = getModifiersBonus(uid);
if (!(mod instanceof Mergeable)) { continue; }
if (!(mod instanceof Mergeable)) {
continue;
}
// Clone
res.registerModifierBonus(uid, ((Mergeable) mod).cloneData());
@ -1001,46 +1118,4 @@ 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";
/**
* 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);}
}
}
}