mirror of
				https://github.com/mcMMO-Dev/mcMMO.git
				synced 2025-10-31 09:13:43 +01:00 
			
		
		
		
	| @@ -1,4 +1,9 @@ | |||||||
| Version 2.1.210 | 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 | Version 2.1.209 | ||||||
|     Fixed a bug where some config files did not get trimmed completely |     Fixed a bug where some config files did not get trimmed completely | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| package com.gmail.nossr50.config; | 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 { | public class PersistentDataConfig extends BukkitConfig { | ||||||
|     private static PersistentDataConfig instance; |     private static PersistentDataConfig instance; | ||||||
|   | |||||||
| @@ -10,6 +10,8 @@ import com.gmail.nossr50.events.fake.FakeEntityDamageEvent; | |||||||
| import com.gmail.nossr50.events.fake.FakeEntityTameEvent; | import com.gmail.nossr50.events.fake.FakeEntityTameEvent; | ||||||
| import com.gmail.nossr50.events.skills.rupture.McMMOEntityDamageByRuptureEvent; | import com.gmail.nossr50.events.skills.rupture.McMMOEntityDamageByRuptureEvent; | ||||||
| import com.gmail.nossr50.mcMMO; | 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.party.PartyManager; | ||||||
| import com.gmail.nossr50.runnables.TravelingBlockMetaCleanup; | import com.gmail.nossr50.runnables.TravelingBlockMetaCleanup; | ||||||
| import com.gmail.nossr50.skills.archery.Archery; | 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.taming.TamingManager; | ||||||
| import com.gmail.nossr50.skills.unarmed.UnarmedManager; | import com.gmail.nossr50.skills.unarmed.UnarmedManager; | ||||||
| import com.gmail.nossr50.util.*; | 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.NotificationManager; | ||||||
| import com.gmail.nossr50.util.player.UserManager; | import com.gmail.nossr50.util.player.UserManager; | ||||||
| import com.gmail.nossr50.util.random.RandomChanceUtil; | import com.gmail.nossr50.util.random.RandomChanceUtil; | ||||||
| @@ -51,7 +51,7 @@ import org.jetbrains.annotations.NotNull; | |||||||
|  |  | ||||||
| public class EntityListener implements Listener { | public class EntityListener implements Listener { | ||||||
|     private final mcMMO pluginRef; |     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 |      * 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) { |     public EntityListener(final mcMMO pluginRef) { | ||||||
|         this.pluginRef = pluginRef; |         this.pluginRef = pluginRef; | ||||||
|         persistentDataLayer = mcMMO.getCompatibilityManager().getPersistentDataLayer(); |         mobMetadataService = mcMMO.getMetadataService().getMobMetadataService(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| //    @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) | //    @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) | ||||||
| @@ -94,11 +94,11 @@ public class EntityListener implements Listener { | |||||||
|             LivingEntity livingEntity = (LivingEntity) event.getEntity(); |             LivingEntity livingEntity = (LivingEntity) event.getEntity(); | ||||||
|  |  | ||||||
|             //Transfer metadata keys from mob-spawned mobs to new mobs |             //Transfer metadata keys from mob-spawned mobs to new mobs | ||||||
|             if(persistentDataLayer.hasMobFlags(livingEntity)) { |             if(mobMetadataService.hasMobFlags(livingEntity)) { | ||||||
|                 for(Entity entity : event.getTransformedEntities()) { |                 for(Entity entity : event.getTransformedEntities()) { | ||||||
|                     if(entity instanceof LivingEntity) { |                     if(entity instanceof LivingEntity) { | ||||||
|                         LivingEntity transformedEntity = (LivingEntity) entity; |                         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) { |             if(event.getEntity() instanceof Enderman) { | ||||||
|                 Enderman enderman = (Enderman) event.getEntity(); |                 Enderman enderman = (Enderman) event.getEntity(); | ||||||
|  |  | ||||||
|                 if(!persistentDataLayer.hasMobFlag(MobMetaFlagType.EXPLOITED_ENDERMEN, enderman)) { |                 if(!mobMetadataService.hasMobFlag(MobMetaFlagType.EXPLOITED_ENDERMEN, enderman)) { | ||||||
|                     persistentDataLayer.flagMetadata(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) { |     private void trackSpawnedAndPassengers(LivingEntity livingEntity, MobMetaFlagType mobMetaFlagType) { | ||||||
|         persistentDataLayer.flagMetadata(mobMetaFlagType, livingEntity); |         mobMetadataService.flagMetadata(mobMetaFlagType, livingEntity); | ||||||
|  |  | ||||||
|         for(Entity passenger : livingEntity.getPassengers()) { |         for(Entity passenger : livingEntity.getPassengers()) { | ||||||
|             if(passenger != null) { |             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) |     @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) | ||||||
|     public void onEntityBreed(EntityBreedEvent event) { |     public void onEntityBreed(EntityBreedEvent event) { | ||||||
|         if(ExperienceConfig.getInstance().isCOTWBreedingPrevented()) { |         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); |                 event.setCancelled(true); | ||||||
|                 Animals mom = (Animals) event.getMother(); |                 Animals mom = (Animals) event.getMother(); | ||||||
|                 Animals father = (Animals) event.getFather(); |                 Animals father = (Animals) event.getFather(); | ||||||
| @@ -1007,12 +1007,12 @@ public class EntityListener implements Listener { | |||||||
|  |  | ||||||
|         if (!UserManager.hasPlayerDataKey(player) |         if (!UserManager.hasPlayerDataKey(player) | ||||||
|                 || (ExperienceConfig.getInstance().isNPCInteractionPrevented() && Misc.isNPCEntityExcludingVillagers(livingEntity)) |                 || (ExperienceConfig.getInstance().isNPCInteractionPrevented() && Misc.isNPCEntityExcludingVillagers(livingEntity)) | ||||||
|                 || persistentDataLayer.hasMobFlag(MobMetaFlagType.EGG_MOB, livingEntity) |                 || mobMetadataService.hasMobFlag(MobMetaFlagType.EGG_MOB, livingEntity) | ||||||
|                 || persistentDataLayer.hasMobFlag(MobMetaFlagType.MOB_SPAWNER_MOB, livingEntity)) { |                 || mobMetadataService.hasMobFlag(MobMetaFlagType.MOB_SPAWNER_MOB, livingEntity)) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         persistentDataLayer.flagMetadata(MobMetaFlagType.PLAYER_TAMED_MOB, livingEntity); |         mobMetadataService.flagMetadata(MobMetaFlagType.PLAYER_TAMED_MOB, livingEntity); | ||||||
|  |  | ||||||
|         //Profile not loaded |         //Profile not loaded | ||||||
|         if(UserManager.getPlayer(player) == null) |         if(UserManager.getPlayer(player) == null) | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ import com.gmail.nossr50.database.DatabaseManagerFactory; | |||||||
| import com.gmail.nossr50.datatypes.skills.PrimarySkillType; | import com.gmail.nossr50.datatypes.skills.PrimarySkillType; | ||||||
| import com.gmail.nossr50.datatypes.skills.subskills.acrobatics.Roll; | import com.gmail.nossr50.datatypes.skills.subskills.acrobatics.Roll; | ||||||
| import com.gmail.nossr50.listeners.*; | import com.gmail.nossr50.listeners.*; | ||||||
|  | import com.gmail.nossr50.metadata.MetadataService; | ||||||
| import com.gmail.nossr50.party.PartyManager; | import com.gmail.nossr50.party.PartyManager; | ||||||
| import com.gmail.nossr50.runnables.SaveTimerTask; | import com.gmail.nossr50.runnables.SaveTimerTask; | ||||||
| import com.gmail.nossr50.runnables.backups.CleanBackupsTask; | import com.gmail.nossr50.runnables.backups.CleanBackupsTask; | ||||||
| @@ -77,8 +78,9 @@ import java.util.List; | |||||||
| public class mcMMO extends JavaPlugin { | public class mcMMO extends JavaPlugin { | ||||||
|  |  | ||||||
|  |  | ||||||
|     /* Managers */ |     /* Managers & Services */ | ||||||
|     private static PlatformManager platformManager; |     private static PlatformManager platformManager; | ||||||
|  |     private static MetadataService metadataService; | ||||||
|     private static ChunkManager       placeStore; |     private static ChunkManager       placeStore; | ||||||
|     private static RepairableManager  repairableManager; |     private static RepairableManager  repairableManager; | ||||||
|     private static SalvageableManager salvageableManager; |     private static SalvageableManager salvageableManager; | ||||||
| @@ -175,6 +177,9 @@ public class mcMMO extends JavaPlugin { | |||||||
|             //Platform Manager |             //Platform Manager | ||||||
|             platformManager = new PlatformManager(); |             platformManager = new PlatformManager(); | ||||||
|  |  | ||||||
|  |             //metadata service | ||||||
|  |             metadataService = new MetadataService(this); | ||||||
|  |  | ||||||
|             //Filter out any debug messages (if debug/verbose logging is not enabled) |             //Filter out any debug messages (if debug/verbose logging is not enabled) | ||||||
|             getLogger().setFilter(new LogFilter(this)); |             getLogger().setFilter(new LogFilter(this)); | ||||||
|  |  | ||||||
| @@ -466,6 +471,10 @@ public class mcMMO extends JavaPlugin { | |||||||
|         return platformManager.getCompatibilityManager(); |         return platformManager.getCompatibilityManager(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public static MetadataService getMetadataService() { | ||||||
|  |         return metadataService; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Deprecated |     @Deprecated | ||||||
|     public static void setDatabaseManager(DatabaseManager databaseManager) { |     public static void setDatabaseManager(DatabaseManager databaseManager) { | ||||||
|         mcMMO.databaseManager = databaseManager; |         mcMMO.databaseManager = databaseManager; | ||||||
|   | |||||||
| @@ -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(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -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<String> 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; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package com.gmail.nossr50.util.compat.layers.persistentdata; | package com.gmail.nossr50.metadata; | ||||||
| 
 | 
 | ||||||
| public enum MobMetaFlagType { | public enum MobMetaFlagType { | ||||||
|     MOB_SPAWNER_MOB, |     MOB_SPAWNER_MOB, | ||||||
							
								
								
									
										187
									
								
								src/main/java/com/gmail/nossr50/metadata/MobMetadataService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								src/main/java/com/gmail/nossr50/metadata/MobMetadataService.java
									
									
									
									
									
										Normal file
									
								
							| @@ -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<Entity, HashSet<MobMetaFlagType>> mobRegistry; //transient data | ||||||
|  |     private final @NotNull EnumMap<MobMetaFlagType, NamespacedKey> 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<MobMetaFlagType> 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<MobMetaFlagType> 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); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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.datatypes.skills.subskills.taming.TamingSummon; | ||||||
| import com.gmail.nossr50.locale.LocaleLoader; | import com.gmail.nossr50.locale.LocaleLoader; | ||||||
| import com.gmail.nossr50.mcMMO; | import com.gmail.nossr50.mcMMO; | ||||||
|  | import com.gmail.nossr50.metadata.MobMetaFlagType; | ||||||
| import com.gmail.nossr50.skills.SkillManager; | import com.gmail.nossr50.skills.SkillManager; | ||||||
| import com.gmail.nossr50.util.Misc; | import com.gmail.nossr50.util.Misc; | ||||||
| import com.gmail.nossr50.util.Permissions; | 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.player.NotificationManager; | ||||||
| import com.gmail.nossr50.util.random.RandomChanceSkillStatic; | import com.gmail.nossr50.util.random.RandomChanceSkillStatic; | ||||||
| import com.gmail.nossr50.util.random.RandomChanceUtil; | import com.gmail.nossr50.util.random.RandomChanceUtil; | ||||||
| @@ -475,7 +475,7 @@ public class TamingManager extends SkillManager { | |||||||
|  |  | ||||||
|     private void applyMetaDataToCOTWEntity(LivingEntity summonedEntity) { |     private void applyMetaDataToCOTWEntity(LivingEntity summonedEntity) { | ||||||
|         //This helps identify the entity as being summoned by COTW |         //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); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -273,7 +273,7 @@ public class TransientEntityTracker { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         //Remove our metadata |         //Remove our metadata | ||||||
|         mcMMO.getCompatibilityManager().getPersistentDataLayer().removeMobFlags(livingEntity); |         mcMMO.getMetadataService().getMobMetadataService().removeMobFlags(livingEntity); | ||||||
|  |  | ||||||
|         //Clean from trackers |         //Clean from trackers | ||||||
|         unregisterEntity(livingEntity); |         unregisterEntity(livingEntity); | ||||||
|   | |||||||
| @@ -18,11 +18,6 @@ public class TransientMetadataTools { | |||||||
|             entity.removeMetadata(MetadataConstants.METADATA_KEY_CUSTOM_NAME, pluginRef); |             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 |         //Involved in changing mob names to hearts | ||||||
|         if (entity.hasMetadata(MetadataConstants.METADATA_KEY_NAME_VISIBILITY)) { |         if (entity.hasMetadata(MetadataConstants.METADATA_KEY_NAME_VISIBILITY)) { | ||||||
|             entity.setCustomNameVisible(entity.getMetadata(MetadataConstants.METADATA_KEY_NAME_VISIBILITY).get(0).asBoolean()); |             entity.setCustomNameVisible(entity.getMetadata(MetadataConstants.METADATA_KEY_NAME_VISIBILITY).get(0).asBoolean()); | ||||||
| @@ -35,7 +30,7 @@ public class TransientMetadataTools { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         //Cleanup mob metadata |         //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 |         //TODO: This loop has some redundancy, this whole method needs to be rewritten | ||||||
|         for(String key : MetadataConstants.MOB_METADATA_KEYS) { |         for(String key : MetadataConstants.MOB_METADATA_KEYS) { | ||||||
|   | |||||||
| @@ -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.AbstractBungeeSerializerCompatibilityLayer; | ||||||
| import com.gmail.nossr50.util.compat.layers.bungee.BungeeLegacySerializerCompatibilityLayer; | 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.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.AbstractMasterAnglerCompatibility; | ||||||
| import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer; | import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer; | ||||||
| import com.gmail.nossr50.util.nms.NMSVersion; | 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 |  * 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 { | public class CompatibilityManager { | ||||||
|     private @NotNull HashMap<CompatibilityType, Boolean> supportedLayers; |     private @NotNull HashMap<CompatibilityType, Boolean> supportedLayers; | ||||||
|     private boolean isFullyCompatibleServerSoftware = true; //true if all compatibility layers load successfully |     private boolean isFullyCompatibleServerSoftware = true; //true if all compatibility layers load successfully | ||||||
| @@ -33,8 +30,6 @@ public class CompatibilityManager { | |||||||
|     private final @NotNull NMSVersion nmsVersion; |     private final @NotNull NMSVersion nmsVersion; | ||||||
|  |  | ||||||
|     /* Compatibility Layers */ |     /* Compatibility Layers */ | ||||||
| //    private PlayerAttackCooldownExploitPreventionLayer playerAttackCooldownExploitPreventionLayer; |  | ||||||
|     private AbstractPersistentDataLayer persistentDataLayer; |  | ||||||
|     private AbstractBungeeSerializerCompatibilityLayer bungeeSerializerCompatibilityLayer; |     private AbstractBungeeSerializerCompatibilityLayer bungeeSerializerCompatibilityLayer; | ||||||
|     private AbstractMasterAnglerCompatibility masterAnglerCompatibility; |     private AbstractMasterAnglerCompatibility masterAnglerCompatibility; | ||||||
|  |  | ||||||
| @@ -64,7 +59,6 @@ public class CompatibilityManager { | |||||||
|      * For any unsupported layers, load a dummy layer |      * For any unsupported layers, load a dummy layer | ||||||
|      */ |      */ | ||||||
|     private void initCompatibilityLayers() { |     private void initCompatibilityLayers() { | ||||||
|         initPersistentDataLayer(); |  | ||||||
|         initBungeeSerializerLayer(); |         initBungeeSerializerLayer(); | ||||||
|         initMasterAnglerLayer(); |         initMasterAnglerLayer(); | ||||||
|  |  | ||||||
| @@ -89,17 +83,6 @@ public class CompatibilityManager { | |||||||
|         supportedLayers.put(CompatibilityType.BUNGEE_SERIALIZER, true); |         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 |     //TODO: move to text manager | ||||||
|     public void reportCompatibilityStatus(@NotNull CommandSender commandSender) { |     public void reportCompatibilityStatus(@NotNull CommandSender commandSender) { | ||||||
|         if(isFullyCompatibleServerSoftware) { |         if(isFullyCompatibleServerSoftware) { | ||||||
| @@ -171,10 +154,6 @@ public class CompatibilityManager { | |||||||
|         return bungeeSerializerCompatibilityLayer; |         return bungeeSerializerCompatibilityLayer; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public AbstractPersistentDataLayer getPersistentDataLayer() { |  | ||||||
|         return persistentDataLayer; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public @Nullable AbstractMasterAnglerCompatibility getMasterAnglerCompatibilityLayer() { |     public @Nullable AbstractMasterAnglerCompatibility getMasterAnglerCompatibilityLayer() { | ||||||
|         return masterAnglerCompatibility; |         return masterAnglerCompatibility; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -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<String> 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; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -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<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, 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); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -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<MobMetaFlagType, NamespacedKey> 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); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -10,6 +10,8 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType; | |||||||
| import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent; | import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent; | ||||||
| import com.gmail.nossr50.events.fake.FakeEntityDamageEvent; | import com.gmail.nossr50.events.fake.FakeEntityDamageEvent; | ||||||
| import com.gmail.nossr50.mcMMO; | 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.party.PartyManager; | ||||||
| import com.gmail.nossr50.runnables.skills.AwardCombatXpTask; | import com.gmail.nossr50.runnables.skills.AwardCombatXpTask; | ||||||
| import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager; | 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.taming.TamingManager; | ||||||
| import com.gmail.nossr50.skills.unarmed.UnarmedManager; | import com.gmail.nossr50.skills.unarmed.UnarmedManager; | ||||||
| import com.gmail.nossr50.util.*; | 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.NotificationManager; | ||||||
| import com.gmail.nossr50.util.player.UserManager; | import com.gmail.nossr50.util.player.UserManager; | ||||||
| import com.google.common.collect.ImmutableMap; | import com.google.common.collect.ImmutableMap; | ||||||
| @@ -50,8 +50,8 @@ public final class CombatUtils { | |||||||
|  |  | ||||||
|     private CombatUtils() {} |     private CombatUtils() {} | ||||||
|  |  | ||||||
|     private static @NotNull AbstractPersistentDataLayer getPersistentData() { |     private static @NotNull MobMetadataService getMobMetadataService() { | ||||||
|         return mcMMO.getCompatibilityManager().getPersistentDataLayer(); |         return mcMMO.getMetadataService().getMobMetadataService(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     //Likely.. because who knows what plugins are throwing around |     //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; |                 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(); |                 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(); |                 baseXP *= ExperienceConfig.getInstance().getNetherPortalXpMultiplier(); | ||||||
|             } else if(getPersistentData().hasMobFlag(MobMetaFlagType.EGG_MOB, target)) { |             } else if(getMobMetadataService().hasMobFlag(MobMetaFlagType.EGG_MOB, target)) { | ||||||
|                 baseXP *= ExperienceConfig.getInstance().getEggXpMultiplier(); |                 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(); |                 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(); |                 baseXP *= ExperienceConfig.getInstance().getTamedMobXpMultiplier(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,9 +10,9 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType; | |||||||
| import com.gmail.nossr50.datatypes.skills.SuperAbilityType; | import com.gmail.nossr50.datatypes.skills.SuperAbilityType; | ||||||
| import com.gmail.nossr50.locale.LocaleLoader; | import com.gmail.nossr50.locale.LocaleLoader; | ||||||
| import com.gmail.nossr50.mcMMO; | import com.gmail.nossr50.mcMMO; | ||||||
|  | import com.gmail.nossr50.metadata.ItemMetadataService; | ||||||
| import com.gmail.nossr50.util.ItemUtils; | import com.gmail.nossr50.util.ItemUtils; | ||||||
| import com.gmail.nossr50.util.Misc; | 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.NotificationManager; | ||||||
| import com.gmail.nossr50.util.player.UserManager; | import com.gmail.nossr50.util.player.UserManager; | ||||||
| import com.gmail.nossr50.util.text.StringUtils; | import com.gmail.nossr50.util.text.StringUtils; | ||||||
| @@ -156,8 +156,7 @@ public final class SkillUtils { | |||||||
|             ItemUtils.addDigSpeedToItem(heldItem, heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED)); |             ItemUtils.addDigSpeedToItem(heldItem, heldItem.getEnchantmentLevel(Enchantment.DIG_SPEED)); | ||||||
|  |  | ||||||
|             //1.13.2+ will have persistent metadata for this item |             //1.13.2+ will have persistent metadata for this item | ||||||
|             AbstractPersistentDataLayer compatLayer = mcMMO.getCompatibilityManager().getPersistentDataLayer(); |             mcMMO.getMetadataService().getItemMetadataService().setSuperAbilityBoostedItem(heldItem, originalDigSpeed); | ||||||
|             compatLayer.setSuperAbilityBoostedItem(heldItem, originalDigSpeed); |  | ||||||
|         } else { |         } else { | ||||||
|             int duration = 0; |             int duration = 0; | ||||||
|             int amplifier = 0; |             int amplifier = 0; | ||||||
| @@ -214,20 +213,22 @@ public final class SkillUtils { | |||||||
|  |  | ||||||
|  |  | ||||||
|         //1.13.2+ will have persistent metadata for this itemStack |         //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(); |             ItemMeta itemMeta = itemStack.getItemMeta(); | ||||||
|  |  | ||||||
|             // This is safe to call without prior checks. |             if(itemMeta != null) { | ||||||
|             itemMeta.removeEnchant(Enchantment.DIG_SPEED); |                 // This is safe to call without prior checks. | ||||||
|  |                 itemMeta.removeEnchant(Enchantment.DIG_SPEED); | ||||||
|  |  | ||||||
|             itemStack.setItemMeta(itemMeta); |                 itemStack.setItemMeta(itemMeta); | ||||||
|             ItemUtils.removeAbilityLore(itemStack); |                 ItemUtils.removeAbilityLore(itemStack); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(compatLayer.isSuperAbilityBoosted(itemStack)) { |         if(itemMetadataService.isSuperAbilityBoosted(itemStack)) { | ||||||
|             compatLayer.removeBonusDigSpeedOnSuperAbilityTool(itemStack); |             itemMetadataService.removeBonusDigSpeedOnSuperAbilityTool(itemStack); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ public class SmeltingTracker { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void setFurnaceOwner(Furnace furnace, Player player) { |     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) { |     private void printOwnershipGainDebug(Furnace furnace, McMMOPlayer mcMMOPlayer) { | ||||||
| @@ -65,7 +65,7 @@ public class SmeltingTracker { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public @Nullable OfflinePlayer getFurnaceOwner(Furnace furnace) { |     public @Nullable OfflinePlayer getFurnaceOwner(Furnace furnace) { | ||||||
|         UUID uuid = mcMMO.getCompatibilityManager().getPersistentDataLayer().getFurnaceOwner(furnace); |         UUID uuid = mcMMO.getMetadataService().getBlockMetadataService().getFurnaceOwner(furnace); | ||||||
|  |  | ||||||
|         if(uuid != null) { |         if(uuid != null) { | ||||||
|             return Bukkit.getOfflinePlayer(uuid); |             return Bukkit.getOfflinePlayer(uuid); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 nossr50
					nossr50