Memory leak fixes, optimizations, and persistence

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

View File

@ -0,0 +1,7 @@
package com.gmail.nossr50.api.exceptions;
public class IncompleteNamespacedKeyRegister extends RuntimeException {
public IncompleteNamespacedKeyRegister(String message) {
super(message);
}
}

View File

@ -175,6 +175,8 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
/* Spawned Mob modifier */
public double getSpawnedMobXpMultiplier() { return config.getDouble("Experience_Formula.Mobspawners.Multiplier", 0.0); }
public double getEggXpMultiplier() { return config.getDouble("Experience_Formula.Eggs.Multiplier", 0.0); }
public double getNetherPortalXpMultiplier() { return config.getDouble("Experience_Formula.Nether_Portal.Multiplier", 0.0); }
public double getBredMobXpMultiplier() { return config.getDouble("Experience_Formula.Breeding.Multiplier", 1.0); }
/* Skill modifiers */

View File

@ -5,7 +5,6 @@ import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.WorldBlacklist;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.datatypes.skills.subskills.interfaces.InteractType;
import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent;
@ -22,6 +21,8 @@ import com.gmail.nossr50.skills.unarmed.UnarmedManager;
import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
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;
@ -46,30 +47,36 @@ import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.projectiles.ProjectileSource;
import org.jetbrains.annotations.NotNull;
public class EntityListener implements Listener {
private final mcMMO plugin;
private final mcMMO pluginRef;
private final @NotNull AbstractPersistentDataLayer persistentDataLayer;
public EntityListener(final mcMMO plugin) {
this.plugin = plugin;
public EntityListener(final mcMMO pluginRef) {
this.pluginRef = pluginRef;
persistentDataLayer = mcMMO.getCompatibilityManager().getPersistentDataLayer();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onEntityTransform(EntityTransformEvent event)
{
//Transfer metadata keys from mob-spawned mobs to new mobs
if(event.getEntity().getMetadata(mcMMO.entityMetadataKey) != null || event.getEntity().getMetadata(mcMMO.entityMetadataKey).size() >= 1)
{
for(Entity entity : event.getTransformedEntities())
{
entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
public void onEntityTransform(EntityTransformEvent event) {
if(event.getEntity() instanceof LivingEntity) {
LivingEntity livingEntity = (LivingEntity) event.getEntity();
//Transfer metadata keys from mob-spawned mobs to new mobs
if(persistentDataLayer.hasMobFlags(livingEntity)) {
for(Entity entity : event.getTransformedEntities()) {
if(entity instanceof LivingEntity) {
LivingEntity transformedEntity = (LivingEntity) entity;
persistentDataLayer.addMobFlags(livingEntity, transformedEntity);
}
}
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityTargetEntity(EntityTargetLivingEntityEvent event)
{
public void onEntityTargetEntity(EntityTargetLivingEntityEvent event) {
if(!ExperienceConfig.getInstance().isEndermanEndermiteFarmingPrevented())
return;
@ -82,8 +89,13 @@ public class EntityListener implements Listener {
//Prevent entities from giving XP if they target endermite
if(event.getTarget() instanceof Endermite)
{
if(!event.getEntity().hasMetadata(mcMMO.entityMetadataKey))
event.getEntity().setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
if(event.getEntity() instanceof Enderman) {
Enderman enderman = (Enderman) event.getEntity();
if(!persistentDataLayer.hasMobFlag(MobMetaFlagType.EXPLOITED_ENDERMEN, enderman)) {
persistentDataLayer.flagMetadata(MobMetaFlagType.EXPLOITED_ENDERMEN, enderman);
}
}
}
}
@ -119,8 +131,8 @@ public class EntityListener implements Listener {
projectile.setMetadata(mcMMO.infiniteArrowKey, mcMMO.metadataValue);
}
projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(plugin, Math.min(event.getForce() * AdvancedConfig.getInstance().getForceMultiplier(), 1.0)));
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(pluginRef, Math.min(event.getForce() * AdvancedConfig.getInstance().getForceMultiplier(), 1.0)));
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(pluginRef, projectile.getLocation()));
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@ -145,8 +157,8 @@ public class EntityListener implements Listener {
if(!(projectile instanceof Arrow))
return;
projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(plugin, 1.0));
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(pluginRef, 1.0));
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(pluginRef, projectile.getLocation()));
for(Enchantment enchantment : player.getInventory().getItemInMainHand().getEnchantments().keySet()) {
if(enchantment.getName().equalsIgnoreCase("piercing"))
@ -185,74 +197,38 @@ public class EntityListener implements Listener {
Entity entity = event.getEntity();
if (entity instanceof FallingBlock || entity instanceof Enderman) {
boolean isTracked = entity.hasMetadata(mcMMO.entityMetadataKey);
if (mcMMO.getPlaceStore().isTrue(block) && !isTracked) {
mcMMO.getPlaceStore().setFalse(block);
entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
}
else if (isTracked) {
mcMMO.getPlaceStore().setTrue(block);
}
} else if ((block.getType() == Material.REDSTONE_ORE)) {
}
else {
trackMovingBlocks(block, entity); //ignore the IDE warning
//Apparently redstone ore will throw these events
} else if ((block.getType() != Material.REDSTONE_ORE)) {
if (mcMMO.getPlaceStore().isTrue(block)) {
mcMMO.getPlaceStore().setFalse(block);
}
}
}
/*@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEntityDamageDebugLowest(EntityDamageEvent event)
{
if(event instanceof FakeEntityDamageByEntityEvent)
return;
/**
* This is a complex hack to track blocks for this event
* This event is called when a block starts its movement, or ends its movement
* It can start the movement through physics (falling blocks) or through being picked up (endermen)
* Since this event can be cancelled, its even weirder to track this stuff
* @param block this will either be the block that was originally picked up, or the block in its final destination
* @param movementSourceEntity this will either be an Endermen or a Falling Block
*/
private void trackMovingBlocks(@NotNull Block block, @NotNull Entity movementSourceEntity) {
if(event instanceof FakeEntityDamageEvent)
return;
Bukkit.broadcastMessage(ChatColor.DARK_AQUA+"DMG Before Events: "
+ChatColor.RESET+event.getDamage());
//A block that has reached its destination, either being placed by endermen or having finished its fall
if(movementSourceEntity.hasMetadata(mcMMO.travelingBlock)) {
mcMMO.getPlaceStore().setTrue(block);
movementSourceEntity.removeMetadata(mcMMO.travelingBlock, pluginRef);
} else {
//A block that is starting movement (from either Endermen or Falling/Physics)
if(mcMMO.getPlaceStore().isTrue(block)) {
mcMMO.getPlaceStore().setFalse(block);
movementSourceEntity.setMetadata(mcMMO.blockMetadataKey, mcMMO.metadataValue);
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityDamageDebugMonitor(EntityDamageEvent event)
{
if(event instanceof FakeEntityDamageByEntityEvent)
return;
if(event instanceof FakeEntityDamageEvent)
return;
if(!(event.getEntity() instanceof LivingEntity))
return;
LivingEntity entity = (LivingEntity) event.getEntity();
double rawDamage = event.getDamage();
double dmgAfterReduction = event.getFinalDamage();
Bukkit.broadcastMessage(ChatColor.GOLD+"DMG After Events: "
+ event.getEntity().getName()+ChatColor.RESET
+"RawDMG["+rawDamage+"], "
+"FinalDMG=["+dmgAfterReduction+"]");
Bukkit.broadcastMessage(
event.getEntity().getName()
+ChatColor.GREEN
+" HP "
+ChatColor.RESET
+entity.getHealth()
+ChatColor.YELLOW
+" -> "
+ChatColor.RESET
+(entity.getHealth()-event.getFinalDamage()));
Bukkit.broadcastMessage("");
}*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityCombustByEntityEvent(EntityCombustByEntityEvent event) {
//Prevent players from setting fire to each other if they are in the same party
@ -284,6 +260,10 @@ public class EntityListener implements Listener {
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
if (event instanceof FakeEntityDamageByEntityEvent) {
return;
}
double damage = event.getFinalDamage();
Entity defender = event.getEntity();
Entity attacker = event.getDamager();
@ -292,35 +272,31 @@ public class EntityListener implements Listener {
{
if(attacker instanceof Player) {
if(!WorldGuardManager.getInstance().hasMainFlag((Player) attacker))
if(!WorldGuardManager.getInstance().hasMainFlag((Player) attacker)) {
return;
}
} else if(attacker instanceof Projectile) {
Projectile projectile = (Projectile) attacker;
if(projectile.getShooter() instanceof Player) {
if(!WorldGuardManager.getInstance().hasMainFlag((Player) projectile.getShooter()))
if(!WorldGuardManager.getInstance().hasMainFlag((Player) projectile.getShooter())) {
return;
}
}
}
}
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
return;
if (event instanceof FakeEntityDamageByEntityEvent) {
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld())) {
return;
}
// Don't process this event for marked entities, for players this is handled above,
// However, for entities, we do not wanna cancel this event to allow plugins to observe changes
// properly
if (defender.getMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY).size() > 0) {
return;
}
if (CombatUtils.isProcessingNoInvulnDamage()) {
return;
@ -344,6 +320,10 @@ public class EntityListener implements Listener {
return;
}
if (CombatUtils.hasIgnoreDamageMetadata(target)) {
return;
}
if (attacker instanceof Tameable) {
AnimalTamer animalTamer = ((Tameable) attacker).getOwner();
@ -422,7 +402,7 @@ public class EntityListener implements Listener {
}
CombatUtils.processCombatAttack(event, attacker, target);
CombatUtils.handleHealthbars(attacker, target, event.getFinalDamage(), plugin);
CombatUtils.handleHealthbars(attacker, target, event.getFinalDamage(), pluginRef);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
@ -490,7 +470,7 @@ public class EntityListener implements Listener {
* Process Registered Interactions
*/
InteractionManager.processEvent(event, plugin, InteractType.ON_ENTITY_DAMAGE);
InteractionManager.processEvent(event, pluginRef, InteractType.ON_ENTITY_DAMAGE);
/*
* Old code
@ -646,29 +626,7 @@ public class EntityListener implements Listener {
*/
@EventHandler(priority = EventPriority.LOWEST)
public void onEntityDeathLowest(EntityDeathEvent event) {
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
return;
LivingEntity entity = event.getEntity();
if (Misc.isNPCEntityExcludingVillagers(entity)) {
return;
}
if (entity.hasMetadata(mcMMO.customNameKey)) {
entity.setCustomName(entity.getMetadata(mcMMO.customNameKey).get(0).asString());
entity.removeMetadata(mcMMO.customNameKey, plugin);
}
if (entity.hasMetadata(mcMMO.customVisibleKey)) {
entity.setCustomNameVisible(entity.getMetadata(mcMMO.customVisibleKey).get(0).asBoolean());
entity.removeMetadata(mcMMO.customVisibleKey, plugin);
}
if (entity.hasMetadata(mcMMO.entityMetadataKey)) {
entity.removeMetadata(mcMMO.entityMetadataKey, plugin);
}
mcMMO.getTransientMetadataTools().cleanAllMobMetadata(event.getEntity());
}
/**
@ -704,33 +662,41 @@ public class EntityListener implements Listener {
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
return;
LivingEntity entity = event.getEntity();
LivingEntity livingEntity = event.getEntity();
switch (event.getSpawnReason()) {
case NETHER_PORTAL:
trackSpawnedAndPassengers(livingEntity, MobMetaFlagType.NETHER_PORTAL_MOB);
break;
case SPAWNER:
case SPAWNER_EGG:
entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
Entity passenger = entity.getPassenger();
if (passenger != null) {
passenger.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
}
return;
trackSpawnedAndPassengers(livingEntity, MobMetaFlagType.MOB_SPAWNER_MOB);
break;
case DISPENSE_EGG:
case EGG:
trackSpawnedAndPassengers(livingEntity, MobMetaFlagType.EGG_MOB);
break;
case BREEDING:
entity.setMetadata(mcMMO.bredMetadataKey, mcMMO.metadataValue);
return;
trackSpawnedAndPassengers(livingEntity, MobMetaFlagType.PLAYER_BRED_MOB);
break;
default:
}
}
private void trackSpawnedAndPassengers(LivingEntity livingEntity, MobMetaFlagType mobMetaFlagType) {
persistentDataLayer.flagMetadata(mobMetaFlagType, livingEntity);
for(Entity passenger : livingEntity.getPassengers()) {
if(passenger != null) {
persistentDataLayer.flagMetadata(mobMetaFlagType, livingEntity);
}
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
public void onEntityBreed(EntityBreedEvent event) {
if(ExperienceConfig.getInstance().isCOTWBreedingPrevented()) {
if(event.getFather().hasMetadata(mcMMO.COTW_TEMPORARY_SUMMON) || event.getMother().hasMetadata(mcMMO.COTW_TEMPORARY_SUMMON)) {
if(persistentDataLayer.hasMobFlag(MobMetaFlagType.COTW_SUMMONED_MOB, event.getFather()) || persistentDataLayer.hasMobFlag(MobMetaFlagType.COTW_SUMMONED_MOB, event.getMother())) {
event.setCancelled(true);
Animals mom = (Animals) event.getMother();
Animals father = (Animals) event.getFather();
@ -745,7 +711,6 @@ public class EntityListener implements Listener {
NotificationManager.sendPlayerInformationChatOnly(player, "Taming.Summon.COTW.BreedingDisallowed");
}
}
}
}
@ -769,7 +734,7 @@ public class EntityListener implements Listener {
// We can make this assumption because we (should) be the only ones
// using this exact metadata
Player player = plugin.getServer().getPlayerExact(entity.getMetadata(mcMMO.tntMetadataKey).get(0).asString());
Player player = pluginRef.getServer().getPlayerExact(entity.getMetadata(mcMMO.tntMetadataKey).get(0).asString());
if (!UserManager.hasPlayerDataKey(player)) {
return;
@ -815,7 +780,7 @@ public class EntityListener implements Listener {
// We can make this assumption because we (should) be the only ones
// using this exact metadata
Player player = plugin.getServer().getPlayerExact(entity.getMetadata(mcMMO.tntMetadataKey).get(0).asString());
Player player = pluginRef.getServer().getPlayerExact(entity.getMetadata(mcMMO.tntMetadataKey).get(0).asString());
if (!UserManager.hasPlayerDataKey(player)) {
return;
@ -983,13 +948,16 @@ public class EntityListener implements Listener {
return;
}
LivingEntity entity = event.getEntity();
LivingEntity livingEntity = event.getEntity();
if (!UserManager.hasPlayerDataKey(player) || Misc.isNPCEntityExcludingVillagers(entity) || entity.hasMetadata(mcMMO.entityMetadataKey)) {
if (!UserManager.hasPlayerDataKey(player)
|| Misc.isNPCEntityExcludingVillagers(livingEntity)
|| persistentDataLayer.hasMobFlag(MobMetaFlagType.EGG_MOB, livingEntity)
|| persistentDataLayer.hasMobFlag(MobMetaFlagType.MOB_SPAWNER_MOB, livingEntity)) {
return;
}
entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
persistentDataLayer.flagMetadata(MobMetaFlagType.PLAYER_TAMED_MOB, livingEntity);
//Profile not loaded
if(UserManager.getPlayer(player) == null)
@ -997,7 +965,7 @@ public class EntityListener implements Listener {
return;
}
UserManager.getPlayer(player).getTamingManager().awardTamingXP(entity);
UserManager.getPlayer(player).getTamingManager().awardTamingXP(livingEntity);
}
/**
@ -1069,15 +1037,4 @@ public class EntityListener implements Listener {
}
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPigZapEvent(PigZapEvent event) {
/* WORLD BLACKLIST CHECK */
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
return;
if (event.getEntity().hasMetadata(mcMMO.entityMetadataKey)) {
event.getPigZombie().setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
}
}
}

View File

@ -81,6 +81,7 @@ public class mcMMO extends JavaPlugin {
private static MaterialMapStore materialMapStore;
private static PlayerLevelUtils playerLevelUtils;
private static SmeltingTracker smeltingTracker;
private static TransientMetadataTools transientMetadataTools;
/* Adventure */
private static BukkitAudiences audiences;
@ -120,11 +121,9 @@ public class mcMMO extends JavaPlugin {
public static final String FISH_HOOK_REF_METAKEY = "mcMMO: Fish Hook Tracker";
public static final String DODGE_TRACKER = "mcMMO: Dodge Tracker";
public static final String CUSTOM_DAMAGE_METAKEY = "mcMMO: Custom Damage";
public static final String COTW_TEMPORARY_SUMMON = "mcMMO: COTW Entity";
public final static String entityMetadataKey = "mcMMO: Spawned Entity";
public final static String travelingBlock = "mcMMO: Traveling Block";
public final static String blockMetadataKey = "mcMMO: Piston Tracking";
public final static String tntMetadataKey = "mcMMO: Tracked TNT";
public final static String funfettiMetadataKey = "mcMMO: Funfetti";
public final static String customNameKey = "mcMMO: Custom Name";
public final static String customVisibleKey = "mcMMO: Name Visibility";
public final static String droppedItemKey = "mcMMO: Tracked Item";
@ -133,12 +132,9 @@ public class mcMMO extends JavaPlugin {
public final static String bowForceKey = "mcMMO: Bow Force";
public final static String arrowDistanceKey = "mcMMO: Arrow Distance";
public final static String BONUS_DROPS_METAKEY = "mcMMO: Double Drops";
//public final static String customDamageKey = "mcMMO: Custom Damage";
public final static String disarmedItemKey = "mcMMO: Disarmed Item";
public final static String playerDataKey = "mcMMO: Player Data";
public final static String greenThumbDataKey = "mcMMO: Green Thumb";
public final static String databaseCommandKey = "mcMMO: Processing Database Command";
public final static String bredMetadataKey = "mcMMO: Bred Animal";
public static FixedMetadataValue metadataValue;
@ -282,6 +278,8 @@ public class mcMMO extends JavaPlugin {
smeltingTracker = new SmeltingTracker();
audiences = BukkitAudiences.create(this);
transientMetadataTools = new TransientMetadataTools(this);
}
public static PlayerLevelUtils getPlayerLevelUtils() {
@ -699,4 +697,8 @@ public class mcMMO extends JavaPlugin {
public static boolean isProjectKorraEnabled() {
return projectKorraEnabled;
}
public static TransientMetadataTools getTransientMetadataTools() {
return transientMetadataTools;
}
}

View File

@ -17,6 +17,7 @@ import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.StringUtils;
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;
@ -485,12 +486,9 @@ public class TamingManager extends SkillManager {
callOfWildEntity.setRemoveWhenFarAway(false);
}
private void applyMetaDataToCOTWEntity(LivingEntity callOfWildEntity) {
//This is used to prevent XP gains for damaging this entity
callOfWildEntity.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
private void applyMetaDataToCOTWEntity(LivingEntity summonedEntity) {
//This helps identify the entity as being summoned by COTW
callOfWildEntity.setMetadata(mcMMO.COTW_TEMPORARY_SUMMON, mcMMO.metadataValue);
mcMMO.getCompatibilityManager().getPersistentDataLayer().flagMetadata(MobMetaFlagType.COTW_SUMMONED_MOB, summonedEntity);
}
/**

View File

@ -0,0 +1,37 @@
package com.gmail.nossr50.util;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotPersistentDataLayer_1_13;
import org.bukkit.entity.LivingEntity;
public class TransientMetadataTools {
private final mcMMO pluginRef;
public TransientMetadataTools(mcMMO pluginRef) {
this.pluginRef = pluginRef;
}
public void cleanAllMobMetadata(LivingEntity livingEntity) {
//Since its not written anywhere, apparently the GC won't touch objects with metadata still present on them
if (livingEntity.hasMetadata(mcMMO.customNameKey)) {
livingEntity.setCustomName(livingEntity.getMetadata(mcMMO.customNameKey).get(0).asString());
livingEntity.removeMetadata(mcMMO.customNameKey, pluginRef);
}
//Involved in changing mob names to hearts
if (livingEntity.hasMetadata(mcMMO.customVisibleKey)) {
livingEntity.setCustomNameVisible(livingEntity.getMetadata(mcMMO.customVisibleKey).get(0).asBoolean());
livingEntity.removeMetadata(mcMMO.customVisibleKey, pluginRef);
}
//Gets assigned to endermen, potentially doesn't get cleared before this point
if(livingEntity.hasMetadata(mcMMO.travelingBlock)) {
livingEntity.removeMetadata(mcMMO.travelingBlock, pluginRef);
}
//1.13.2 uses transient mob flags and needs to be cleaned up
if(mcMMO.getCompatibilityManager().getPersistentDataLayer() instanceof SpigotPersistentDataLayer_1_13) {
mcMMO.getCompatibilityManager().getPersistentDataLayer().removeMobFlags(livingEntity);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -20,6 +20,8 @@ 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;
@ -41,8 +43,13 @@ import java.util.List;
import java.util.Map;
public final class CombatUtils {
private CombatUtils() {}
private static AbstractPersistentDataLayer getPersistentData() {
return mcMMO.getCompatibilityManager().getPersistentDataLayer();
}
//Likely.. because who knows what plugins are throwing around
public static boolean isDamageLikelyFromNormalCombat(DamageCause damageCause) {
switch (damageCause) {
@ -106,6 +113,14 @@ public final class CombatUtils {
applyScaledModifiers(initialDamage, finalDamage, event);
processCombatXP(mcMMOPlayer, target, PrimarySkillType.SWORDS);
printFinalDamageDebug(player, event, mcMMOPlayer);
}
private static void printFinalDamageDebug(Player player, EntityDamageByEntityEvent event, McMMOPlayer mcMMOPlayer) {
if(mcMMOPlayer.isDebugMode()) {
player.sendMessage("Final Damage value after mcMMO modifiers: "+ event.getFinalDamage());
}
}
// public static void strengthDebug(Player player) {
@ -181,6 +196,8 @@ public final class CombatUtils {
applyScaledModifiers(initialDamage, finalDamage, event);
processCombatXP(mcMMOPlayer, target, PrimarySkillType.AXES);
printFinalDamageDebug(player, event, mcMMOPlayer);
}
private static void processUnarmedCombat(LivingEntity target, Player player, EntityDamageByEntityEvent event) {
@ -223,6 +240,8 @@ public final class CombatUtils {
applyScaledModifiers(initialDamage, finalDamage, event);
processCombatXP(mcMMOPlayer, target, PrimarySkillType.UNARMED);
printFinalDamageDebug(player, event, mcMMOPlayer);
}
private static void processTamingCombat(LivingEntity target, Player master, Wolf wolf, EntityDamageByEntityEvent event) {
@ -299,6 +318,8 @@ public final class CombatUtils {
applyScaledModifiers(initialDamage, finalDamage, event);
processCombatXP(mcMMOPlayer, target, PrimarySkillType.ARCHERY, forceMultiplier * distanceMultiplier);
printFinalDamageDebug(player, event, mcMMOPlayer);
}
/**
@ -372,6 +393,7 @@ public final class CombatUtils {
if (PrimarySkillType.SWORDS.getPermissions(player)) {
processSwordCombat(target, player, event);
}
}
else if (ItemUtils.isAxe(heldItem)) {
@ -428,6 +450,7 @@ public final class CombatUtils {
}
}
}
}
/**
@ -547,21 +570,21 @@ public final class CombatUtils {
dealDamage(target, damage, DamageCause.CUSTOM, attacker);
}
/**
* Attempt to damage target for value dmg with reason ENTITY_ATTACK with damager attacker
*
* @param target LivingEntity which to attempt to damage
* @param damage Amount of damage to attempt to do
* @param attacker Player to pass to event as damager
*/
public static void dealDamage(LivingEntity target, double damage, Map<DamageModifier, Double> modifiers, LivingEntity attacker) {
if (target.isDead()) {
return;
}
// Aren't we applying the damage twice????
target.damage(getFakeDamageFinalResult(attacker, target, damage, modifiers));
}
// /**
// * Attempt to damage target for value dmg with reason ENTITY_ATTACK with damager attacker
// *
// * @param target LivingEntity which to attempt to damage
// * @param damage Amount of damage to attempt to do
// * @param attacker Player to pass to event as damager
// */
// public static void dealDamage(LivingEntity target, double damage, Map<DamageModifier, Double> modifiers, LivingEntity attacker) {
// if (target.isDead()) {
// return;
// }
//
// // Aren't we applying the damage twice????
// target.damage(getFakeDamageFinalResult(attacker, target, damage, modifiers));
// }
/**
* Attempt to damage target for value dmg with reason ENTITY_ATTACK with damager attacker
@ -576,8 +599,11 @@ public final class CombatUtils {
return;
}
if(canDamage(attacker, target, cause, damage))
if(canDamage(attacker, target, cause, damage)) {
applyIgnoreDamageMetadata(target);
target.damage(damage);
removeIgnoreDamageMetadata(target);
}
}
private static boolean processingNoInvulnDamage;
@ -596,21 +622,33 @@ public final class CombatUtils {
// cause do have issues around plugin observability. This is not a perfect solution, but it appears to be the best one here
// We also set no damage ticks to 0, to ensure that damage is applied for this case, and reset it back to the original value
// Snapshot current state so we can pop up properly
boolean wasMetaSet = target.getMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY).size() != 0;
boolean wasMetaSet = hasIgnoreDamageMetadata(target);
boolean wasProcessing = processingNoInvulnDamage;
// set markers
processingNoInvulnDamage = true;
target.setMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY, mcMMO.metadataValue);
applyIgnoreDamageMetadata(target);
int noDamageTicks = target.getNoDamageTicks();
target.setNoDamageTicks(0);
target.damage(damage, attacker);
target.setNoDamageTicks(noDamageTicks);
if (!wasMetaSet)
target.removeMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY, mcMMO.p);
removeIgnoreDamageMetadata(target);
if (!wasProcessing)
processingNoInvulnDamage = false;
}
public static void removeIgnoreDamageMetadata(LivingEntity target) {
target.removeMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY, mcMMO.p);
}
public static void applyIgnoreDamageMetadata(LivingEntity target) {
target.setMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY, mcMMO.metadataValue);
}
public static boolean hasIgnoreDamageMetadata(LivingEntity target) {
return target.getMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY).size() != 0;
}
public static void dealNoInvulnerabilityTickDamageRupture(LivingEntity target, double damage, Entity attacker, int toolTier) {
if (target.isDead()) {
return;
@ -767,19 +805,20 @@ public final class CombatUtils {
}
}
if (target.hasMetadata(mcMMO.entityMetadataKey)
//Epic Spawners compatibility
|| target.hasMetadata("ES")) {
if(getPersistentData().hasMobFlag(MobMetaFlagType.COTW_SUMMONED_MOB, target)) {
baseXP = 0;
} else if(getPersistentData().hasMobFlag(MobMetaFlagType.MOB_SPAWNER_MOB, target) || target.hasMetadata("ES")) {
baseXP *= ExperienceConfig.getInstance().getSpawnedMobXpMultiplier();
}
if (target.hasMetadata(mcMMO.bredMetadataKey)) {
} else if(getPersistentData().hasMobFlag(MobMetaFlagType.NETHER_PORTAL_MOB, target)) {
baseXP *= ExperienceConfig.getInstance().getNetherPortalXpMultiplier();
} else if(getPersistentData().hasMobFlag(MobMetaFlagType.EGG_MOB, target)) {
baseXP *= ExperienceConfig.getInstance().getEggXpMultiplier();
} else if (getPersistentData().hasMobFlag(MobMetaFlagType.PLAYER_BRED_MOB, target)) {
baseXP *= ExperienceConfig.getInstance().getBredMobXpMultiplier();
}
xpGainReason = XPGainReason.PVE;
baseXP *= 10;
xpGainReason = XPGainReason.PVE;
}
baseXP *= multiplier;