Memory leak fixes, optimizations, and persistence

This commit is contained in:
nossr50
2020-10-08 15:25:40 -07:00
parent 0767e62965
commit 20c69b63af
14 changed files with 546 additions and 224 deletions

View File

@@ -1,32 +1,128 @@
package com.gmail.nossr50.util.compat.layers.persistentdata;
import com.gmail.nossr50.api.exceptions.IncompleteNamespacedKeyRegister;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.layers.AbstractCompatibilityLayer;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Furnace;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.UUID;
import java.util.*;
public abstract class AbstractPersistentDataLayer extends AbstractCompatibilityLayer {
public static final String LEGACY_ABILITY_TOOL_LORE = "mcMMO Ability Tool";
public final NamespacedKey superAbilityBoosted;
public final String SUPER_ABILITY_BOOSTED = "super_ability_boosted";
protected final @NotNull NamespacedKey NSK_SUPER_ABILITY_BOOSTED_ITEM;
protected final @NotNull NamespacedKey NSK_MOB_SPAWNER_MOB;
protected final @NotNull NamespacedKey NSK_EGG_MOB;
protected final @NotNull NamespacedKey NSK_NETHER_GATE_MOB;
protected final @NotNull NamespacedKey NSK_COTW_SUMMONED_MOB;
protected final @NotNull NamespacedKey NSK_PLAYER_BRED_MOB;
protected final @NotNull NamespacedKey NSK_PLAYER_TAMED_MOB;
protected final @NotNull NamespacedKey NSK_VILLAGER_TRADE_ORIGIN_ITEM;
protected final @NotNull NamespacedKey NSK_EXPLOITED_ENDERMEN;
//Never change these constants
public final @NotNull String STR_SUPER_ABILITY_BOOSTED_ITEM = "super_ability_boosted";
public final @NotNull String STR_MOB_SPAWNER_MOB = "mcmmo_mob_spawner_mob";
public final @NotNull String STR_EGG_MOB = "mcmmo_egg_mob";
public final @NotNull String STR_NETHER_PORTAL_MOB = "mcmmo_nethergate_mob";
public final @NotNull String STR_COTW_SUMMONED_MOB = "mcmmo_cotw_summoned_mob";
public final @NotNull String STR_PLAYER_BRED_MOB = "mcmmo_player_bred_mob";
public final @NotNull String STR_PLAYER_TAMED_MOB = "mcmmo_player_tamed_mob";
public final @NotNull String STR_VILLAGER_TRADE_ORIGIN_ITEM = "mcmmo_villager_trade_origin_item";
public final @NotNull String STR_EXPLOITED_ENDERMEN = "mcmmo_exploited_endermen";
/*
* Don't modify these keys
*/
public final @NotNull String STR_FURNACE_UUID_MOST_SIG = "furnace_uuid_most_sig";
public final @NotNull String STR_FURNACE_UUID_LEAST_SIG = "furnace_uuid_least_sig";
protected final @NotNull NamespacedKey NSK_FURNACE_UUID_MOST_SIG;
protected final @NotNull NamespacedKey NSK_FURNACE_UUID_LEAST_SIG;
public final @NotNull String LEGACY_ABILITY_TOOL_LORE = "mcMMO Ability Tool";
protected static final byte SIMPLE_FLAG_VALUE = (byte) 0x1;
public AbstractPersistentDataLayer() {
superAbilityBoosted = getNamespacedKey(SUPER_ABILITY_BOOSTED);
NSK_SUPER_ABILITY_BOOSTED_ITEM = getNamespacedKey(STR_SUPER_ABILITY_BOOSTED_ITEM);
NSK_MOB_SPAWNER_MOB = getNamespacedKey(STR_MOB_SPAWNER_MOB);
NSK_EGG_MOB = getNamespacedKey(STR_EGG_MOB);
NSK_NETHER_GATE_MOB = getNamespacedKey(STR_NETHER_PORTAL_MOB);
NSK_COTW_SUMMONED_MOB = getNamespacedKey(STR_COTW_SUMMONED_MOB);
NSK_PLAYER_BRED_MOB = getNamespacedKey(STR_PLAYER_BRED_MOB);
NSK_PLAYER_TAMED_MOB = getNamespacedKey(STR_PLAYER_TAMED_MOB);
NSK_VILLAGER_TRADE_ORIGIN_ITEM = getNamespacedKey(STR_VILLAGER_TRADE_ORIGIN_ITEM);
NSK_EXPLOITED_ENDERMEN = getNamespacedKey(STR_EXPLOITED_ENDERMEN);
NSK_FURNACE_UUID_MOST_SIG = getNamespacedKey(STR_FURNACE_UUID_MOST_SIG);
NSK_FURNACE_UUID_LEAST_SIG = getNamespacedKey(STR_FURNACE_UUID_LEAST_SIG);
initializeLayer();
}
public @NotNull NamespacedKey getNamespacedKey(@NotNull String key) {
/**
* Helper method to simplify generating namespaced keys
* @param key the {@link String} value of the key
* @return the generated {@link NamespacedKey}
*/
private @NotNull NamespacedKey getNamespacedKey(@NotNull String key) {
return new NamespacedKey(mcMMO.p, key);
}
/**
* Whether or not a target {@link LivingEntity} has a specific mcMMO mob flags
* @param flag the type of mob flag to check for
* @param livingEntity the living entity to check for metadata
* @return true if the mob has metadata values for target {@link MobMetaFlagType}
*/
public abstract boolean hasMobFlag(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity);
/**
* Whether or not a target {@link LivingEntity} has any mcMMO mob flags
* @param livingEntity the living entity to check for metadata
* @return true if the mob has any mcMMO mob related metadata values
*/
public abstract boolean hasMobFlags(@NotNull LivingEntity livingEntity);
/**
* Copies all mcMMO mob flags from one {@link LivingEntity} to another {@link LivingEntity}
* This does not clear existing mcMMO mob flags on the target
* @param sourceEntity entity to copy from
* @param targetEntity entity to copy to
*/
public abstract void addMobFlags(@NotNull LivingEntity sourceEntity, @NotNull LivingEntity targetEntity);
/**
* Adds a mob flag to a {@link LivingEntity} which effectively acts a true/false boolean
* Existence of the flag can be considered a true value, non-existence can be considered false for all intents and purposes
* @param flag the desired flag to assign
* @param livingEntity the target living entity
*/
public abstract void flagMetadata(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity);
/**
* Removes a specific mob flag from target {@link LivingEntity}
* @param flag desired flag to remove
* @param livingEntity the target living entity
*/
public abstract void removeMobFlag(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity);
/**
* Remove all mcMMO related mob flags from the target {@link LivingEntity}
* @param livingEntity target entity
*/
public void removeMobFlags(@NotNull LivingEntity livingEntity) {
for(MobMetaFlagType flag : MobMetaFlagType.values()) {
removeMobFlag(flag, livingEntity);
}
}
public abstract @Nullable UUID getFurnaceOwner(@NotNull Furnace furnace);
public abstract void setFurnaceOwner(@NotNull Furnace furnace, @NotNull UUID uuid);
@@ -39,7 +135,7 @@ public abstract class AbstractPersistentDataLayer extends AbstractCompatibilityL
public abstract void removeBonusDigSpeedOnSuperAbilityTool(@NotNull ItemStack itemStack);
public boolean isLegacyAbilityTool(ItemStack itemStack) {
public boolean isLegacyAbilityTool(@NotNull ItemStack itemStack) {
ItemMeta itemMeta = itemStack.getItemMeta();
if(itemMeta == null)
@@ -53,7 +149,7 @@ public abstract class AbstractPersistentDataLayer extends AbstractCompatibilityL
return lore.contains(LEGACY_ABILITY_TOOL_LORE);
}
public static String getLegacyAbilityToolLore() {
public @NotNull String getLegacyAbilityToolLore() {
return LEGACY_ABILITY_TOOL_LORE;
}
}

View File

@@ -0,0 +1,11 @@
package com.gmail.nossr50.util.compat.layers.persistentdata;
public enum MobMetaFlagType {
MOB_SPAWNER_MOB,
EGG_MOB,
NETHER_PORTAL_MOB,
COTW_SUMMONED_MOB,
PLAYER_BRED_MOB,
PLAYER_TAMED_MOB,
EXPLOITED_ENDERMEN,
}

View File

@@ -1,9 +1,11 @@
package com.gmail.nossr50.util.compat.layers.persistentdata;
import com.gmail.nossr50.api.exceptions.IncompleteNamespacedKeyRegister;
import com.gmail.nossr50.datatypes.meta.UUIDMeta;
import com.gmail.nossr50.mcMMO;
import org.bukkit.block.Furnace;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
@@ -11,6 +13,7 @@ import org.bukkit.inventory.meta.tags.ItemTagType;
import org.bukkit.metadata.Metadatable;
import org.jetbrains.annotations.NotNull;
import java.util.EnumMap;
import java.util.UUID;
/**
@@ -18,19 +21,94 @@ import java.util.UUID;
*/
public class SpigotPersistentDataLayer_1_13 extends AbstractPersistentDataLayer {
private final String FURNACE_OWNER_METADATA_KEY = "mcMMO_furnace_owner";
private final @NotNull String KEY_FURNACE_OWNER = "mcMMO_furnace_owner";
private final @NotNull EnumMap<MobMetaFlagType, String> mobFlagKeyMap;
public SpigotPersistentDataLayer_1_13() {
mobFlagKeyMap = new EnumMap<>(MobMetaFlagType.class);
initMobFlagKeyMap();
}
@Override
public boolean initializeLayer() {
return true;
}
private void initMobFlagKeyMap() throws IncompleteNamespacedKeyRegister {
for(MobMetaFlagType flagType : MobMetaFlagType.values()) {
switch(flagType) {
case MOB_SPAWNER_MOB:
mobFlagKeyMap.put(flagType, STR_MOB_SPAWNER_MOB);
break;
case EGG_MOB:
mobFlagKeyMap.put(flagType, STR_EGG_MOB);
break;
case NETHER_PORTAL_MOB:
mobFlagKeyMap.put(flagType, STR_NETHER_PORTAL_MOB);
break;
case COTW_SUMMONED_MOB:
mobFlagKeyMap.put(flagType, STR_COTW_SUMMONED_MOB);
break;
case PLAYER_BRED_MOB:
mobFlagKeyMap.put(flagType, STR_PLAYER_BRED_MOB);
break;
case PLAYER_TAMED_MOB:
mobFlagKeyMap.put(flagType, STR_PLAYER_TAMED_MOB);
break;
case EXPLOITED_ENDERMEN:
mobFlagKeyMap.put(flagType, STR_EXPLOITED_ENDERMEN);
break;
default:
throw new IncompleteNamespacedKeyRegister("Missing flag register for: "+flagType.toString());
}
}
}
@Override
public boolean hasMobFlag(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) {
return livingEntity.hasMetadata(mobFlagKeyMap.get(flag));
}
@Override
public boolean hasMobFlags(@NotNull LivingEntity livingEntity) {
for(String currentKey : mobFlagKeyMap.values()) {
if(livingEntity.hasMetadata(currentKey)) {
return true;
}
}
return false;
}
@Override
public void addMobFlags(@NotNull LivingEntity sourceEntity, @NotNull LivingEntity targetEntity) {
for(MobMetaFlagType flag : MobMetaFlagType.values()) {
if(hasMobFlag(flag, sourceEntity)) {
flagMetadata(flag, targetEntity);
}
}
}
@Override
public void flagMetadata(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) {
if(!hasMobFlag(flag, livingEntity)) {
livingEntity.setMetadata(mobFlagKeyMap.get(flag), mcMMO.metadataValue);
}
}
@Override
public void removeMobFlag(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) {
if(hasMobFlag(flag, livingEntity)) {
livingEntity.removeMetadata(mobFlagKeyMap.get(flag), mcMMO.p);
}
}
@Override
public UUID getFurnaceOwner(@NotNull Furnace furnace) {
Metadatable metadatable = (Metadatable) furnace;
if(metadatable.getMetadata(FURNACE_OWNER_METADATA_KEY).size() > 0) {
UUIDMeta uuidMeta = (UUIDMeta) metadatable.getMetadata(FURNACE_OWNER_METADATA_KEY).get(0);
if(metadatable.getMetadata(KEY_FURNACE_OWNER).size() > 0) {
UUIDMeta uuidMeta = (UUIDMeta) metadatable.getMetadata(KEY_FURNACE_OWNER).get(0);
return (UUID) uuidMeta.value();
} else {
return null;
@@ -41,11 +119,11 @@ public class SpigotPersistentDataLayer_1_13 extends AbstractPersistentDataLayer
public void setFurnaceOwner(@NotNull Furnace furnace, @NotNull UUID uuid) {
Metadatable metadatable = (Metadatable) furnace;
if(metadatable.getMetadata(FURNACE_OWNER_METADATA_KEY).size() > 0) {
metadatable.removeMetadata(FURNACE_OWNER_METADATA_KEY, mcMMO.p);
if(metadatable.getMetadata(KEY_FURNACE_OWNER).size() > 0) {
metadatable.removeMetadata(KEY_FURNACE_OWNER, mcMMO.p);
}
metadatable.setMetadata(FURNACE_OWNER_METADATA_KEY, new UUIDMeta(mcMMO.p, uuid));
metadatable.setMetadata(KEY_FURNACE_OWNER, new UUIDMeta(mcMMO.p, uuid));
}
@Override
@@ -57,7 +135,7 @@ public class SpigotPersistentDataLayer_1_13 extends AbstractPersistentDataLayer
return;
}
itemMeta.getCustomTagContainer().setCustomTag(superAbilityBoosted, ItemTagType.INTEGER, originalDigSpeed);
itemMeta.getCustomTagContainer().setCustomTag(NSK_SUPER_ABILITY_BOOSTED_ITEM, ItemTagType.INTEGER, originalDigSpeed);
itemStack.setItemMeta(itemMeta);
}
@@ -69,7 +147,7 @@ public class SpigotPersistentDataLayer_1_13 extends AbstractPersistentDataLayer
return false;
CustomItemTagContainer tagContainer = itemMeta.getCustomTagContainer();
return tagContainer.hasCustomTag(superAbilityBoosted, ItemTagType.INTEGER);
return tagContainer.hasCustomTag(NSK_SUPER_ABILITY_BOOSTED_ITEM, ItemTagType.INTEGER);
}
@Override
@@ -81,8 +159,8 @@ public class SpigotPersistentDataLayer_1_13 extends AbstractPersistentDataLayer
CustomItemTagContainer tagContainer = itemMeta.getCustomTagContainer();
if(tagContainer.hasCustomTag(superAbilityBoosted , ItemTagType.INTEGER)) {
return tagContainer.getCustomTag(superAbilityBoosted, ItemTagType.INTEGER);
if(tagContainer.hasCustomTag(NSK_SUPER_ABILITY_BOOSTED_ITEM, ItemTagType.INTEGER)) {
return tagContainer.getCustomTag(NSK_SUPER_ABILITY_BOOSTED_ITEM, ItemTagType.INTEGER);
} else {
return 0;
}

View File

@@ -1,9 +1,11 @@
package com.gmail.nossr50.util.compat.layers.persistentdata;
import com.gmail.nossr50.api.exceptions.IncompleteNamespacedKeyRegister;
import com.gmail.nossr50.mcMMO;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Furnace;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
@@ -12,28 +14,96 @@ import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumMap;
import java.util.UUID;
public class SpigotPersistentDataLayer_1_14 extends AbstractPersistentDataLayer {
/*
* Don't modify these keys
*/
public static final String FURNACE_UUID_MOST_SIG = "furnace_uuid_most_sig";
public static final String FURNACE_UUID_LEAST_SIG = "furnace_uuid_least_sig";
private final @NotNull EnumMap<MobMetaFlagType, NamespacedKey> mobFlagKeyMap;
private NamespacedKey furnaceOwner_MostSig_Key;
private NamespacedKey furnaceOwner_LeastSig_Key;
public SpigotPersistentDataLayer_1_14() {
mobFlagKeyMap = new EnumMap<>(MobMetaFlagType.class);
initMobFlagKeyMap();
}
@Override
public boolean initializeLayer() {
initNamespacedKeys();
return true;
}
private void initNamespacedKeys() {
furnaceOwner_MostSig_Key = getNamespacedKey(FURNACE_UUID_MOST_SIG);
furnaceOwner_LeastSig_Key = getNamespacedKey(FURNACE_UUID_LEAST_SIG);
/**
* Registers the namespaced keys required by the API (CB/Spigot)
*/
private void initMobFlagKeyMap() throws IncompleteNamespacedKeyRegister {
for(MobMetaFlagType mobMetaFlagType : MobMetaFlagType.values()) {
switch(mobMetaFlagType) {
case MOB_SPAWNER_MOB:
mobFlagKeyMap.put(mobMetaFlagType, NSK_MOB_SPAWNER_MOB);
break;
case EGG_MOB:
mobFlagKeyMap.put(mobMetaFlagType, NSK_EGG_MOB);
break;
case NETHER_PORTAL_MOB:
mobFlagKeyMap.put(mobMetaFlagType, NSK_NETHER_GATE_MOB);
break;
case COTW_SUMMONED_MOB:
mobFlagKeyMap.put(mobMetaFlagType, NSK_COTW_SUMMONED_MOB);
break;
case PLAYER_BRED_MOB:
mobFlagKeyMap.put(mobMetaFlagType, NSK_PLAYER_BRED_MOB);
break;
case EXPLOITED_ENDERMEN:
mobFlagKeyMap.put(mobMetaFlagType, NSK_EXPLOITED_ENDERMEN);
break;
case PLAYER_TAMED_MOB:
mobFlagKeyMap.put(mobMetaFlagType, NSK_PLAYER_TAMED_MOB);
break;
default:
throw new IncompleteNamespacedKeyRegister("missing namespaced key register for type: "+ mobMetaFlagType.toString());
}
}
}
@Override
public boolean hasMobFlag(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) {
return livingEntity.getPersistentDataContainer().has(mobFlagKeyMap.get(flag), PersistentDataType.SHORT);
}
@Override
public boolean hasMobFlags(@NotNull LivingEntity livingEntity) {
for(NamespacedKey currentKey : mobFlagKeyMap.values()) {
if(livingEntity.getPersistentDataContainer().has(currentKey, PersistentDataType.BYTE)) {
return true;
}
}
return false;
}
@Override
public void addMobFlags(@NotNull LivingEntity sourceEntity, @NotNull LivingEntity targetEntity) {
for(MobMetaFlagType flag : MobMetaFlagType.values()) {
if(hasMobFlag(flag, sourceEntity)) {
flagMetadata(flag, targetEntity);
}
}
}
@Override
public void flagMetadata(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) {
if(!hasMobFlag(flag, livingEntity)) {
PersistentDataContainer persistentDataContainer = livingEntity.getPersistentDataContainer();
persistentDataContainer.set(mobFlagKeyMap.get(flag), PersistentDataType.BYTE, SIMPLE_FLAG_VALUE);
}
}
@Override
public void removeMobFlag(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) {
if(hasMobFlag(flag, livingEntity)) {
PersistentDataContainer persistentDataContainer = livingEntity.getPersistentDataContainer();
persistentDataContainer.remove(mobFlagKeyMap.get(flag));
}
}
@Override
@@ -42,8 +112,8 @@ public class SpigotPersistentDataLayer_1_14 extends AbstractPersistentDataLayer
PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer();
//Too lazy to make a custom data type for this stuff
Long mostSigBits = dataContainer.get(furnaceOwner_MostSig_Key, PersistentDataType.LONG);
Long leastSigBits = dataContainer.get(furnaceOwner_LeastSig_Key, PersistentDataType.LONG);
Long mostSigBits = dataContainer.get(NSK_FURNACE_UUID_MOST_SIG, PersistentDataType.LONG);
Long leastSigBits = dataContainer.get(NSK_FURNACE_UUID_LEAST_SIG, PersistentDataType.LONG);
if(mostSigBits != null && leastSigBits != null) {
return new UUID(mostSigBits, leastSigBits);
@@ -56,8 +126,8 @@ public class SpigotPersistentDataLayer_1_14 extends AbstractPersistentDataLayer
public void setFurnaceOwner(@NotNull Furnace furnace, @NotNull UUID uuid) {
PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer();
dataContainer.set(furnaceOwner_MostSig_Key, PersistentDataType.LONG, uuid.getMostSignificantBits());
dataContainer.set(furnaceOwner_LeastSig_Key, PersistentDataType.LONG, uuid.getLeastSignificantBits());
dataContainer.set(NSK_FURNACE_UUID_MOST_SIG, PersistentDataType.LONG, uuid.getMostSignificantBits());
dataContainer.set(NSK_FURNACE_UUID_LEAST_SIG, PersistentDataType.LONG, uuid.getLeastSignificantBits());
furnace.update();
}
@@ -72,7 +142,7 @@ public class SpigotPersistentDataLayer_1_14 extends AbstractPersistentDataLayer
ItemMeta itemMeta = itemStack.getItemMeta();
PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer();
dataContainer.set(superAbilityBoosted, PersistentDataType.INTEGER, originalDigSpeed);
dataContainer.set(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER, originalDigSpeed);
itemStack.setItemMeta(itemMeta);
}
@@ -87,7 +157,7 @@ public class SpigotPersistentDataLayer_1_14 extends AbstractPersistentDataLayer
PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer();
//If this value isn't null, then the tool can be considered dig speed boosted
Integer boostValue = dataContainer.get(superAbilityBoosted, PersistentDataType.INTEGER);
Integer boostValue = dataContainer.get(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER);
return boostValue != null;
}
@@ -102,12 +172,12 @@ public class SpigotPersistentDataLayer_1_14 extends AbstractPersistentDataLayer
PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer();
if(dataContainer.get(superAbilityBoosted, PersistentDataType.INTEGER) == null) {
if(dataContainer.get(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER) == null) {
mcMMO.p.getLogger().severe("Value should never be null for a boosted item");
return 0;
} else {
//Too lazy to make a custom data type for this stuff
Integer boostValue = dataContainer.get(superAbilityBoosted, PersistentDataType.INTEGER);
Integer boostValue = dataContainer.get(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER);
return Math.max(boostValue, 0);
}
}
@@ -127,7 +197,7 @@ public class SpigotPersistentDataLayer_1_14 extends AbstractPersistentDataLayer
}
PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer();
dataContainer.remove(superAbilityBoosted); //Remove persistent data
dataContainer.remove(NSK_SUPER_ABILITY_BOOSTED_ITEM); //Remove persistent data
//TODO: needed?
itemStack.setItemMeta(itemMeta);