The old Effects format can now be read again (and its supposed to attempt to update it)

Enchantments are now supported in Upgrading Templates. Solves #23
This commit is contained in:
Gunging 2021-02-22 18:09:32 -06:00
parent b177766e74
commit 3cc3c966cb
15 changed files with 447 additions and 72 deletions

View File

@ -231,6 +231,9 @@ public class Type {
return MMOItems.plugin.getTypes().has(format) ? MMOItems.plugin.getTypes().get(format) : null;
}
@Override
public String toString() { return getId(); }
/**
* Used in command executors and completions for easier manipulation
*

View File

@ -33,7 +33,7 @@ public class UpgradeTemplate {
* Loads an Upgrade Template directly from the YML file. Neat!
*/
public UpgradeTemplate(@NotNull ConfigurationSection config) {
Validate.notNull(config, "You must specify a config section.");
Validate.notNull(config, FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), "You must specify a config section."));
// Build ID
id = config.getName().toLowerCase().replace("_", "-").replace(" ", "-");
@ -44,6 +44,7 @@ public class UpgradeTemplate {
// For ever stat
for (String key : config.getKeys(false)) {
//UPGRD//MMOItems. Log("\u00a7a>>> \u00a77Stat \u00a72" + key);
// Get internal stat ID
String statFormat = key.toUpperCase().replace("-", "_");
@ -120,15 +121,11 @@ public class UpgradeTemplate {
// For every Stat-UpgradeInfo pair
for (ItemStat stat : perStatUpgradeInfos.keySet()) {
// If it has the data to begin with?
if (mmoitem.hasData(stat)) {
// Initializes Stat History
StatHistory<StatData> hist = StatHistory.From(mmoitem, stat);
// Initializes Stat History
StatHistory<StatData> hist = StatHistory.From(mmoitem, stat);
// The Stat History now manages applying upgrades.
mmoitem.setData(stat, hist.Recalculate());
}
// The Stat History now manages applying upgrades.
mmoitem.setData(stat, hist.Recalculate());
}
}
@ -143,12 +140,12 @@ public class UpgradeTemplate {
*
* @return A string ready to just have its colors parsed and inserted into lore.
* @param value The <code>toString()</code> of this will replace all instances of <code>#stat#</code> the user specifies in the config.
* @param isNegative Should 'negative' coloration be used instead of positive? The user uses the color code <code><b>&p</b></code> in this place.
* @param isNegative Should 'negative' coloration be used instead of positive? The user uses the placeholder <code><b>< p ></b></code> in this place.
*/
@NotNull public static String getUpgradeChangeSuffix(@NotNull String value, boolean isNegative) {
// Get the base
String base = Objects.requireNonNull(MMOItems.plugin.getConfig().getString("item-upgrading.stat-change-suffix", " &8(&p#stat#&8)"));
String base = Objects.requireNonNull(MMOItems.plugin.getConfig().getString("item-upgrading.stat-change-suffix", " &8(<p>#stat#&8)"));
String succ = Objects.requireNonNull(MMOItems.plugin.getConfig().getString("item-upgrading.stat-change-positive", "&a"));
String fauc = Objects.requireNonNull(MMOItems.plugin.getConfig().getString("item-upgrading.stat-change-negative", "&c"));

View File

@ -4,11 +4,13 @@ import com.google.gson.JsonArray;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.util.LegacyComponent;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.item.util.DynamicLore;
import net.Indyuce.mmoitems.api.util.message.FriendlyFeedbackPalette_MMOItems;
import net.Indyuce.mmoitems.stat.data.MaterialData;
import net.Indyuce.mmoitems.stat.data.StringListData;
import net.Indyuce.mmoitems.stat.data.type.StatData;
@ -102,27 +104,27 @@ public class ItemStackBuilder {
*/
public NBTItem buildNBT() {
// Clone as to not conflict in any way
this.mmoitem = mmoitem.clone();
//GEM//MMOItems.Log("\u00a7e+ \u00a77Building \u00a7c" + mmoitem.getType().getName() + " " + mmoitem.getId() + "\u00a77 (Size \u00a7e" + mmoitem.mergeableStatHistory.size() + "\u00a77 Historic)");
MMOItem builtMMOItem = mmoitem.clone();
//GEM//MMOItems. Log("\u00a7e+ \u00a77Building \u00a7c" + mmoitem.getType().getName() + " " + mmoitem.getId() + "\u00a77 (Size \u00a7e" + mmoitem.mergeableStatHistory.size() + "\u00a77 Historic)");
// For every stat within this item
for (ItemStat stat : mmoitem.getStats())
for (ItemStat stat : builtMMOItem.getStats())
// Attempt to add
try {
//GEM//MMOItems.Log("\u00a7e -+- \u00a77Applying \u00a76" + stat.getNBTPath());
//GEM//MMOItems. Log("\u00a7e -+- \u00a77Applying \u00a76" + stat.getNBTPath());
// Make necessary lore changes
stat.whenApplied(this, mmoitem.getData(stat));
stat.whenApplied(this, builtMMOItem.getData(stat));
// Does the item have any stat history regarding thay?
StatHistory<StatData> s = mmoitem.getStatHistory(stat);
StatHistory<StatData> s = builtMMOItem.getStatHistory(stat);
// Found it?
if (s != null) {
//GEM//MMOItems.Log("\u00a7a -+- \u00a77Found History");
//GEM//MMOItems. Log("\u00a7a -+- \u00a77Found History");
// Add to NBT
addItemTag(new ItemTag(histroy_keyword + stat.getId(), s.toNBTString()));
@ -130,28 +132,31 @@ public class ItemStackBuilder {
// Something went wrong...
} catch (IllegalArgumentException|NullPointerException exception) {
MMOItems.plugin.getLogger().log(Level.WARNING,
ChatColor.GRAY + "An error occurred while trying to generate item '"
+ ChatColor.RED + mmoitem.getId() + ChatColor.GRAY + "' with stat '"
+ ChatColor.GOLD + stat.getId() + ChatColor.GRAY + "': "
+ ChatColor.YELLOW + exception.getMessage());
// That
MMOItems.plugin.getLogger().log(Level.WARNING, FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(),
"An error occurred while trying to generate item '$f{0}$b' with stat '$f{1}$b': {2}",
builtMMOItem.getId(),
stat.getId(),
exception.getMessage()));
}
// Display gem stone lore hint thing
if (mmoitem.getType() == Type.GEM_STONE)
if (builtMMOItem.getType() == Type.GEM_STONE) {
lore.insert("gem-stone-lore", ItemStat.translate("gem-stone-lore"));
}
// Display item type
lore.insert("item-type",
ItemStat.translate("item-type").replace("#",
mmoitem.getStats().contains(ItemStats.DISPLAYED_TYPE)
? mmoitem.getData(ItemStats.DISPLAYED_TYPE).toString()
: mmoitem.getType().getName()));
builtMMOItem.getStats().contains(ItemStats.DISPLAYED_TYPE)
? builtMMOItem.getData(ItemStats.DISPLAYED_TYPE).toString()
: builtMMOItem.getType().getName()));
// Calculate lore with placeholders
if (mmoitem.hasData(ItemStats.LORE)) {
if (builtMMOItem.hasData(ItemStats.LORE)) {
List<String> parsed = new ArrayList<>();
((StringListData) mmoitem.getData(ItemStats.LORE)).getList()
((StringListData) builtMMOItem.getData(ItemStats.LORE)).getList()
.forEach(str -> parsed.add(lore.applyLorePlaceholders(str)));
lore.insert("lore", parsed);
}
@ -164,14 +169,14 @@ public class ItemStackBuilder {
tags.add(new ItemTag("MMOITEMS_DYNAMIC_LORE", array.toString()));
meta.setLore(list);
if (mmoitem.hasData(ItemStats.NAME) && meta.hasDisplayName()) {
if (builtMMOItem.hasData(ItemStats.NAME) && meta.hasDisplayName()) {
meta.setDisplayName(getMeta().getDisplayName());
}
item.setItemMeta(meta);
NBTItem nbtItem = NBTItem.get(item);
if (mmoitem.hasData(ItemStats.NAME) && meta.hasDisplayName()) {
if (builtMMOItem.hasData(ItemStats.NAME) && meta.hasDisplayName()) {
nbtItem.setDisplayNameComponent(LegacyComponent.parse(meta.getDisplayName()));
}

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.api.item.mmoitem;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.UpgradeTemplate;
import net.Indyuce.mmoitems.api.item.ItemReference;

View File

@ -1,12 +1,15 @@
package net.Indyuce.mmoitems.api.item.template;
import io.lumine.mythic.lib.api.util.PostLoadObject;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackCategory;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.ItemTier;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.item.ItemReference;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.api.player.RPGPlayer;
import net.Indyuce.mmoitems.api.util.message.FriendlyFeedbackPalette_MMOItems;
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.apache.commons.lang.Validate;
@ -61,6 +64,9 @@ public class MMOItemTemplate extends PostLoadObject implements ItemReference {
@Override
protected void whenPostLoaded(ConfigurationSection config) {
FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FriendlyFeedbackPalette_MMOItems.get());
ffp.ActivatePrefix(true, getType().toString() + " " + getId());
if (config.contains("option"))
for (TemplateOption option : TemplateOption.values())
if (config.getBoolean("option." + option.name().toLowerCase().replace("_", "-")))
@ -73,24 +79,30 @@ public class MMOItemTemplate extends PostLoadObject implements ItemReference {
config.getConfigurationSection("modifiers." + key));
modifiers.put(modifier.getId(), modifier);
} catch (IllegalArgumentException exception) {
MMOItems.plugin.getLogger().log(Level.INFO,
"Could not load modifier '" + key + "' from item template '" + type.getId() + "." + id + "': " + exception.getMessage());
// Log
ffp.Log(FriendlyFeedbackCategory.INFORMATION, "Could not load modifier '$f{0}$b': {1}", key, exception.getMessage());
}
Validate.notNull(config.getConfigurationSection("base"), "Could not find base item data");
Validate.notNull(config.getConfigurationSection("base"), FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(),"Could not find base item data"));
for (String key : config.getConfigurationSection("base").getKeys(false))
try {
String id = key.toUpperCase().replace("-", "_");
Validate.isTrue(MMOItems.plugin.getStats().has(id), "Could not find stat with ID '" + id + "'");
Validate.isTrue(MMOItems.plugin.getStats().has(id), FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(),"Could not find stat with ID '$i{0}$b'", id));
ItemStat stat = MMOItems.plugin.getStats().get(id);
RandomStatData data = stat.whenInitialized(config.get("base." + key));
if (data != null)
base.put(stat, data);
} catch (IllegalArgumentException exception) {
MMOItems.plugin.getLogger().log(Level.INFO, "Could not load base item data '" + key + "' from item template '" + type.getId() + "."
+ id + "': " + exception.getMessage());
// Log
ffp.Log(FriendlyFeedbackCategory.INFORMATION, "Could not load base item data '$f{0}$b': {1}", key, exception.getMessage());
}
// Print all failures
ffp.SendTo(FriendlyFeedbackCategory.INFORMATION, MMOItems.getConsole());
}
public Map<ItemStat, RandomStatData> getBaseItemData() {

View File

@ -62,6 +62,8 @@ public class ReloadCommandTreeNode extends CommandTreeNode {
+ MMOItems.plugin.getTiers().getAll().size() + ChatColor.GRAY + " Item Tiers");
sender.sendMessage(MMOItems.plugin.getPrefix() + "- " + ChatColor.RED
+ MMOItems.plugin.getSets().getAll().size() + ChatColor.GRAY + " Item Sets");
sender.sendMessage(MMOItems.plugin.getPrefix() + "- " + ChatColor.RED
+ MMOItems.plugin.getUpgrades().getAll().size() + ChatColor.GRAY + " Upgrade Templates");
}
public void reloadRecipes(CommandSender sender) {

View File

@ -1,5 +1,7 @@
package net.Indyuce.mmoitems.manager;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackCategory;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.ConfigFile;
import net.Indyuce.mmoitems.api.ItemTier;
@ -8,6 +10,7 @@ import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
import net.Indyuce.mmoitems.api.item.template.TemplateModifier;
import net.Indyuce.mmoitems.api.util.TemplateMap;
import io.lumine.mythic.lib.api.item.NBTItem;
import net.Indyuce.mmoitems.api.util.message.FriendlyFeedbackPalette_MMOItems;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
@ -239,7 +242,10 @@ public class TemplateManager implements Reloadable {
templates.clear();
modifiers.clear();
MMOItems.plugin.getLogger().log(Level.INFO, "Loading template modifiers, please wait..");
FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FriendlyFeedbackPalette_MMOItems.get());
ffp.ActivatePrefix(true, "Item Templates");
ffp.Log(FriendlyFeedbackCategory.INFORMATION, "Loading template modifiers, please wait..");
for (File file : new File(MMOItems.plugin.getDataFolder() + "/modifiers").listFiles()) {
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
for (String key : config.getKeys(false))
@ -247,11 +253,13 @@ public class TemplateManager implements Reloadable {
TemplateModifier modifier = new TemplateModifier(config.getConfigurationSection(key));
modifiers.put(modifier.getId(), modifier);
} catch (IllegalArgumentException exception) {
MMOItems.plugin.getLogger().log(Level.INFO, "Could not load template modifier '" + key + "': " + exception.getMessage());
// Log
ffp.Log(FriendlyFeedbackCategory.INFORMATION, "Could not load template modifier '" + key + "': " + exception.getMessage());
}
}
MMOItems.plugin.getLogger().log(Level.INFO, "Loading item templates, please wait..");
ffp.Log(FriendlyFeedbackCategory.INFORMATION, "Loading item templates, please wait...");
for (Type type : MMOItems.plugin.getTypes().getAll()) {
FileConfiguration config = type.getConfigFile().getConfig();
for (String key : config.getKeys(false))
@ -259,9 +267,15 @@ public class TemplateManager implements Reloadable {
MMOItemTemplate template = new MMOItemTemplate(type, config.getConfigurationSection(key));
template.postLoad();
registerTemplate(template);
} catch (IllegalArgumentException exception) {
MMOItems.plugin.getLogger().log(Level.INFO, "Could not load item template '" + key + "': " + exception.getMessage());
// Log
ffp.Log(FriendlyFeedbackCategory.INFORMATION, "Could not load item template '" + key + "': " + exception.getMessage());
}
}
// Print all failures
ffp.SendTo(FriendlyFeedbackCategory.INFORMATION, MMOItems.getConsole());
}
}

View File

@ -23,12 +23,11 @@ public class UpgradeManager implements Reloadable {
templates.clear();
FileConfiguration config = new ConfigFile("upgrade-templates").getConfig();
for (String key : config.getKeys(false))
try {
registerTemplate(new UpgradeTemplate(config.getConfigurationSection(key)));
} catch (IllegalArgumentException exception) {
MMOItems.plugin.getLogger().log(Level.WARNING, "Could not load upgrade template '" + key + "': " + exception.getMessage());
}
for (String key : config.getKeys(false)) {
// Register
registerTemplate(new UpgradeTemplate(config.getConfigurationSection(key)));
}
}
public Collection<UpgradeTemplate> getAll() {

View File

@ -9,6 +9,8 @@ import java.util.Set;
import com.google.gson.*;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
import net.Indyuce.mmoitems.api.util.message.FriendlyFeedbackPalette_MMOItems;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@ -47,7 +49,7 @@ public class Effects extends ItemStat {
@Override
public RandomStatData whenInitialized(Object object) {
Validate.isTrue(object instanceof ConfigurationSection, "Must specify a config section");
Validate.isTrue(object instanceof ConfigurationSection, FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(),"Must specify a config section"));
return new RandomPotionEffectListData((ConfigurationSection) object);
}
@ -74,11 +76,10 @@ public class Effects extends ItemStat {
@Override
public void whenInput(@NotNull EditionInventory inv, @NotNull String message, Object... info) {
String[] split = message.split("\\|");
Validate.isTrue(split.length > 1, "Use this format: {Potion Effect Name}|{Duration Numeric Formula}|{Amplifier Numeric Formula}.");
Validate.isTrue(split.length > 1, FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(),"Use this format: $e{Potion Effect Name}|{Duration Numeric Formula}|{Amplifier Numeric Formula}$b."));
PotionEffectType effect = PotionEffectType.getByName(split[0].replace("-", "_").replace(" ", "_").toUpperCase());
Validate.notNull(effect, split[0] + " is not a valid potion effect. All potion effects "
+ "can be found here: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/potion/PotionEffectType.html");
Validate.notNull(effect, split[0] + FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get()," is not a valid potion effect. All potion effects can be found here:$e https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/potion/PotionEffectType.html"));
NumericStatFormula duration = new NumericStatFormula(split[1]);
NumericStatFormula amplifier = split.length > 2 ? new NumericStatFormula(split[2]) : new NumericStatFormula(1, 0, 0, 0);

View File

@ -2,7 +2,18 @@ package net.Indyuce.mmoitems.stat;
import java.util.*;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
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;
import io.lumine.mythic.lib.api.util.ui.PlusMinusPercent;
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
import net.Indyuce.mmoitems.api.util.message.FriendlyFeedbackPalette_MMOItems;
import net.Indyuce.mmoitems.stat.data.DoubleData;
import net.Indyuce.mmoitems.stat.data.type.UpgradeInfo;
import net.Indyuce.mmoitems.stat.type.DoubleStat;
import net.Indyuce.mmoitems.stat.type.Upgradable;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Material;
@ -29,7 +40,7 @@ import io.lumine.mythic.lib.api.util.AltChar;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Enchants extends ItemStat {
public class Enchants extends ItemStat implements Upgradable {
public Enchants() {
super("ENCHANTS", Material.ENCHANTED_BOOK, "Enchantments", new String[] { "The item enchants." }, new String[] { "all" });
}
@ -110,35 +121,308 @@ public class Enchants extends ItemStat {
// Create enchant data from this items' enchantments
EnchantListData enchants = new EnchantListData();
mmoitem.getNBT().getItem().getItemMeta().getEnchants().keySet()
.forEach(enchant -> enchants.addEnchant(enchant, mmoitem.getNBT().getItem().getItemMeta().getEnchantLevel(enchant)));
if (enchants.getEnchants().size() > 0)
mmoitem.setData(ItemStats.ENCHANTS, enchants);
// For each enchantment
for (Enchantment enchant : mmoitem.getNBT().getItem().getItemMeta().getEnchants().keySet()) {
// Add Level
enchants.addEnchant(enchant, mmoitem.getNBT().getItem().getItemMeta().getEnchantLevel(enchant));
}
// If there was any enchantments, recognize the Stat Data
if (enchants.getEnchants().size() > 0) { mmoitem.setData(ItemStats.ENCHANTS, enchants); }
}
/**
* This is not writen into a custom tag, rather saved into the item's enchantments themselves.
* Thus this returns null.
* Since GemStones shall be removable, the enchantments must also be stored.
*/
@Nullable
@Override
public StatData getLoadedNBT(@NotNull ArrayList<ItemTag> storedTags) { return null; }
public StatData getLoadedNBT(@NotNull ArrayList<ItemTag> storedTags) {
// Find tag
ItemTag enchantTag = ItemTag.getTagAtPath(getNBTPath(), storedTags);
// Found?
if (enchantTag != null) {
// Must be thay string list shit
ArrayList<String> enchants = ItemTag.getStringListFromTag(enchantTag);
// New
EnchantListData data = new EnchantListData();
// Examine each
for (String str : enchants) {
// Split
String[] split = str.split(" ");
if (split.length >= 2) {
// Find
String enchantment = split[0];
String level = split[1];
// Get Namespaced
Enchantment ench = null;
try { ench = Enchantment.getByKey(NamespacedKey.minecraft(enchantment)); } catch (Exception ignored) {}
// Parse Integer
Integer lvl = SilentNumbers.IntegerParse(level);
// Worked?
if (ench != null && lvl != null) {
// Add
data.addEnchant(ench, lvl);
}
}
}
// Thats it
return data;
}
return null;
}
@Override
public void whenApplied(@NotNull ItemStackBuilder item, @NotNull StatData data) {
// Enchant Item
EnchantListData enchants = (EnchantListData) data;
for (Enchantment enchant : enchants.getEnchants())
item.getMeta().addEnchant(enchant, enchants.getLevel(enchant), true);
for (Enchantment enchant : enchants.getEnchants()) { item.getMeta().addEnchant(enchant, enchants.getLevel(enchant), true); }
// Apply tags
item.addItemTag(getAppliedNBT(data));
}
/**
* This is not writen into a custom tag, rather saved into the item's enchantments themselves.
* Thus this returns an empty list
* Since GemStones shall be removable, the enchantments must also be stored.
*/
@NotNull
@Override
public ArrayList<ItemTag> getAppliedNBT(@NotNull StatData data) { return new ArrayList<>(); }
public ArrayList<ItemTag> getAppliedNBT(@NotNull StatData data) {
ArrayList<ItemTag> ret = new ArrayList<>();
// Add enchantment pair data
ArrayList<String> enchantments = new ArrayList<>();
for (Enchantment enchantment : ((EnchantListData) data).getEnchants()) {
enchantments.add(enchantment.getKey().getKey() + " " + ((EnchantListData) data).getLevel(enchantment)); }
// Add that one tag
ret.add(ItemTag.fromStringList(getNBTPath(), enchantments));
return ret;
}
@NotNull
@Override
public UpgradeInfo loadUpgradeInfo(@Nullable Object obj) throws IllegalArgumentException {
//UPGRD//MMOItems. Log("\u00a7a --> \u00a77Loading Enchants");
return EnchantUpgradeInfo.GetFrom(obj);
}
@NotNull
@Override
public StatData apply(@NotNull StatData original, @NotNull UpgradeInfo info, int level) {
//UPGRD//MMOItems. Log("\u00a7a --> \u00a77Applying Enchants Upgrade");
// Must be DoubleData
if (original instanceof EnchantListData && info instanceof EnchantUpgradeInfo) {
//UPGRD//MMOItems. Log("\u00a7a -> \u00a77Valid Instances");
// Get value
EnchantListData dataEnchants = ((EnchantListData) original);
EnchantUpgradeInfo eui = (EnchantUpgradeInfo) info;
// For every enchantment
for (Enchantment e : eui.getAffectedEnchantments()) {
int lSimulation = level;
//UPGRD//MMOItems. Log("\u00a7b >\u00a79> \u00a77Enchantment \u00a7f" + e.getName());
// Get current level
double value = dataEnchants.getLevel(e);
//UPGRD//MMOItems. Log("\u00a7b -> \u00a77Original Level \u00a7f" + value);
PlusMinusPercent pmp = eui.getPMP(e);
if (pmp == null) { continue; }
//UPGRD//MMOItems. Log("\u00a7b -> \u00a77Operation \u00a7f" + pmp.toString());
// If leveling up
if (lSimulation > 0) {
// While still positive
while (lSimulation > 0) {
// Apply PMP Operation Positively
//UPGRD//MMOItems. Log("\u00a7c -> \u00a77Preop \u00a7f" + value);
//UPGRD//MMOItems. Log("\u00a78 -> Operation \u00a77" + pmp.toString());
value = pmp.apply(value);
//UPGRD//MMOItems. Log("\u00a76 -> \u00a77Postop \u00a7f" + value);
//UPGRD//MMOItems. Log("\u00a77 -> \u00a77------------------");
// Decrease
lSimulation--;
}
// Degrading the item
} else if (lSimulation < 0) {
// While still negative
while (lSimulation < 0) {
// Apply PMP Operation Reversibly
//UPGRD//MMOItems. Log("\u00a73 -> \u00a77Preop \u00a7f" + value);
value = pmp.reverse(value);
//UPGRD//MMOItems. Log("\u00a7d -> \u00a77Postop \u00a7f" + value);
//UPGRD//MMOItems. Log("\u00a77 -> \u00a77------------------");
// Decrease
lSimulation++;
}
}
// Update
//UPGRD//MMOItems. Log("\u00a7b -> \u00a77Final level \u00a7f" + value);
dataEnchants.addEnchant(e, SilentNumbers.Round(value));
}
// Yes
return dataEnchants;
}
// Upgraded
return original;
}
public static class EnchantUpgradeInfo implements UpgradeInfo {
@NotNull HashMap<Enchantment, PlusMinusPercent> perEnchantmentOperations = new HashMap<>();
/**
* Generate a <code>DoubleUpgradeInfo</code> from this <code><b>String List</b></code>
* that represents several pairs of {@link Enchantment}-{@link PlusMinusPercent}.
* <p></p>
* To keep older MMOItems versions working the same way, instead of having no prefix
* to use the <i>set</i> function of the PMP, one must use an <b><code>s</code></b> prefix.
* @param obj A <code><u>String List</u></code> in the format:
* <p><code>Enchantment PMP</code>
* </p><code>Enchantment PMP</code>
* <p><code>Enchantment PMP</code>
* </p><code>...</code>
* @throws IllegalArgumentException If any part of the operation goes wrong (including reading any PMP).
*/
@NotNull public static EnchantUpgradeInfo GetFrom(@Nullable Object obj) throws IllegalArgumentException {
// Shall not be null
Validate.notNull(obj, FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), "Upgrade operation list must not be null"));
// Does the string exist?
if (!(obj instanceof List)) {
// Throw exception
throw new IllegalArgumentException(
FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), "Expected a list of strings instead of $i{0}", obj.toString()));
}
ArrayList<String> strlst = new ArrayList<>(); boolean failure = false;
StringBuilder unreadableStatements = new StringBuilder();
for (Object entry : (List) obj) {
// Only strings
if (entry instanceof String) {
strlst.add((String) entry);
} else {
// No
failure = true;
// Append info
unreadableStatements.append(FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), " Invalid list entry $i{0}$b;", obj.toString()));
}
}
if (failure) {
// Throw exception
throw new IllegalArgumentException(
FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), "Could not read enchantment list:") + unreadableStatements.toString());
}
// No empty lists
if (strlst.isEmpty()) {
throw new IllegalArgumentException(
FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), "Upgrade operation list is empty"));
}
// Create ret
EnchantUpgradeInfo eui = new EnchantUpgradeInfo();
for (String str : strlst) {
//UPGRD//MMOItems. Log("\u00a7e --> \u00a77Entry \u00a76" + str);
String[] split = str.split(" ");
// At least two
if (split.length >= 2) {
// Get
String enchStr = split[0];
String pmpStr = split[1];
// Adapt to PMP format
char c = pmpStr.charAt(0); if (c == 's') { pmpStr = pmpStr.substring(1); } else if (c != '+' && c != '-' && c != 'n') { pmpStr = '+' + pmpStr; }
// Is it a valid plus minus percent?
FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FriendlyFeedbackPalette_MMOItems.get());
PlusMinusPercent pmpRead = PlusMinusPercent.getFromString(pmpStr, ffp);
Enchantment ench = null;
try { ench = Enchantment.getByKey(NamespacedKey.minecraft(enchStr)); } catch (Exception ignored) {}
// L
if (pmpRead == null) { unreadableStatements.append(' ').append(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR).get(0).forConsole(ffp.getPalette())); failure = true; }
if (ench == null) { unreadableStatements.append(FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), " Invalid Enchantment $i{0}$b.", enchStr)); failure = true; }
// Valid? add
if (pmpRead != null && ench != null) {
//UPGRD//MMOItems. Log("\u00a7a s-> \u00a77Added");
eui.addEnchantmentOperation(ench, pmpRead);
}
// Not enough arguments to be read
} else {
// Nope
failure = true;
unreadableStatements.append(FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), " Invalid list entry $i{0}$b. List entries are of the format 'esharpness +1$b'.", str));
}
}
if (failure) {
// Throw exception
throw new IllegalArgumentException(
FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), "Could not read enchantment list:") + unreadableStatements.toString());
}
// Success
return eui;
}
public EnchantUpgradeInfo() { }
/**
* The operation every level will perform.
* @see PlusMinusPercent
*/
@Nullable public PlusMinusPercent getPMP(@NotNull Enchantment ench) { return perEnchantmentOperations.get(ench); }
/**
* Includes an enchantment to be upgraded by this template.
*/
public void addEnchantmentOperation(@NotNull Enchantment e, @NotNull PlusMinusPercent op) { perEnchantmentOperations.put(e, op); }
/**
* Which enchantments have operations defined here?
*/
@NotNull public Set<Enchantment> getAffectedEnchantments() { return perEnchantmentOperations.keySet(); }
}
}

