// Path: src/main/java/org/cyclops/everlastingabilities/Reference.java
// @SuppressWarnings("javadoc")
// public class Reference {
// 	
//     // Mod info
//     public static final String MOD_ID = "everlastingabilities";
//     public static final String GA_TRACKING_ID = "UA-65307010-9";
//     public static final String VERSION_URL = "https://raw.githubusercontent.com/CyclopsMC/Versions/master/" + MinecraftHelpers.getMinecraftVersionMajorMinor() + "/EverlastingAbilities.txt";
//     
//     // Paths
//     public static final String TEXTURE_PATH_GUI = "textures/gui/";
//     public static final String TEXTURE_PATH_SKINS = "textures/skins/";
//     public static final String TEXTURE_PATH_MODELS = "textures/models/";
//     public static final String TEXTURE_PATH_ENTITIES = "textures/entities/";
//     public static final String TEXTURE_PATH_GUIBACKGROUNDS = "textures/gui/title/background/";
//     public static final String TEXTURE_PATH_ITEMS = "textures/items/";
//     public static final String TEXTURE_PATH_PARTICLES = "textures/particles/";
//     public static final String MODEL_PATH = "models/";
// 
// }
// 
// Path: src/main/java/org/cyclops/everlastingabilities/api/Ability.java
// public class Ability implements Comparable<Ability> {
// 
//     public static final Ability EMPTY = new Ability(new AbilityType("", "", () -> Rarity.COMMON, () -> 0, () -> 0, () -> true, () -> true, () -> true, () -> true), 0);
// 
//     private final IAbilityType abilityType;
//     private final int level;
// 
//     public Ability(@Nonnull IAbilityType abilityType, int level) {
//         this.abilityType = Objects.requireNonNull(abilityType);
//         this.level = level;
//     }
// 
//     public IAbilityType getAbilityType() {
//         return abilityType;
//     }
// 
//     public int getLevel() {
//         return level;
//     }
// 
//     @Override
//     public String toString() {
//         return String.format("[%s @ %s]", abilityType.getTranslationKey(), level);
//     }
// 
//     @Override
//     public int compareTo(Ability other) {
//         return this.toString().compareTo(other.toString());
//     }
// 
//     public ITextComponent getTextComponent() {
//         return new StringTextComponent("[")
//                 .append(new TranslationTextComponent(abilityType.getTranslationKey()))
//                 .appendString(" @ " + level + "]");
//     }
// 
//     public boolean isEmpty() {
//         return getLevel() <= 0;
//     }
// 
// }
// 
// Path: src/main/java/org/cyclops/everlastingabilities/api/IAbilityType.java
// public interface IAbilityType extends IForgeRegistryEntry<IAbilityType> {
// 
//     public String getTranslationKey();
//     public String getUnlocalizedDescription();
//     public Rarity getRarity();
//     public int getMaxLevel();
//     public default int getMaxLevelInfinitySafe() {
//         return getMaxLevel() < 0 ? Integer.MAX_VALUE : getMaxLevel();
//     }
//     public int getBaseXpPerLevel();
//     public boolean isObtainableOnPlayerSpawn();
//     public boolean isObtainableOnMobSpawn();
//     public boolean isObtainableOnCraft();
//     public boolean isObtainableOnLoot();
// 
//     public void onTick(PlayerEntity player, int level);
//     public void onChangedLevel(PlayerEntity player, int oldLevel, int newLevel);
// 
// }
// 
// Path: src/main/java/org/cyclops/everlastingabilities/capability/MutableAbilityStoreConfig.java
// public class MutableAbilityStoreConfig extends CapabilityConfig {
// 
//     /**
//      * The unique instance.
//      */
//     public static MutableAbilityStoreConfig _instance;
// 
//     @CapabilityInject(IMutableAbilityStore.class)
//     public static Capability<IMutableAbilityStore> CAPABILITY = null;
// 
//     /**
//      * Make a new instance.
//      */
//     public MutableAbilityStoreConfig() {
//         super(EverlastingAbilities._instance,
//                 "mutableAbilityStore",
//                 IMutableAbilityStore.class,
//                 new AbilityStoreStorage(),
//                 DefaultMutableAbilityStore::new);
//     }
// }


import lombok.NonNull;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT;
import net.minecraft.nbt.ListNBT;
import org.cyclops.everlastingabilities.Reference;
import org.cyclops.everlastingabilities.api.Ability;
import org.cyclops.everlastingabilities.api.IAbilityType;
import org.cyclops.everlastingabilities.capability.MutableAbilityStoreConfig;
import java.util.Collection;
import java.util.Map;
package org.cyclops.everlastingabilities.api.capability;



/**
 * Wrapper for an item ability store.
 * TODO: This is just to avoid a Forge bug where cap NBT is not always sent to the client.
 * @author rubensworks
 */
public class ItemStackMutableAbilityStore implements IMutableAbilityStore {

    private static final String NBT_STORE = Reference.MOD_ID + ":abilityStoreStack";

    private final ItemStack itemStack;

    public ItemStackMutableAbilityStore(ItemStack itemStack) {
        this.itemStack = itemStack;
    }

