MMOItems 7 now compiles. Beginning of (dynamic) map components

This commit is contained in:
Jules 2025-01-09 01:58:34 +01:00
parent 9301f2269b
commit a9726c633c
87 changed files with 1837 additions and 1659 deletions

View File

@ -3,230 +3,231 @@ package net.Indyuce.mmoitems;
import io.lumine.mythic.lib.version.VMaterial;
import net.Indyuce.mmoitems.stat.*;
import net.Indyuce.mmoitems.stat.block.*;
import net.Indyuce.mmoitems.stat.component.builtin.*;
import net.Indyuce.mmoitems.stat.component.builtin.api.*;
import net.Indyuce.mmoitems.stat.type.*;
import org.bukkit.Material;
/**
* A central file for the plugin since new stats are added ALL the time.
* It is also much safer to initialize class objects OUTSIDE of the field type class.
* A central file for all hard-coded item stats and options.
*/
@SuppressWarnings("unused")
public class ItemStats {
// Main Item Stats
public static final ItemStat
REVISION_ID = new RevisionID(),
MATERIAL = new MaterialStat(),
SKULL_TEXTURE = new SkullTextureStat(),
ITEM_DAMAGE = new ItemDamage(),
CUSTOM_MODEL_DATA = new CustomModelData(),
MAX_DURABILITY = new MaximumDurability(),
MAX_ITEM_DAMAGE = new MaxItemDamage(),
WILL_BREAK = new LostWhenBroken(),
NAME = new DisplayName(),
LORE = new Lore(),
NBT_TAGS = new NBTTags(),
MAX_STACK_SIZE = new MaxStackSize(),
CAN_BREAK = new CanBreak(),
LORE_FORMAT = new LoreFormat(),
TOOLTIP = new TooltipStat(),
public static final ItemStat<DoubleComponent> REVISION_ID = new RevisionID();
public static final ItemStat<MaterialComponent> MATERIAL = new MaterialStat();
public static final ItemStat<SkullTextureComponent> SKULL_TEXTURE = new SkullTextureStat();
public static final ItemStat<DoubleComponent> ITEM_DAMAGE = new ItemDamage();
public static final ItemStat<IntegerComponent> CUSTOM_MODEL_DATA = new CustomModelData();
public static final ItemStat<IntegerComponent> MAX_DURABILITY = new MaximumDurability();
public static final ItemStat<IntegerComponent> MAX_ITEM_DAMAGE = new MaxItemDamage();
public static final ItemStat<BooleanComponent> WILL_BREAK = new LostWhenBroken();
public static final ItemStat<StringComponent> NAME = new DisplayName();
public static final ItemStat<ArrayComponent<StringComponent>> LORE = new Lore();
public static final ItemStat<ArrayComponent<StringComponent>> NBT_TAGS = new NBTTags();
public static final ItemStat<IntegerComponent> MAX_STACK_SIZE = new MaxStackSize();
public static final ItemStat<ArrayComponent<MaterialComponent>> CAN_BREAK = new CanBreak();
public static final ItemStat<StringComponent> LORE_FORMAT = new LoreFormat();
public static final ItemStat<StringComponent> TOOLTIP = new TooltipStat();
// Block Specific Stats
BLOCK_ID = new BlockID(),
REQUIRED_POWER = new RequiredPower(),
REQUIRE_POWER_TO_BREAK = new RequirePowerToBreak(),
MIN_XP = new MinXP(),
MAX_XP = new MaxXP(),
GEN_TEMPLATE = new GenTemplate(),
public static final ItemStat<DoubleComponent> BLOCK_ID = new BlockID();
public static final ItemStat<DoubleComponent> REQUIRED_POWER = new RequiredPower();
public static final ItemStat<BooleanComponent> REQUIRE_POWER_TO_BREAK = new RequirePowerToBreak();
public static final ItemStat<DoubleComponent> MIN_XP = new MinXP();
public static final ItemStat<DoubleComponent> MAX_XP = new MaxXP();
public static final ItemStat<StringComponent> GEN_TEMPLATE = new GenTemplate();
// Misc Stats
DISPLAYED_TYPE = new DisplayedType(),
ENCHANTS = new Enchants(),
HIDE_ENCHANTS = new HideEnchants(),
PERMISSION = new Permission(),
ITEM_PARTICLES = new ItemParticles(),
ARROW_PARTICLES = new ArrowParticles(),
PROJECTILE_PARTICLES = new ProjectileParticles(),
public static final ItemStat<StringComponent> DISPLAYED_TYPE = new DisplayedType();
public static final ItemStat ENCHANTS = new Enchants();
public static final ItemStat<BooleanComponent> HIDE_ENCHANTS = new HideEnchants();
public static final ItemStat<ArrayComponent<StringComponent>> PERMISSION = new Permission();
public static final ItemStat<ObjectComponent> ITEM_PARTICLES = new ItemParticles();
public static final ItemStat<ObjectComponent> ARROW_PARTICLES = new ArrowParticles();
public static final ItemStat<ObjectComponent> PROJECTILE_PARTICLES = new ProjectileParticles();
// Disable Interaction Stats
DISABLE_INTERACTION = new DisableStat("INTERACTION", VMaterial.GRASS_BLOCK.get(), "Disable Interaction", "Disable any unwanted interaction: block placement, item use...", new String[]{"!block", "all"}),
DISABLE_CRAFTING = new DisableStat("CRAFTING", Material.CRAFTING_TABLE, "Disable Crafting", "Players can't use this item while crafting.", null),
DISABLE_SMELTING = new DisableStat("SMELTING", Material.FURNACE, "Disable Smelting", "Players can't use this item in furnaces.", null),
DISABLE_SMITHING = new DisableStat("SMITHING", Material.DAMAGED_ANVIL, "Disable Smithing", "Players can't smith this item in smithing tables.", null),
DISABLE_ENCHANTING = new DisableStat("ENCHANTING", Material.ENCHANTING_TABLE, "Disable Enchanting", "Players can't enchant this item.", new String[]{"!block", "all"}),
DISABLE_REPAIRING = new DisableStat("REPAIRING", Material.ANVIL, "Disable Repairing", "Players can't use this item in anvils.", new String[]{"!block", "all"}),
DISABLE_ARROW_SHOOTING = new DisableStat("ARROW_SHOOTING", Material.ARROW, "Disable Arrow Shooting", "Players can't shoot this item using a bow.", null).setCompatibleMaterials(Material.ARROW),
DISABLE_DROP = new DisableStat("DROPING", Material.LAVA_BUCKET, "Disable Item Dropping", "Disables the dropping of this item!", null),
DISABLE_ARROW_CONSUMPTION = new DisableStat("ARROW_CONSUMPTION", Material.ARROW, "Disable Arrow Consumption", "Disable arrow requirement and consumption.", new String[]{"crossbow"}),
public static final ItemStat DISABLE_INTERACTION = new DisableStat("INTERACTION", VMaterial.GRASS_BLOCK.get(), "Disable Interaction", "Disable any unwanted interaction: block placement, item use...", new String[]{"!block", "all"});
public static final ItemStat DISABLE_CRAFTING = new DisableStat("CRAFTING", Material.CRAFTING_TABLE, "Disable Crafting", "Players can't use this item while crafting.", null);
public static final ItemStat DISABLE_SMELTING = new DisableStat("SMELTING", Material.FURNACE, "Disable Smelting", "Players can't use this item in furnaces.", null);
public static final ItemStat DISABLE_SMITHING = new DisableStat("SMITHING", Material.DAMAGED_ANVIL, "Disable Smithing", "Players can't smith this item in smithing tables.", null);
public static final ItemStat DISABLE_ENCHANTING = new DisableStat("ENCHANTING", Material.ENCHANTING_TABLE, "Disable Enchanting", "Players can't enchant this item.", new String[]{"!block", "all"});
public static final ItemStat DISABLE_REPAIRING = new DisableStat("REPAIRING", Material.ANVIL, "Disable Repairing", "Players can't use this item in anvils.", new String[]{"!block", "all"});
public static final ItemStat DISABLE_ARROW_SHOOTING = new DisableStat("ARROW_SHOOTING", Material.ARROW, "Disable Arrow Shooting", "Players can't shoot this item using a bow.", null).setCompatibleMaterials(Material.ARROW);
public static final ItemStat DISABLE_DROP = new DisableStat("DROPING", Material.LAVA_BUCKET, "Disable Item Dropping", "Disables the dropping of this item!", null);
public static final ItemStat DISABLE_ARROW_CONSUMPTION = new DisableStat("ARROW_CONSUMPTION", Material.ARROW, "Disable Arrow Consumption", "Disable arrow requirement and consumption.", new String[]{"crossbow"});
// Special item interactions/skills
LEFT_CLICK_SCRIPT = new ActionLeftClick(),
RIGHT_CLICK_SCRIPT = new ActionRightClick(),
DISABLE_ATTACK_PASSIVE = new DisableStat("ATTACK_PASSIVE", Material.BARRIER, "Disable On-Hit Effect", "Disables on-hit effects granted by the item type.", new String[]{"weapon"}),
public static final ItemStat// Special item interactions/skills
LEFT_CLICK_SCRIPT = new ActionLeftClick();
public static final ItemStat RIGHT_CLICK_SCRIPT = new ActionRightClick();
public static final ItemStat DISABLE_ATTACK_PASSIVE = new DisableStat("ATTACK_PASSIVE", Material.BARRIER, "Disable On-Hit Effect", "Disables on-hit effects granted by the item type.", new String[]{"weapon"});
// RPG Stats
REQUIRED_LEVEL = new RequiredLevel(),
REQUIRED_CLASS = new RequiredClass(),
ATTACK_DAMAGE = new AttackDamage(),
ATTACK_SPEED = new AttackSpeed(),
CRITICAL_STRIKE_CHANCE = new DoubleStat("CRITICAL_STRIKE_CHANCE", Material.NETHER_STAR, "Critical Strike Chance", "Critical Strikes deal more damage, in % chance.", new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
CRITICAL_STRIKE_POWER = new DoubleStat("CRITICAL_STRIKE_POWER", Material.NETHER_STAR, "Critical Strike Power", new String[]{"The extra damage weapon crits deals.", "(Stacks with default value)", "In %."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
SKILL_CRITICAL_STRIKE_CHANCE = new DoubleStat("SKILL_CRITICAL_STRIKE_CHANCE", Material.NETHER_STAR, "Skill Critical Strike Chance", new String[]{"Increases the chance of dealing skill crits (in %)."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
SKILL_CRITICAL_STRIKE_POWER = new DoubleStat("SKILL_CRITICAL_STRIKE_POWER", Material.NETHER_STAR, "Skill Critical Strike Power", new String[]{"Extra damage dealt (in %) by skill crits.", "(Stacks with default value)", "In %."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
BLOCK_POWER = new DoubleStat("BLOCK_POWER", Material.IRON_HELMET, "Block Power", new String[]{"The % of the damage your", "armor/shield can block.", "Default: 25%"}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
BLOCK_RATING = new DoubleStat("BLOCK_RATING", Material.IRON_HELMET, "Block Rating", new String[]{"The chance your piece of armor", "has to block any entity attack."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
BLOCK_COOLDOWN_REDUCTION = new DoubleStat("BLOCK_COOLDOWN_REDUCTION", Material.IRON_HELMET, "Block Cooldown Reduction", new String[]{"Reduces the blocking cooldown (%)."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
DODGE_RATING = new DoubleStat("DODGE_RATING", Material.FEATHER, "Dodge Rating", new String[]{"The chance to dodge an attack.", "Dodging completely negates", "the attack damage."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
DODGE_COOLDOWN_REDUCTION = new DoubleStat("DODGE_COOLDOWN_REDUCTION", Material.FEATHER, "Dodge Cooldown Reduction", new String[]{"Reduces the dodging cooldown (%)."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
PARRY_RATING = new DoubleStat("PARRY_RATING", Material.BUCKET, "Parry Rating", new String[]{"The chance to parry an attack.", "Parrying negates the damage", "and knocks the attacker back."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
PARRY_COOLDOWN_REDUCTION = new DoubleStat("PARRY_COOLDOWN_REDUCTION", Material.BUCKET, "Parry Cooldown Reduction", new String[]{"Reduces the parrying cooldown (%)."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE),
COOLDOWN_REDUCTION = new DoubleStat("COOLDOWN_REDUCTION", Material.BOOK, "Cooldown Reduction", new String[]{"Reduces cooldowns of item and player skills (%)."}).setCategory(StatCategories.OFFENSE),
RANGE = new DoubleStat("RANGE", Material.STICK, "Range", new String[]{"The range of your item attacks."}, new String[]{"staff", "whip", "wand", "musket", "gem_stone"}).setCategory(StatCategories.RANGED_WEAPONS),
MANA_COST = new ManaCost(),
STAMINA_COST = new DoubleStat("STAMINA_COST", Material.LIGHT_GRAY_DYE, "Stamina Cost", new String[]{"Stamina spent by your weapon to be used."}, new String[]{"weapon"}).setCategory(StatCategories.USE_COST),
ARROW_VELOCITY = new DoubleStat("ARROW_VELOCITY", Material.ARROW, "Arrow Velocity", new String[]{"Determines how far your", "weapon can shoot.", "Default: 1.0"}, new String[]{"gem_stone", "bow", "crossbow"}).setCategory(StatCategories.RANGED_WEAPONS),
ARROW_POTION_EFFECTS = new ArrowPotionEffects(),
PVE_DAMAGE = new DoubleStat("PVE_DAMAGE", Material.PORKCHOP, "PvE Damage", new String[]{"Additional damage against", "non human entities in %."}, new String[]{"equipment", "gem_stone"}).setCategory(StatCategories.OFFENSE),
PVP_DAMAGE = new DoubleStat("PVP_DAMAGE", Material.SKELETON_SKULL, "PvP Damage", new String[]{"Additional damage", "against players in %."}, new String[]{"equipment", "gem_stone"}).setCategory(StatCategories.OFFENSE),
BLUNT_POWER = new DoubleStat("BLUNT_POWER", Material.IRON_AXE, "Blunt Power", new String[]{"The radius of the AoE attack.", "If set to 2.0, enemies within 2 blocks", "around your target will take damage.", "&9This stat only applies to Blunt weapons."}, new String[]{"weapon", "gem_stone"}).setCategory(StatCategories.DAMAGE_MITIGATION),
BLUNT_RATING = new DoubleStat("BLUNT_RATING", Material.BRICK, "Blunt Rating", new String[]{"The force of the blunt attack.", "If set to 50%, enemies hit by the attack", "will take 50% of the initial damage.", "&9This stat only applies to Blunt weapons."}, new String[]{"weapon", "gem_stone"}).setCategory(StatCategories.DAMAGE_MITIGATION),
WEAPON_DAMAGE = new DoubleStat("WEAPON_DAMAGE", Material.IRON_SWORD, "Weapon Damage", new String[]{"Additional on-hit weapon damage in %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
SKILL_DAMAGE = new DoubleStat("SKILL_DAMAGE", Material.BOOK, "Skill Damage", new String[]{"Additional ability damage in %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
PROJECTILE_DAMAGE = new DoubleStat("PROJECTILE_DAMAGE", Material.ARROW, "Projectile Damage", new String[]{"Additional skill/weapon projectile damage."}).setCategory(StatCategories.DAMAGE_MITIGATION),
MAGIC_DAMAGE = new DoubleStat("MAGIC_DAMAGE", Material.MAGMA_CREAM, "Magic Damage", new String[]{"Additional magic skill damage in %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
PHYSICAL_DAMAGE = new DoubleStat("PHYSICAL_DAMAGE", Material.IRON_AXE, "Physical Damage", new String[]{"Additional skill/weapon physical damage."}).setCategory(StatCategories.DAMAGE_MITIGATION),
DEFENSE = new DoubleStat("DEFENSE", Material.SHIELD, "Defense", new String[]{"Reduces damage from any source.", "Formula can be set in MMOLib Config."}).setCategory(StatCategories.DAMAGE_MITIGATION),
DAMAGE_REDUCTION = new DoubleStat("DAMAGE_REDUCTION", Material.IRON_CHESTPLATE, "Damage Reduction", new String[]{"Reduces damage from any source.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
FALL_DAMAGE_REDUCTION = new DoubleStat("FALL_DAMAGE_REDUCTION", Material.FEATHER, "Fall Damage Reduction", new String[]{"Reduces fall damage.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
PROJECTILE_DAMAGE_REDUCTION = new DoubleStat("PROJECTILE_DAMAGE_REDUCTION", Material.SNOWBALL, "Projectile Damage Reduction", new String[]{"Reduces projectile damage.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
PHYSICAL_DAMAGE_REDUCTION = new DoubleStat("PHYSICAL_DAMAGE_REDUCTION", Material.LEATHER_CHESTPLATE, "Physical Damage Reduction", new String[]{"Reduces physical damage.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
FIRE_DAMAGE_REDUCTION = new DoubleStat("FIRE_DAMAGE_REDUCTION", Material.BLAZE_POWDER, "Fire Damage Reduction", new String[]{"Reduces fire damage.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
MAGIC_DAMAGE_REDUCTION = new DoubleStat("MAGIC_DAMAGE_REDUCTION", Material.POTION, "Magic Damage Reduction", new String[]{"Reduce magic damage dealt by potions.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
PVE_DAMAGE_REDUCTION = new DoubleStat("PVE_DAMAGE_REDUCTION", Material.PORKCHOP, "PvE Damage Reduction", new String[]{"Reduces damage dealt by mobs.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
PVP_DAMAGE_REDUCTION = new DoubleStat("PVP_DAMAGE_REDUCTION", Material.SKELETON_SKULL, "PvP Damage Reduction", new String[]{"Reduces damage dealt by players", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION),
UNDEAD_DAMAGE = new DoubleStat("UNDEAD_DAMAGE", Material.SKELETON_SKULL, "Undead Damage", new String[]{"Deals additional damage to undead.", "In %."}).setCategory(StatCategories.OFFENSE),
LIFESTEAL = new DoubleStat("LIFESTEAL", Material.REDSTONE, "Lifesteal", new String[]{"Percentage of damage you gain back as", "health when inflicting weapon damage."}).setCategory(StatCategories.OFFENSE),
SPELL_VAMPIRISM = new DoubleStat("SPELL_VAMPIRISM", Material.REDSTONE, "Spell Vampirism", new String[]{"Percentage of damage you gain back as", "health when inflicting skill damage."}).setCategory(StatCategories.OFFENSE),
public static final ItemStat// RPG Stats
REQUIRED_LEVEL = new RequiredLevel();
public static final ItemStat REQUIRED_CLASS = new RequiredClass();
public static final ItemStat ATTACK_DAMAGE = new AttackDamage();
public static final ItemStat ATTACK_SPEED = new AttackSpeed();
public static final ItemStat CRITICAL_STRIKE_CHANCE = new DoubleStat("CRITICAL_STRIKE_CHANCE", Material.NETHER_STAR, "Critical Strike Chance", "Critical Strikes deal more damage, in % chance.", new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat CRITICAL_STRIKE_POWER = new DoubleStat("CRITICAL_STRIKE_POWER", Material.NETHER_STAR, "Critical Strike Power", new String[]{"The extra damage weapon crits deals.", "(Stacks with default value)", "In %."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat SKILL_CRITICAL_STRIKE_CHANCE = new DoubleStat("SKILL_CRITICAL_STRIKE_CHANCE", Material.NETHER_STAR, "Skill Critical Strike Chance", new String[]{"Increases the chance of dealing skill crits (in %)."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat SKILL_CRITICAL_STRIKE_POWER = new DoubleStat("SKILL_CRITICAL_STRIKE_POWER", Material.NETHER_STAR, "Skill Critical Strike Power", new String[]{"Extra damage dealt (in %) by skill crits.", "(Stacks with default value)", "In %."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat BLOCK_POWER = new DoubleStat("BLOCK_POWER", Material.IRON_HELMET, "Block Power", new String[]{"The % of the damage your", "armor/shield can block.", "Default: 25%"}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat BLOCK_RATING = new DoubleStat("BLOCK_RATING", Material.IRON_HELMET, "Block Rating", new String[]{"The chance your piece of armor", "has to block any entity attack."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat BLOCK_COOLDOWN_REDUCTION = new DoubleStat("BLOCK_COOLDOWN_REDUCTION", Material.IRON_HELMET, "Block Cooldown Reduction", new String[]{"Reduces the blocking cooldown (%)."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat DODGE_RATING = new DoubleStat("DODGE_RATING", Material.FEATHER, "Dodge Rating", new String[]{"The chance to dodge an attack.", "Dodging completely negates", "the attack damage."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat DODGE_COOLDOWN_REDUCTION = new DoubleStat("DODGE_COOLDOWN_REDUCTION", Material.FEATHER, "Dodge Cooldown Reduction", new String[]{"Reduces the dodging cooldown (%)."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat PARRY_RATING = new DoubleStat("PARRY_RATING", Material.BUCKET, "Parry Rating", new String[]{"The chance to parry an attack.", "Parrying negates the damage", "and knocks the attacker back."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat PARRY_COOLDOWN_REDUCTION = new DoubleStat("PARRY_COOLDOWN_REDUCTION", Material.BUCKET, "Parry Cooldown Reduction", new String[]{"Reduces the parrying cooldown (%)."}, new String[]{"!miscellaneous", "!block", "all"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat COOLDOWN_REDUCTION = new DoubleStat("COOLDOWN_REDUCTION", Material.BOOK, "Cooldown Reduction", new String[]{"Reduces cooldowns of item and player skills (%)."}).setCategory(StatCategories.OFFENSE);
public static final ItemStat RANGE = new DoubleStat("RANGE", Material.STICK, "Range", new String[]{"The range of your item attacks."}, new String[]{"staff", "whip", "wand", "musket", "gem_stone"}).setCategory(StatCategories.RANGED_WEAPONS);
public static final ItemStat MANA_COST = new ManaCost();
public static final ItemStat STAMINA_COST = new DoubleStat("STAMINA_COST", Material.LIGHT_GRAY_DYE, "Stamina Cost", new String[]{"Stamina spent by your weapon to be used."}, new String[]{"weapon"}).setCategory(StatCategories.USE_COST);
public static final ItemStat ARROW_VELOCITY = new DoubleStat("ARROW_VELOCITY", Material.ARROW, "Arrow Velocity", new String[]{"Determines how far your", "weapon can shoot.", "Default: 1.0"}, new String[]{"gem_stone", "bow", "crossbow"}).setCategory(StatCategories.RANGED_WEAPONS);
public static final ItemStat ARROW_POTION_EFFECTS = new ArrowPotionEffects();
public static final ItemStat PVE_DAMAGE = new DoubleStat("PVE_DAMAGE", Material.PORKCHOP, "PvE Damage", new String[]{"Additional damage against", "non human entities in %."}, new String[]{"equipment", "gem_stone"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat PVP_DAMAGE = new DoubleStat("PVP_DAMAGE", Material.SKELETON_SKULL, "PvP Damage", new String[]{"Additional damage", "against players in %."}, new String[]{"equipment", "gem_stone"}).setCategory(StatCategories.OFFENSE);
public static final ItemStat BLUNT_POWER = new DoubleStat("BLUNT_POWER", Material.IRON_AXE, "Blunt Power", new String[]{"The radius of the AoE attack.", "If set to 2.0, enemies within 2 blocks", "around your target will take damage.", "&9This stat only applies to Blunt weapons."}, new String[]{"weapon", "gem_stone"}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat BLUNT_RATING = new DoubleStat("BLUNT_RATING", Material.BRICK, "Blunt Rating", new String[]{"The force of the blunt attack.", "If set to 50%, enemies hit by the attack", "will take 50% of the initial damage.", "&9This stat only applies to Blunt weapons."}, new String[]{"weapon", "gem_stone"}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat WEAPON_DAMAGE = new DoubleStat("WEAPON_DAMAGE", Material.IRON_SWORD, "Weapon Damage", new String[]{"Additional on-hit weapon damage in %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat SKILL_DAMAGE = new DoubleStat("SKILL_DAMAGE", Material.BOOK, "Skill Damage", new String[]{"Additional ability damage in %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat PROJECTILE_DAMAGE = new DoubleStat("PROJECTILE_DAMAGE", Material.ARROW, "Projectile Damage", new String[]{"Additional skill/weapon projectile damage."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat MAGIC_DAMAGE = new DoubleStat("MAGIC_DAMAGE", Material.MAGMA_CREAM, "Magic Damage", new String[]{"Additional magic skill damage in %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat PHYSICAL_DAMAGE = new DoubleStat("PHYSICAL_DAMAGE", Material.IRON_AXE, "Physical Damage", new String[]{"Additional skill/weapon physical damage."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat DEFENSE = new DoubleStat("DEFENSE", Material.SHIELD, "Defense", new String[]{"Reduces damage from any source.", "Formula can be set in MMOLib Config."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat DAMAGE_REDUCTION = new DoubleStat("DAMAGE_REDUCTION", Material.IRON_CHESTPLATE, "Damage Reduction", new String[]{"Reduces damage from any source.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat FALL_DAMAGE_REDUCTION = new DoubleStat("FALL_DAMAGE_REDUCTION", Material.FEATHER, "Fall Damage Reduction", new String[]{"Reduces fall damage.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat PROJECTILE_DAMAGE_REDUCTION = new DoubleStat("PROJECTILE_DAMAGE_REDUCTION", Material.SNOWBALL, "Projectile Damage Reduction", new String[]{"Reduces projectile damage.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat PHYSICAL_DAMAGE_REDUCTION = new DoubleStat("PHYSICAL_DAMAGE_REDUCTION", Material.LEATHER_CHESTPLATE, "Physical Damage Reduction", new String[]{"Reduces physical damage.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat FIRE_DAMAGE_REDUCTION = new DoubleStat("FIRE_DAMAGE_REDUCTION", Material.BLAZE_POWDER, "Fire Damage Reduction", new String[]{"Reduces fire damage.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat MAGIC_DAMAGE_REDUCTION = new DoubleStat("MAGIC_DAMAGE_REDUCTION", Material.POTION, "Magic Damage Reduction", new String[]{"Reduce magic damage dealt by potions.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat PVE_DAMAGE_REDUCTION = new DoubleStat("PVE_DAMAGE_REDUCTION", Material.PORKCHOP, "PvE Damage Reduction", new String[]{"Reduces damage dealt by mobs.", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat PVP_DAMAGE_REDUCTION = new DoubleStat("PVP_DAMAGE_REDUCTION", Material.SKELETON_SKULL, "PvP Damage Reduction", new String[]{"Reduces damage dealt by players", "In %."}).setCategory(StatCategories.DAMAGE_MITIGATION);
public static final ItemStat UNDEAD_DAMAGE = new DoubleStat("UNDEAD_DAMAGE", Material.SKELETON_SKULL, "Undead Damage", new String[]{"Deals additional damage to undead.", "In %."}).setCategory(StatCategories.OFFENSE);
public static final ItemStat LIFESTEAL = new DoubleStat("LIFESTEAL", Material.REDSTONE, "Lifesteal", new String[]{"Percentage of damage you gain back as", "health when inflicting weapon damage."}).setCategory(StatCategories.OFFENSE);
public static final ItemStat SPELL_VAMPIRISM = new DoubleStat("SPELL_VAMPIRISM", Material.REDSTONE, "Spell Vampirism", new String[]{"Percentage of damage you gain back as", "health when inflicting skill damage."}).setCategory(StatCategories.OFFENSE);
// Extra Stats
UNBREAKABLE = new Unbreakable(),
TIER = new ItemTierStat(),
SET = new ItemSetStat(),
ARMOR = new Armor(),
ARMOR_TOUGHNESS = new ArmorToughness(),
MAX_HEALTH = new MaxHealth(),
UNSTACKABLE = new Unstackable(),
MAX_MANA = new DoubleStat("MAX_MANA", Material.LAPIS_LAZULI, "Max Mana", new String[]{"Adds mana to your max mana bar."}).setCategory(StatCategories.MISC_STATS),
KNOCKBACK_RESISTANCE = new KnockbackResistance(),
MOVEMENT_SPEED = new MovementSpeed(),
TWO_HANDED = new BooleanStat("TWO_HANDED", Material.IRON_INGOT, "Two Handed", "If set to true, players will be significantly slower (emcumbered) when holding two items, one being Two Handed.", new String[]{"handheld"}).setCategory(StatCategories.MISC),
REQUIRED_BIOMES = new RequiredBiomes(),
DROP_ON_DEATH = new DisableDeathDrop(),
HIDE_DURABILITY_BAR = new HideDurabilityBar(),
public static final ItemStat// Extra Stats
UNBREAKABLE = new Unbreakable();
public static final ItemStat TIER = new ItemTierStat();
public static final ItemStat SET = new ItemSetStat();
public static final ItemStat ARMOR = new Armor();
public static final ItemStat ARMOR_TOUGHNESS = new ArmorToughness();
public static final ItemStat MAX_HEALTH = new MaxHealth();
public static final ItemStat UNSTACKABLE = new Unstackable();
public static final ItemStat MAX_MANA = new DoubleStat("MAX_MANA", Material.LAPIS_LAZULI, "Max Mana", new String[]{"Adds mana to your max mana bar."}).setCategory(StatCategories.MISC_STATS);
public static final ItemStat KNOCKBACK_RESISTANCE = new KnockbackResistance();
public static final ItemStat MOVEMENT_SPEED = new MovementSpeed();
public static final ItemStat TWO_HANDED = new BooleanStat("TWO_HANDED", Material.IRON_INGOT, "Two Handed", "If set to true, players will be significantly slower (emcumbered) when holding two items, one being Two Handed.", new String[]{"handheld"}).setCategory(StatCategories.MISC);
public static final ItemStat REQUIRED_BIOMES = new RequiredBiomes();
public static final ItemStat DROP_ON_DEATH = new DisableDeathDrop();
public static final ItemStat HIDE_DURABILITY_BAR = new HideDurabilityBar();
// Extra Attributes (1.20.2+)
MAX_ABSORPTION = new MaxAbsorption(),
BLOCK_BREAK_SPEED = new BlockBreakSpeed(),
BLOCK_INTERACTION_RANGE = new BlockInteractionRange(),
ENTITY_INTERACTION_RANGE = new EntityInteractionRange(),
FALL_DAMAGE_MULTIPLIER = new FallDamageMultiplier(),
GRAVITY = new Gravity(),
JUMP_STRENGTH = new JumpStrength(),
SAFE_FALL_DISTANCE = new SafeFallDistance(),
SCALE = new Scale(),
STEP_HEIGHT = new StepHeight(),
BURNING_TIME = new BurningTime(),
EXPLOSION_KNOCKBACK_RESISTANCE = new ExplosionKnockbackResistance(),
MINING_EFFICIENCY = new MiningEfficiency(),
MOVEMENT_EFFICIENCY = new MovementEfficiency(),
OXYGEN_BONUS = new OxygenBonus(),
SNEAKING_SPEED = new SneakingSpeed(),
SUBMERGED_MINING_SPEED = new SubmergedMiningSpeed(),
SWEEPING_DAMAGE_RATIO = new SweepingDamageRatio(),
WATER_MOVEMENT_EFFICIENCY = new WaterMovementEfficiency(),
public static final ItemStat// Extra Attributes (1.20.2+)
MAX_ABSORPTION = new MaxAbsorption();
public static final ItemStat BLOCK_BREAK_SPEED = new BlockBreakSpeed();
public static final ItemStat BLOCK_INTERACTION_RANGE = new BlockInteractionRange();
public static final ItemStat ENTITY_INTERACTION_RANGE = new EntityInteractionRange();
public static final ItemStat FALL_DAMAGE_MULTIPLIER = new FallDamageMultiplier();
public static final ItemStat GRAVITY = new Gravity();
public static final ItemStat JUMP_STRENGTH = new JumpStrength();
public static final ItemStat SAFE_FALL_DISTANCE = new SafeFallDistance();
public static final ItemStat SCALE = new Scale();
public static final ItemStat STEP_HEIGHT = new StepHeight();
public static final ItemStat BURNING_TIME = new BurningTime();
public static final ItemStat EXPLOSION_KNOCKBACK_RESISTANCE = new ExplosionKnockbackResistance();
public static final ItemStat MINING_EFFICIENCY = new MiningEfficiency();
public static final ItemStat MOVEMENT_EFFICIENCY = new MovementEfficiency();
public static final ItemStat OXYGEN_BONUS = new OxygenBonus();
public static final ItemStat SNEAKING_SPEED = new SneakingSpeed();
public static final ItemStat SUBMERGED_MINING_SPEED = new SubmergedMiningSpeed();
public static final ItemStat SWEEPING_DAMAGE_RATIO = new SweepingDamageRatio();
public static final ItemStat WATER_MOVEMENT_EFFICIENCY = new WaterMovementEfficiency();
// Permanent Effects
PERM_EFFECTS = new PermanentEffects(),
GRANTED_PERMISSIONS = new GrantedPermissions(),
public static final ItemStat// Permanent Effects
PERM_EFFECTS = new PermanentEffects();
public static final ItemStat GRANTED_PERMISSIONS = new GrantedPermissions();
// Consumable Stats
RESTORE_HEALTH = new RestoreHealth(),
RESTORE_FOOD = new RestoreFood(),
RESTORE_SATURATION = new RestoreSaturation(),
RESTORE_MANA = new RestoreMana(),
RESTORE_STAMINA = new RestoreStamina(),
CAN_IDENTIFY = new CanIdentify(),
CAN_DECONSTRUCT = new CanDeconstruct(),
CAN_DESKIN = new CanDeskin(),
EFFECTS = new Effects(),
SOULBINDING_CHANCE = new SoulbindingChance(),
SOULBOUND_BREAK_CHANCE = new SoulbindingBreakChance(),
SOULBOUND_LEVEL = new SoulboundLevel(),
// AUTO_SOULBIND = new BooleanStat("AUTO_SOULBIND", VersionMaterial.ENDER_EYE.toMaterial(), "Auto-Soulbind", new String[]{"Automatically soulbinds this item to", "a player when he acquires it."}, new String[]{"!consumable", "all"}),
ITEM_COOLDOWN = new DoubleStat("ITEM_COOLDOWN", Material.COOKED_CHICKEN, "Item Cooldown", new String[]{"This cooldown applies for consumables", "as well as for item commands."}, new String[]{"!armor", "!gem_stone", "!block", "all"}).setCategory(StatCategories.ABILITIES),
COOLDOWN_REFERENCE = new StringStat("COOLDOWN_REFERENCE", Material.CHICKEN, "Cooldown Reference", "Two items with the same cooldown reference will share their cooldowns. This is useful for health or mana pots for example.", new String[]{"!armor", "!gem_stone", "!block", "all"}).setCategory(StatCategories.ABILITIES),
VANILLA_EATING_ANIMATION = new VanillaEatingAnimation(),
GEM_COLOR = new GemColor(),
GEM_UPGRADE_SCALING = new GemUpgradeScaling(),
ITEM_TYPE_RESTRICTION = new ItemTypeRestriction(),
MAX_CONSUME = new MaxConsume(),
SUCCESS_RATE = new SuccessRate(),
public static final ItemStat// Consumable Stats
RESTORE_HEALTH = new RestoreHealth();
public static final ItemStat RESTORE_FOOD = new RestoreFood();
public static final ItemStat RESTORE_SATURATION = new RestoreSaturation();
public static final ItemStat RESTORE_MANA = new RestoreMana();
public static final ItemStat RESTORE_STAMINA = new RestoreStamina();
public static final ItemStat CAN_IDENTIFY = new CanIdentify();
public static final ItemStat CAN_DECONSTRUCT = new CanDeconstruct();
public static final ItemStat CAN_DESKIN = new CanDeskin();
public static final ItemStat EFFECTS = new Effects();
public static final ItemStat SOULBINDING_CHANCE = new SoulbindingChance();
public static final ItemStat SOULBOUND_BREAK_CHANCE = new SoulbindingBreakChance();
public static final ItemStat SOULBOUND_LEVEL = new SoulboundLevel();
public static final ItemStat// AUTO_SOULBIND = new BooleanStat("AUTO_SOULBIND", VersionMaterial.ENDER_EYE.toMaterial(), "Auto-Soulbind", new String[]{"Automatically soulbinds this item to", "a player when he acquires it."}, new String[]{"!consumable", "all"}),
ITEM_COOLDOWN = new DoubleStat("ITEM_COOLDOWN", Material.COOKED_CHICKEN, "Item Cooldown", new String[]{"This cooldown applies for consumables", "as well as for item commands."}, new String[]{"!armor", "!gem_stone", "!block", "all"}).setCategory(StatCategories.ABILITIES);
public static final ItemStat COOLDOWN_REFERENCE = new StringStat("COOLDOWN_REFERENCE", Material.CHICKEN, "Cooldown Reference", "Two items with the same cooldown reference will share their cooldowns. This is useful for health or mana pots for example.", new String[]{"!armor", "!gem_stone", "!block", "all"}).setCategory(StatCategories.ABILITIES);
public static final ItemStat VANILLA_EATING_ANIMATION = new VanillaEatingAnimation();
public static final ItemStat GEM_COLOR = new GemColor();
public static final ItemStat GEM_UPGRADE_SCALING = new GemUpgradeScaling();
public static final ItemStat ITEM_TYPE_RESTRICTION = new ItemTypeRestriction();
public static final ItemStat MAX_CONSUME = new MaxConsume();
public static final ItemStat SUCCESS_RATE = new SuccessRate();
// Crafting Stats
CRAFTING = new Crafting(),
CRAFT_PERMISSION = new CraftingPermission(),
public static final ItemStat// Crafting Stats
CRAFTING = new Crafting();
public static final ItemStat CRAFT_PERMISSION = new CraftingPermission();
//CRAFT_AMOUNT = new DoubleStat("CRAFTED_AMOUNT", Material.WOODEN_AXE, "Crafted Amount", new String[]{"The stack count for", "this item when crafted."}, new String[0]),
// Unique Stats
AUTOSMELT = new BooleanStat("AUTOSMELT", Material.COAL, "Autosmelt", "When toggled on, your tool will automatically smelt mined ores.", new String[]{"tool"}).setCategory(StatCategories.TOOLS),
BOUNCING_CRACK = new BooleanStat("BOUNCING_CRACK", Material.COBBLESTONE_WALL, "Bouncing Crack", "When toggled on, your tool will also break nearby blocks.", new String[]{"tool"}).setCategory(StatCategories.TOOLS),
PICKAXE_POWER = new PickaxePower(),
//CUSTOM_SOUNDS = new CustomSounds(),
public static final ItemStat// Unique Stats
AUTOSMELT = new BooleanStat("AUTOSMELT", Material.COAL, "Autosmelt", "When toggled on, your tool will automatically smelt mined ores.", new String[]{"tool"}).setCategory(StatCategories.TOOLS);
public static final ItemStat BOUNCING_CRACK = new BooleanStat("BOUNCING_CRACK", Material.COBBLESTONE_WALL, "Bouncing Crack", "When toggled on, your tool will also break nearby blocks.", new String[]{"tool"}).setCategory(StatCategories.TOOLS);
public static final ItemStat PICKAXE_POWER = new PickaxePower();
public static final ItemStat//CUSTOM_SOUNDS = new CustomSounds(),
//ELEMENTS = new Elements(),
COMMANDS = new Commands(),
COMMANDS = new Commands();
// STAFF_SPIRIT = new StaffSpiritStat(),
LUTE_ATTACK_SOUND = new LuteAttackSoundStat(),
LUTE_ATTACK_EFFECT = new LuteAttackEffectStat(),
NOTE_WEIGHT = new DoubleStat("NOTE_WEIGHT", Material.MUSIC_DISC_MALL, "Note Weight", new String[]{"Defines how the projectile cast", "by your lute tilts downwards."}, new String[]{"lute"}).setCategory(StatCategories.RANGED_WEAPONS),
REMOVE_ON_CRAFT = new BooleanStat("REMOVE_ON_CRAFT", Material.GLASS_BOTTLE, "Remove on Craft", "If the item should be completely removed when used in a recipe, or if it should become an empty bottle or bucket.", null).setCompatibleMaterials(Material.POTION, Material.SPLASH_POTION, Material.LINGERING_POTION, Material.MILK_BUCKET, Material.LAVA_BUCKET, Material.WATER_BUCKET).setCategory(StatCategories.MISC),
COMPATIBLE_TYPES = new CompatibleTypes(),
COMPATIBLE_IDS = new CompatibleIds(),
COMPATIBLE_MATERIALS = new CompatibleMaterials(),
GEM_SOCKETS = new GemSockets(),
RANDOM_UNSOCKET = new RandomUnsocket(),
public static final ItemStat<StringComponent> LUTE_ATTACK_SOUND = new LuteAttackSoundStat();
public static final ItemStat<StringComponent> LUTE_ATTACK_EFFECT = new LuteAttackEffectStat();
public static final ItemStat<DoubleComponent> NOTE_WEIGHT = new DoubleStat("NOTE_WEIGHT", Material.MUSIC_DISC_MALL, "Note Weight", new String[]{"Defines how the projectile cast", "by your lute tilts downwards."}, new String[]{"lute"}).setCategory(StatCategories.RANGED_WEAPONS);
public static final ItemStat<BooleanComponent> REMOVE_ON_CRAFT = new BooleanStat("REMOVE_ON_CRAFT", Material.GLASS_BOTTLE, "Remove on Craft", "If the item should be completely removed when used in a recipe, or if it should become an empty bottle or bucket.", null).setCompatibleMaterials(Material.POTION, Material.SPLASH_POTION, Material.LINGERING_POTION, Material.MILK_BUCKET, Material.LAVA_BUCKET, Material.WATER_BUCKET).setCategory(StatCategories.MISC);
public static final ItemStat<ArrayComponent<StringComponent>> COMPATIBLE_TYPES = new CompatibleTypes();
public static final ItemStat<ArrayComponent<StringComponent>> COMPATIBLE_IDS = new CompatibleIds();
public static final ItemStat<ArrayComponent<MaterialComponent>> COMPATIBLE_MATERIALS = new CompatibleMaterials();
public static final ItemStat<GemstonesComponent> GEM_SOCKETS = new GemSockets();
public static final ItemStat<DoubleComponent> RANDOM_UNSOCKET = new RandomUnsocket();
//todo CAN_UNSOCKET = new CanUnsocket(),
REPAIR = new RepairPower(),
REPAIR_PERCENT = new RepairPowerPercent(),
REPAIR_TYPE = new RepairReference(),
INEDIBLE = new BooleanStat("INEDIBLE", Material.POISONOUS_POTATO, "Inedible", "Makes it impossible to right-click consume this consumable.", new String[]{"consumable"}).setCategory(StatCategories.CONSUMABLES),
DISABLE_RIGHT_CLICK_CONSUME = new DisableStat("RIGHT_CLICK_CONSUME", Material.BAKED_POTATO, "Infinite Consume", "Players will be able to right-click this consumable and benefit from its effects, but it won't be consumed.", new String[]{"consumable"}).setCategory(StatCategories.CONSUMABLES),
KNOCKBACK = new DoubleStat("KNOCKBACK", Material.IRON_HORSE_ARMOR, "Knockback", new String[]{"Using this musket will knock", "the user back if positive."}, new String[]{"musket", "gem_stone"}).setCategory(StatCategories.RANGED_WEAPONS),
RECOIL = new DoubleStat("RECOIL", Material.IRON_HORSE_ARMOR, "Recoil", new String[]{"Corresponds to the shooting innacuracy."}, new String[]{"musket", "gem_stone"}).setCategory(StatCategories.RANGED_WEAPONS),
HANDWORN = new BooleanStat("HANDWORN", Material.STRING, "Handworn", "This item can be held along with a two-handed weapon in the other hand, bypassing the encumbered debuff.", new String[]{"catalyst", "off_catalyst", "main_catalyst"}).setCategory(StatCategories.MISC),
AMPHIBIAN = new Amphibian(),
public static final ItemStat<DoubleComponent> REPAIR = new RepairPower();
public static final ItemStat<DoubleComponent> REPAIR_PERCENT = new RepairPowerPercent();
public static final ItemStat<StringComponent> REPAIR_TYPE = new RepairReference();
public static final ItemStat<BooleanComponent> INEDIBLE = new BooleanStat("INEDIBLE", Material.POISONOUS_POTATO, "Inedible", "Makes it impossible to right-click consume this consumable.", new String[]{"consumable"}).setCategory(StatCategories.CONSUMABLES);
public static final ItemStat<BooleanComponent> DISABLE_RIGHT_CLICK_CONSUME = new DisableStat("RIGHT_CLICK_CONSUME", Material.BAKED_POTATO, "Infinite Consume", "Players will be able to right-click this consumable and benefit from its effects, but it won't be consumed.", new String[]{"consumable"}).setCategory(StatCategories.CONSUMABLES);
public static final ItemStat<DoubleComponent> KNOCKBACK = new DoubleStat("KNOCKBACK", Material.IRON_HORSE_ARMOR, "Knockback", new String[]{"Using this musket will knock", "the user back if positive."}, new String[]{"musket", "gem_stone"}).setCategory(StatCategories.RANGED_WEAPONS);
public static final ItemStat<DoubleComponent> RECOIL = new DoubleStat("RECOIL", Material.IRON_HORSE_ARMOR, "Recoil", new String[]{"Corresponds to the shooting innacuracy."}, new String[]{"musket", "gem_stone"}).setCategory(StatCategories.RANGED_WEAPONS);
public static final ItemStat<BooleanComponent> HANDWORN = new BooleanStat("HANDWORN", Material.STRING, "Handworn", "This item can be held along with a two-handed weapon in the other hand, bypassing the encumbered debuff.", new String[]{"catalyst", "off_catalyst", "main_catalyst"}).setCategory(StatCategories.MISC);
public static final ItemStat<StringComponent> AMPHIBIAN = new Amphibian();
// Abilities & Upgrading
ABILITIES = new Abilities(),
UPGRADE = new UpgradeStat(),
DOWNGRADE_ON_BREAK = new BooleanStat("BREAK_DOWNGRADE", Material.DAMAGED_ANVIL, "Downgrade when Broken", "If this item's durability reaches 0, it will be fully repaired but also downgraded by one level. &cIt will only break if it cannot be downgraded further.\n&7Requires to define an &6Upgrade Template.\n&7Required to define &6Custom Durability", new String[]{"equipment"}).setCategory(StatCategories.UPGRADING),
DOWNGRADE_ON_DEATH = new BooleanStat("DEATH_DOWNGRADE", Material.DAMAGED_ANVIL, "Downgrade on Death", "If the wearer of this item dies, it may downgrade (based on &6Death Downgrade Chance &7stat).\nRequired to define an &6Upgrade Template.\nRequires keep-inventory gamerule. ", new String[]{"equipment"}).setCategory(StatCategories.UPGRADING),
DOWNGRADE_ON_DEATH_CHANCE = new DoubleStat("DEATH_DOWNGRADE_CHANCE", Material.SKELETON_SKULL, "Death Downgrade Chance", "Probability that an item with &cDowngrade on Death &7will be downgraded when the player dies.\n\n Exceeding 100% will for sure downgrade one item, and roll again to downgrade another (with the excess probability). The same item won't be downgraded twice.", new String[]{"equipment"}, false).setCategory(StatCategories.UPGRADING),
public static final ItemStat<ArrayComponent<ObjectComponent>> ABILITIES = new Abilities();
public static final ItemStat<UpgradeComponent> UPGRADE = new UpgradeStat();
public static final ItemStat<BooleanComponent> DOWNGRADE_ON_BREAK = new BooleanStat("BREAK_DOWNGRADE", Material.DAMAGED_ANVIL, "Downgrade when Broken", "If this item's durability reaches 0, it will be fully repaired but also downgraded by one level. &cIt will only break if it cannot be downgraded further.\n&7Requires to define an &6Upgrade Template.\n&7Required to define &6Custom Durability", new String[]{"equipment"}).setCategory(StatCategories.UPGRADING);
public static final ItemStat<BooleanComponent> DOWNGRADE_ON_DEATH = new BooleanStat("DEATH_DOWNGRADE", Material.DAMAGED_ANVIL, "Downgrade on Death", "If the wearer of this item dies, it may downgrade (based on &6Death Downgrade Chance &7stat).\nRequired to define an &6Upgrade Template.\nRequires keep-inventory gamerule. ", new String[]{"equipment"}).setCategory(StatCategories.UPGRADING);
public static final ItemStat<DoubleComponent> DOWNGRADE_ON_DEATH_CHANCE = new DoubleStat("DEATH_DOWNGRADE_CHANCE", Material.SKELETON_SKULL, "Death Downgrade Chance", "Probability that an item with &cDowngrade on Death &7will be downgraded when the player dies.\n\n Exceeding 100% will for sure downgrade one item, and roll again to downgrade another (with the excess probability). The same item won't be downgraded twice.", new String[]{"equipment"}, false).setCategory(StatCategories.UPGRADING);
// Unique Item Stats
DYE_COLOR = new DyeColor(),
HIDE_DYE = new HideDye(),
ARMOR_TRIM = new ArmorTrimStat(),
HIDE_ARMOR_TRIM = new HideTrim(),
POTION_EFFECTS = new PotionEffects(),
POTION_COLOR = new PotionColor(),
SHIELD_PATTERN = new ShieldPatternStat(),
HIDE_POTION_EFFECTS = new HidePotionEffects(),
public static final ItemStat<ObjectComponent> DYE_COLOR = new DyeColor();
public static final ItemStat<BooleanComponent> HIDE_DYE = new HideDye();
public static final ItemStat<ObjectComponent> ARMOR_TRIM = new ArmorTrimStat();
public static final ItemStat<BooleanComponent> HIDE_ARMOR_TRIM = new HideTrim();
public static final ItemStat<ArrayComponent<PotionEffectComponent>> POTION_EFFECTS = new PotionEffects();
public static final ItemStat<ColorComponent> POTION_COLOR = new PotionColor();
public static final ItemStat<ShieldStyleComponent> SHIELD_PATTERN = new ShieldPatternStat();
public static final ItemStat<BooleanComponent> HIDE_POTION_EFFECTS = new HidePotionEffects();
// Internal Stats
SOULBOUND = new Soulbound(),
CUSTOM_DURABILITY = new CustomDurability(),
ITEM_LEVEL = new ItemLevel(),
BROWSER_DISPLAY_IDX = new BrowserDisplayIDX();
public static final ItemStat<ArrayComponent<StringComponent>> NAME_PREFIXES = new DisplayNamePrefixes();
public static final ItemStat<ArrayComponent<StringComponent>> NAME_SUFFIXES = new DisplayNameSuffixes();
public static final ItemStat<ObjectComponent> SOULBOUND = new Soulbound();
public static final ItemStat<IntegerComponent> CUSTOM_DURABILITY = new CustomDurability();
public static final ItemStat<IntegerComponent> ITEM_LEVEL = new ItemLevel();
public static final ItemStat<DoubleComponent> BROWSER_DISPLAY_IDX = new BrowserDisplayIDX();
/**
* @see ItemDamage
@ -234,5 +235,5 @@ public class ItemStats {
* @deprecated
*/
@Deprecated
public static final ItemStat DURABILITY = ITEM_DAMAGE;
public static final ItemStat<DoubleComponent> DURABILITY = ITEM_DAMAGE;
}

View File

@ -46,6 +46,8 @@ public class ItemStackBuilder {
private final List<ItemTag> tags = new ArrayList<>();
/**
* TODO nothing wrong with this impl?
*
* @deprecated Temp fix before MI7
*/
@Deprecated

View File

@ -14,7 +14,7 @@ import net.Indyuce.mmoitems.stat.data.StringData;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.stat.type.NameData;
import net.Indyuce.mmoitems.stat.data.NameData;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import net.Indyuce.mmoitems.util.Buildable;
import org.jetbrains.annotations.NotNull;

View File

@ -10,6 +10,7 @@ import net.Indyuce.mmoitems.api.UpgradeTemplate;
import net.Indyuce.mmoitems.api.item.ItemReference;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.util.MMOItemReforger;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.data.*;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
@ -37,6 +38,8 @@ public class MMOItem implements ItemReference {
@NotNull
private final Map<ItemStat, StatData> stats = new HashMap<>();
public final Map<ItemStat<?>, StatComponent> components = new HashMap<>();
/**
* Constructor used to generate an ItemStack based on some stat data
*
@ -82,6 +85,12 @@ public class MMOItem implements ItemReference {
} else setData(stat, data);
}
@Nullable
public <C extends StatComponent> C getComponent(@NotNull ItemStat<C> stat) {
StatComponent found = components.get(stat);
return found == null ? null : (C) found;
}
public void setData(@NotNull ItemStat stat, @NotNull StatData data) {
stats.put(stat, data);
}

View File

@ -34,12 +34,7 @@ public class MMOItemTemplate implements ItemReference, PreloadedObject {
private final String id;
private final int revId;
/**
* Base item data
*/
private final Map<ItemStat, RandomStatData> base = new HashMap<>();
public final Map<ItemStat<?>, Model<?>> modernItemData = new HashMap<>();
private final Map<ItemStat<?>, Model<?>> models = new HashMap<>();
@Nullable
private NumericStatFormula modifierCapacity;
@ -85,21 +80,14 @@ public class MMOItemTemplate implements ItemReference, PreloadedObject {
Validate.notNull(stat, FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "Could not find stat with ID '$i{0}$b'", id));
// Check for a block with alternative syntax
boolean alternativeSyntax = MMOItems.plugin.getStats().alternativeSyntaxCheck(modernItemData, key, config::get);
boolean alternativeSyntax = MMOItems.plugin.getStats().checkAlternateYAMLSyntax(MMOItemTemplate.this, key, config::get);
if (alternativeSyntax) continue;
// Modern code
if (stat.getComponentType() != null) {
// Load a model
Model<?> model = stat.getComponentType().fromConfig(config.get("base." + key));
modernItemData.put(stat, model);
continue;
}
models.put(stat, model);
// TODO remove deprecated code after statdatas are gone
RandomStatData<?> data = stat.whenInitialized(config.get("base." + key));
if (data != null) base.put(stat, data);
} catch (IllegalArgumentException exception) {
} catch (RuntimeException exception) {
// Log
ffp.log(FriendlyFeedbackCategory.INFORMATION, "Could not load base item data '$f{0}$b': {1}", key, exception.getMessage());
@ -147,9 +135,14 @@ public class MMOItemTemplate implements ItemReference, PreloadedObject {
return postLoadAction;
}
@NotNull
@Deprecated
public Map<ItemStat, RandomStatData> getBaseItemData() {
return base;
return new HashMap<>();
}
@NotNull
public Map<ItemStat<?>, Model<?>> getModels() {
return models;
}
@Nullable

View File

@ -85,7 +85,7 @@ public class ItemEdition extends EditionInventory {
return new ArrayList<>(getEdited().getType().getAvailableStats()).stream()
.filter(stat -> stat.getComponentType() != null) // TODO remove this line.
.filter(stat -> stat.hasValidMaterial(getCachedItem()) && !stat.isInternal())
.map(stat -> new Entry(stat.getId().toLowerCase(), stat.getCategory(), stat.getComponentType(), template.modernItemData.get(stat)))
.map(stat -> new Entry(stat.getId().toLowerCase(), stat.getCategory(), stat.getComponentType(), template.getModels().get(stat)))
.collect(Collectors.toList());
// TODO abstraction over objects, arrays and dicts
@ -101,7 +101,7 @@ public class ItemEdition extends EditionInventory {
AtomicInteger counter = new AtomicInteger();
ComponentType subtype = ((ArrayComponentType<?>) topmost.ctype).getSubType();
return topmost.model == null ? new ArrayList<>() :
((ArrayModel<?>) topmost.model).getKeyedSubmodels().stream()
((ArrayModel<?>) topmost.model).getKeyedModels().stream()
.map(submodel -> new Entry(String.valueOf(counter.getAndIncrement()), null, subtype, submodel.getValue()))
.collect(Collectors.toList());
// return ((ArrayComponentType) topmost.ctype).get
@ -242,7 +242,7 @@ public class ItemEdition extends EditionInventory {
}
ctype = stat.getComponentType();
model = template.modernItemData.get(stat);
model = template.getModels().get(stat);
key = stat.getId().toLowerCase();
} else {

View File

@ -0,0 +1,56 @@
package net.Indyuce.mmoitems.item;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.api.GemstoneComponent;
import net.Indyuce.mmoitems.stat.component.builtin.api.GemstonesComponent;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* Used to modify an item which has already been generated.
* <p>
* There would be two ways to modify it:
* <p>
* Either selectively change one stat and only update it. In that case you don't need
* to load all stats and components from the item, just load the item and only read
* the NBT or meta properties that make sense,
* <p>
* Either fully load the item from scratch into the component map, edit it as much as
* needed and regenerate the item afterward. Of course this takes more performance.
*
* @author Jules
*/
public class LiveItemEditor {
private final Map<ItemStat<?>, StatComponent> components = new HashMap<>();
private Set<UUID> gemstoneUuidCache;
/**
* This is used when clearing histories of components.
*
* @return A set of UUIDs of gemstones currently applied to the item.
*/
@NotNull
public Set<UUID> getGemstoneIdCache() {
if (gemstoneUuidCache == null) {
// Check gemstones
GemstonesComponent gemstones = (GemstonesComponent) components.get(ItemStats.GEM_SOCKETS);
if (gemstones == null) return gemstoneUuidCache = Set.of();
gemstoneUuidCache = new HashSet<>();
for (GemstoneComponent gemstone : gemstones.getGemstones())
gemstoneUuidCache.add(gemstone.getUniqueId());
}
return gemstoneUuidCache;
}
public void flushGemstoneIdCache() {
gemstoneUuidCache = null;
}
}

View File

@ -9,16 +9,15 @@ import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.StatCategories;
import net.Indyuce.mmoitems.api.ConfigFile;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
import net.Indyuce.mmoitems.stat.ElementalStat;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.behaviour.ConsumableItemInteraction;
import net.Indyuce.mmoitems.stat.behaviour.ItemRestriction;
import net.Indyuce.mmoitems.stat.behaviour.PlayerConsumable;
import net.Indyuce.mmoitems.stat.category.StatCategory;
import net.Indyuce.mmoitems.stat.component.model.Model;
import net.Indyuce.mmoitems.stat.component.type.builtin.NumberComponentType;
import net.Indyuce.mmoitems.stat.syntax.SyntaxAdapter;
import net.Indyuce.mmoitems.stat.syntax.SyntaxAdapters;
import net.Indyuce.mmoitems.stat.yaml.SyntaxAdapter;
import net.Indyuce.mmoitems.stat.type.*;
import net.Indyuce.mmoitems.util.ElementStatType;
import org.apache.commons.lang.Validate;
@ -48,7 +47,7 @@ public class StatManager {
private final Map<String, ItemStat<?>> legacyAliases = new HashMap<>();
@BackwardsCompatibility(version = "6.10.1")
private final Map<String, SyntaxAdapter> legacyConfigAdapters = new HashMap<>();
private final Map<String, SyntaxAdapter> yamlSyntaxAdapters = new HashMap<>();
/*
* These lists are sets of stats collected when the stats are registered for
@ -69,9 +68,6 @@ public class StatManager {
// Builtin categories
forEachField(StatCategories.class, StatCategory.class, this::registerCategory, "Couldn't register category called '%s': %s");
// Load builtin config adapters
forEachField(SyntaxAdapters.class, SyntaxAdapter.class, this::registerSyntaxAdapter, "Internal error '%s': %s");
// Load builtin stats
forEachField(ItemStats.class, ItemStat.class, this::register, "Couldn't register stat called '%s': %s");
loadElementalStats(); // Needed on startup otherwise templates cant use them
@ -148,17 +144,17 @@ public class StatManager {
categories.put(category.getId(), category);
}
public void registerSyntaxAdapter(@NotNull SyntaxAdapter adapter) {
legacyConfigAdapters.put(adapter.getKey(), adapter);
public void registerYAMLSyntaxAdapter(@NotNull SyntaxAdapter adapter) {
yamlSyntaxAdapters.put(adapter.getKey(), adapter);
}
@BackwardsCompatibility(version = "6.10.1")
public boolean alternativeSyntaxCheck(@NotNull Map<ItemStat<?>, Model<?>> data,
public boolean checkAlternateYAMLSyntax(@NotNull MMOItemTemplate template,
@NotNull String configKey,
@NotNull Function<String, Object> supplier) {
final SyntaxAdapter adapter = legacyConfigAdapters.get(UtilityMethods.enumName(configKey).toLowerCase()); // Snake case
final SyntaxAdapter adapter = yamlSyntaxAdapters.get(UtilityMethods.enumName(configKey).toLowerCase()); // Snake case
final boolean result = adapter != null;
if (result) adapter.adapt(data, supplier.apply(configKey));
if (result) adapter.adapt(template, supplier.apply(configKey));
return result;
}

View File

@ -61,7 +61,7 @@ public class Abilities extends ItemStat<ArrayComponent<ObjectComponent>> {
Model<?> modifierMap = obj.getModel("modifiers");
if (modifierMap != null) {
ObjectModel asModel = (ObjectModel) modifierMap;
asModel.getComponents().forEach((key, comp) -> {
asModel.getModels().forEach((key, comp) -> {
lore.add("");
lore.add("* " + key + ": " + ((NumberModel) comp).getFormula().toString());
});
@ -72,6 +72,8 @@ public class Abilities extends ItemStat<ArrayComponent<ObjectComponent>> {
//.setFlattened(true)
.build();
// TODO ui display rules
setComponentType(ArrayComponentType.arrayOf(abilityType)
.actionLoreTags("Left click to edit abilities.", "Right click to remove all abilities.")
.icon(Material.FIRE_CHARGE)
@ -129,7 +131,7 @@ public class Abilities extends ItemStat<ArrayComponent<ObjectComponent>> {
}
/*
TODO write to lore
TODO lore display rules
@Override
public void whenApplied(@NotNull ItemStackBuilder item, @NotNull AbilityListData data) {
final List<String> abilityLore = new ArrayList<>();

View File

@ -5,10 +5,12 @@ import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.annotation.VersionDependant;
import net.Indyuce.mmoitems.stat.behaviour.GemStoneStat;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponentImpl;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import net.Indyuce.mmoitems.stat.component.type.builtin.ObjectComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.StringComponentType;
import net.Indyuce.mmoitems.stat.data.StringData;
import net.Indyuce.mmoitems.stat.type.StringStat;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.util.HintedString;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
@ -20,31 +22,36 @@ import org.bukkit.inventory.meta.trim.TrimPattern;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* Both armor trim pattern and material
*
* @author Jules
*/
@HasCategory(cat = "item")
@VersionDependant(version = {1, 20})
public class ArmorTrimStat extends StringStat implements GemStoneStat {
public class ArmorTrimStat extends ItemStat<ObjectComponent> implements GemStoneStat {
public ArmorTrimStat() {
super("ARMOR_TRIM", new String[]{"armor", "skin"});
setAliases("TRIM");
setItemMetaSaved(true);
if (!isEnabled()) return;
// VERSION DEPENDENT CODE AHEAD!!
setComponentType(ObjectComponentType.init()
.addField("material", StringComponentType
.addField("Material", StringComponentType
.withChoices(Registry.TRIM_MATERIAL.stream().map(mat -> new HintedString(mat.getKey().toString())).collect(Collectors.toList()))
.adaptor(ArmorTrimStat::fixNamespacedKey)
.icon(Material.LEATHER_CHESTPLATE)
.name("Trim Material")
.trimdesc("Material to trim your armor with.")
.build())
.addField("pattern", StringComponentType
.addField("Pattern", StringComponentType
.withChoices(Registry.TRIM_PATTERN.stream().map(pattern -> new HintedString(pattern.getKey().toString())).collect(Collectors.toList()))
.adaptor(ArmorTrimStat::fixNamespacedKey)
.icon(Material.LEATHER_CHESTPLATE)
@ -56,33 +63,39 @@ public class ArmorTrimStat extends StringStat implements GemStoneStat {
.trimdesc("Options for armor trim.")
.build());
// TODO syntax adapter from 'trim-material' and 'trim-pattern' instead.
// TODO syntax adapter from 'trim-material' and 'trim-pattern' instead. syntax of pre-MI7
}
@Nullable
@Override
public ObjectComponent read(ReadMMOItem mmoitem) {
if (!(mmoitem.getNBT().getItem().getItemMeta() instanceof ArmorMeta)) return null;
final ArmorMeta meta = (ArmorMeta) mmoitem.getNBT().getItem().getItemMeta();
ArmorTrim trim = meta.getTrim();
if (trim == null) return null;
ObjectComponent component = new ObjectComponentImpl();
component.set("Material", new StringComponent(trim.getMaterial().getKey().toString()));
component.set("Pattern", new StringComponent(trim.getPattern().getKey().toString()));
return component;
}
@Override
public void write(ItemStackBuilder builder, @NotNull ObjectComponent component) {
if (!(builder.getMeta() instanceof ArmorMeta)) return;
TrimMaterial material = Registry.TRIM_MATERIAL.get(NamespacedKey.fromString(Objects.requireNonNull(component.get("Material"), "No trim material").getAsString()));
TrimPattern pattern = Registry.TRIM_PATTERN.get(NamespacedKey.fromString(Objects.requireNonNull(component.get("Pattern"), "No trim pattern").getAsString()));
if (material == null || pattern == null) return;
((ArmorMeta) builder.getMeta()).setTrim(new ArmorTrim(material, pattern));
}
public static String fixNamespacedKey(String str) {
return NamespacedKey.fromString(str.toLowerCase().replace("-", "_")).toString();
}
@Override
public void whenApplied(@NotNull ItemStackBuilder item, @NotNull StringData data) {
if (!(item.getMeta() instanceof ArmorMeta)) return;
@Nullable TrimMaterial material = Registry.TRIM_MATERIAL.get(NamespacedKey.fromString(data.toString().toLowerCase()));
if (material == null) return;
final ArmorMeta meta = (ArmorMeta) item.getMeta();
final ArmorTrim currentTrim = meta.hasTrim() ? meta.getTrim() : new ArmorTrim(TrimMaterial.AMETHYST, TrimPattern.COAST);
meta.setTrim(new ArmorTrim(material, currentTrim.getPattern()));
}
@Override
public void whenLoaded(@NotNull ReadMMOItem mmoitem) {
if (!(mmoitem.getNBT().getItem().getItemMeta() instanceof ArmorMeta)) return;
final ArmorMeta meta = (ArmorMeta) mmoitem.getNBT().getItem().getItemMeta();
if (!meta.hasTrim()) return;
mmoitem.setData(this, new StringData(meta.getTrim().getMaterial().getKey().toString()));
}
/*
@Nullable

View File

@ -12,14 +12,16 @@ import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @see net.Indyuce.mmoitems.api.interaction.projectile.ArrowParticles
*/
@HasCategory(cat = "misc")
public class ArrowParticles extends ItemStat<ObjectComponent> {
public ArrowParticles() {
super("ARROW_PARTICLES", new String[]{"bow", "crossbow"});
// {Particle, Amount, Offset, Red, Green Blue, Speed}
// TODO could have been used a Color component but we can't for backwards compatibility. sucks!
// Could have used a Color component, but we can't for backwards compatibility
// TODO change component to match syntax, hardcore ArrowParticleComponent and make other syntax valid too
// TODO syntax adapter, color.red, color.green, color.blue. rest is fine
@ -39,10 +41,10 @@ public class ArrowParticles extends ItemStat<ObjectComponent> {
.addField("Speed", NumberComponentType.decimal()
.icon(Material.LIGHT_GRAY_DYE)
.name("Speed")
.trimdesc("How much particles will fly away from their initial spawn location. Set to 0 to have the particles stationnary. You should first try a low value like 0.05-0.1.")
.trimdesc("How much particles will fly away from their initial spawn location. Set to 0 to have the particles stationary. You should first try a low value like 0.05-0.1.")
.build())
// Color value components
// Color value Components
.addField("Red", NumberComponentType.integer()
.icon(Material.RED_WOOL)
.name("Red Color Value")

View File

@ -38,7 +38,7 @@ public class ArrowPotionEffects extends ItemStat<ArrayComponent<ObjectComponent>
.addField("duration", NumberComponentType.decimal()
.icon(Material.CLOCK)
.name("Effect Duration").build())
.allowStringFormat(" ")
.stringSeparatedStringFormat(" ")
.icon(Material.TIPPED_ARROW)
.name("Potion Effect")
.build();
@ -62,7 +62,7 @@ public class ArrowPotionEffects extends ItemStat<ArrayComponent<ObjectComponent>
String permEffectFormat = getGeneralStatFormat();
for (ObjectComponent effect : component.getComponents()) {
for (ObjectComponent effect : component.asList()) {
PotionEffectType type = PotionEffectType.getByName(effect.get("type").getAsString());
int level = effect.get("level").getAsInteger();
double duration = effect.get("duration").getAsDouble();

View File

@ -38,8 +38,8 @@ public class CanBreak extends ItemStat<ArrayComponent<MaterialComponent>> {
public void write(ItemStackBuilder builder, @NotNull ArrayComponent<MaterialComponent> component) {
// Convert to list of materials
List<Material> materials = new ArrayList<>(component.getComponents().size());
for (MaterialComponent subcomp : component.getComponents())
List<Material> materials = new ArrayList<>(component.asList().size());
for (MaterialComponent subcomp : component.asList())
materials.add(subcomp.getMaterial());
builder.addFutureAction(nbt -> nbt.setCanMine(materials)); // Register to item meta

View File

@ -1,57 +1,55 @@
package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import io.lumine.mythic.lib.comp.adventure.AdventureParser;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.ItemTier;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.behaviour.GemStoneStat;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import net.Indyuce.mmoitems.stat.data.StringData;
import net.Indyuce.mmoitems.stat.type.NameData;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import net.Indyuce.mmoitems.stat.component.type.builtin.StringComponentType;
import net.Indyuce.mmoitems.stat.type.StringStat;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@HasCategory(cat = "tooltip")
public class DisplayName extends StringStat implements GemStoneStat {
public DisplayName() {
super("NAME", Material.NAME_TAG, "Display Name",
"The item display name.",
null);
super("NAME", null);
// Has to load multiple NBTTags for backwards compatibility.
// TODO remove option, there are only a handful of stats that actually do that
setIndirectNbtMapping(true);
setComponentType(StringComponentType.init()
.icon(Material.NAME_TAG)
.name("Display Name")
.trimdesc("The item display name.")
.build());
}
@Override
public void write(ItemStackBuilder builder, @NotNull StringComponent component) {
// Make sure stat history exists
// TODO remove?
builder.getMMOItem().computeStatHistory(this);
// Get prefixes and suffixes
ArrayComponent<StringComponent> prefixes = builder.getMMOItem().getComponent(ItemStats.NAME_PREFIXES);
ArrayComponent<StringComponent> suffixes = builder.getMMOItem().getComponent(ItemStats.NAME_SUFFIXES);
final ItemTier tier = builder.getMMOItem().getTier();
final AdventureParser parser = MythicLib.plugin.getAdventureParser();
String format = component.getValue();
String format = bakeName(component, prefixes, suffixes);
// Bake
// Some built-in placeholders
format = format.replace("<tier-name>", tier != null ? parser.stripColors(tier.getUnparsedName()) : "")
.replace("<tier-color>", tier != null ? parser.lastColor(tier.getUnparsedName(), true) : "&f")
.replace("<tier-color-cleaned>", tier != null ? parser.lastColor(tier.getUnparsedName(), false) : "");
// Is this upgradable?
format = cropUpgrade(format);
if (builder.getMMOItem().hasUpgradeTemplate())
@ -60,7 +58,34 @@ public class DisplayName extends StringStat implements GemStoneStat {
builder.getMeta().setDisplayName(format);
// Add NBT
builder.addItemTag(getAppliedNBT(data));
writeStringToNbt(builder, component);
}
@NotNull
private String bakeName(
@NotNull StringComponent mainName,
@Nullable ArrayComponent<StringComponent> prefixes,
@Nullable ArrayComponent<StringComponent> suffixes
) {
StringBuilder sb = new StringBuilder();
// Append prefixes
if (prefixes != null) for (StringComponent prefix : prefixes) {
if (!sb.isEmpty()) sb.append(' ');
sb.append(prefix);
}
// Append main name
if (!sb.isEmpty()) sb.append(' ');
sb.append(mainName.getValue());
// Append suffixes
if (suffixes != null) for (StringComponent suffix : suffixes) {
if (!sb.isEmpty()) sb.append(' ');
sb.append(suffix);
}
return sb.toString();
}
@NotNull
@ -166,30 +191,14 @@ public class DisplayName extends StringStat implements GemStoneStat {
.replace("+-", "-");
}
@Nullable
@Override
public StringComponent read(ReadMMOItem mmoitem) {
return super.read(mmoitem);
/*
/**
* This is not saved as a custom NBT data, instead it is stored as the name of the item itself.
* Alas this returns an empty list
*
@NotNull
@Override
public ArrayList<ItemTag> getAppliedNBT(@NotNull StringData stringData) {
Validate.isTrue(stringData instanceof NameData, "Data is not name data");
NameData data = (NameData) stringData;
ArrayList<ItemTag> tags = new ArrayList<>();
// Append those
tags.add(new ItemTag(getNBTPath(), data.getMainName()));
if (data.hasPrefixes()) tags.add(data.compressPrefixes(getNBTPath() + "_PRE"));
if (data.hasSuffixes()) tags.add(data.compressSuffixes(getNBTPath() + "_SUF"));
return tags;
}
@Override
public void whenLoaded(@NotNull ReadMMOItem mmoitem) {
TODO allow for name edition etc etc.
// Get tags
ArrayList<ItemTag> relevantTags = new ArrayList<>();
boolean stored = false;
@ -294,44 +303,6 @@ public class DisplayName extends StringStat implements GemStoneStat {
}
}
}
}
}
*/
@Nullable
@Override
public StringData getLoadedNBT(@NotNull ArrayList<ItemTag> storedTags) {
// You got a double right
ItemTag tg = ItemTag.getTagAtPath(getNBTPath(), storedTags);
// Found righ
if (tg != null) {
// Get number
String value = (String) tg.getValue();
// That's it
NameData nd = new NameData(value);
nd.readPrefixes(ItemTag.getTagAtPath(getNBTPath() + "_PRE", storedTags));
nd.readSuffixes(ItemTag.getTagAtPath(getNBTPath() + "_SUF", storedTags));
return nd;
}
// Fail
return null;
}
@NotNull
@Override
public StringData getClearStatData() {
return new NameData(null);
}
@Override
public StringData whenInitialized(Object object) {
return new NameData(object.toString());
}*/
}
}

View File

@ -0,0 +1,26 @@
package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.util.annotation.BackwardsCompatibility;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.behaviour.GemStoneStat;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import net.Indyuce.mmoitems.stat.component.type.builtin.ArrayComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.StringComponentType;
import net.Indyuce.mmoitems.stat.type.StringListStat;
import org.jetbrains.annotations.NotNull;
@BackwardsCompatibility(version = "7.0")
@HasCategory(cat = "tooltip")
public class DisplayNamePrefixes extends StringListStat implements GemStoneStat {
public DisplayNamePrefixes() {
super("NAME_PRE", null);
setComponentType(ArrayComponentType.arrayOf(StringComponentType.init().build())
.internal(true)
.build());
setDisplayInLore(false);
}
}

View File

@ -0,0 +1,22 @@
package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.util.annotation.BackwardsCompatibility;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.behaviour.GemStoneStat;
import net.Indyuce.mmoitems.stat.component.type.builtin.ArrayComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.StringComponentType;
import net.Indyuce.mmoitems.stat.type.StringListStat;
@BackwardsCompatibility(version = "7.0")
@HasCategory(cat = "tooltip")
public class DisplayNameSuffixes extends StringListStat implements GemStoneStat {
public DisplayNameSuffixes() {
super("NAME_SUF", null);
setComponentType(ArrayComponentType.arrayOf(StringComponentType.init().build())
.internal(true)
.build());
setDisplayInLore(false);
}
}

View File

@ -38,7 +38,7 @@ public class Effects extends ItemStat<ArrayComponent<ObjectComponent>> implement
@Deprecated
public static ComponentType<?, ?> potionEffectComponentType() {
return ObjectComponentType.init()
.allowStringFormat(" ")
.stringSeparatedStringFormat(" ")
.addField("Type", StringComponentType.potionEffectType()
.icon(Material.POTION)
.name("Potion Effect Type")

View File

@ -1,9 +1,15 @@
package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.element.Element;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.component.model.builtin.NumberModel;
import net.Indyuce.mmoitems.stat.yaml.SyntaxAdapter;
import net.Indyuce.mmoitems.stat.type.DoubleStat;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.util.ElementStatType;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
@HasCategory(cat = "elements")
public class ElementalStat extends DoubleStat {
@ -11,6 +17,24 @@ public class ElementalStat extends DoubleStat {
super(statType.getConcatenatedTagPath(element), new String[]{"equipment", "ornament", "gem_stone"});
}
public static final SyntaxAdapter ALTERNATE_SYNTAX = new SyntaxAdapter("element", (template, obj) -> {
Validate.isTrue(obj instanceof ConfigurationSection, "Not a configuration section");
ConfigurationSection config = (ConfigurationSection) obj;
for (Element element : Element.values())
for (ElementStatType statType : ElementStatType.values()) {
final String path = statType.getConcatenatedConfigPath(element);
if (!config.contains(path)) continue;
String statId = statType.getConcatenatedTagPath(element); //
ItemStat<?> stat = MMOItems.plugin.getStats().get(statId);
Validate.notNull(stat, "Could not find elemental stat with ID '" + statId + "'");
NumberModel model = new NumberModel(config.get(path));
baseData.put(stat, new NumberModel(formula));
}
});
/*
public static void updateComponentType() {

View File

@ -1,8 +1,5 @@
package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.util.AltChar;
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;
@ -12,41 +9,36 @@ import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
import net.Indyuce.mmoitems.comp.enchants.EnchantPlugin;
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
import net.Indyuce.mmoitems.input.LegacyItemInputHandler;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.composite.EnchantComponent;
import net.Indyuce.mmoitems.stat.component.builtin.api.EnchantComponent;
import net.Indyuce.mmoitems.stat.component.type.ComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.ArrayComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.NumberComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.ObjectComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.StringComponentType;
import net.Indyuce.mmoitems.stat.data.EnchantListData;
import net.Indyuce.mmoitems.stat.data.random.RandomEnchantListData;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.data.type.UpgradeInfo;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import net.Indyuce.mmoitems.stat.type.Upgradable;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
@HasCategory(cat = "item")
public class Enchants extends ItemStat<ArrayComponent<EnchantComponent>> implements Upgradable {
@ -54,7 +46,7 @@ public class Enchants extends ItemStat<ArrayComponent<EnchantComponent>> impleme
super("ENCHANTS", Material.ENCHANTED_BOOK, "Enchantments", new String[]{"The item enchants."}, new String[0]);
ComponentType<?, ?> enchantComponentType = ObjectComponentType.init()
.allowStringFormat(" ")
.stringSeparatedStringFormat(" ")
.implementation(EnchantComponent::new)
.addField("Enchant", StringComponentType.enchant().build())
.addField("Level", NumberComponentType.integer().build())
@ -72,66 +64,17 @@ public class Enchants extends ItemStat<ArrayComponent<EnchantComponent>> impleme
.trimdesc("The item enchants.")
.build());
// TODO ui display rules
setItemMetaSaved(true);
}
public void whenClicked(@NotNull EditionInventory inv, @NotNull InventoryClickEvent event) {
if (event.getAction() == InventoryAction.PICKUP_ALL)
new LegacyItemInputHandler(inv, ItemStats.ENCHANTS).enable("Write in the chat the enchant you want to add.",
ChatColor.AQUA + "Format: {Enchant Name} {Enchant Level Numeric Formula}");
if (event.getAction() == InventoryAction.PICKUP_HALF) {
if (inv.getEditedSection().contains("enchants")) {
Set<String> set = inv.getEditedSection().getConfigurationSection("enchants").getKeys(false);
String last = Arrays.asList(set.toArray(new String[0])).get(set.size() - 1);
inv.getEditedSection().set("enchants." + last, null);
if (set.size() <= 1)
inv.getEditedSection().set("enchants", null);
inv.registerTemplateEdition();
inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + "Successfully removed " + last.substring(0, 1).toUpperCase()
+ last.substring(1).toLowerCase().replace("_", " ") + ".");
}
}
}
@Deprecated
public void whenInput(@NotNull EditionInventory inv, @NotNull String message, Object... info) {
final String[] split = message.split(" ");
final Enchantment enchant = getEnchant(split[0]);
Validate.notNull(enchant, split[0]
+ " is not a valid enchantment! All enchants can be found here: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/enchantments/Enchantment.html");
final NumericStatFormula formula = split.length > 1 ? new NumericStatFormula(message.substring(message.indexOf(" ") + 1))
: new NumericStatFormula(1, 0, 0, 0);
formula.fillConfigurationSection(inv.getEditedSection(), "enchants." + enchant.getKey().getKey());
inv.registerTemplateEdition();
inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + enchant.getKey().getKey() + " " + formula + " successfully added.");
}
public void whenDisplayed(List<String> lore, Optional<RandomEnchantListData> statData) {
if (statData.isPresent()) {
lore.add(ChatColor.GRAY + "Current Value:");
RandomEnchantListData data = statData.get();
data.getEnchants().forEach(enchant -> lore.add(ChatColor.GRAY + "* " + UtilityMethods.caseOnWords(enchant.getKey().getKey().replace("_", " "))
+ " " + data.getLevel(enchant).toString()));
} else
lore.add(ChatColor.GRAY + "Current Value: " + ChatColor.RED + "None");
lore.add("");
lore.add(ChatColor.YELLOW + AltChar.listDash + " Click to add an enchant.");
lore.add(ChatColor.YELLOW + AltChar.listDash + " Right click to remove the last enchant.");
}
@Nullable
@Override
public ArrayComponent<EnchantComponent> read(ReadMMOItem mmoitem) {
// Create enchant data from this items' enchantments
ArrayComponent<EnchantComponent> enchants = new ArrayComponent<>();
EnchantListData enchants = new EnchantListData();
// Get the Item Meta
ItemStack item = mmoitem.getNBT().getItem();
@ -143,9 +86,7 @@ public class Enchants extends ItemStat<ArrayComponent<EnchantComponent>> impleme
// For each enchantment, in the usual way
for (Enchantment enchant : itemMeta.getEnchants().keySet()) {
// Add Level
enchants.addEnchant(enchant, itemMeta.getEnchantLevel(enchant));
enchants.asList().add(new EnchantComponent(enchant, itemMeta.getEnchantLevel(enchant)));
}
// For each enchantment 'stored' in the item
@ -155,14 +96,13 @@ public class Enchants extends ItemStat<ArrayComponent<EnchantComponent>> impleme
for (Enchantment enchant : ((EnchantmentStorageMeta) itemMeta).getStoredEnchants().keySet()) {
// Add Level
enchants.addEnchant(enchant, ((EnchantmentStorageMeta) itemMeta).getStoredEnchantLevel(enchant));
enchants.asList().add(new EnchantComponent(enchant, ((EnchantmentStorageMeta) itemMeta).getStoredEnchantLevel(enchant)));
}
}
}
}
// Recognize the Stat Data
mmoitem.setData(ItemStats.ENCHANTS, enchants);
return enchants.asList().isEmpty() ? null : enchants;
/*
TODO this code is fucking garbage
@ -224,68 +164,12 @@ public class Enchants extends ItemStat<ArrayComponent<EnchantComponent>> impleme
return eld;
}
/**
* Since GemStones shall be removable, the enchantments must also be stored.
*/
@Nullable
@Override
public EnchantListData getLoadedNBT(@NotNull ArrayList<ItemTag> storedTags) {
public void write(ItemStackBuilder builder, @NotNull ArrayComponent<EnchantComponent> component) {
// 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 = getEnchant(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 write(ItemStackBuilder builder, @NotNull ArrayComponent<ObjectComponent> component) {
for (Enchantment enchant : enchants.getEnchants()) {
int lvl = enchants.getLevel(enchant);
for (EnchantComponent enchantComponent : component.asList()) {
int lvl = enchantComponent.getLevel();
Enchantment enchant = enchantComponent.getEnchant();
// If it's an enchanted item, has to be registered as a stored enchant instead
if (builder.getItemStack().getType() == Material.ENCHANTED_BOOK) {
@ -311,26 +195,6 @@ public class Enchants extends ItemStat<ArrayComponent<EnchantComponent>> impleme
writeJsonToNbt(builder, component);
}
/**
* Since GemStones shall be removable, the enchantments must also be stored.
*/
@NotNull
@Override
public ArrayList<ItemTag> getAppliedNBT(@NotNull EnchantListData data) {
ArrayList<ItemTag> ret = new ArrayList<>();
// Add enchantment pair data
ArrayList<String> enchantments = new ArrayList<>();
for (Enchantment enchantment : data.getEnchants()) {
enchantments.add(enchantment.getKey().getKey() + " " + 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 {

View File

@ -3,12 +3,12 @@ package net.Indyuce.mmoitems.stat;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.component.builtin.composite.GemstoneComponent;
import net.Indyuce.mmoitems.stat.component.builtin.composite.GemstonesComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import net.Indyuce.mmoitems.stat.component.builtin.api.GemstoneComponent;
import net.Indyuce.mmoitems.stat.component.builtin.api.GemstonesComponent;
import net.Indyuce.mmoitems.stat.component.type.builtin.ArrayComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.ObjectComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.StringComponentType;
import net.Indyuce.mmoitems.stat.data.GemstoneData;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
@ -36,9 +36,9 @@ public class GemSockets extends ItemStat<GemstonesComponent> {
setComponentType(ObjectComponentType.init()
// No description needed, the UI directly skips the object level.
.addField("Sockets", ArrayComponentType.arrayOf(StringComponentType.init().build()).build())
.addField("EmptySlots", ArrayComponentType.arrayOf(StringComponentType.init().build()).build())
// Gemstones part. It is internal
// Gemstones (internal) part
.addField("Gemstones", ArrayComponentType.arrayOf(ObjectComponentType.init()
.implementation(GemstoneComponent::new)
.build())
@ -81,35 +81,30 @@ public class GemSockets extends ItemStat<GemstonesComponent> {
@Override
public void write(ItemStackBuilder builder, @NotNull GemstonesComponent component) {
// TODO finish rewrite
// Write to NBT
writeJsonToNbt(builder, component);
// Lore
// Find upgrade level
int itemLevel = builder.getMMOItem().hasUpgradeTemplate() ? builder.getMMOItem().getUpgradeLevel() : 0;
// Applied gemstones
List<String> lore = new ArrayList<>();
for (GemstoneData gem : sockets.getGemstones()) {
if (component.getGemstones() != null) for (GemstoneComponent gem : component.getGemstones()) {
String gemName = gem.getName();
// Upgrades?
if (item.getMMOItem().hasUpgradeTemplate()) {
int iLvl = item.getMMOItem().getUpgradeLevel();
if (iLvl != 0) {
Integer gLvl = gem.getLevel();
if (gLvl != null) {
int dLevel = iLvl - gLvl;
gemName = DisplayName.appendUpgradeLevel(gemName, dLevel);
}
}
if (itemLevel != 0) {
int gemLevel = gem.getLevel();
if (gemLevel != 0) gemName = DisplayName.appendUpgradeLevel(gemName, itemLevel - gemLevel);
}
lore.add(filledGemSocketFormat.replace("{name}", gemName));
}
sockets.getEmptySlots().forEach(slot -> lore.add(emptyGemSocketFormat.replace("{name}", slot)));
item.getLore().insert("gem-stones", lore);
// Empty sockets
for (StringComponent emptySocket : component.getSockets())
lore.add(emptyGemSocketFormat.replace("{name}", emptySocket.toString()));
builder.getLore().insert("gem-stones", lore);
}
}

View File

@ -40,7 +40,7 @@ public class Lore extends StringListStat implements GemStoneStat {
// Insert in lore
List<String> toList = new ArrayList<>();
for (StringComponent subcomp : component.getComponents())
for (StringComponent subcomp : component.asList())
toList.add(subcomp.toString());
builder.getLore().insert("lore", toList);
}

View File

@ -86,7 +86,6 @@ public class NBTTags extends StringListStat {
* Unlike other StringLists, this adds every content of the array as a different tag rather than as a JsonArray compound.
*/
@NotNull
@Override
public ArrayList<ItemTag> getAppliedNBT(@NotNull StringListData data) {

View File

@ -1,134 +1,59 @@
package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.util.AltChar;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
import net.Indyuce.mmoitems.input.LegacyItemInputHandler;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.data.random.RandomPotionEffectData;
import net.Indyuce.mmoitems.stat.data.random.RandomPotionEffectListData;
import net.Indyuce.mmoitems.stat.component.builtin.api.PotionEffectComponent;
import net.Indyuce.mmoitems.stat.component.type.builtin.ArrayComponentType;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@HasCategory(cat = "misc")
public class PermanentEffects extends ItemStat<ArrayComponent<ObjectComponent>> {
public class PermanentEffects extends ItemStat<ArrayComponent<PotionEffectComponent>> {
public PermanentEffects() {
super("PERM_EFFECTS", Material.POTION, "Permanent Effects", new String[]{"The potion effects your", "item grants to the holder."},
new String[]{"!miscellaneous", "!block", "all"});
super("PERM_EFFECTS", new String[]{"!miscellaneous", "!block", "all"});
setComponentType(ArrayComponentType.arrayOf(Effects.potionEffectComponentType())
.icon(Material.POTION)
.name("Permanent Effects")
.trimdesc("Permanent potion effects granted as long as the item is handheld/worn/equipped.")
.build());
setLegacyLanguagePath("perm-effect");
// TODO dictionary needed with key
// TODO syntax adapting required
}
@Nullable
@Override
public StatComponent read(ReadMMOItem mmoitem) {
public ArrayComponent<PotionEffectComponent> read(ReadMMOItem mmoitem) {
return readJsonFromNbt(mmoitem);
}
@Override
public RandomPotionEffectListData whenInitialized(Object object) {
Validate.isTrue(object instanceof ConfigurationSection, "Must specify a config section");
ConfigurationSection config = (ConfigurationSection) object;
RandomPotionEffectListData effects = new RandomPotionEffectListData();
for (String effect : config.getKeys(false)) {
PotionEffectType type = PotionEffectType.getByName(effect.toUpperCase().replace("-", "_").replace(" ", "_"));
Validate.notNull(type, "Could not find potion effect type named '" + effect + "'");
effects.add(new RandomPotionEffectData(type, new NumericStatFormula(config.get(effect))));
}
return effects;
}
@Deprecated
public void whenClicked(@NotNull EditionInventory inv, @NotNull InventoryClickEvent event) {
if (event.getAction() == InventoryAction.PICKUP_ALL)
new LegacyItemInputHandler(inv, ItemStats.PERM_EFFECTS).enable("Write in the chat the permanent potion effect you want to add.",
ChatColor.AQUA + "Format: {Effect Name} {Amplifier Numeric Formula}");
if (event.getAction() == InventoryAction.PICKUP_HALF) {
if (inv.getEditedSection().contains("perm-effects")) {
Set<String> set = inv.getEditedSection().getConfigurationSection("perm-effects").getKeys(false);
String last = new ArrayList<>(set).get(set.size() - 1);
inv.getEditedSection().set("perm-effects." + last, null);
if (set.size() <= 1)
inv.getEditedSection().set("perm-effects", null);
inv.registerTemplateEdition();
inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + "Successfully removed " + last.substring(0, 1).toUpperCase()
+ last.substring(1).toLowerCase() + ".");
}
}
}
@Deprecated
public void whenInput(@NotNull EditionInventory inv, @NotNull String message, Object... info) {
String[] split = message.split(" ");
Validate.isTrue(split.length >= 2, "Use this format: {Effect Name} {Effect Amplifier Numeric Formula}. Example: 'speed 1 0.3' "
+ "stands for Speed 1, plus 0.3 level per item level (rounded up to lower int)");
PotionEffectType effect = PotionEffectType.getByName(split[0].replace("-", "_"));
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");
NumericStatFormula formula = new NumericStatFormula(message.substring(message.indexOf(" ") + 1));
formula.fillConfigurationSection(inv.getEditedSection(), "perm-effects." + effect.getName());
inv.registerTemplateEdition();
inv.getPlayer().sendMessage(
MMOItems.plugin.getPrefix() + ChatColor.GOLD + effect.getName() + " " + formula + ChatColor.GRAY + " successfully added.");
}
@Deprecated
public void whenDisplayed(List<String> lore, Optional<RandomPotionEffectListData> statData) {
if (statData.isPresent()) {
lore.add(ChatColor.GRAY + "Current Value:");
RandomPotionEffectListData data = statData.get();
for (RandomPotionEffectData effect : data.getEffects())
lore.add(ChatColor.GRAY + "* " + ChatColor.GREEN + UtilityMethods.caseOnWords(effect.getType().getName().replace("_", " ").toLowerCase())
+ " " + effect.getAmplifier().toString());
} else
lore.add(ChatColor.GRAY + "Current Value: " + ChatColor.RED + "None");
lore.add("");
lore.add(ChatColor.YELLOW + AltChar.listDash + " Click to add an effect.");
lore.add(ChatColor.YELLOW + AltChar.listDash + " Right click to remove the last effect.");
}
/*
@Override
public void whenApplied(@NotNull ItemStackBuilder item, @NotNull PotionEffectListData data) {
public void write(ItemStackBuilder builder, @NotNull ArrayComponent<PotionEffectComponent> component) {
List<String> lore = new ArrayList<>();
String permEffectFormat = getGeneralStatFormat();
data.getEffects().forEach(effect -> lore.add(permEffectFormat
for (PotionEffectComponent effect : component.asList()) {
lore.add(permEffectFormat
.replace("{effect}", MMOItems.plugin.getLanguage().getPotionEffectName(effect.getType())
+ " " + MMOUtils.intToRoman(effect.getLevel()))));
item.getLore().insert("perm-effects", lore);
// Yes
item.addItemTag(getAppliedNBT(data));
+ " " + MMOUtils.intToRoman(effect.getLevel())));
}
builder.getLore().insert("perm-effects", lore);
// Add to NBT
writeJsonToNbt(builder, component);
}
*/
}

View File

@ -3,7 +3,7 @@ package net.Indyuce.mmoitems.stat;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.component.builtin.composite.ColorComponent;
import net.Indyuce.mmoitems.stat.component.builtin.api.ColorComponent;
import net.Indyuce.mmoitems.stat.component.type.builtin.ObjectComponentType;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.bukkit.Color;

View File

@ -4,7 +4,7 @@ import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.composite.PotionEffectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.api.PotionEffectComponent;
import net.Indyuce.mmoitems.stat.component.type.builtin.ArrayComponentType;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.bukkit.Material;
@ -38,16 +38,16 @@ public class PotionEffects extends ItemStat<ArrayComponent<PotionEffectComponent
// Read all custom potion effects
ArrayComponent<PotionEffectComponent> arrayComponent = new ArrayComponent<>();
for (PotionEffect effect : ((PotionMeta) mmoitem.getNBT().getItem().getItemMeta()).getCustomEffects())
arrayComponent.getComponents().add(new PotionEffectComponent(effect));
arrayComponent.asList().add(new PotionEffectComponent(effect));
return arrayComponent.getComponents().isEmpty() ? null : arrayComponent;
return arrayComponent.asList().isEmpty() ? null : arrayComponent;
}
@Override
public void write(ItemStackBuilder builder, @NotNull ArrayComponent<PotionEffectComponent> component) {
if (!builder.getItemStack().getType().name().contains("POTION")) return;
for (PotionEffectComponent effect : component.getComponents())
for (PotionEffectComponent effect : component.asList())
((PotionMeta) builder.getMeta()).addCustomEffect(effect.toBukkit(), false);
}
}

View File

@ -21,7 +21,7 @@ import org.jetbrains.annotations.Nullable;
* @see net.Indyuce.mmoitems.api.interaction.weapon.untargeted.Lute
* @deprecated Legacy hard-coded weapons including lutes and muskets are deprecated and marked for removal/replacement
*/
@Deprecated(forRemoval = true, since = "7.0")
@Deprecated(since = "7.0")
@HasCategory(cat = "misc")
public class ProjectileParticles extends ItemStat<ObjectComponent> {
public ProjectileParticles() {

View File

@ -1,18 +1,16 @@
package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import io.lumine.mythic.lib.gson.JsonParser;
import net.Indyuce.mmoitems.api.player.RPGPlayer;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.behaviour.GemStoneStat;
import net.Indyuce.mmoitems.stat.behaviour.ItemRestriction;
import net.Indyuce.mmoitems.stat.data.StringListData;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import net.Indyuce.mmoitems.stat.type.StringListStat;
import org.bukkit.Material;
import java.util.ArrayList;
/**
* @author Gunging
*/
@ -25,40 +23,36 @@ public class RequiredBiomes extends StringListStat implements ItemRestriction, G
@Override
public boolean canUse(RPGPlayer player, NBTItem item, boolean message) {
// bruh
if (!item.hasTag(getNBTPath())) { return true; }
String format = item.getString(getNBTPath());
if (format == null || format.isEmpty()) return true;
// Find the relevant tags
ArrayList<ItemTag> relevantTags = new ArrayList<>();
if (item.hasTag(getNBTPath())) { relevantTags.add(ItemTag.getTagAtPath(getNBTPath(), item, SupportedNBTTagValues.STRING)); }
// Generate data
StringListData data = (StringListData) getLoadedNBT(relevantTags);
ArrayComponent<StringComponent> biomes = (ArrayComponent<StringComponent>) getComponentType().fromJson(JsonParser.parseString(format));
boolean counter = false;
if (data != null) {
// Check every string, must match once
for (String biome : data.getList()) {
for (StringComponent biome : biomes) {
// Crop
String tst = biome.toLowerCase().replace(" ", "_").replace("-", "_");
if (tst.startsWith("!")) { counter = true; tst = tst.substring(1); }
String tst = biome.toString().toLowerCase().replace(" ", "_").replace("-", "_");
if (tst.startsWith("!")) {
counter = true;
tst = tst.substring(1);
}
// Get biome
String b = player.getPlayer().getLocation().getBlock().getBiome().getKey().getKey();
// Check
if (b.contains(tst)) { return !counter; }
if (b.contains(tst)) return !counter;
}
// If the biome evaded all restrictions it will return true; if the biome didn't met any specifications it will be false.
return counter;
}
@Override
public boolean isDynamic() {
return true;
}
@Override
public boolean isDynamic() { return true; }
}

View File

@ -33,7 +33,7 @@ public class RequiredClass extends StringListStat implements ItemRestriction, Ge
@Override
public boolean canUse(RPGPlayer player, NBTItem item, boolean message) {
String requiredClass = item.getString(ItemStats.REQUIRED_CLASS.getNBTPath());
String requiredClass = item.getString(getNBTPath());
if (!requiredClass.equals("") && !hasRightClass(player, requiredClass) && !player.getPlayer().hasPermission("mmoitems.bypass.class")) {
if (message) {
Message.WRONG_CLASS.format(ChatColor.RED).send(player.getPlayer());

View File

@ -2,14 +2,18 @@ package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
import io.lumine.mythic.lib.util.annotation.BackwardsCompatibility;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.behaviour.PlayerConsumable;
import net.Indyuce.mmoitems.stat.data.DoubleData;
import net.Indyuce.mmoitems.stat.type.DoubleStat;
import net.Indyuce.mmoitems.stat.yaml.SyntaxAdapter;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
@ -27,6 +31,8 @@ public class RestoreFood extends DoubleStat implements PlayerConsumable {
"Food Restoration",
new String[]{"Food units given when consumed."},
new String[]{"consumable"});
registerAlternateYAMLSyntax(ALTERNATE_SYNTAX);
}
@Override
@ -54,4 +60,25 @@ public class RestoreFood extends DoubleStat implements PlayerConsumable {
return 0;
}
}
@BackwardsCompatibility(version = "6.7ish")
public static final SyntaxAdapter ALTERNATE_SYNTAX = new SyntaxAdapter("restore", (template, obj) -> {
Validate.isTrue(obj instanceof ConfigurationSection, "Not a configuration section");
ConfigurationSection config = (ConfigurationSection) obj;
Object configObject = config.get("food");
if (configObject != null) readModelFromConfig(ItemStats.RESTORE_FOOD, template, configObject);
configObject = config.get("health");
if (configObject != null) readModelFromConfig(ItemStats.RESTORE_HEALTH, template, configObject);
configObject = config.get("mana");
if (configObject != null) readModelFromConfig(ItemStats.RESTORE_FOOD, template, configObject);
configObject = config.get("saturation");
if (configObject != null) readModelFromConfig(ItemStats.RESTORE_FOOD, template, configObject);
configObject = config.get("stamina");
if (configObject != null) readModelFromConfig(ItemStats.RESTORE_STAMINA, template, configObject);
});
}

View File

@ -1,55 +1,72 @@
package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.util.AltChar;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import io.lumine.mythic.lib.util.Lazy;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
import net.Indyuce.mmoitems.input.LegacyItemInputHandler;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.api.ShieldStyleComponent;
import net.Indyuce.mmoitems.stat.component.type.ComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.ArrayComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.ObjectComponentType;
import net.Indyuce.mmoitems.stat.data.ShieldPatternData;
import net.Indyuce.mmoitems.stat.component.type.builtin.StringComponentType;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import net.Indyuce.mmoitems.util.HintedString;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.block.Banner;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@HasCategory(cat = "item")
public class ShieldPatternStat extends ItemStat<ObjectComponent> {
public class ShieldPatternStat extends ItemStat<ShieldStyleComponent> {
private static final Lazy<List<HintedString>> PATTERN_TYPE_NAMES = Lazy.of(() -> Arrays.stream(PatternType.values())
.map(t -> new HintedString(t.name()))
.collect(Collectors.toList()));
public ShieldPatternStat() {
super("SHIELD_PATTERN", Material.SHIELD, "Shield Pattern", new String[]{"The color & patterns", "of your shield."},
new String[0], Material.SHIELD);
super("SHIELD_PATTERN", null);
ComponentType<?, ?> layerComponentType = ObjectComponentType.init()
.addField("Pattern", StringComponentType.fromEnum(PatternType::valueOf, PATTERN_TYPE_NAMES).build())
.addField("Color", ObjectComponentType.color().build())
.inputable(true)
.build();
setComponentType(ObjectComponentType.init()
.addField("Color", ObjectComponentType.color()
.icon(Material.RED_WOOL)
.name("Base Color")
.trimdesc("The base/background color of your shield.")
.build())
.addField("Layers", ArrayComponentType.arrayOf(layerComponentType)
.icon(Material.SHIELD)
.name("Layers")
.trimdesc("Edit pattern layers here")
.build())
.icon(Material.SHIELD)
.name("Shield Style")
.trimdesc("The base color and patterns applied onto your shield.")
.build());
// Shield pattern is already saved in the item meta.
setItemMetaSaved(true);
// TODO need a YAML syntax adapter
setCompatibleMaterials(Material.SHIELD);
}
/*
// TODO need a YAML syntax adapter. layers are at the same level as color, as if array 'Layers' did not exist
@Override
public ShieldPatternData whenInitialized(Object object) {
Validate.isTrue(object instanceof ConfigurationSection, "Must specify a config section");
@ -72,128 +89,39 @@ public class ShieldPatternStat extends ItemStat<ObjectComponent> {
return shieldPattern;
}
*/
@Override
public void whenApplied(@NotNull ItemStackBuilder item, @NotNull ShieldPatternData data) {
BlockStateMeta meta = (BlockStateMeta) item.getMeta();
public void write(ItemStackBuilder builder, @NotNull ShieldStyleComponent component) {
BlockStateMeta meta = (BlockStateMeta) builder.getMeta();
Banner banner = (Banner) meta.getBlockState();
banner.setBaseColor(data.getBaseColor());
banner.setPatterns(data.getPatterns());
((BlockStateMeta) item.getMeta()).setBlockState(banner);
item.getMeta().addItemFlags(HidePotionEffects.ITEM_FLAG);
}
@Deprecated
public void whenClicked(@NotNull EditionInventory inv, @NotNull InventoryClickEvent event) {
if (event.getAction() == InventoryAction.PICKUP_ALL)
new LegacyItemInputHandler(inv, ItemStats.SHIELD_PATTERN, 0).enable("Write in the chat the color of your shield.");
if (event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
inv.getEditedSection().set("shield-pattern.color", null);
inv.registerTemplateEdition();
inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + "Successfully reset the shield color.");
}
if (event.getAction() == InventoryAction.PICKUP_HALF)
new LegacyItemInputHandler(inv, ItemStats.SHIELD_PATTERN, 1).enable("Write in the chat the pattern you want to add.",
ChatColor.AQUA + "Format: [PATTERN_TYPE] [DYE_COLOR]");
if (event.getAction() == InventoryAction.DROP_ONE_SLOT && inv.getEditedSection().contains("shield-pattern")) {
Set<String> set = inv.getEditedSection().getConfigurationSection("shield-pattern").getKeys(false);
String last = new ArrayList<>(set).get(set.size() - 1);
if (last.equalsIgnoreCase("color"))
return;
inv.getEditedSection().set("shield-pattern." + last, null);
inv.registerTemplateEdition();
inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + "Successfully removed the last pattern.");
}
}
@Deprecated
public void whenInput(@NotNull EditionInventory inv, @NotNull String message, Object... info) {
int editedStatData = (int) info[0];
if (editedStatData == 1) {
String[] split = message.split(" ");
Validate.isTrue(split.length == 2, message + " is not a valid [PATTERN_TYPE] [DYE_COLOR].");
PatternType patternType = PatternType.valueOf(split[0].toUpperCase().replace("-", "_").replace(" ", "_"));
DyeColor dyeColor = DyeColor.valueOf(split[1].toUpperCase().replace("-", "_").replace(" ", "_"));
int availableKey = generateNewKey(inv.getEditedSection().getConfigurationSection("shield-pattern"));
Validate.isTrue(availableKey >= 0, "You can have more than 100 shield patterns on a single item.");
inv.getEditedSection().set("shield-pattern." + availableKey + ".pattern", patternType.name());
inv.getEditedSection().set("shield-pattern." + availableKey + ".color", dyeColor.name());
inv.registerTemplateEdition();
inv.getPlayer().sendMessage(
MMOItems.plugin.getPrefix() + UtilityMethods.caseOnWords(patternType.name().toLowerCase().replace("_", " ")) + " successfully added.");
return;
}
DyeColor color = DyeColor.valueOf(message.toUpperCase().replace("-", "_").replace(" ", "_"));
inv.getEditedSection().set("shield-pattern.color", color.name());
inv.registerTemplateEdition();
inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + "Shield color successfully changed.");
}
public void whenDisplayed(List<String> lore, Optional<ShieldPatternData> statData) {
if (statData.isPresent()) {
lore.add(ChatColor.GRAY + "Current Value:");
ShieldPatternData data = statData.get();
lore.add(ChatColor.GRAY + "* Base Color: "
+ (data.getBaseColor() != null
? ChatColor.GREEN + UtilityMethods.caseOnWords(data.getBaseColor().name().toLowerCase().replace("_", " "))
: ChatColor.RED + "None"));
data.getPatterns().forEach(pattern -> lore.add(ChatColor.GRAY + "* " + ChatColor.GREEN + pattern.getPattern().name() + ChatColor.GRAY
+ " - " + ChatColor.GREEN + pattern.getColor().name()));
} else
lore.add(ChatColor.GRAY + "Current Value: " + ChatColor.RED + "None");
lore.add("");
lore.add(ChatColor.YELLOW + AltChar.listDash + " Left Click to change the shield color.");
lore.add(ChatColor.YELLOW + AltChar.listDash + " Shift Left Click to reset the shield color.");
lore.add(ChatColor.YELLOW + AltChar.listDash + " Right Click to add a pattern.");
lore.add(ChatColor.YELLOW + AltChar.listDash + " Drop to remove the last pattern.");
// Base color
DyeColor baseColor = component.getBaseColor();
if (baseColor != null) banner.setBaseColor(baseColor);
// Patterns
List<Pattern> patterns = component.patternsToBukkit();
if (!patterns.isEmpty()) banner.setPatterns(patterns);
((BlockStateMeta) builder.getMeta()).setBlockState(banner);
builder.getMeta().addItemFlags(HidePotionEffects.ITEM_FLAG);
}
@Nullable
@Override
public void whenLoaded(@NotNull ReadMMOItem mmoitem) {
public ShieldStyleComponent read(ReadMMOItem mmoitem) {
if (mmoitem.getNBT().getItem().getItemMeta() instanceof BlockStateMeta
&& ((BlockStateMeta) mmoitem.getNBT().getItem().getItemMeta()).hasBlockState()
&& ((BlockStateMeta) mmoitem.getNBT().getItem().getItemMeta()).getBlockState() instanceof Banner) {
// Load block state from meta
Banner banner = (Banner) ((BlockStateMeta) mmoitem.getNBT().getItem().getItemMeta()).getBlockState();
ShieldPatternData shieldPattern = new ShieldPatternData(banner.getBaseColor());
shieldPattern.addAll(banner.getPatterns());
mmoitem.setData(ItemStats.SHIELD_PATTERN, shieldPattern);
}
// Read as component
return new ShieldStyleComponent(banner);
}
@NotNull
@Override
public ShieldPatternData getClearStatData() {
return new ShieldPatternData(DyeColor.YELLOW);
}
/**
* This stat is saved not as a custom tag, but as the vanilla Pattern itself.
* Alas this method returns null.
*/
@Nullable
@Override
public ShieldPatternData getLoadedNBT(@NotNull ArrayList<ItemTag> storedTags) {
return null;
}
private int generateNewKey(ConfigurationSection section) {
int counter = 0;
while (section.contains(String.valueOf(counter)))
counter++;
return -1;
}
}

View File

@ -2,7 +2,6 @@ package net.Indyuce.mmoitems.stat;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.gson.JsonParser;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
@ -68,9 +67,9 @@ public class Soulbound extends ItemStat<ObjectComponent> implements ItemRestrict
@Override
public boolean canUse(RPGPlayer player, NBTItem item, boolean message) {
if (item.hasTag(ItemStats.SOULBOUND.getNBTPath()) && !item.getString(ItemStats.SOULBOUND.getNBTPath()).contains(player.getPlayer().getUniqueId().toString()) && !player.getPlayer().hasPermission("mmoitems.bypass.soulbound")) {
if (item.hasTag(getNBTPath()) && !item.getString(getNBTPath()).contains(player.getPlayer().getUniqueId().toString()) && !player.getPlayer().hasPermission("mmoitems.bypass.soulbound")) {
if (message) {
int level = new JsonParser().parse(item.getString(ItemStats.SOULBOUND.getNBTPath())).getAsJsonObject().get("Level").getAsInt();
int level = new JsonParser().parse(item.getString(getNBTPath())).getAsJsonObject().get("Level").getAsInt();
Message.SOULBOUND_RESTRICTION.format(ChatColor.RED).send(player.getPlayer());
player.getPlayer().playSound(player.getPlayer().getLocation(), Sound.ENTITY_VILLAGER_NO, 1, 1.5f);
player.getPlayer()

View File

@ -16,7 +16,7 @@ import net.Indyuce.mmoitems.api.util.message.Message;
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
import net.Indyuce.mmoitems.stat.annotation.HasCategory;
import net.Indyuce.mmoitems.stat.behaviour.ConsumableItemInteraction;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.api.UpgradeComponent;
import net.Indyuce.mmoitems.stat.component.type.builtin.BooleanComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.NumberComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.ObjectComponentType;
@ -37,7 +37,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Random;
@HasCategory(cat = "upgrading")
public class UpgradeStat extends ItemStat<ObjectComponent> implements ConsumableItemInteraction {
public class UpgradeStat extends ItemStat<UpgradeComponent> implements ConsumableItemInteraction {
private static final Random RANDOM = new Random();
public UpgradeStat() {
@ -61,6 +61,7 @@ public class UpgradeStat extends ItemStat<ObjectComponent> implements Consumable
*/
setComponentType(ObjectComponentType.init()
.implementation(UpgradeComponent::new)
.addField("Template", StringComponentType.init()
.icon(Material.ANVIL)
.name("Upgrade Template")
@ -108,24 +109,23 @@ public class UpgradeStat extends ItemStat<ObjectComponent> implements Consumable
@Nullable
@Override
public ObjectComponent read(ReadMMOItem mmoitem) {
public UpgradeComponent read(ReadMMOItem mmoitem) {
return readJsonFromNbt(mmoitem);
}
@Override
public void whenApplied(@NotNull ItemStackBuilder item, @NotNull UpgradeData data) {
if (!(data instanceof UpgradeData)) return;
public void write(ItemStackBuilder builder, @NotNull UpgradeComponent component) {
// Show in lore
item.addItemTag(getAppliedNBT(data));
// Write to NBT
writeJsonToNbt(builder, component);
// Special placeholder
item.getLore().registerPlaceholder("upgrade_level", String.valueOf(data.getLevel()));
builder.getLore().registerPlaceholder("upgrade_level", String.valueOf(component.getLevel()));
// Show in lore
if (data.getMaxUpgrades() > 0)
item.getLore().insert(getPath(),
getGeneralStatFormat().replace("{value}", String.valueOf(data.getMaxUpgrades())));
// Write to lore
if (component.getMaxUpgrades() > 0)
builder.getLore().insert(getPath(),
getGeneralStatFormat().replace("{value}", String.valueOf(component.getMaxUpgrades())));
}
@Deprecated

View File

@ -1,7 +1,7 @@
package net.Indyuce.mmoitems.stat.annotation;
public class InvalidComponentKeyException extends RuntimeException {
public InvalidComponentKeyException() {
super("Invalid component key");
public InvalidComponentKeyException(Object caller, String key) {
super(String.format("Component %s has no key %s", caller.getClass().getSimpleName(), key));
}
}

View File

@ -8,6 +8,7 @@ import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
//TODO define isEmpty()
public abstract class StatComponent {
@Nullable
@ -16,6 +17,8 @@ public abstract class StatComponent {
}
public String getAsString() {
// Same return value as #toString() but casting will throw an error
// if it's not a string, which is expected behaviour.
return ((StringComponent) this).getValue();
}

View File

@ -5,10 +5,12 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterator;
import java.util.function.Consumer;
public class ArrayComponent<C extends StatComponent> extends StatComponent {
public class ArrayComponent<C extends StatComponent> extends StatComponent implements Iterable<C> {
private final List<C> components = new ArrayList<>();
@Nullable
@ -16,13 +18,25 @@ public class ArrayComponent<C extends StatComponent> extends StatComponent {
return components.get(index);
}
public void forEachComponent(Consumer<C> action) {
@NotNull
public List<C> asList() {
return components;
}
@NotNull
@Override
public Iterator<C> iterator() {
return components.iterator();
}
@Override
public void forEach(Consumer<? super C> action) {
for (C component : components)
action.accept(component);
}
@NotNull
public List<C> getComponents() {
return components;
@Override
public Spliterator<C> spliterator() {
return components.spliterator();
}
}

View File

@ -0,0 +1,14 @@
package net.Indyuce.mmoitems.stat.component.builtin;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import java.util.HashMap;
import java.util.Map;
public class MapComponent<V extends StatComponent> extends StatComponent {
private final Map<String, V> map = new HashMap<>();
public Map<String, V> asMap() {
return map;
}
}

View File

@ -86,6 +86,7 @@ public class MaterialComponent extends StatComponent implements Model<MaterialCo
public Builder() {
actionLoreTags("Left click to edit the material.", "Right click to reset to default.");
terminal(true);
inputable(true);
}
public Type build() {

View File

@ -24,6 +24,11 @@ public abstract class ObjectComponent extends StatComponent {
@Nullable
public abstract StatComponent get(@NotNull String key);
/**
* Only triggers on non-null and non-empty components inside the object.
*
* @param action Action to perform on every subcomponent
*/
public abstract void forEachComponent(@NotNull BiConsumer<String, StatComponent> action);
@NotNull

View File

@ -89,6 +89,7 @@ public class SkullTextureComponent extends SimpleComponent<Object> implements Mo
public Builder() {
actionLoreTags("Left click to input a skull texture.", "Right click to remove.");
terminal(true);
inputable(true);
}
public Type build() {

View File

@ -1,4 +1,4 @@
package net.Indyuce.mmoitems.stat.component.builtin.composite;
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.skill.RegisteredSkill;
import net.Indyuce.mmoitems.stat.component.StatComponent;

View File

@ -1,5 +1,6 @@
package net.Indyuce.mmoitems.stat.component.builtin.composite;
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.DoubleComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
@ -14,6 +15,10 @@ import java.util.function.BiConsumer;
public class ColorComponent extends ObjectComponent {
private DoubleComponent red, green, blue;
private static final String RED = "Red";
private static final String GREEN = "Green";
private static final String BLUE = "Blue";
public ColorComponent(Color color) {
red = new DoubleComponent(color.getRed());
green = new DoubleComponent(color.getGreen());
@ -23,17 +28,17 @@ public class ColorComponent extends ObjectComponent {
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
switch (key) {
case "red":
case RED:
red = (DoubleComponent) component;
break;
case "green":
return;
case GREEN:
green = (DoubleComponent) component;
break;
case "blue":
return;
case BLUE:
blue = (DoubleComponent) component;
break;
return;
default:
throw new IllegalArgumentException("Illegal key");
throw new InvalidComponentKeyException(this, key);
}
}
@ -41,28 +46,28 @@ public class ColorComponent extends ObjectComponent {
@Override
public StatComponent get(@NotNull String key) {
switch (key) {
case "red":
case RED:
return red;
case "green":
case GREEN:
return green;
case "blue":
case BLUE:
return blue;
default:
throw new IllegalArgumentException("Illegal key");
throw new InvalidComponentKeyException(this, key);
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
action.accept("red", red);
action.accept("green", red);
action.accept("blue", red);
if (red != null) action.accept(RED, red);
if (red != null) action.accept(GREEN, red);
if (red != null) action.accept(BLUE, red);
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return List.of("red", "green", "blue");
return List.of(RED, GREEN, BLUE);
}
public Color toColor() {

View File

@ -1,4 +1,4 @@
package net.Indyuce.mmoitems.stat.component.builtin.composite;
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;

View File

@ -0,0 +1,97 @@
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.Enchants;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.IntegerComponent;
import net.Indyuce.mmoitems.stat.component.builtin.NumberComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.BiConsumer;
public class EnchantComponent extends ObjectComponent {
private StringComponent enchant;
private IntegerComponent level;
private static final String ENCHANT = "Enchant";
private static final String LEVEL = "Level";
public EnchantComponent() {
// Empty constructor
}
public EnchantComponent(@Nullable Enchantment enchant, int level) {
setEnchant(enchant);
setLevel(level);
}
//region API
@Nullable
public Enchantment getEnchant() {
return enchant == null ? null : Enchants.getEnchant(enchant.toString());
}
public void setEnchant(@Nullable Enchantment enchant) {
this.enchant = enchant == null ? null : new StringComponent(enchant.getKey().toString());
}
public int getLevel() {
return level.getValue();
}
public void setLevel(int level) {
this.level = level == 0 ? null : new IntegerComponent(level);
}
//endregion
//region ObjectComponent Interface
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
switch (key) {
case ENCHANT:
enchant = (StringComponent) component;
return;
case LEVEL:
level = new IntegerComponent(((NumberComponent) component).intValue());
return;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
switch (key) {
case ENCHANT:
return enchant;
case LEVEL:
return level;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
if (enchant != null) action.accept("Enchant", enchant);
if (level != null) action.accept("Level", level);
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return Arrays.asList("enchant", "level");
}
//endregion
}

View File

@ -0,0 +1,128 @@
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.IntegerComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.function.BiConsumer;
public class GemstoneComponent extends ObjectComponent {
private StringComponent name;
private StringComponent uuid;
private StringComponent mmoitemType;
private StringComponent mmoitemId;
private StringComponent socketColor;
private IntegerComponent level;
public GemstoneComponent() {
}
private static final String NAME = "Name";
private static final String HISTORIC_UUID = "History";
private static final String MMOITEM_TYPE = "Type";
private static final String MMOITEM_ID = "Id";
private static final String LEVEL = "Level";
private static final String SOCKET_COLOR = "Color";
//region API
@NotNull
public String getName() {
return Objects.requireNonNull(name).toString();
}
@NotNull
public UUID getUniqueId() {
return UUID.fromString(String.valueOf(uuid));
}
public void setName(@NotNull String name) {
this.name = new StringComponent(Objects.requireNonNull(name, "Name cannot be null"));
}
public void setUUID(@NotNull UUID uuid) {
this.uuid = new StringComponent(Objects.requireNonNull(uuid, "UUID cannot be null").toString());
}
public int getLevel() {
return level == null ? 0 : level.getValue();
}
//endregion
//region ObjectComponent Interface
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
switch (key) {
case NAME:
name = (StringComponent) component;
return;
case HISTORIC_UUID:
uuid = (StringComponent) component;
return;
case MMOITEM_TYPE:
mmoitemType = (StringComponent) component;
return;
case MMOITEM_ID:
mmoitemId = (StringComponent) component;
return;
case SOCKET_COLOR:
socketColor = (StringComponent) component;
return;
case LEVEL:
level = (IntegerComponent) component;
return;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
switch (key) {
case NAME:
return name;
case HISTORIC_UUID:
return uuid;
case MMOITEM_TYPE:
return mmoitemType;
case MMOITEM_ID:
return mmoitemId;
case SOCKET_COLOR:
return socketColor;
case LEVEL:
return level;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
action.accept(NAME, name);
action.accept(HISTORIC_UUID, uuid);
if (mmoitemId != null) action.accept(MMOITEM_ID, mmoitemId);
if (mmoitemType != null) action.accept(MMOITEM_TYPE, mmoitemType);
if (socketColor != null) action.accept(SOCKET_COLOR, socketColor);
if (level != null) action.accept(LEVEL, level);
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return List.of(NAME, HISTORIC_UUID, MMOITEM_TYPE, MMOITEM_ID, SOCKET_COLOR, LEVEL);
}
//endregion
}

View File

@ -0,0 +1,78 @@
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.function.BiConsumer;
public class GemstonesComponent extends ObjectComponent {
private ArrayComponent<GemstoneComponent> gemstones;
private ArrayComponent<StringComponent> sockets;
private static final String SOCKETS = "EmptySlots";
private static final String GEMSTONES = "Gemstones";
public void setGemstones(@Nullable ArrayComponent<GemstoneComponent> gemstones) {
this.gemstones = gemstones;
}
public void setSockets(@Nullable ArrayComponent<StringComponent> sockets) {
this.sockets = sockets;
}
@Nullable
public ArrayComponent<GemstoneComponent> getGemstones() {
return gemstones;
}
@Nullable
public ArrayComponent<StringComponent> getSockets() {
return sockets;
}
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
switch (key) {
case SOCKETS:
sockets = (ArrayComponent<StringComponent>) component;
return;
case GEMSTONES:
gemstones = (ArrayComponent<GemstoneComponent>) component;
return;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
switch (key) {
case SOCKETS:
return sockets;
case GEMSTONES:
return gemstones;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
if (sockets != null) action.accept(SOCKETS, sockets);
if (gemstones != null) action.accept(GEMSTONES, gemstones);
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return List.of(SOCKETS, GEMSTONES);
}
}

View File

@ -0,0 +1,58 @@
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.function.BiConsumer;
public class NameComponent extends ObjectComponent {
private StringComponent baseName;
private ArrayComponent<StringComponent> prefixes;
private ArrayComponent<StringComponent> suffixes;
//region API
//endregion
//region ObjectComponent Interface
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
switch (key) {
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
switch (key) {
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return List.of();
}
//endregion
}

View File

@ -0,0 +1,123 @@
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.DoubleComponent;
import net.Indyuce.mmoitems.stat.component.builtin.IntegerComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.BiConsumer;
public class PotionEffectComponent extends ObjectComponent {
private StringComponent type;
private DoubleComponent duration;
private IntegerComponent level;
public PotionEffectComponent() {
// Empty constructor
}
public PotionEffectComponent(@NotNull PotionEffect effect) {
type = new StringComponent(effect.getType().getName());
setDuration(effect.getDuration() * 20);
setLevel(effect.getAmplifier() + 1);
}
private static final String TYPE = "Type";
private static final String DURATION = "Duration";
private static final String LEVEL = "Level";
//region API
public void setType(@Nullable PotionEffectType type) {
this.type = type == null ? null : new StringComponent(type.getName());
}
@Nullable
public PotionEffectType getType() {
return type == null ? null : PotionEffectType.getByName(type.getValue());
}
public void setDuration(double duration) {
this.duration = duration == 0 ? null : new DoubleComponent(duration);
}
public double getDuration() {
return duration == null ? 0 : duration.getValue();
}
public void setLevel(int level) {
this.level = level == 0 ? null : new IntegerComponent(level);
}
public int getLevel() {
return level == null ? 0 : level.getValue();
}
@NotNull
public PotionEffect toBukkit() {
PotionEffectType type = Objects.requireNonNull(getType(), "Type cannot be null");
int duration = (int) (getDuration() * 20);
int amplifier = getLevel() - 1;
return new PotionEffect(type, duration, amplifier);
}
//endregion
//region ObjectComponent Interface
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
switch (key) {
case TYPE:
type = (StringComponent) component;
return;
case DURATION:
duration = (DoubleComponent) component;
return;
case LEVEL:
level = (IntegerComponent) component;
return;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
switch (key) {
case TYPE:
return type;
case DURATION:
return duration;
case LEVEL:
return level;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
if (type != null) action.accept(TYPE, type);
if (duration != null) action.accept(DURATION, duration);
if (level != null) action.accept(LEVEL, level);
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return List.of(TYPE, DURATION, LEVEL);
}
//endregion
}

View File

@ -0,0 +1,110 @@
package net.Indyuce.mmoitems.stat.component.builtin.api;
import dev.aurelium.slate.util.Validate;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import org.bukkit.DyeColor;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.function.BiConsumer;
public class ShieldPatternComponent extends ObjectComponent {
private StringComponent dyeColor;
private StringComponent patternType;
private static final String DYE_COLOR = "Color";
private static final String PATTERN_TYPE = "Pattern";
public ShieldPatternComponent() {
// Empty constructor
}
public ShieldPatternComponent(@Nullable PatternType patternType, @Nullable DyeColor dyeColor) {
setDyeColor(dyeColor);
setPatternType(patternType);
}
public ShieldPatternComponent(@NotNull Pattern pattern) {
dyeColor = new StringComponent(pattern.getPattern().name());
patternType = new StringComponent(pattern.getPattern().name());
}
//region API
@Nullable
public DyeColor getDyeColor() {
return dyeColor == null ? null : DyeColor.valueOf(dyeColor.getValue());
}
@Nullable
public PatternType getPatternType() {
return patternType == null ? null : PatternType.valueOf(patternType.getValue());
}
public void setDyeColor(@Nullable DyeColor dyeColor) {
this.dyeColor = dyeColor == null ? null : new StringComponent(dyeColor.name());
}
public void setPatternType(@Nullable PatternType patternType) {
this.patternType = patternType == null ? null : new StringComponent(patternType.name());
}
@NotNull
public Pattern toBukkit() {
Validate.notNull(dyeColor, "Null dye color");
Validate.notNull(patternType, "Null pattern type");
return new Pattern(DyeColor.valueOf(dyeColor.getValue()), PatternType.valueOf(patternType.getValue()));
}
//endregion
//region ObjectComponent Interface
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
switch (key) {
case DYE_COLOR:
dyeColor = (StringComponent) component;
return;
case PATTERN_TYPE:
patternType = (StringComponent) component;
return;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
switch (key) {
case DYE_COLOR:
return dyeColor;
case PATTERN_TYPE:
return patternType;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
if (dyeColor != null) action.accept(DYE_COLOR, dyeColor);
if (patternType != null) action.accept(PATTERN_TYPE, patternType);
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return List.of(DYE_COLOR, PATTERN_TYPE);
}
//endregion
}

View File

@ -0,0 +1,121 @@
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import org.bukkit.DyeColor;
import org.bukkit.block.Banner;
import org.bukkit.block.banner.Pattern;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.BiConsumer;
public class ShieldStyleComponent extends ObjectComponent {
private StringComponent baseColor;
private ArrayComponent<ShieldPatternComponent> patterns;
public ShieldStyleComponent() {
// Empty constructor
}
public ShieldStyleComponent(@Nullable DyeColor baseColor) {
setBaseColor(baseColor);
}
public ShieldStyleComponent(@NotNull Banner banner) {
setBaseColor(banner.getBaseColor());
patternsFromBukkit(banner.getPatterns());
}
private static final String BASE_COLOR = "Color";
private static final String LAYERS = "Layers";
//region API
public void setBaseColor(@Nullable DyeColor baseColor) {
this.baseColor = baseColor == null ? null : new StringComponent(baseColor.name());
}
@Nullable
public DyeColor getBaseColor() {
return baseColor == null ? null : DyeColor.valueOf(baseColor.getValue());
}
public void setPatterns(@Nullable ArrayComponent<ShieldPatternComponent> patterns) {
this.patterns = patterns;
}
@Nullable
public ArrayComponent<ShieldPatternComponent> getPatterns() {
return patterns;
}
@NotNull
public List<Pattern> patternsToBukkit() {
List<Pattern> list = new ArrayList<>();
if (patterns != null) for (ShieldPatternComponent layer : patterns.asList())
try {
list.add(layer.toBukkit());
} catch (NullPointerException exception) {
// Ignore
}
return list;
}
public void patternsFromBukkit(List<Pattern> patterns) {
this.patterns = new ArrayComponent<>();
for (Pattern pattern : patterns)
this.patterns.asList().add(new ShieldPatternComponent(pattern));
}
//endregion
//region ObjectComponent Interface
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
switch (key) {
case BASE_COLOR:
baseColor = (StringComponent) component;
return;
case LAYERS:
patterns = (ArrayComponent<ShieldPatternComponent>) component;
return;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
switch (key) {
case BASE_COLOR:
return baseColor;
case LAYERS:
return patterns;
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
if (baseColor != null) action.accept(BASE_COLOR, baseColor);
if (patterns != null) action.accept(LAYERS, patterns);
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return List.of(BASE_COLOR, LAYERS);
}
//endregion
}

View File

@ -1,8 +1,8 @@
package net.Indyuce.mmoitems.stat.component.builtin.composite;
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import org.bukkit.potion.PotionEffect;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -10,27 +10,38 @@ import java.util.Collection;
import java.util.List;
import java.util.function.BiConsumer;
public class PotionEffectComponent extends ObjectComponent {
// TODO
public class TemplateClass extends ObjectComponent {
private static final String SOME_KEY = "SomeKey";
private static final String SOME_OTHER_KEY = "SomeOtherKey";
private static final String LAST_KEY = "LastKey";
public PotionEffectComponent(PotionEffect bukkit) {
//region API
}
//endregion
//region ObjectComponent Interface
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
throw new RuntimeException("not implemented");
switch (key) {
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
throw new RuntimeException("not implemented");
switch (key) {
default:
throw new InvalidComponentKeyException(this, key);
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
throw new RuntimeException("not implemented");
}
@NotNull
@ -39,7 +50,5 @@ public class PotionEffectComponent extends ObjectComponent {
return List.of();
}
public PotionEffect toBukkit() {
throw new RuntimeException("not implemented");
}
//endregion
}

View File

@ -1,4 +1,4 @@
package net.Indyuce.mmoitems.stat.component.builtin.composite;
package net.Indyuce.mmoitems.stat.component.builtin.api;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
@ -9,7 +9,17 @@ import java.util.Collection;
import java.util.List;
import java.util.function.BiConsumer;
public class GemstoneComponent extends ObjectComponent {
@Deprecated
public class UpgradeComponent extends ObjectComponent {
public int getLevel() {
return 0;
}
public int getMaxUpgrades() {
return 0;
}
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
@ -31,7 +41,4 @@ public class GemstoneComponent extends ObjectComponent {
public Collection<String> getComponentKeys() {
return List.of();
}
// TODO
}

View File

@ -1,64 +0,0 @@
package net.Indyuce.mmoitems.stat.component.builtin.composite;
import net.Indyuce.mmoitems.stat.annotation.InvalidComponentKeyException;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.IntegerComponent;
import net.Indyuce.mmoitems.stat.component.builtin.NumberComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.SimpleComponent;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.BiConsumer;
public class EnchantComponent extends ObjectComponent {
// TODO is this a string component of enchantment component
private SimpleComponent<Enchantment> enchant;
private IntegerComponent level;
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
switch (key) {
case "Level":
level = new IntegerComponent(((NumberComponent) component).intValue());
case "Enchant":
enchant = (SimpleComponent<Enchantment>) component;
}
}
public Enchantment getEnchant() {
return enchant.getValue();
}
public int getLevel() {
return level.getValue();
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
switch (key) {
case "Enchant":
return enchant;
case "Level":
return level;
default:
throw new InvalidComponentKeyException();
}
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
action.accept("Enchant", enchant);
action.accept("Level", level);
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return Arrays.asList("enchant", "level");
}
}

View File

@ -1,36 +0,0 @@
package net.Indyuce.mmoitems.stat.component.builtin.composite;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.function.BiConsumer;
public class GemstonesComponent extends ObjectComponent {
// TODO
@Override
public void set(@NotNull String key, @NotNull StatComponent component) {
}
@Nullable
@Override
public StatComponent get(@NotNull String key) {
return null;
}
@Override
public void forEachComponent(@NotNull BiConsumer<String, StatComponent> action) {
}
@NotNull
@Override
public Collection<String> getComponentKeys() {
return List.of();
}
}

View File

@ -15,30 +15,30 @@ import java.util.List;
import java.util.stream.Collectors;
public class ArrayModel<C extends StatComponent> implements Model<ArrayComponent<C>> {
private final List<Pair<String, Model<?>>> submodels = new ArrayList<>();
private final List<Pair<String, Model<?>>> models = new ArrayList<>();
public List<Pair<String, Model<?>>> getKeyedSubmodels() {
return submodels;
public List<Pair<String, Model<?>>> getKeyedModels() {
return models;
}
public List<Model<?>> getSubmodels() {
return submodels.stream().map(Pair::getValue).collect(Collectors.toList());
public List<Model<?>> getModels() {
return models.stream().map(Pair::getValue).collect(Collectors.toList());
}
@Nullable
@Override
public Model<?> getModel(@NotNull String key) {
int index = Integer.parseInt(key); // Return exception if keying is wrong
Pair<String, Model<?>> found = submodels.get(index);
Pair<String, Model<?>> found = models.get(index);
return found == null ? null : found.getValue();
}
public ArrayComponent<C> randomize(ArrayComponentType<C> componentType, MMOItemBuilder builder) {
ArrayComponent<C> randomized = new ArrayComponent<>();
for (Pair<String, Model<?>> submodel : submodels) {
for (Pair<String, Model<?>> submodel : models) {
C c = (C) ((ComponentType) componentType.getSubType()).randomize(submodel.getValue(), builder);
randomized.getComponents().add(c);
randomized.asList().add(c);
}
// allow for some sort of syntax to pick a random number of elements from the list

View File

@ -0,0 +1,37 @@
package net.Indyuce.mmoitems.stat.component.model.builtin;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.MapComponent;
import net.Indyuce.mmoitems.stat.component.model.Model;
import net.Indyuce.mmoitems.stat.component.type.ComponentType;
import net.Indyuce.mmoitems.stat.component.type.builtin.MapComponentType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
public class MapModel<V extends StatComponent> implements Model<MapComponent<V>> {
private final Map<String, Model<?>> models = new HashMap<>();
public Map<String, Model<?>> getModels() {
return models;
}
@Nullable
@Override
public Model<?> getModel(@NotNull String key) {
return models.get(key);
}
public MapComponent<V> randomize(MapComponentType componentType, MMOItemBuilder builder) {
MapComponent<V> comp = new MapComponent<>();
for (Map.Entry<String, Model<?>> entry : models.entrySet()) {
comp.asMap().put(entry.getKey(), componentType.subtype.randomize(entry.getValue(), builder));
}
return comp;
}
}

View File

@ -13,22 +13,22 @@ import java.util.HashMap;
import java.util.Map;
public class ObjectModel implements Model<ObjectComponent> {
private final Map<String, Model<?>> components = new HashMap<>();
private final Map<String, Model<?>> models = new HashMap<>();
public Map<String, Model<?>> getComponents() {
return components;
public Map<String, Model<?>> getModels() {
return models;
}
@Nullable
@Override
public Model<?> getModel(@NotNull String key) {
return components.get(key);
return models.get(key);
}
public ObjectComponent randomize(ObjectComponentType componentType, MMOItemBuilder builder) {
ObjectComponentImpl comp = new ObjectComponentImpl();
for (Map.Entry<String, Model<?>> entry : components.entrySet()) {
for (Map.Entry<String, Model<?>> entry : models.entrySet()) {
ComponentType subtype = componentType.getChildType(entry.getKey());
comp.set(entry.getKey(), subtype.randomize(entry.getValue(), builder));
}

View File

@ -22,7 +22,7 @@ public class ArrayComponentType<C extends StatComponent>
extends ComponentType<ArrayModel<C>, ArrayComponent<C>> {
/**
* The component type that you can find inside your array.
* The component type that you can find inside the array.
* This must be specified for MMOItems to parse tags containing
* arrays of arbitrary types into component objects.
*/
@ -58,7 +58,7 @@ public class ArrayComponentType<C extends StatComponent>
if (fullUiDisplay) {
// Empty list
List<Pair<String, Model<?>>> list = model.getKeyedSubmodels();
List<Pair<String, Model<?>>> list = model.getKeyedModels();
if (list.isEmpty()) {
lore.append(emptyList);
return;
@ -75,7 +75,7 @@ public class ArrayComponentType<C extends StatComponent>
// Simply print number of elements
else {
lore.clearBuffer();
lore.append(String.format(listCountFormat, model.getKeyedSubmodels().size()));
lore.append(String.format(listCountFormat, model.getKeyedModels().size()));
}
}
@ -89,7 +89,7 @@ public class ArrayComponentType<C extends StatComponent>
for (String key : ((ConfigurationSection) object).getKeys(false)) {
Object value = ((ConfigurationSection) object).get(key);
Validate.notNull(value, "Null value while constructing array model");
model.getKeyedSubmodels().add(Pair.of(key, subtype.fromConfig(value)));
model.getKeyedModels().add(Pair.of(key, subtype.fromConfig(value)));
}
return model;
@ -101,7 +101,7 @@ public class ArrayComponentType<C extends StatComponent>
int counter = 0;
for (Object element : (List<?>) object)
model.getKeyedSubmodels().add(Pair.of(String.valueOf(counter++), subtype.fromConfig(element)));
model.getKeyedModels().add(Pair.of(String.valueOf(counter++), subtype.fromConfig(element)));
return model;
}
@ -129,18 +129,18 @@ public class ArrayComponentType<C extends StatComponent>
ArrayComponent<C> arr = new ArrayComponent<>();
for (JsonElement el : json.getAsJsonArray())
arr.getComponents().add(subtype.fromJson(el));
arr.asList().add(subtype.fromJson(el));
return arr;
}
@Override
public JsonElement toJson(@NotNull ArrayComponent<C> component) {
if (component.getComponents().isEmpty()) return null;
if (component.asList().isEmpty()) return null;
JsonArray array = new JsonArray();
for (C comp : component.getComponents()) {
for (C comp : component.asList()) {
JsonElement subelement = subtype.toJson(comp);
if (subelement != null) array.add(subelement);
}

View File

@ -85,6 +85,7 @@ public class BooleanComponentType extends ComponentType<BooleanModel, BooleanCom
Builder() {
actionLoreTags("Left click to switch this value.", "Right click to choose a probability to have this option.");
terminal(true);
inputable(true);
}
public BooleanComponentType build() {

View File

@ -0,0 +1,94 @@
package net.Indyuce.mmoitems.stat.component.type.builtin;
import io.lumine.mythic.lib.gson.JsonElement;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.stat.component.LoreWrapper;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.MapComponent;
import net.Indyuce.mmoitems.stat.component.model.Model;
import net.Indyuce.mmoitems.stat.component.model.builtin.MapModel;
import net.Indyuce.mmoitems.stat.component.type.ComponentType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* A dynamic map with key validation if necessary. Objects are structures with
* a set number of fields, maps can contain any field. This comes handy for
* modifier maps (abilities) or even enchant maps.
*/
public class MapComponentType<C extends StatComponent>
extends ComponentType<MapModel<C>, MapComponent<C>> {
/**
* The component type that you can find inside the map.
* This must be specified for MMOItems to parse tags containing
* arrays of arbitrary types into component objects.
*/
private ComponentType<?, C> subtype;
public ComponentType<?, C> getSubtype() {
return subtype;
}
@Override
public void displayInEditor(LoreWrapper lore, MapModel<C> model) {
}
@Override
public MapModel<C> fromConfig(@NotNull Object object) {
return null;
}
@Nullable
@Override
public Object inputToConfig(@NotNull String playerInput) {
return null;
}
@NotNull
@Override
public MapComponent<C> fromJson(@NotNull JsonElement json) {
return null;
}
@Nullable
@Override
public JsonElement toJson(@NotNull MapComponent<C> component) {
return null;
}
@Override
public MapComponent<C> generateEmptyComponent() {
return null;
}
@Override
public MapComponent<C> randomize(MapModel<C> model, MMOItemBuilder builder) {
return null;
}
//region Build
@NotNull
public static <M extends Model<C>, T extends ComponentType<M, C>, C extends StatComponent> MapComponentType<C>.Builder mapOf(T of) {
return new MapComponentType<C>().new Builder().of(of);
}
public class Builder extends ComponentType<MapModel<C>, MapComponent<C>>.Builder {
Builder() {
}
public <M extends Model<C>> Builder of(@NotNull ComponentType<M, C> subtype) {
MapComponentType.this.subtype = subtype;
return this;
}
@NotNull
public MapComponentType<C> build() {
return (MapComponentType<C>) super.build();
}
}
//endregion
}

View File

@ -189,6 +189,7 @@ public class NumberComponentType extends ComponentType<NumberModel, NumberCompon
Builder() {
actionLoreTags("Left click to edit this number.", "Right click to remove this option.");
terminal(true);
inputable(true);
}
public Builder attribute(@Nullable Attribute attribute) {

View File

@ -8,6 +8,7 @@ import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ObjectComponentImpl;
import net.Indyuce.mmoitems.stat.component.model.builtin.ObjectModel;
import net.Indyuce.mmoitems.stat.component.type.ComponentType;
import net.Indyuce.mmoitems.stat.yaml.SyntaxAdapter;
import net.Indyuce.mmoitems.util.Pair;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
@ -25,6 +26,13 @@ public class ObjectComponentType extends ComponentType<ObjectModel, ObjectCompon
private String stringFormatSeparatorPattern;
/**
* There are some stats
*
* @see SyntaxAdapter
*/
private boolean syntacticShortcut;
/*
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
@ -99,7 +107,7 @@ public class ObjectComponentType extends ComponentType<ObjectModel, ObjectCompon
int counter = 0;
for (Map.Entry<String, ComponentType<?, ?>> entry : fields.entrySet()) {
String sub = split[counter++];
comp.getComponents().put(entry.getKey(), entry.getValue().fromConfig(sub));
comp.getModels().put(entry.getKey(), entry.getValue().fromConfig(sub));
}
return comp;
@ -118,7 +126,7 @@ public class ObjectComponentType extends ComponentType<ObjectModel, ObjectCompon
if (sub == null) continue;
// TODO object validation
comp.getComponents().put(entry.getKey(), entry.getValue().fromConfig(sub));
comp.getModels().put(entry.getKey(), entry.getValue().fromConfig(sub));
}
return comp;
@ -181,7 +189,7 @@ public class ObjectComponentType extends ComponentType<ObjectModel, ObjectCompon
.addField("Red", NumberComponentType.integer().icon(Material.RED_WOOL).name("Red").build())
.addField("Green", NumberComponentType.integer().icon(Material.GREEN_WOOL).name("Green").build())
.addField("Blue", NumberComponentType.integer().icon(Material.BLUE_WOOL).name("Blue").build())
.allowStringFormat(" ");
.stringSeparatedStringFormat(" ");
}
public class Builder extends ComponentType<ObjectModel, ObjectComponent>.Builder {
@ -199,7 +207,7 @@ public class ObjectComponentType extends ComponentType<ObjectModel, ObjectCompon
return this;
}
public Builder allowStringFormat(String separatorPattern) {
public Builder stringSeparatedStringFormat(String separatorPattern) {
Validate.notNull(separatorPattern, "Separator cannot be null");
stringFormatSeparatorPattern = separatorPattern;
return this;

View File

@ -229,6 +229,7 @@ public class StringComponentType extends ComponentType<StringModel, StringCompon
Builder() {
actionLoreTags("Left click to edit this string.", "Right click to remove this option.");
terminal(true);
inputable(true);
}
public Builder adaptor(@Nullable Function<String, String> adaptor) {

View File

@ -5,16 +5,14 @@ import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.stat.component.LoreWrapper;
import net.Indyuce.mmoitems.stat.component.builtin.VoidComponent;
import net.Indyuce.mmoitems.stat.component.type.ComponentType;
import org.bukkit.ChatColor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class VoidComponentType extends ComponentType<VoidComponent, VoidComponent> {
private static final String UI_NO_VAL = ChatColor.RED + "No Input";
@Override
public void displayInEditor(LoreWrapper lore, VoidComponent model) {
lore.append(UI_NO_VAL);
lore.clearBuffer();
}
@Override
@ -58,7 +56,6 @@ public class VoidComponentType extends ComponentType<VoidComponent, VoidComponen
public class Builder extends ComponentType<VoidComponent, VoidComponent>.Builder {
Builder() {
terminal(true);
}
@NotNull

View File

@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.UUID;
@Deprecated
@SuppressWarnings("unused")
public class GemstoneData {
private final String name;

View File

@ -1,7 +1,6 @@
package net.Indyuce.mmoitems.stat.type;
package net.Indyuce.mmoitems.stat.data;
import io.lumine.mythic.lib.api.item.ItemTag;
import net.Indyuce.mmoitems.stat.data.StringData;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

View File

@ -1,66 +0,0 @@
package net.Indyuce.mmoitems.stat.data;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import org.jetbrains.annotations.NotNull;
@Deprecated
public class RestoreData implements StatData, Mergeable<RestoreData> {
private double health, food, saturation;
public RestoreData(double health, double food, double saturation) {
this.health = health;
this.food = food;
this.saturation = saturation;
}
public double getHealth() {
return health;
}
public double getFood() {
return food;
}
public double getSaturation() {
return saturation;
}
public void setHealth(double value) {
health = value;
}
public void setFood(double value) {
food = value;
}
public void setSaturation(double value) {
saturation = value;
}
@Override
public boolean isEmpty() {
return food == 0 && health == 0 && saturation == 0;
}
@Override
public void mergeWith(@NotNull RestoreData targetData) {
health += targetData.health;
food += targetData.food;
saturation += targetData.saturation;
}
@Override
@NotNull
public RestoreData clone() {
return new RestoreData(health, food, saturation);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof RestoreData)) {
return false;
}
return ((RestoreData) obj).getFood() == getFood() && ((RestoreData) obj).getHealth() == getHealth() && ((RestoreData) obj).getSaturation() == getSaturation();
}
}

View File

@ -1,76 +0,0 @@
package net.Indyuce.mmoitems.stat.data.random;
import io.lumine.mythic.lib.skill.trigger.TriggerType;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.skill.RegisteredSkill;
import net.Indyuce.mmoitems.stat.data.AbilityData;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @deprecated TODO replace using RandomComponent's
*/
@Deprecated
public class RandomAbilityData {
private final RegisteredSkill ability;
private final TriggerType triggerType;
private final Map<String, NumericStatFormula> modifiers = new HashMap<>();
public RandomAbilityData(ConfigurationSection config) {
Validate.isTrue(config.contains("type"), "Missing ability type");
Validate.isTrue(config.contains("mode"), "Missing ability trigger type/casting mode");
String abilityFormat = config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_");
Validate.isTrue(MMOItems.plugin.getSkills().hasSkill(abilityFormat), "Could not find ability called '" + abilityFormat + "'");
ability = MMOItems.plugin.getSkills().getSkill(abilityFormat);
String modeFormat = config.getString("mode").toUpperCase().replace("-", "_").replace(" ", "_");
triggerType = MMOUtils.backwardsCompatibleTriggerType(modeFormat);
for (String key : config.getKeys(false))
if (!key.equalsIgnoreCase("mode") && !key.equalsIgnoreCase("type") && ability.getHandler().getModifiers().contains(key))
modifiers.put(key, new NumericStatFormula(config.get(key)));
}
public RandomAbilityData(RegisteredSkill ability, TriggerType triggerType) {
this.ability = ability;
this.triggerType = triggerType;
}
public RegisteredSkill getAbility() {
return ability;
}
public TriggerType getTriggerType() {
return triggerType;
}
public Set<String> getModifiers() {
return modifiers.keySet();
}
public void setModifier(String path, NumericStatFormula value) {
modifiers.put(path, value);
}
public boolean hasModifier(String path) {
return modifiers.containsKey(path);
}
public NumericStatFormula getModifier(String path) {
return modifiers.get(path);
}
public AbilityData randomize(MMOItemBuilder builder) {
AbilityData data = new AbilityData(ability, triggerType);
modifiers.forEach((key, formula) -> data.setModifier(key, formula.calculate(builder.getLevel())));
return data;
}
}

View File

@ -1,35 +0,0 @@
package net.Indyuce.mmoitems.stat.data.random;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.stat.data.AbilityListData;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* @deprecated TODO replace using RandomComponent's
*/
@Deprecated
public class RandomAbilityListData implements RandomStatData<AbilityListData> {
private final Set<RandomAbilityData> abilities = new LinkedHashSet<>();
public RandomAbilityListData(RandomAbilityData... abilities) {
add(abilities);
}
public void add(RandomAbilityData... abilities) {
this.abilities.addAll(Arrays.asList(abilities));
}
public Set<RandomAbilityData> getAbilities() {
return abilities;
}
@Override
public AbilityListData randomize(MMOItemBuilder builder) {
AbilityListData list = new AbilityListData();
abilities.forEach(random -> list.add(random.randomize(builder)));
return list;
}
}

View File

@ -1,29 +0,0 @@
package net.Indyuce.mmoitems.stat.data.random;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.stat.data.BooleanData;
import java.util.Random;
public class RandomBooleanData implements RandomStatData<BooleanData> {
private final double chance;
private static final Random random = new Random();
public RandomBooleanData(boolean state) {
chance = state ? 1 : 0;
}
public RandomBooleanData(double chance) {
this.chance = chance;
}
public double getChance() {
return chance;
}
@Override
public BooleanData randomize(MMOItemBuilder builder) {
return new BooleanData(random.nextDouble() < chance);
}
}

View File

@ -1,88 +0,0 @@
package net.Indyuce.mmoitems.stat.data.random;
import io.lumine.mythic.lib.element.Element;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.stat.data.DoubleData;
import net.Indyuce.mmoitems.stat.data.ElementListData;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.util.ElementStatType;
import net.Indyuce.mmoitems.util.Pair;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* @deprecated TODO replace using RandomComponent's
*/
@Deprecated
public class RandomElementListData implements RandomStatData<ElementListData>, UpdatableRandomStatData<ElementListData> {
private final Map<Pair<Element, ElementStatType>, NumericStatFormula> stats = new LinkedHashMap<>();
public RandomElementListData(ConfigurationSection config) {
Validate.notNull(config, "Config cannot be null");
for (Element element : Element.values())
for (ElementStatType statType : ElementStatType.values()) {
final String path = statType.getConcatenatedConfigPath(element);
if (config.contains(path))
stats.put(Pair.of(element, statType), new NumericStatFormula(config.get(path)));
}
}
public boolean hasStat(Element element, ElementStatType statType) {
return stats.containsKey(Pair.of(element, statType));
}
@NotNull
public NumericStatFormula getStat(Element element, ElementStatType statType) {
return stats.getOrDefault(Pair.of(element, statType), NumericStatFormula.ZERO);
}
public Set<Pair<Element, ElementStatType>> getKeys() {
return stats.keySet();
}
public void setStat(Element element, ElementStatType statType, NumericStatFormula formula) {
stats.put(Pair.of(element, statType), formula);
}
@Override
public ElementListData randomize(MMOItemBuilder builder) {
ElementListData elements = new ElementListData();
stats.forEach((key, value) -> elements.setStat(key.getKey(), key.getValue(), value.calculate(builder.getLevel())));
return elements;
}
@NotNull
@Override
@SuppressWarnings("unchecked")
public ElementListData reroll(@NotNull ItemStat stat, @NotNull ElementListData original, int determinedItemLevel) {
// Start brand new
ElementListData elements = new ElementListData();
ElementListData originalElements = (ElementListData) original;
// Evaluate each
for (Element element : Element.values())
for (ElementStatType statType : ElementStatType.values()) {
// Whats its
NumericStatFormula currentTemplateData = getStat(element, statType);
DoubleData itemData = new DoubleData(originalElements.getStat(element, statType));
// Evaluate
DoubleData result = currentTemplateData.reroll(stat, itemData, determinedItemLevel);
// Apply
elements.setStat(element, statType, result.getValue());
}
// THats it
return elements;
}
}

View File

@ -1,50 +0,0 @@
package net.Indyuce.mmoitems.stat.data.random;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.stat.Enchants;
import net.Indyuce.mmoitems.stat.data.EnchantListData;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.enchantments.Enchantment;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @deprecated TODO replace using RandomComponent's
*/
@Deprecated
public class RandomEnchantListData implements RandomStatData<EnchantListData> {
private final Map<Enchantment, NumericStatFormula> enchants = new HashMap<>();
public RandomEnchantListData(ConfigurationSection config) {
Validate.notNull(config, "Config cannot be null");
for (String key : config.getKeys(false)) {
Enchantment enchant = Enchants.getEnchant(key);
Validate.notNull(enchant, "Could not find enchant with key '" + key + "'");
addEnchant(enchant, new NumericStatFormula(config.get(key)));
}
}
public Set<Enchantment> getEnchants() {
return enchants.keySet();
}
public NumericStatFormula getLevel(Enchantment enchant) {
return enchants.get(enchant);
}
public void addEnchant(Enchantment enchant, NumericStatFormula formula) {
enchants.put(enchant, formula);
}
@Override
public EnchantListData randomize(MMOItemBuilder builder) {
EnchantListData list = new EnchantListData();
enchants.forEach((enchant, formula) -> list.addEnchant(enchant, (int) Math.max(formula.calculate(builder.getLevel()), enchant.getStartLevel())));
return list;
}
}

View File

@ -1,54 +0,0 @@
package net.Indyuce.mmoitems.stat.data.random;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.stat.data.PotionEffectData;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.potion.PotionEffectType;
/**
* @deprecated TODO replace using RandomComponent's
*/
@Deprecated
public class RandomPotionEffectData {
private final PotionEffectType type;
private final NumericStatFormula duration, amplifier;
public RandomPotionEffectData(ConfigurationSection config) {
Validate.notNull(config, "Potion effect config cannot be null");
type = PotionEffectType.getByName(config.getName().toUpperCase().replace("-", "_").replace(" ", "_"));
Validate.notNull(type, "Could not find potion effect with name '" + config.getName() + "'");
duration = new NumericStatFormula(config.get("duration"));
amplifier = new NumericStatFormula(config.get("amplifier"));
}
public RandomPotionEffectData(PotionEffectType type, NumericStatFormula amplifier) {
this(type, new NumericStatFormula((double) MMOUtils.getEffectDuration(type) / 20d, 0, 0, 0), amplifier);
}
public RandomPotionEffectData(PotionEffectType type, NumericStatFormula duration, NumericStatFormula amplifier) {
this.type = type;
this.duration = duration;
this.amplifier = amplifier;
}
public PotionEffectType getType() {
return type;
}
public NumericStatFormula getDuration() {
return duration;
}
public NumericStatFormula getAmplifier() {
return amplifier;
}
public PotionEffectData randomize(MMOItemBuilder builder) {
return new PotionEffectData(type, duration.calculate(builder.getLevel()), (int) amplifier.calculate(builder.getLevel()));
}
}

View File

@ -1,92 +0,0 @@
package net.Indyuce.mmoitems.stat.data.random;
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
import net.Indyuce.mmoitems.stat.data.PotionEffectListData;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.potion.PotionEffectType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @deprecated TODO replace using RandomComponent's
*/
@Deprecated
public class RandomPotionEffectListData implements RandomStatData<PotionEffectListData> {
private final List<RandomPotionEffectData> effects = new ArrayList<>();
public RandomPotionEffectListData(ConfigurationSection config) {
Validate.notNull(config, "Config cannot be null");
// 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(FFPMMOItems.get(), "Incorrect format, expected $e{Effect}: {Duration},{Amplifier}$b instead of $i{0} {1}$b.", key, spl));
}
// L
} else {
throw new IllegalArgumentException(FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.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) {
add(effects);
}
public void add(RandomPotionEffectData... effects) {
this.effects.addAll(Arrays.asList(effects));
}
public List<RandomPotionEffectData> getEffects() {
return effects;
}
@Override
public PotionEffectListData randomize(MMOItemBuilder builder) {
PotionEffectListData list = new PotionEffectListData();
effects.forEach(random -> list.add(random.randomize(builder)));
return list;
}
}

View File

@ -1,27 +0,0 @@
package net.Indyuce.mmoitems.stat.data.random;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.stat.data.RequiredLevelData;
/**
* Used by the item level restriction as well as attribute
* and profession item requirements for MMOCore and AureliumSkills
*
* @deprecated TODO replace using RandomComponent's
*/
@Deprecated
public class RandomRequiredLevelData extends NumericStatFormula {
public RandomRequiredLevelData(Object object) {
super(object);
}
public RandomRequiredLevelData(double base, double scale, double spread, double maxSpread) {
super(base, scale, spread, maxSpread);
}
@Override
public RequiredLevelData randomize(MMOItemBuilder builder) {
return new RequiredLevelData(calculate(builder.getLevel()));
}
}

View File

@ -1,39 +0,0 @@
package net.Indyuce.mmoitems.stat.data.random;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.stat.data.RestoreData;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
/**
* @deprecated TODO replace using RandomComponent's
*/
public class RandomRestoreData implements RandomStatData<RestoreData> {
private final NumericStatFormula health, food, saturation;
public RandomRestoreData(ConfigurationSection config) {
Validate.notNull(config, "Could not load restore config");
health = config.contains("health") ? new NumericStatFormula(config) : NumericStatFormula.ZERO;
food = config.contains("food") ? new NumericStatFormula(config) : NumericStatFormula.ZERO;
saturation = config.contains("saturation") ? new NumericStatFormula(config) : NumericStatFormula.ZERO;
}
public NumericStatFormula getHealth() {
return health;
}
public NumericStatFormula getFood() {
return food;
}
public NumericStatFormula getSaturation() {
return saturation;
}
@Override
public RestoreData randomize(MMOItemBuilder builder) {
return new RestoreData(health.calculate(builder.getLevel()), food.calculate(builder.getLevel()), saturation.calculate(builder.getLevel()));
}
}

View File

@ -8,8 +8,8 @@ import net.Indyuce.mmoitems.stat.data.type.StatData;
* are the first instances called when loading gen templates from config files.
*
* @author cympe
* @deprecated TODO replace using RandomComponent's
*/
@Deprecated
public interface RandomStatData<S extends StatData> {
/**

View File

@ -1,8 +1,8 @@
package net.Indyuce.mmoitems.stat.nbt;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ItemTagContainer implements TagContainer {
private final NBTItem item;
@ -12,7 +12,48 @@ public class ItemTagContainer implements TagContainer {
}
@Override
public void inject(@NotNull ItemTag tag) {
this.item.addTag(tag);
public void remove(@NotNull String... keys) {
item.removeTag(keys);
}
@Nullable
@Override
public String getString(@NotNull String key) {
return item.getString(key);
}
@Override
public double getDouble(@NotNull String key) {
return item.getDouble(key);
}
@Override
public int getInteger(@NotNull String key) {
return item.getInteger(key);
}
@Override
public boolean getBoolean(@NotNull String key) {
return item.getBoolean(key);
}
@Override
public void setString(@NotNull String key, String value) {
item.setString(key, value);
}
@Override
public void setDouble(@NotNull String key, double value) {
item.setDouble(key, value);
}
@Override
public void setInteger(@NotNull String key, int value) {
item.setInteger(key, value);
}
@Override
public void setBoolean(@NotNull String key, boolean value) {
item.setBoolean(key, value);
}
}

View File

@ -0,0 +1,55 @@
package net.Indyuce.mmoitems.stat.nbt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class StatHistoryTagContainer implements TagContainer {
// TODO
@Override
public void remove(@NotNull String... keys) {
}
@Nullable
@Override
public String getString(@NotNull String key) {
return "";
}
@Override
public double getDouble(@NotNull String key) {
return 0;
}
@Override
public int getInteger(@NotNull String key) {
return 0;
}
@Override
public boolean getBoolean(@NotNull String key) {
return false;
}
@Override
public void setString(@NotNull String key, String value) {
}
@Override
public void setDouble(@NotNull String key, double value) {
}
@Override
public void setInteger(@NotNull String key, int value) {
}
@Override
public void setBoolean(@NotNull String key, boolean value) {
}
}

View File

@ -1,10 +1,27 @@
package net.Indyuce.mmoitems.stat.nbt;
import io.lumine.mythic.lib.api.item.ItemTag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
// TODO rework.
public interface TagContainer {
public void inject(@NotNull ItemTag tag);
public void remove(@NotNull String... keys);
@Nullable
public String getString(@NotNull String key);
public double getDouble(@NotNull String key);
public int getInteger(@NotNull String key);
public boolean getBoolean(@NotNull String key);
public void setString(@NotNull String key, String value);
public void setDouble(@NotNull String key, double value);
public void setInteger(@NotNull String key, int value);
public void setBoolean(@NotNull String key, boolean value);
}

View File

@ -1,26 +0,0 @@
package net.Indyuce.mmoitems.stat.syntax;
import net.Indyuce.mmoitems.stat.component.model.Model;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
import java.util.function.BiConsumer;
public class SyntaxAdapter {
private final String key;
private final BiConsumer<Map<ItemStat<?>, Model<?>>, Object> adapter;
public SyntaxAdapter(String key, BiConsumer<Map<ItemStat<?>, Model<?>>, Object> adapter) {
this.key = key;
this.adapter = adapter;
}
public String getKey() {
return key;
}
public void adapt(@NotNull Map<ItemStat<?>, Model<?>> template, @NotNull Object obj) {
adapter.accept(template, obj);
}
}

View File

@ -1,57 +0,0 @@
package net.Indyuce.mmoitems.stat.syntax;
import io.lumine.mythic.lib.element.Element;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.util.NumericStatFormula;
import net.Indyuce.mmoitems.stat.component.model.builtin.NumberModel;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.util.ElementStatType;
import org.apache.commons.lang.Validate;
import org.bukkit.configuration.ConfigurationSection;
public class SyntaxAdapters {
public static final SyntaxAdapter ELEMENTS = new SyntaxAdapter("element", (baseData, obj) -> {
Validate.isTrue(obj instanceof ConfigurationSection, "Not a configuration section");
ConfigurationSection config = (ConfigurationSection) obj;
for (Element element : Element.values())
for (ElementStatType statType : ElementStatType.values()) {
final String path = statType.getConcatenatedConfigPath(element);
if (config.contains(path)) {
NumericStatFormula formula = new NumericStatFormula(config.get(path));
String statId = statType.getConcatenatedTagPath(element);
ItemStat<?> stat = MMOItems.plugin.getStats().get(statId);
Validate.notNull(stat, "Could not find elemental stat with ID '" + statId + "'");
baseData.put(stat, new NumberModel(formula));
}
}
});
/*
public static final SyntaxAdapter RESTORE = new SyntaxAdapter("restore", (baseData, obj) -> {
Validate.isTrue(obj instanceof ConfigurationSection, "Not a configuration section");
ConfigurationSection config = (ConfigurationSection) obj;
Object mana = config.get("mana");
if (mana != null) obj
if (config.get("mana"))
for (Element element : Element.values())
for (ElementStatType statType : ElementStatType.values()) {
final String path = statType.getConcatenatedConfigPath(element);
if (config.contains(path)) {
NumericStatFormula formula = new NumericStatFormula(config.get(path));
String statId = statType.getConcatenatedTagPath(element);
ItemStat<?> stat = MMOItems.plugin.getStats().get(statId);
Validate.notNull(stat, "Could not find elemental stat with ID '" + statId + "'");
baseData.put(stat, formula);
}
}
});
*/
}

View File

@ -0,0 +1,10 @@
package net.Indyuce.mmoitems.stat.type;
public enum HistoryPolicy {
/**
* Any stat managed by MMOItems has a classic
*/
CLASSIC,
}

View File

@ -9,14 +9,17 @@ import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
import net.Indyuce.mmoitems.stat.annotation.VersionDependant;
import net.Indyuce.mmoitems.stat.category.StatCategory;
import net.Indyuce.mmoitems.stat.component.StatComponent;
import net.Indyuce.mmoitems.stat.component.builtin.ArrayComponent;
import net.Indyuce.mmoitems.stat.component.builtin.StringComponent;
import net.Indyuce.mmoitems.stat.component.model.Model;
import net.Indyuce.mmoitems.stat.component.type.ComponentType;
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.yaml.SyntaxAdapter;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
@ -53,8 +56,6 @@ public abstract class ItemStat<C extends StatComponent> {
*/
private boolean itemMetaSaved = true;
private boolean indirectNbtMapping = true;
/**
* @see #readTranslationFile(ConfigurationSection)
*/
@ -132,14 +133,6 @@ public abstract class ItemStat<C extends StatComponent> {
return displayInLore;
}
public boolean isIndirectNbtMapping() {
return indirectNbtMapping;
}
public void setIndirectNbtMapping(boolean indirectNbtMapping) {
this.indirectNbtMapping = indirectNbtMapping;
}
public void setComponentType(ComponentType componentType) {
this.componentType = (ComponentType<?, StatComponent>) componentType;
@ -166,6 +159,10 @@ public abstract class ItemStat<C extends StatComponent> {
return this;
}
public void registerAlternateYAMLSyntax(@NotNull SyntaxAdapter adapter) {
MMOItems.plugin.getStats().registerYAMLSyntaxAdapter(adapter);
}
/**
* When random stat data is being read from a config file
*
@ -490,7 +487,7 @@ public abstract class ItemStat<C extends StatComponent> {
String[] split = format.split(separator);
ArrayComponent<StringComponent> array = new ArrayComponent<>();
for (String s : split) array.getComponents().add(new StringComponent(s));
for (String s : split) array.asList().add(new StringComponent(s));
return array;
}
@ -500,7 +497,7 @@ public abstract class ItemStat<C extends StatComponent> {
boolean notEmpty = false;
StringBuilder fullString = new StringBuilder();
for (StringComponent subcomp : component.getComponents()) {
for (StringComponent subcomp : component.asList()) {
fullString.append(subcomp.getValue());
if (notEmpty) fullString.append(separator);
else notEmpty = true;
@ -515,4 +512,12 @@ public abstract class ItemStat<C extends StatComponent> {
}
//endregion
/**
* @see SyntaxAdapter
*/
protected static void readModelFromConfig(@NotNull ItemStat<?> stat, @NotNull MMOItemTemplate template, @NotNull Object configObject) {
Model<?> model = stat.getComponentType().fromConfig(configObject);
if (model != null) template.getModels().put(stat, model);
}
}

View File

@ -11,6 +11,7 @@ import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
import net.Indyuce.mmoitems.item.LiveItemEditor;
import net.Indyuce.mmoitems.stat.data.EnchantListData;
import net.Indyuce.mmoitems.stat.data.GemSocketsData;
import net.Indyuce.mmoitems.stat.data.GemstoneData;
@ -38,6 +39,8 @@ public class StatHistory {
private StatData originalData;
private MMOItem parent;
private LiveItemEditor liveItemEditor;
private HashMap<UUID, StatData> perModifierBonus = new HashMap<>();
private ArrayList<StatData> perExternalData = new ArrayList<>();
private HashMap<UUID, StatData> perGemstoneData = new HashMap<>();
@ -85,6 +88,7 @@ public class StatHistory {
* Its an important assumption in several methods
* like Enchants.separateEnchantments()
*/
// TODO enchantments.
if (getOriginalData() instanceof EnchantListData) {
if (((EnchantListData) getOriginalData()).getEnchants().size() != 0) {
//CLR//MMOItems.log("\u00a7a -+- \u00a77Found Enchantments, \u00a7cnot clear. \u00a78{\u00a77" + getItemStat().getId() + "\u00a78}");
@ -278,6 +282,7 @@ public class StatHistory {
public void purgeGemstones() {
// No socket history can be found => clear all gems
// TODO invent a gem stone UUID cache in the MMOItem class.
GemSocketsData data = (GemSocketsData) getMMOItem().getData(ItemStats.GEM_SOCKETS);
if (data == null) {
perGemstoneData.clear();

View File

@ -23,13 +23,13 @@ public class StringListStat extends ItemStat<ArrayComponent<StringComponent>> {
public void write(ItemStackBuilder builder, @NotNull ArrayComponent<StringComponent> component) {
// Empty stuff
if (component.getComponents().isEmpty()) return;
if (component.asList().isEmpty()) return;
if (displaysInLore()) {
boolean notEmpty = false;
StringBuilder joined = new StringBuilder();
for (StringComponent subcomp : component.getComponents()) {
for (StringComponent subcomp : component.asList()) {
joined.append(subcomp.getValue());
if (notEmpty) joined.append(", ");
else notEmpty = true;

View File

@ -0,0 +1,24 @@
package net.Indyuce.mmoitems.stat.yaml;
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
import org.jetbrains.annotations.NotNull;
import java.util.function.BiConsumer;
public class SyntaxAdapter {
private final String key;
private final BiConsumer<MMOItemTemplate, Object> adapter;
public SyntaxAdapter(String key, BiConsumer<MMOItemTemplate, Object> adapter) {
this.key = key;
this.adapter = adapter;
}
public String getKey() {
return key;
}
public void adapt(@NotNull MMOItemTemplate template, @NotNull Object obj) {
adapter.accept(template, obj);
}
}

View File

@ -1,9 +1,8 @@
package net.Indyuce.mmoitems.listener.reforging;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.event.MMOItemReforgeEvent;
import net.Indyuce.mmoitems.stat.type.NameData;
import net.Indyuce.mmoitems.stat.data.NameData;
import net.Indyuce.mmoitems.stat.type.StatHistory;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;