View File

@ -8,6 +8,7 @@ import java.util.Random;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -173,7 +174,7 @@ public class UpgradeStat extends ItemStat implements ConsumableItemInteraction {
VolatileMMOItem mmoitem = consumable.getMMOItem();
Player player = playerData.getPlayer();
if (mmoitem.hasData(ItemStats.UPGRADE) && target.hasTag("MMOITEMS_UPGRADE")) {
if (mmoitem.hasData(ItemStats.UPGRADE) && target.hasTag(ItemStats.UPGRADE.getNBTPath())) {
if (target.getItem().getAmount() > 1) {
Message.CANT_UPGRADED_STACK.format(ChatColor.RED).send(player);
player.playSound(player.getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 2);

View File

@ -10,6 +10,7 @@ import org.bukkit.enchantments.Enchantment;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class EnchantListData implements StatData, Mergeable {
private final Map<Enchantment, Integer> enchants = new HashMap<>();
@ -18,7 +19,8 @@ public class EnchantListData implements StatData, Mergeable {
return enchants.keySet();
}
public int getLevel(Enchantment enchant) {
public int getLevel(@NotNull Enchantment enchant) {
if (!enchants.containsKey(enchant)) { return 0; }
return enchants.get(enchant);
}

View File

@ -9,6 +9,7 @@ import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import io.lumine.mythic.lib.MythicLib;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -115,6 +116,7 @@ public class UpgradeData implements StatData, RandomStatData {
nameData.setString(level == 0 ? nameData.toString() + suffix.replace("#lvl#", "" + (level + 1))
: nameData.toString().replace(suffix.replace("#lvl#", "" + level), suffix.replace("#lvl#", "" + (level + 1))));
}
/*TODO: implement this as a new dynamic lore type
else if (mmoitem.hasData(ItemStats.LORE)) {
StringListData loreData = (StringListData) mmoitem.getData(ItemStats.LORE);

View File

@ -4,21 +4,73 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.api.util.message.FriendlyFeedbackPalette_MMOItems;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.stat.data.PotionEffectListData;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import org.bukkit.potion.PotionEffectType;
public class RandomPotionEffectListData implements RandomStatData {
private final List<RandomPotionEffectData> effects = new ArrayList<>();
boolean containsObsoleteConfigurations = false;
public void MarkForSaveAll() { containsObsoleteConfigurations = true; }
public boolean isMarkedForSaveAll() { return containsObsoleteConfigurations; }
public RandomPotionEffectListData(ConfigurationSection config) {
Validate.notNull(config, "Config cannot be null");
for (String key : config.getKeys(false))
this.effects.add(new RandomPotionEffectData(config.getConfigurationSection(key)));
// For every config section
for (String key : config.getKeys(false)) {
ConfigurationSection asSection = config.getConfigurationSection(key);
// Valid?
if (asSection != null) {
this.effects.add(new RandomPotionEffectData(asSection));
// Attempt legacy way: EFFECT: 22,8
} else {
// Must have at least two members
String spl = config.getString(key);
if (spl != null) {
String[] split = spl.split(",");
if (split.length >= 1) {
// Firstone a double, scond an integer
Double duration = SilentNumbers.DoubleParse(split[0]);
Integer amplifier = SilentNumbers.IntegerParse(split[1]);
PotionEffectType effect = PotionEffectType.getByName(key.toUpperCase().replace("-", "_").replace(" ", "_"));
// Valid?
if (duration != null && amplifier != null && effect != null) {
// Parsed OG
effects.add(new RandomPotionEffectData(effect, new NumericStatFormula(duration), new NumericStatFormula(amplifier)));
// L
} else {
throw new IllegalArgumentException(FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), "Incorrect format, expected $e{Effect}: {Duration},{Amplifier}$b instead of $i{0} {1}$b.", key, spl));
}
// L
} else {
throw new IllegalArgumentException(FriendlyFeedbackProvider.QuickForConsole(FriendlyFeedbackPalette_MMOItems.get(), "Incorrect format, expected $e{Effect}: {Duration},{Amplifier}$b instead of $i{0} {1}$b.", key, spl));
}
} else {
throw new IllegalArgumentException("Config cannot be null");
}
}
}
}
public RandomPotionEffectListData(RandomPotionEffectData... effects) {

View File

@ -125,9 +125,9 @@ public class StatHistory<S extends StatData> {
// Found? Thats it
if (hist != null) {
//GEM////UPGRD//MMOItems. Log("Found Stat History of \u00a76" + ofStat.getNBTPath() + "\u00a77 in this \u00a7c" + ofItem.getType().getName() + " " + ofItem.getId());
//UPGRD//MMOItems. Log("Found Stat History of \u00a76" + ofStat.getNBTPath() + "\u00a77 in this \u00a7c" + ofItem.getType().getName() + " " + ofItem.getId());
return hist; }
//GEM////UPGRD//MMOItems. Log("\u00a7aCreated Hisotry of \u00a76" + ofStat.getNBTPath() + "\u00a7a of this \u00a7c" + ofItem.getType().getName() + " " + ofItem.getId());
//UPGRD//MMOItems. Log("\u00a7aCreated Hisotry of \u00a76" + ofStat.getNBTPath() + "\u00a7a of this \u00a7c" + ofItem.getType().getName() + " " + ofItem.getId());
// That is Mergeable right...
Validate.isTrue(ofStat.getClearStatData() instanceof Mergeable, "Non-Mergeable stat data wont have a Stat History; they cannot be modified dynamically in the first place.");
@ -136,11 +136,11 @@ public class StatHistory<S extends StatData> {
StatData original = ofItem.getData(ofStat);
if (original == null) {
original = ofStat.getClearStatData();
//GEM// //UPGRD//MMOItems. Log("\u00a7e +\u00a77 Item didnt have this stat, original set as blanc.");
//UPGRD//MMOItems. Log("\u00a7e +\u00a77 Item didnt have this stat, original set as blanc.");
}
else {
original = ((Mergeable) original).cloneData();
//GEM////UPGRD//MMOItems. Log("\u00a7a +\u00a77 Found original data");
//UPGRD//MMOItems. Log("\u00a7a +\u00a77 Found original data");
}
// Create new