    protected IMutableAbilityStore getInnerStore() {
        IMutableAbilityStore store = new DefaultMutableAbilityStore();
        CompoundNBT root = itemStack.getOrCreateTag();
        if (!root.contains(NBT_STORE)) {
            root.put(NBT_STORE, new ListNBT());
        }
        INBT nbt = root.get(NBT_STORE);
// Path: src/main/java/org/cyclops/everlastingabilities/Reference.java
// @SuppressWarnings("javadoc")
// public class Reference {
// 	
//     // Mod info
//     public static final String MOD_ID = "everlastingabilities";
//     public static final String GA_TRACKING_ID = "UA-65307010-9";
//     public static final String VERSION_URL = "https://raw.githubusercontent.com/CyclopsMC/Versions/master/" + MinecraftHelpers.getMinecraftVersionMajorMinor() + "/EverlastingAbilities.txt";
//     
//     // Paths
//     public static final String TEXTURE_PATH_GUI = "textures/gui/";
//     public static final String TEXTURE_PATH_SKINS = "textures/skins/";
//     public static final String TEXTURE_PATH_MODELS = "textures/models/";
//     public static final String TEXTURE_PATH_ENTITIES = "textures/entities/";
//     public static final String TEXTURE_PATH_GUIBACKGROUNDS = "textures/gui/title/background/";
//     public static final String TEXTURE_PATH_ITEMS = "textures/items/";
//     public static final String TEXTURE_PATH_PARTICLES = "textures/particles/";
//     public static final String MODEL_PATH = "models/";
// 
// }
// 
// Path: src/main/java/org/cyclops/everlastingabilities/api/Ability.java
// public class Ability implements Comparable<Ability> {
// 
//     public static final Ability EMPTY = new Ability(new AbilityType("", "", () -> Rarity.COMMON, () -> 0, () -> 0, () -> true, () -> true, () -> true, () -> true), 0);
// 
//     private final IAbilityType abilityType;
//     private final int level;
// 
//     public Ability(@Nonnull IAbilityType abilityType, int level) {
//         this.abilityType = Objects.requireNonNull(abilityType);
//         this.level = level;
//     }
// 
//     public IAbilityType getAbilityType() {
//         return abilityType;
//     }
// 
//     public int getLevel() {
//         return level;
//     }
// 
//     @Override
//     public String toString() {
//         return String.format("[%s @ %s]", abilityType.getTranslationKey(), level);
//     }
// 
//     @Override
//     public int compareTo(Ability other) {
//         return this.toString().compareTo(other.toString());
//     }
// 
//     public ITextComponent getTextComponent() {
//         return new StringTextComponent("[")
//                 .append(new TranslationTextComponent(abilityType.getTranslationKey()))
//                 .appendString(" @ " + level + "]");
//     }
// 
//     public boolean isEmpty() {
//         return getLevel() <= 0;
//     }
// 
// }
// 
// Path: src/main/java/org/cyclops/everlastingabilities/api/IAbilityType.java
// public interface IAbilityType extends IForgeRegistryEntry<IAbilityType> {
// 
//     public String getTranslationKey();
//     public String getUnlocalizedDescription();
//     public Rarity getRarity();
//     public int getMaxLevel();
//     public default int getMaxLevelInfinitySafe() {
//         return getMaxLevel() < 0 ? Integer.MAX_VALUE : getMaxLevel();
//     }
//     public int getBaseXpPerLevel();
//     public boolean isObtainableOnPlayerSpawn();
//     public boolean isObtainableOnMobSpawn();
//     public boolean isObtainableOnCraft();
//     public boolean isObtainableOnLoot();
// 
//     public void onTick(PlayerEntity player, int level);
//     public void onChangedLevel(PlayerEntity player, int oldLevel, int newLevel);
// 
// }
// 
// Path: src/main/java/org/cyclops/everlastingabilities/capability/MutableAbilityStoreConfig.java
// public class MutableAbilityStoreConfig extends CapabilityConfig {
// 
//     /**
//      * The unique instance.
//      */
//     public static MutableAbilityStoreConfig _instance;
// 
//     @CapabilityInject(IMutableAbilityStore.class)
//     public static Capability<IMutableAbilityStore> CAPABILITY = null;
// 
//     /**
//      * Make a new instance.
//      */
//     public MutableAbilityStoreConfig() {
//         super(EverlastingAbilities._instance,
//                 "mutableAbilityStore",
//                 IMutableAbilityStore.class,
//                 new AbilityStoreStorage(),
//                 DefaultMutableAbilityStore::new);
//     }
// }


// Path: src/main/java/org/cyclops/everlastingabilities/api/capability/ItemStackMutableAbilityStore.java
import lombok.NonNull;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT;
import net.minecraft.nbt.ListNBT;
import org.cyclops.everlastingabilities.Reference;
import org.cyclops.everlastingabilities.api.Ability;
import org.cyclops.everlastingabilities.api.IAbilityType;
import org.cyclops.everlastingabilities.capability.MutableAbilityStoreConfig;
import java.util.Collection;
import java.util.Map;

package org.cyclops.everlastingabilities.api.capability;



/**
 * Wrapper for an item ability store.
 * TODO: This is just to avoid a Forge bug where cap NBT is not always sent to the client.
 * @author rubensworks
 */
public class ItemStackMutableAbilityStore implements IMutableAbilityStore {

    private static final String NBT_STORE = Reference.MOD_ID + ":abilityStoreStack";

    private final ItemStack itemStack;

    public ItemStackMutableAbilityStore(ItemStack itemStack) {
        this.itemStack = itemStack;
    }

    protected IMutableAbilityStore getInnerStore() {
        IMutableAbilityStore store = new DefaultMutableAbilityStore();
        CompoundNBT root = itemStack.getOrCreateTag();
        if (!root.contains(NBT_STORE)) {
            root.put(NBT_STORE, new ListNBT());
        }
        INBT nbt = root.get(NBT_STORE);
        MutableAbilityStoreConfig.CAPABILITY.readNBT(store, null, nbt);