From 3be15d3f65fa1054bf827e78e702a0cf352b5f72 Mon Sep 17 00:00:00 2001 From: nossr50 Date: Mon, 17 Jan 2022 15:32:02 -0800 Subject: [PATCH] Rewrite how mob/item/block metadata is tracked/retrieved Fixes #4720 --- Changelog.txt | 5 + .../nossr50/config/PersistentDataConfig.java | 2 +- .../nossr50/listeners/EntityListener.java | 28 +-- src/main/java/com/gmail/nossr50/mcMMO.java | 11 +- .../metadata/BlockMetadataService.java | 49 ++++ .../nossr50/metadata/ItemMetadataService.java | 110 +++++++++ .../nossr50/metadata/MetadataService.java | 71 ++++++ .../MobMetaFlagType.java | 2 +- .../nossr50/metadata/MobMetadataService.java | 187 +++++++++++++++ .../nossr50/skills/taming/TamingManager.java | 4 +- .../nossr50/util/TransientEntityTracker.java | 2 +- .../nossr50/util/TransientMetadataTools.java | 7 +- .../util/compat/CompatibilityManager.java | 23 +- .../AbstractPersistentDataLayer.java | 137 ----------- .../SpigotPersistentDataLayer_1_13.java | 172 -------------- .../SpigotPersistentDataLayer_1_14.java | 220 ------------------ .../nossr50/util/skills/CombatUtils.java | 20 +- .../gmail/nossr50/util/skills/SkillUtils.java | 23 +- .../nossr50/util/skills/SmeltingTracker.java | 4 +- 19 files changed, 477 insertions(+), 600 deletions(-) create mode 100644 src/main/java/com/gmail/nossr50/metadata/BlockMetadataService.java create mode 100644 src/main/java/com/gmail/nossr50/metadata/ItemMetadataService.java create mode 100644 src/main/java/com/gmail/nossr50/metadata/MetadataService.java rename src/main/java/com/gmail/nossr50/{util/compat/layers/persistentdata => metadata}/MobMetaFlagType.java (74%) create mode 100644 src/main/java/com/gmail/nossr50/metadata/MobMetadataService.java delete mode 100644 src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/AbstractPersistentDataLayer.java delete mode 100644 src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer_1_13.java delete mode 100644 src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer_1_14.java diff --git a/Changelog.txt b/Changelog.txt index ee1f53163..9a33c8ee2 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,4 +1,9 @@ Version 2.1.210 + Fixed a memory leak involving mob metadata + + NOTES: + There was a big rewrite in this update relating to how various types of metadata were being tracked/stored/retrieved + If you run into issues with this version of mcMMO, please post about it on GitHub Version 2.1.209 Fixed a bug where some config files did not get trimmed completely diff --git a/src/main/java/com/gmail/nossr50/config/PersistentDataConfig.java b/src/main/java/com/gmail/nossr50/config/PersistentDataConfig.java index 11b605eaa..089db89b8 100644 --- a/src/main/java/com/gmail/nossr50/config/PersistentDataConfig.java +++ b/src/main/java/com/gmail/nossr50/config/PersistentDataConfig.java @@ -1,6 +1,6 @@ package com.gmail.nossr50.config; -import com.gmail.nossr50.util.compat.layers.persistentdata.MobMetaFlagType; +import com.gmail.nossr50.metadata.MobMetaFlagType; public class PersistentDataConfig extends BukkitConfig { private static PersistentDataConfig instance; diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java index 6690efab3..14a940763 100644 --- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java @@ -10,6 +10,8 @@ import com.gmail.nossr50.events.fake.FakeEntityDamageEvent; import com.gmail.nossr50.events.fake.FakeEntityTameEvent; import com.gmail.nossr50.events.skills.rupture.McMMOEntityDamageByRuptureEvent; import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.metadata.MobMetaFlagType; +import com.gmail.nossr50.metadata.MobMetadataService; import com.gmail.nossr50.party.PartyManager; import com.gmail.nossr50.runnables.TravelingBlockMetaCleanup; import com.gmail.nossr50.skills.archery.Archery; @@ -19,8 +21,6 @@ import com.gmail.nossr50.skills.taming.Taming; import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.skills.unarmed.UnarmedManager; import com.gmail.nossr50.util.*; -import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDataLayer; -import com.gmail.nossr50.util.compat.layers.persistentdata.MobMetaFlagType; import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.random.RandomChanceUtil; @@ -51,7 +51,7 @@ import org.jetbrains.annotations.NotNull; public class EntityListener implements Listener { private final mcMMO pluginRef; - private final @NotNull AbstractPersistentDataLayer persistentDataLayer; + private final @NotNull MobMetadataService mobMetadataService; /** * We can use this {@link NamespacedKey} for {@link Enchantment} comparisons to @@ -61,7 +61,7 @@ public class EntityListener implements Listener { public EntityListener(final mcMMO pluginRef) { this.pluginRef = pluginRef; - persistentDataLayer = mcMMO.getCompatibilityManager().getPersistentDataLayer(); + mobMetadataService = mcMMO.getMetadataService().getMobMetadataService(); } // @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @@ -94,11 +94,11 @@ public class EntityListener implements Listener { LivingEntity livingEntity = (LivingEntity) event.getEntity(); //Transfer metadata keys from mob-spawned mobs to new mobs - if(persistentDataLayer.hasMobFlags(livingEntity)) { + if(mobMetadataService.hasMobFlags(livingEntity)) { for(Entity entity : event.getTransformedEntities()) { if(entity instanceof LivingEntity) { LivingEntity transformedEntity = (LivingEntity) entity; - persistentDataLayer.addMobFlags(livingEntity, transformedEntity); + mobMetadataService.addMobFlags(livingEntity, transformedEntity); } } } @@ -122,8 +122,8 @@ public class EntityListener implements Listener { if(event.getEntity() instanceof Enderman) { Enderman enderman = (Enderman) event.getEntity(); - if(!persistentDataLayer.hasMobFlag(MobMetaFlagType.EXPLOITED_ENDERMEN, enderman)) { - persistentDataLayer.flagMetadata(MobMetaFlagType.EXPLOITED_ENDERMEN, enderman); + if(!mobMetadataService.hasMobFlag(MobMetaFlagType.EXPLOITED_ENDERMEN, enderman)) { + mobMetadataService.flagMetadata(MobMetaFlagType.EXPLOITED_ENDERMEN, enderman); } } } @@ -729,11 +729,11 @@ public class EntityListener implements Listener { } private void trackSpawnedAndPassengers(LivingEntity livingEntity, MobMetaFlagType mobMetaFlagType) { - persistentDataLayer.flagMetadata(mobMetaFlagType, livingEntity); + mobMetadataService.flagMetadata(mobMetaFlagType, livingEntity); for(Entity passenger : livingEntity.getPassengers()) { if(passenger != null) { - persistentDataLayer.flagMetadata(mobMetaFlagType, livingEntity); + mobMetadataService.flagMetadata(mobMetaFlagType, livingEntity); } } } @@ -741,7 +741,7 @@ public class EntityListener implements Listener { @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) public void onEntityBreed(EntityBreedEvent event) { if(ExperienceConfig.getInstance().isCOTWBreedingPrevented()) { - if(persistentDataLayer.hasMobFlag(MobMetaFlagType.COTW_SUMMONED_MOB, event.getFather()) || persistentDataLayer.hasMobFlag(MobMetaFlagType.COTW_SUMMONED_MOB, event.getMother())) { + if(mobMetadataService.hasMobFlag(MobMetaFlagType.COTW_SUMMONED_MOB, event.getFather()) || mobMetadataService.hasMobFlag(MobMetaFlagType.COTW_SUMMONED_MOB, event.getMother())) { event.setCancelled(true); Animals mom = (Animals) event.getMother(); Animals father = (Animals) event.getFather(); @@ -1007,12 +1007,12 @@ public class EntityListener implements Listener { if (!UserManager.hasPlayerDataKey(player) || (ExperienceConfig.getInstance().isNPCInteractionPrevented() && Misc.isNPCEntityExcludingVillagers(livingEntity)) - || persistentDataLayer.hasMobFlag(MobMetaFlagType.EGG_MOB, livingEntity) - || persistentDataLayer.hasMobFlag(MobMetaFlagType.MOB_SPAWNER_MOB, livingEntity)) { + || mobMetadataService.hasMobFlag(MobMetaFlagType.EGG_MOB, livingEntity) + || mobMetadataService.hasMobFlag(MobMetaFlagType.MOB_SPAWNER_MOB, livingEntity)) { return; } - persistentDataLayer.flagMetadata(MobMetaFlagType.PLAYER_TAMED_MOB, livingEntity); + mobMetadataService.flagMetadata(MobMetaFlagType.PLAYER_TAMED_MOB, livingEntity); //Profile not loaded if(UserManager.getPlayer(player) == null) diff --git a/src/main/java/com/gmail/nossr50/mcMMO.java b/src/main/java/com/gmail/nossr50/mcMMO.java index 28e78225c..8a8d3192b 100644 --- a/src/main/java/com/gmail/nossr50/mcMMO.java +++ b/src/main/java/com/gmail/nossr50/mcMMO.java @@ -18,6 +18,7 @@ import com.gmail.nossr50.database.DatabaseManagerFactory; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.subskills.acrobatics.Roll; import com.gmail.nossr50.listeners.*; +import com.gmail.nossr50.metadata.MetadataService; import com.gmail.nossr50.party.PartyManager; import com.gmail.nossr50.runnables.SaveTimerTask; import com.gmail.nossr50.runnables.backups.CleanBackupsTask; @@ -77,8 +78,9 @@ import java.util.List; public class mcMMO extends JavaPlugin { - /* Managers */ + /* Managers & Services */ private static PlatformManager platformManager; + private static MetadataService metadataService; private static ChunkManager placeStore; private static RepairableManager repairableManager; private static SalvageableManager salvageableManager; @@ -175,6 +177,9 @@ public class mcMMO extends JavaPlugin { //Platform Manager platformManager = new PlatformManager(); + //metadata service + metadataService = new MetadataService(this); + //Filter out any debug messages (if debug/verbose logging is not enabled) getLogger().setFilter(new LogFilter(this)); @@ -466,6 +471,10 @@ public class mcMMO extends JavaPlugin { return platformManager.getCompatibilityManager(); } + public static MetadataService getMetadataService() { + return metadataService; + } + @Deprecated public static void setDatabaseManager(DatabaseManager databaseManager) { mcMMO.databaseManager = databaseManager; diff --git a/src/main/java/com/gmail/nossr50/metadata/BlockMetadataService.java b/src/main/java/com/gmail/nossr50/metadata/BlockMetadataService.java new file mode 100644 index 000000000..1545cd608 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/metadata/BlockMetadataService.java @@ -0,0 +1,49 @@ +package com.gmail.nossr50.metadata; + +import com.gmail.nossr50.mcMMO; +import org.bukkit.block.Furnace; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataHolder; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +import static com.gmail.nossr50.metadata.MetadataService.NSK_FURNACE_UUID_LEAST_SIG; +import static com.gmail.nossr50.metadata.MetadataService.NSK_FURNACE_UUID_MOST_SIG; + +public class BlockMetadataService { + + private final @NotNull mcMMO pluginRef; + + public BlockMetadataService(@NotNull mcMMO pluginRef) { + this.pluginRef = pluginRef; + } + + public @Nullable UUID getFurnaceOwner(@NotNull Furnace furnace) { + //Get container from entity + PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer(); + + //Too lazy to make a custom data type for this stuff + 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); + } else { + return null; + } + } + + public void setFurnaceOwner(@NotNull Furnace furnace, @NotNull UUID uuid) { + PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer(); + + dataContainer.set(NSK_FURNACE_UUID_MOST_SIG, PersistentDataType.LONG, uuid.getMostSignificantBits()); + dataContainer.set(NSK_FURNACE_UUID_LEAST_SIG, PersistentDataType.LONG, uuid.getLeastSignificantBits()); + + furnace.update(); + } + + +} diff --git a/src/main/java/com/gmail/nossr50/metadata/ItemMetadataService.java b/src/main/java/com/gmail/nossr50/metadata/ItemMetadataService.java new file mode 100644 index 000000000..f1d1e9471 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/metadata/ItemMetadataService.java @@ -0,0 +1,110 @@ +package com.gmail.nossr50.metadata; + +import com.gmail.nossr50.mcMMO; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +import static com.gmail.nossr50.metadata.MetadataService.NSK_SUPER_ABILITY_BOOSTED_ITEM; + +public class ItemMetadataService { + + public final @NotNull String LEGACY_ABILITY_TOOL_LORE = "mcMMO Ability Tool"; + public final @NotNull mcMMO pluginRef; + + public ItemMetadataService(@NotNull mcMMO pluginRef) { + this.pluginRef = pluginRef; + } + + public void setSuperAbilityBoostedItem(@NotNull ItemStack itemStack, int originalDigSpeed) { + if (itemStack.getItemMeta() == null) { + mcMMO.p.getLogger().severe("Can not assign persistent data to an item with null item metadata"); + return; + } + + ItemMeta itemMeta = itemStack.getItemMeta(); + PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer(); + + dataContainer.set(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER, originalDigSpeed); + + itemStack.setItemMeta(itemMeta); + } + + public boolean isSuperAbilityBoosted(@NotNull ItemStack itemStack) { + if (itemStack.getItemMeta() == null) + return false; + + ItemMeta itemMeta = itemStack.getItemMeta(); + //Get container from entity + PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer(); + + //If this value isn't null, then the tool can be considered dig speed boosted + Integer boostValue = dataContainer.get(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER); + + return boostValue != null; + } + + public int getSuperAbilityToolOriginalDigSpeed(@NotNull ItemStack itemStack) { + //Get container from entity + ItemMeta itemMeta = itemStack.getItemMeta(); + + if (itemMeta == null) + return 0; + + PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer(); + + 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(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER); + return Math.max(boostValue, 0); + } + } + + public void removeBonusDigSpeedOnSuperAbilityTool(@NotNull ItemStack itemStack) { + int originalSpeed = getSuperAbilityToolOriginalDigSpeed(itemStack); + ItemMeta itemMeta = itemStack.getItemMeta(); + + if(itemMeta != null) { + //TODO: can be optimized + if (itemMeta.hasEnchant(Enchantment.DIG_SPEED)) { + itemMeta.removeEnchant(Enchantment.DIG_SPEED); + } + + if (originalSpeed > 0) { + itemMeta.addEnchant(Enchantment.DIG_SPEED, originalSpeed, true); + } + + PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer(); + dataContainer.remove(NSK_SUPER_ABILITY_BOOSTED_ITEM); //Remove persistent data + + //TODO: needed? + itemStack.setItemMeta(itemMeta); + } + } + + public boolean isLegacyAbilityTool(@NotNull ItemStack itemStack) { + ItemMeta itemMeta = itemStack.getItemMeta(); + + if (itemMeta == null) + return false; + + List lore = itemMeta.getLore(); + + if (lore == null || lore.isEmpty()) + return false; + + return lore.contains(LEGACY_ABILITY_TOOL_LORE); + } + + public @NotNull String getLegacyAbilityToolLore() { + return LEGACY_ABILITY_TOOL_LORE; + } +} diff --git a/src/main/java/com/gmail/nossr50/metadata/MetadataService.java b/src/main/java/com/gmail/nossr50/metadata/MetadataService.java new file mode 100644 index 000000000..d38726737 --- /dev/null +++ b/src/main/java/com/gmail/nossr50/metadata/MetadataService.java @@ -0,0 +1,71 @@ +package com.gmail.nossr50.metadata; + +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.util.MetadataConstants; +import org.bukkit.NamespacedKey; +import org.jetbrains.annotations.NotNull; + +public class MetadataService { + private final @NotNull mcMMO pluginRef; + + protected static final @NotNull NamespacedKey NSK_SUPER_ABILITY_BOOSTED_ITEM; + protected static final @NotNull NamespacedKey NSK_MOB_SPAWNER_MOB; + protected static final @NotNull NamespacedKey NSK_EGG_MOB; + protected static final @NotNull NamespacedKey NSK_NETHER_GATE_MOB; + protected static final @NotNull NamespacedKey NSK_COTW_SUMMONED_MOB; + protected static final @NotNull NamespacedKey NSK_PLAYER_BRED_MOB; + protected static final @NotNull NamespacedKey NSK_PLAYER_TAMED_MOB; + protected static final @NotNull NamespacedKey NSK_VILLAGER_TRADE_ORIGIN_ITEM; + protected static final @NotNull NamespacedKey NSK_EXPLOITED_ENDERMEN; + protected static final @NotNull NamespacedKey NSK_FURNACE_UUID_MOST_SIG; + protected static final @NotNull NamespacedKey NSK_FURNACE_UUID_LEAST_SIG; + + static { + NSK_SUPER_ABILITY_BOOSTED_ITEM = getNamespacedKey(MetadataConstants.METADATA_KEY_SUPER_ABILITY_BOOSTED_ITEM); + NSK_MOB_SPAWNER_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_MOB_SPAWNER_MOB); + NSK_EGG_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_EGG_MOB); + NSK_NETHER_GATE_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_NETHER_PORTAL_MOB); + NSK_COTW_SUMMONED_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_COTW_SUMMONED_MOB); + NSK_PLAYER_BRED_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_PLAYER_BRED_MOB); + NSK_PLAYER_TAMED_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_PLAYER_TAMED_MOB); + NSK_VILLAGER_TRADE_ORIGIN_ITEM = getNamespacedKey(MetadataConstants.METADATA_KEY_VILLAGER_TRADE_ORIGIN_ITEM); + NSK_EXPLOITED_ENDERMEN = getNamespacedKey(MetadataConstants.METADATA_KEY_EXPLOITED_ENDERMEN); + NSK_FURNACE_UUID_MOST_SIG = getNamespacedKey(MetadataConstants.METADATA_KEY_FURNACE_UUID_MOST_SIG); + NSK_FURNACE_UUID_LEAST_SIG = getNamespacedKey(MetadataConstants.METADATA_KEY_FURNACE_UUID_LEAST_SIG); + } + + private final @NotNull ItemMetadataService itemMetadataService; + private final @NotNull MobMetadataService mobMetadataService; + private final @NotNull BlockMetadataService blockMetadataService; + + public MetadataService(@NotNull mcMMO pluginRef) { + this.pluginRef = pluginRef; + + blockMetadataService = new BlockMetadataService(pluginRef); + mobMetadataService = new MobMetadataService(pluginRef); + itemMetadataService = new ItemMetadataService(pluginRef); + } + + /** + * Helper method to simplify generating namespaced keys + * + * @param key the {@link String} value of the key + * + * @return the generated {@link NamespacedKey} + */ + public static @NotNull NamespacedKey getNamespacedKey(@NotNull String key) { + return new NamespacedKey(mcMMO.p, key); + } + + public @NotNull ItemMetadataService getItemMetadataService() { + return itemMetadataService; + } + + public @NotNull MobMetadataService getMobMetadataService() { + return mobMetadataService; + } + + public @NotNull BlockMetadataService getBlockMetadataService() { + return blockMetadataService; + } +} diff --git a/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/MobMetaFlagType.java b/src/main/java/com/gmail/nossr50/metadata/MobMetaFlagType.java similarity index 74% rename from src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/MobMetaFlagType.java rename to src/main/java/com/gmail/nossr50/metadata/MobMetaFlagType.java index 1bf5eb2df..618bcd3a3 100644 --- a/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/MobMetaFlagType.java +++ b/src/main/java/com/gmail/nossr50/metadata/MobMetaFlagType.java @@ -1,4 +1,4 @@ -package com.gmail.nossr50.util.compat.layers.persistentdata; +package com.gmail.nossr50.metadata; public enum MobMetaFlagType { MOB_SPAWNER_MOB, diff --git a/src/main/java/com/gmail/nossr50/metadata/MobMetadataService.java b/src/main/java/com/gmail/nossr50/metadata/MobMetadataService.java new file mode 100644 index 000000000..87af92f4e --- /dev/null +++ b/src/main/java/com/gmail/nossr50/metadata/MobMetadataService.java @@ -0,0 +1,187 @@ +package com.gmail.nossr50.metadata; + +import com.gmail.nossr50.api.exceptions.IncompleteNamespacedKeyRegister; +import com.gmail.nossr50.config.PersistentDataConfig; +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.util.MetadataConstants; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; +import java.util.HashSet; +import java.util.WeakHashMap; + +import static com.gmail.nossr50.metadata.MetadataService.*; + +public class MobMetadataService { + private final @NotNull WeakHashMap> mobRegistry; //transient data + private final @NotNull EnumMap mobFlagKeyMap; //used for persistent data + private final @NotNull mcMMO pluginRef; + private boolean isUsingPersistentData = false; + + public MobMetadataService(@NotNull mcMMO pluginRef) { + this.pluginRef = pluginRef; + mobFlagKeyMap = new EnumMap<>(MobMetaFlagType.class); + mobRegistry = new WeakHashMap<>(); + initMobFlagKeyMap(); + + for (MobMetaFlagType metaFlagType : MobMetaFlagType.values()) { + if (PersistentDataConfig.getInstance().isMobPersistent(metaFlagType)) + isUsingPersistentData = true; + } + } + + /** + * Registers the namespaced keys required by the API (CB/Spigot) + * Used primarily for persistent data + */ + private void initMobFlagKeyMap() throws IncompleteNamespacedKeyRegister { + for (MobMetaFlagType mobMetaFlagType : MobMetaFlagType.values()) { + switch (mobMetaFlagType) { + case MOB_SPAWNER_MOB -> mobFlagKeyMap.put(mobMetaFlagType, NSK_MOB_SPAWNER_MOB); + case EGG_MOB -> mobFlagKeyMap.put(mobMetaFlagType, NSK_EGG_MOB); + case NETHER_PORTAL_MOB -> mobFlagKeyMap.put(mobMetaFlagType, NSK_NETHER_GATE_MOB); + case COTW_SUMMONED_MOB -> mobFlagKeyMap.put(mobMetaFlagType, NSK_COTW_SUMMONED_MOB); + case PLAYER_BRED_MOB -> mobFlagKeyMap.put(mobMetaFlagType, NSK_PLAYER_BRED_MOB); + case EXPLOITED_ENDERMEN -> mobFlagKeyMap.put(mobMetaFlagType, NSK_EXPLOITED_ENDERMEN); + case PLAYER_TAMED_MOB -> mobFlagKeyMap.put(mobMetaFlagType, NSK_PLAYER_TAMED_MOB); + default -> throw new IncompleteNamespacedKeyRegister("missing namespaced key register for type: " + mobMetaFlagType); + } + } + } + + /** + * 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 boolean hasMobFlag(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) { + if (PersistentDataConfig.getInstance().isMobPersistent(flag)) { + return livingEntity.getPersistentDataContainer().has(mobFlagKeyMap.get(flag), PersistentDataType.BYTE); + } else { + if (mobRegistry.containsKey(livingEntity)) { + return mobRegistry.get(livingEntity).contains(flag); + } + + return false; + } + } + + /** + * 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 boolean hasMobFlags(@NotNull LivingEntity livingEntity) { + if (isUsingPersistentData) { + for (MobMetaFlagType metaFlagType : MobMetaFlagType.values()) { + if (hasMobFlag(metaFlagType, livingEntity)) + return true; + } + + return false; + } else { + return mobRegistry.containsKey(livingEntity) && mobRegistry.get(livingEntity).size() > 0; + } + } + + /** + * 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 void addMobFlags(@NotNull LivingEntity sourceEntity, @NotNull LivingEntity targetEntity) { + if (!hasMobFlags(sourceEntity)) + return; + + if (isUsingPersistentData) { + for (MobMetaFlagType flag : MobMetaFlagType.values()) { + if (hasMobFlag(flag, sourceEntity)) { + flagMetadata(flag, targetEntity); + } + } + } else { + HashSet flags = new HashSet<>(mobRegistry.get(sourceEntity)); + mobRegistry.put(targetEntity, flags); + } + } + + /** + * 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 void flagMetadata(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) { + if (PersistentDataConfig.getInstance().isMobPersistent(flag)) { + if (!hasMobFlag(flag, livingEntity)) { + PersistentDataContainer persistentDataContainer = livingEntity.getPersistentDataContainer(); + persistentDataContainer.set(mobFlagKeyMap.get(flag), PersistentDataType.BYTE, MetadataConstants.SIMPLE_FLAG_VALUE); + } + } else { + HashSet flags = mobRegistry.getOrDefault(livingEntity, new HashSet<>()); + flags.add(flag); // add the new flag + mobRegistry.put(livingEntity, flags); //update registry + } + } + + /** + * Removes a specific mob flag from target {@link LivingEntity} + * + * @param flag desired flag to remove + * @param livingEntity the target living entity + */ + public void removeMobFlag(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) { + if (PersistentDataConfig.getInstance().isMobPersistent(flag)) { + if (hasMobFlag(flag, livingEntity)) { + PersistentDataContainer persistentDataContainer = livingEntity.getPersistentDataContainer(); + persistentDataContainer.remove(mobFlagKeyMap.get(flag)); + } + } else { + if (mobRegistry.containsKey(livingEntity)) { + mobRegistry.get(livingEntity).remove(flag); + + if (mobRegistry.get(livingEntity).size() == 0) + mobRegistry.remove(livingEntity); + } + } + } + + /** + * Remove all mcMMO related mob flags from the target {@link LivingEntity} + * + * @param livingEntity target entity + */ + public void removeMobFlags(@NotNull LivingEntity livingEntity) { + if (isUsingPersistentData) { + for (MobMetaFlagType flag : MobMetaFlagType.values()) { + removeMobFlag(flag, livingEntity); + } + } else { + mobRegistry.remove(livingEntity); + } + } +} diff --git a/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java b/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java index cd5f14545..d51b50291 100644 --- a/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java +++ b/src/main/java/com/gmail/nossr50/skills/taming/TamingManager.java @@ -10,10 +10,10 @@ import com.gmail.nossr50.datatypes.skills.subskills.taming.CallOfTheWildType; import com.gmail.nossr50.datatypes.skills.subskills.taming.TamingSummon; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.metadata.MobMetaFlagType; import com.gmail.nossr50.skills.SkillManager; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Permissions; -import com.gmail.nossr50.util.compat.layers.persistentdata.MobMetaFlagType; import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.random.RandomChanceSkillStatic; import com.gmail.nossr50.util.random.RandomChanceUtil; @@ -475,7 +475,7 @@ public class TamingManager extends SkillManager { private void applyMetaDataToCOTWEntity(LivingEntity summonedEntity) { //This helps identify the entity as being summoned by COTW - mcMMO.getCompatibilityManager().getPersistentDataLayer().flagMetadata(MobMetaFlagType.COTW_SUMMONED_MOB, summonedEntity); + mcMMO.getMetadataService().getMobMetadataService().flagMetadata(MobMetaFlagType.COTW_SUMMONED_MOB, summonedEntity); } /** diff --git a/src/main/java/com/gmail/nossr50/util/TransientEntityTracker.java b/src/main/java/com/gmail/nossr50/util/TransientEntityTracker.java index 6e1b44938..e9d2fca83 100644 --- a/src/main/java/com/gmail/nossr50/util/TransientEntityTracker.java +++ b/src/main/java/com/gmail/nossr50/util/TransientEntityTracker.java @@ -273,7 +273,7 @@ public class TransientEntityTracker { } //Remove our metadata - mcMMO.getCompatibilityManager().getPersistentDataLayer().removeMobFlags(livingEntity); + mcMMO.getMetadataService().getMobMetadataService().removeMobFlags(livingEntity); //Clean from trackers unregisterEntity(livingEntity); diff --git a/src/main/java/com/gmail/nossr50/util/TransientMetadataTools.java b/src/main/java/com/gmail/nossr50/util/TransientMetadataTools.java index 15f14c03e..8b21e9d1a 100644 --- a/src/main/java/com/gmail/nossr50/util/TransientMetadataTools.java +++ b/src/main/java/com/gmail/nossr50/util/TransientMetadataTools.java @@ -18,11 +18,6 @@ public class TransientMetadataTools { entity.removeMetadata(MetadataConstants.METADATA_KEY_CUSTOM_NAME, pluginRef); } -// if(entity.hasMetadata(MetadataConstants.METADATA_KEY_OLD_NAME_KEY)) { -// CombatUtils.fixNames(entity); -// entity.removeMetadata(MetadataConstants.METADATA_KEY_OLD_NAME_KEY, pluginRef); -// } - //Involved in changing mob names to hearts if (entity.hasMetadata(MetadataConstants.METADATA_KEY_NAME_VISIBILITY)) { entity.setCustomNameVisible(entity.getMetadata(MetadataConstants.METADATA_KEY_NAME_VISIBILITY).get(0).asBoolean()); @@ -35,7 +30,7 @@ public class TransientMetadataTools { } //Cleanup mob metadata - mcMMO.getCompatibilityManager().getPersistentDataLayer().removeMobFlags(entity); + mcMMO.getMetadataService().getMobMetadataService().removeMobFlags(entity); //TODO: This loop has some redundancy, this whole method needs to be rewritten for(String key : MetadataConstants.MOB_METADATA_KEYS) { diff --git a/src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java b/src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java index f1f0b185b..063c858c5 100644 --- a/src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java +++ b/src/main/java/com/gmail/nossr50/util/compat/CompatibilityManager.java @@ -5,9 +5,6 @@ import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.util.compat.layers.bungee.AbstractBungeeSerializerCompatibilityLayer; import com.gmail.nossr50.util.compat.layers.bungee.BungeeLegacySerializerCompatibilityLayer; import com.gmail.nossr50.util.compat.layers.bungee.BungeeModernSerializerCompatibilityLayer; -import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDataLayer; -import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotPersistentDataLayer_1_13; -import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotPersistentDataLayer_1_14; import com.gmail.nossr50.util.compat.layers.skills.AbstractMasterAnglerCompatibility; import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer; import com.gmail.nossr50.util.nms.NMSVersion; @@ -25,7 +22,7 @@ import java.util.HashMap; * In 2.2 we are switching to modules and that will clean things up significantly * */ -//TODO: I need to rewrite this crap +//TODO: I need to delete this crap public class CompatibilityManager { private @NotNull HashMap supportedLayers; private boolean isFullyCompatibleServerSoftware = true; //true if all compatibility layers load successfully @@ -33,8 +30,6 @@ public class CompatibilityManager { private final @NotNull NMSVersion nmsVersion; /* Compatibility Layers */ -// private PlayerAttackCooldownExploitPreventionLayer playerAttackCooldownExploitPreventionLayer; - private AbstractPersistentDataLayer persistentDataLayer; private AbstractBungeeSerializerCompatibilityLayer bungeeSerializerCompatibilityLayer; private AbstractMasterAnglerCompatibility masterAnglerCompatibility; @@ -64,7 +59,6 @@ public class CompatibilityManager { * For any unsupported layers, load a dummy layer */ private void initCompatibilityLayers() { - initPersistentDataLayer(); initBungeeSerializerLayer(); initMasterAnglerLayer(); @@ -89,17 +83,6 @@ public class CompatibilityManager { supportedLayers.put(CompatibilityType.BUNGEE_SERIALIZER, true); } - private void initPersistentDataLayer() { - if(minecraftGameVersion.isAtLeast(1, 14, 2)) { - persistentDataLayer = new SpigotPersistentDataLayer_1_14(); - } else { - - persistentDataLayer = new SpigotPersistentDataLayer_1_13(); - } - - supportedLayers.put(CompatibilityType.PERSISTENT_DATA, true); - } - //TODO: move to text manager public void reportCompatibilityStatus(@NotNull CommandSender commandSender) { if(isFullyCompatibleServerSoftware) { @@ -171,10 +154,6 @@ public class CompatibilityManager { return bungeeSerializerCompatibilityLayer; } - public AbstractPersistentDataLayer getPersistentDataLayer() { - return persistentDataLayer; - } - public @Nullable AbstractMasterAnglerCompatibility getMasterAnglerCompatibilityLayer() { return masterAnglerCompatibility; } diff --git a/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/AbstractPersistentDataLayer.java b/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/AbstractPersistentDataLayer.java deleted file mode 100644 index 7ecf6dfb3..000000000 --- a/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/AbstractPersistentDataLayer.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.gmail.nossr50.util.compat.layers.persistentdata; - -import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.util.MetadataConstants; -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; - -public abstract class AbstractPersistentDataLayer extends AbstractCompatibilityLayer { - - 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; - - 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"; - - public AbstractPersistentDataLayer() { - NSK_SUPER_ABILITY_BOOSTED_ITEM = getNamespacedKey(MetadataConstants.METADATA_KEY_SUPER_ABILITY_BOOSTED_ITEM); - NSK_MOB_SPAWNER_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_MOB_SPAWNER_MOB); - NSK_EGG_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_EGG_MOB); - NSK_NETHER_GATE_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_NETHER_PORTAL_MOB); - NSK_COTW_SUMMONED_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_COTW_SUMMONED_MOB); - NSK_PLAYER_BRED_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_PLAYER_BRED_MOB); - NSK_PLAYER_TAMED_MOB = getNamespacedKey(MetadataConstants.METADATA_KEY_PLAYER_TAMED_MOB); - NSK_VILLAGER_TRADE_ORIGIN_ITEM = getNamespacedKey(MetadataConstants.METADATA_KEY_VILLAGER_TRADE_ORIGIN_ITEM); - NSK_EXPLOITED_ENDERMEN = getNamespacedKey(MetadataConstants.METADATA_KEY_EXPLOITED_ENDERMEN); - NSK_FURNACE_UUID_MOST_SIG = getNamespacedKey(MetadataConstants.METADATA_KEY_FURNACE_UUID_MOST_SIG); - NSK_FURNACE_UUID_LEAST_SIG = getNamespacedKey(MetadataConstants.METADATA_KEY_FURNACE_UUID_LEAST_SIG); - - initializeLayer(); - } - - - /** - * 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); - - public abstract void setSuperAbilityBoostedItem(@NotNull ItemStack itemStack, int originalDigSpeed); - - public abstract boolean isSuperAbilityBoosted(@NotNull ItemStack itemStack); - - public abstract int getSuperAbilityToolOriginalDigSpeed(@NotNull ItemStack itemStack); - - public abstract void removeBonusDigSpeedOnSuperAbilityTool(@NotNull ItemStack itemStack); - - public boolean isLegacyAbilityTool(@NotNull ItemStack itemStack) { - ItemMeta itemMeta = itemStack.getItemMeta(); - - if(itemMeta == null) - return false; - - List lore = itemMeta.getLore(); - - if(lore == null || lore.isEmpty()) - return false; - - return lore.contains(LEGACY_ABILITY_TOOL_LORE); - } - - public @NotNull String getLegacyAbilityToolLore() { - return LEGACY_ABILITY_TOOL_LORE; - } -} diff --git a/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer_1_13.java b/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer_1_13.java deleted file mode 100644 index 8f7877a1e..000000000 --- a/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer_1_13.java +++ /dev/null @@ -1,172 +0,0 @@ -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 com.gmail.nossr50.util.MetadataConstants; -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; -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; - -/** - * Persistent Data API is unavailable - */ -public class SpigotPersistentDataLayer_1_13 extends AbstractPersistentDataLayer { - - private final @NotNull String KEY_FURNACE_OWNER = "mcMMO_furnace_owner"; - private final @NotNull EnumMap 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, MetadataConstants.METADATA_KEY_MOB_SPAWNER_MOB); - case EGG_MOB -> mobFlagKeyMap.put(flagType, MetadataConstants.METADATA_KEY_EGG_MOB); - case NETHER_PORTAL_MOB -> mobFlagKeyMap.put(flagType, MetadataConstants.METADATA_KEY_NETHER_PORTAL_MOB); - case COTW_SUMMONED_MOB -> mobFlagKeyMap.put(flagType, MetadataConstants.METADATA_KEY_COTW_SUMMONED_MOB); - case PLAYER_BRED_MOB -> mobFlagKeyMap.put(flagType, MetadataConstants.METADATA_KEY_PLAYER_BRED_MOB); - case PLAYER_TAMED_MOB -> mobFlagKeyMap.put(flagType, MetadataConstants.METADATA_KEY_PLAYER_TAMED_MOB); - case EXPLOITED_ENDERMEN -> mobFlagKeyMap.put(flagType, MetadataConstants.METADATA_KEY_EXPLOITED_ENDERMEN); - default -> throw new IncompleteNamespacedKeyRegister("Missing flag register for: " + flagType); - } - } - } - - @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), MetadataConstants.MCMMO_METADATA_VALUE); - } - } - - @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) { - if(furnace.getMetadata(KEY_FURNACE_OWNER).size() > 0) { - UUIDMeta uuidMeta = (UUIDMeta) ((Metadatable) furnace).getMetadata(KEY_FURNACE_OWNER).get(0); - return (UUID) uuidMeta.value(); - } else { - return null; - } - } - - @Override - public void setFurnaceOwner(@NotNull Furnace furnace, @NotNull UUID uuid) { - - if(furnace.getMetadata(KEY_FURNACE_OWNER).size() > 0) { - furnace.removeMetadata(KEY_FURNACE_OWNER, mcMMO.p); - } - - furnace.setMetadata(KEY_FURNACE_OWNER, new UUIDMeta(mcMMO.p, uuid)); - } - - @Override - public void setSuperAbilityBoostedItem(@NotNull ItemStack itemStack, int originalDigSpeed) { - ItemMeta itemMeta = itemStack.getItemMeta(); - - if(itemMeta == null) { - mcMMO.p.getLogger().severe("Item meta should never be null for a super boosted item!"); - return; - } - - itemMeta.getCustomTagContainer().setCustomTag(NSK_SUPER_ABILITY_BOOSTED_ITEM, ItemTagType.INTEGER, originalDigSpeed); - itemStack.setItemMeta(itemMeta); - } - - @Override - public boolean isSuperAbilityBoosted(@NotNull ItemStack itemStack) { - ItemMeta itemMeta = itemStack.getItemMeta(); - - if(itemMeta == null) - return false; - - CustomItemTagContainer tagContainer = itemMeta.getCustomTagContainer(); - return tagContainer.hasCustomTag(NSK_SUPER_ABILITY_BOOSTED_ITEM, ItemTagType.INTEGER); - } - - @Override - public int getSuperAbilityToolOriginalDigSpeed(@NotNull ItemStack itemStack) { - ItemMeta itemMeta = itemStack.getItemMeta(); - - if(itemMeta == null) - return 0; - - CustomItemTagContainer tagContainer = itemMeta.getCustomTagContainer(); - - if(tagContainer.hasCustomTag(NSK_SUPER_ABILITY_BOOSTED_ITEM, ItemTagType.INTEGER)) { - return tagContainer.getCustomTag(NSK_SUPER_ABILITY_BOOSTED_ITEM, ItemTagType.INTEGER); - } else { - return 0; - } - } - - @Override - public void removeBonusDigSpeedOnSuperAbilityTool(@NotNull ItemStack itemStack) { - int originalSpeed = getSuperAbilityToolOriginalDigSpeed(itemStack); - ItemMeta itemMeta = itemStack.getItemMeta(); - - if(itemMeta == null) - return; - - if(itemMeta.hasEnchant(Enchantment.DIG_SPEED)) { - itemMeta.removeEnchant(Enchantment.DIG_SPEED); - } - - - if(originalSpeed > 0) { - itemMeta.addEnchant(Enchantment.DIG_SPEED, originalSpeed, true); - } - - //TODO: needed? - itemStack.setItemMeta(itemMeta); - } -} diff --git a/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer_1_14.java b/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer_1_14.java deleted file mode 100644 index f4b340fec..000000000 --- a/src/main/java/com/gmail/nossr50/util/compat/layers/persistentdata/SpigotPersistentDataLayer_1_14.java +++ /dev/null @@ -1,220 +0,0 @@ -package com.gmail.nossr50.util.compat.layers.persistentdata; - -import com.gmail.nossr50.api.exceptions.IncompleteNamespacedKeyRegister; -import com.gmail.nossr50.config.PersistentDataConfig; -import com.gmail.nossr50.mcMMO; -import com.gmail.nossr50.util.MetadataConstants; -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; -import org.bukkit.persistence.PersistentDataHolder; -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 { - - private final @NotNull EnumMap mobFlagKeyMap; - private final @NotNull SpigotPersistentDataLayer_1_13 transientLayer; - - public SpigotPersistentDataLayer_1_14() { - mobFlagKeyMap = new EnumMap<>(MobMetaFlagType.class); - initMobFlagKeyMap(); - transientLayer = new SpigotPersistentDataLayer_1_13(); //For disabled persistent types - } - - @Override - public boolean initializeLayer() { - return true; - } - - /** - * 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) { - if(PersistentDataConfig.getInstance().isMobPersistent(flag)) { - return livingEntity.getPersistentDataContainer().has(mobFlagKeyMap.get(flag), PersistentDataType.BYTE); - } else { - return transientLayer.hasMobFlag(flag, livingEntity); - } - } - - @Override - public boolean hasMobFlags(@NotNull LivingEntity livingEntity) { - for(MobMetaFlagType currentFlag : MobMetaFlagType.values()) { - if(hasMobFlag(currentFlag, livingEntity)) { - 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(PersistentDataConfig.getInstance().isMobPersistent(flag)) { - if(!hasMobFlag(flag, livingEntity)) { - PersistentDataContainer persistentDataContainer = livingEntity.getPersistentDataContainer(); - persistentDataContainer.set(mobFlagKeyMap.get(flag), PersistentDataType.BYTE, MetadataConstants.SIMPLE_FLAG_VALUE); - } - } else { - transientLayer.flagMetadata(flag, livingEntity); - } - } - - @Override - public void removeMobFlag(@NotNull MobMetaFlagType flag, @NotNull LivingEntity livingEntity) { - if(PersistentDataConfig.getInstance().isMobPersistent(flag)) { - if(hasMobFlag(flag, livingEntity)) { - PersistentDataContainer persistentDataContainer = livingEntity.getPersistentDataContainer(); - persistentDataContainer.remove(mobFlagKeyMap.get(flag)); - } - } else { - transientLayer.removeMobFlag(flag, livingEntity); - } - } - - @Override - public @Nullable UUID getFurnaceOwner(@NotNull Furnace furnace) { - //Get container from entity - PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer(); - - //Too lazy to make a custom data type for this stuff - 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); - } else { - return null; - } - } - - @Override - public void setFurnaceOwner(@NotNull Furnace furnace, @NotNull UUID uuid) { - PersistentDataContainer dataContainer = ((PersistentDataHolder) furnace).getPersistentDataContainer(); - - dataContainer.set(NSK_FURNACE_UUID_MOST_SIG, PersistentDataType.LONG, uuid.getMostSignificantBits()); - dataContainer.set(NSK_FURNACE_UUID_LEAST_SIG, PersistentDataType.LONG, uuid.getLeastSignificantBits()); - - furnace.update(); - } - - @Override - public void setSuperAbilityBoostedItem(@NotNull ItemStack itemStack, int originalDigSpeed) { - if(itemStack.getItemMeta() == null) { - mcMMO.p.getLogger().severe("Can not assign persistent data to an item with null item metadata"); - return; - } - - ItemMeta itemMeta = itemStack.getItemMeta(); - PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer(); - - dataContainer.set(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER, originalDigSpeed); - - itemStack.setItemMeta(itemMeta); - } - - @Override - public boolean isSuperAbilityBoosted(@NotNull ItemStack itemStack) { - if(itemStack.getItemMeta() == null) - return false; - - ItemMeta itemMeta = itemStack.getItemMeta(); - //Get container from entity - PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer(); - - //If this value isn't null, then the tool can be considered dig speed boosted - Integer boostValue = dataContainer.get(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER); - - return boostValue != null; - } - - @Override - public int getSuperAbilityToolOriginalDigSpeed(@NotNull ItemStack itemStack) { - //Get container from entity - ItemMeta itemMeta = itemStack.getItemMeta(); - - if(itemMeta == null) - return 0; - - PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer(); - - 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(NSK_SUPER_ABILITY_BOOSTED_ITEM, PersistentDataType.INTEGER); - return Math.max(boostValue, 0); - } - } - - @Override - public void removeBonusDigSpeedOnSuperAbilityTool(@NotNull ItemStack itemStack) { - int originalSpeed = getSuperAbilityToolOriginalDigSpeed(itemStack); - ItemMeta itemMeta = itemStack.getItemMeta(); - - //TODO: can be optimized - if(itemMeta.hasEnchant(Enchantment.DIG_SPEED)) { - itemMeta.removeEnchant(Enchantment.DIG_SPEED); - } - - if(originalSpeed > 0) { - itemMeta.addEnchant(Enchantment.DIG_SPEED, originalSpeed, true); - } - - PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer(); - dataContainer.remove(NSK_SUPER_ABILITY_BOOSTED_ITEM); //Remove persistent data - - //TODO: needed? - itemStack.setItemMeta(itemMeta); - } -} diff --git a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java index 00e6f01d0..a855f3a4c 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java @@ -10,6 +10,8 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent; import com.gmail.nossr50.events.fake.FakeEntityDamageEvent; import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.metadata.MobMetaFlagType; +import com.gmail.nossr50.metadata.MobMetadataService; import com.gmail.nossr50.party.PartyManager; import com.gmail.nossr50.runnables.skills.AwardCombatXpTask; import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager; @@ -19,8 +21,6 @@ import com.gmail.nossr50.skills.swords.SwordsManager; import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.skills.unarmed.UnarmedManager; import com.gmail.nossr50.util.*; -import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDataLayer; -import com.gmail.nossr50.util.compat.layers.persistentdata.MobMetaFlagType; import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.UserManager; import com.google.common.collect.ImmutableMap; @@ -50,8 +50,8 @@ public final class CombatUtils { private CombatUtils() {} - private static @NotNull AbstractPersistentDataLayer getPersistentData() { - return mcMMO.getCompatibilityManager().getPersistentDataLayer(); + private static @NotNull MobMetadataService getMobMetadataService() { + return mcMMO.getMetadataService().getMobMetadataService(); } //Likely.. because who knows what plugins are throwing around @@ -801,17 +801,17 @@ public final class CombatUtils { } } - if(getPersistentData().hasMobFlag(MobMetaFlagType.COTW_SUMMONED_MOB, target)) { + if(getMobMetadataService().hasMobFlag(MobMetaFlagType.COTW_SUMMONED_MOB, target)) { baseXP = 0; - } else if(getPersistentData().hasMobFlag(MobMetaFlagType.MOB_SPAWNER_MOB, target) || target.hasMetadata("ES")) { + } else if(getMobMetadataService().hasMobFlag(MobMetaFlagType.MOB_SPAWNER_MOB, target) || target.hasMetadata("ES")) { baseXP *= ExperienceConfig.getInstance().getSpawnedMobXpMultiplier(); - } else if(getPersistentData().hasMobFlag(MobMetaFlagType.NETHER_PORTAL_MOB, target)) { + } else if(getMobMetadataService().hasMobFlag(MobMetaFlagType.NETHER_PORTAL_MOB, target)) { baseXP *= ExperienceConfig.getInstance().getNetherPortalXpMultiplier(); - } else if(getPersistentData().hasMobFlag(MobMetaFlagType.EGG_MOB, target)) { + } else if(getMobMetadataService().hasMobFlag(MobMetaFlagType.EGG_MOB, target)) { baseXP *= ExperienceConfig.getInstance().getEggXpMultiplier(); - } else if (getPersistentData().hasMobFlag(MobMetaFlagType.PLAYER_BRED_MOB, target)) { + } else if (getMobMetadataService().hasMobFlag(MobMetaFlagType.PLAYER_BRED_MOB, target)) { baseXP *= ExperienceConfig.getInstance().getBredMobXpMultiplier(); - } else if(getPersistentData().hasMobFlag(MobMetaFlagType.PLAYER_TAMED_MOB, target)) { + } else if(getMobMetadataService().hasMobFlag(MobMetaFlagType.PLAYER_TAMED_MOB, target)) { baseXP *= ExperienceConfig.getInstance().getTamedMobXpMultiplier(); } diff --git a/src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java b/src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java index 9c9e962c5..6a15963ef 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java @@ -10,9 +10,9 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.datatypes.skills.SuperAbilityType; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.metadata.ItemMetadataService; import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.Misc; -import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDataLayer; import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.text.StringUtils; @@ -156,8 +156,7 @@ public final class SkillUtils { ItemUtils.addDigSpeedToItem(heldItem, heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED)); //1.13.2+ will have persistent metadata for this item - AbstractPersistentDataLayer compatLayer = mcMMO.getCompatibilityManager().getPersistentDataLayer(); - compatLayer.setSuperAbilityBoostedItem(heldItem, originalDigSpeed); + mcMMO.getMetadataService().getItemMetadataService().setSuperAbilityBoostedItem(heldItem, originalDigSpeed); } else { int duration = 0; int amplifier = 0; @@ -214,20 +213,22 @@ public final class SkillUtils { //1.13.2+ will have persistent metadata for this itemStack - AbstractPersistentDataLayer compatLayer = mcMMO.getCompatibilityManager().getPersistentDataLayer(); + ItemMetadataService itemMetadataService = mcMMO.getMetadataService().getItemMetadataService(); - if(compatLayer.isLegacyAbilityTool(itemStack)) { + if(itemMetadataService.isLegacyAbilityTool(itemStack)) { ItemMeta itemMeta = itemStack.getItemMeta(); - // This is safe to call without prior checks. - itemMeta.removeEnchant(Enchantment.DIG_SPEED); + if(itemMeta != null) { + // This is safe to call without prior checks. + itemMeta.removeEnchant(Enchantment.DIG_SPEED); - itemStack.setItemMeta(itemMeta); - ItemUtils.removeAbilityLore(itemStack); + itemStack.setItemMeta(itemMeta); + ItemUtils.removeAbilityLore(itemStack); + } } - if(compatLayer.isSuperAbilityBoosted(itemStack)) { - compatLayer.removeBonusDigSpeedOnSuperAbilityTool(itemStack); + if(itemMetadataService.isSuperAbilityBoosted(itemStack)) { + itemMetadataService.removeBonusDigSpeedOnSuperAbilityTool(itemStack); } } diff --git a/src/main/java/com/gmail/nossr50/util/skills/SmeltingTracker.java b/src/main/java/com/gmail/nossr50/util/skills/SmeltingTracker.java index dfa313181..83e993a10 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/SmeltingTracker.java +++ b/src/main/java/com/gmail/nossr50/util/skills/SmeltingTracker.java @@ -34,7 +34,7 @@ public class SmeltingTracker { } private void setFurnaceOwner(Furnace furnace, Player player) { - mcMMO.getCompatibilityManager().getPersistentDataLayer().setFurnaceOwner(furnace, player.getUniqueId()); + mcMMO.getMetadataService().getBlockMetadataService().setFurnaceOwner(furnace, player.getUniqueId()); } private void printOwnershipGainDebug(Furnace furnace, McMMOPlayer mcMMOPlayer) { @@ -65,7 +65,7 @@ public class SmeltingTracker { } public @Nullable OfflinePlayer getFurnaceOwner(Furnace furnace) { - UUID uuid = mcMMO.getCompatibilityManager().getPersistentDataLayer().getFurnaceOwner(furnace); + UUID uuid = mcMMO.getMetadataService().getBlockMetadataService().getFurnaceOwner(furnace); if(uuid != null) { return Bukkit.getOfflinePlayer(uuid);