mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2025-06-09 10:31:25 +02:00
This commit is contained in:
parent
5e9ee1e275
commit
3d16d9432d
@ -1,3 +1,8 @@
|
|||||||
|
Version 2.2.039
|
||||||
|
Added StackOverflow safeguards for abilities dealing damage in mcMMO
|
||||||
|
Improved compatibility with MythicMobs/ModelEngine
|
||||||
|
Improved compatibility with AdvancedEnchantments
|
||||||
|
|
||||||
Version 2.2.038
|
Version 2.2.038
|
||||||
Fix potion match failing for non-english locales
|
Fix potion match failing for non-english locales
|
||||||
FoliaLib Performance improvements (thanks SirSalad)
|
FoliaLib Performance improvements (thanks SirSalad)
|
||||||
|
2
pom.xml
2
pom.xml
@ -2,7 +2,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||||
<artifactId>mcMMO</artifactId>
|
<artifactId>mcMMO</artifactId>
|
||||||
<version>2.2.038</version>
|
<version>2.2.039-SNAPSHOT</version>
|
||||||
<name>mcMMO</name>
|
<name>mcMMO</name>
|
||||||
<url>https://github.com/mcMMO-Dev/mcMMO</url>
|
<url>https://github.com/mcMMO-Dev/mcMMO</url>
|
||||||
<scm>
|
<scm>
|
||||||
|
@ -296,10 +296,6 @@ public class EntityListener implements Listener {
|
|||||||
// However, for entities, we do not wanna cancel this event to allow plugins to observe changes
|
// However, for entities, we do not wanna cancel this event to allow plugins to observe changes
|
||||||
// properly
|
// properly
|
||||||
|
|
||||||
if (CombatUtils.isProcessingNoInvulnDamage()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.getEntity() instanceof ArmorStand) {
|
if (event.getEntity() instanceof ArmorStand) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -572,7 +572,8 @@ public class FishingManager extends SkillManager {
|
|||||||
|
|
||||||
ItemUtils.spawnItem(getPlayer(), target.getLocation(), drop, ItemSpawnReason.FISHING_SHAKE_TREASURE);
|
ItemUtils.spawnItem(getPlayer(), target.getLocation(), drop, ItemSpawnReason.FISHING_SHAKE_TREASURE);
|
||||||
// Make it so you can shake a mob no more than 4 times.
|
// Make it so you can shake a mob no more than 4 times.
|
||||||
CombatUtils.dealDamage(target, Math.min(Math.max(target.getMaxHealth() / 4, 1), 10), getPlayer());
|
double dmg = Math.min(Math.max(target.getMaxHealth() / 4, 1), 10);
|
||||||
|
CombatUtils.safeDealDamage(target, dmg, getPlayer());
|
||||||
applyXpGain(ExperienceConfig.getInstance().getFishingShakeXP(), XPGainReason.PVE);
|
applyXpGain(ExperienceConfig.getInstance().getFishingShakeXP(), XPGainReason.PVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,12 +122,14 @@ public class SwordsManager extends SkillManager {
|
|||||||
*/
|
*/
|
||||||
public void counterAttackChecks(@NotNull LivingEntity attacker, double damage) {
|
public void counterAttackChecks(@NotNull LivingEntity attacker, double damage) {
|
||||||
if (ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.SWORDS_COUNTER_ATTACK, mmoPlayer)) {
|
if (ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.SWORDS_COUNTER_ATTACK, mmoPlayer)) {
|
||||||
CombatUtils.dealDamage(attacker, damage / Swords.counterAttackModifier, getPlayer());
|
CombatUtils.safeDealDamage(attacker, damage / Swords.counterAttackModifier, getPlayer());
|
||||||
|
|
||||||
NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Countered");
|
NotificationManager.sendPlayerInformation(getPlayer(),
|
||||||
|
NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Countered");
|
||||||
|
|
||||||
if (attacker instanceof Player) {
|
if (attacker instanceof Player) {
|
||||||
NotificationManager.sendPlayerInformation((Player)attacker, NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Counter.Hit");
|
NotificationManager.sendPlayerInformation((Player)attacker,
|
||||||
|
NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Counter.Hit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,8 @@ public class WoodcuttingManager extends SkillManager {
|
|||||||
double health = player.getHealth();
|
double health = player.getHealth();
|
||||||
|
|
||||||
if (health > 1) {
|
if (health > 1) {
|
||||||
CombatUtils.dealDamage(player, Misc.getRandom().nextInt((int) (health - 1)));
|
int dmg = Misc.getRandom().nextInt((int) (health - 1));
|
||||||
|
CombatUtils.safeDealDamage(player, dmg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -95,7 +95,8 @@ public final class ChimaeraWing {
|
|||||||
NotificationManager.sendPlayerInformation(player,
|
NotificationManager.sendPlayerInformation(player,
|
||||||
NotificationType.REQUIREMENTS_NOT_MET, "Item.ChimaeraWing.Fail");
|
NotificationType.REQUIREMENTS_NOT_MET, "Item.ChimaeraWing.Fail");
|
||||||
player.setVelocity(new Vector(0, 0.5D, 0));
|
player.setVelocity(new Vector(0, 0.5D, 0));
|
||||||
CombatUtils.dealDamage(player, Misc.getRandom().nextInt((int) (player.getHealth() - 10)));
|
final int dmg = Misc.getRandom().nextInt((int) (player.getHealth() - 10));
|
||||||
|
CombatUtils.safeDealDamage(player, dmg);
|
||||||
mcMMOPlayer.actualizeChimeraWingLastUse();
|
mcMMOPlayer.actualizeChimeraWingLastUse();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,50 @@ import static com.gmail.nossr50.util.skills.ProjectileUtils.isCrossbowProjectile
|
|||||||
|
|
||||||
public final class CombatUtils {
|
public final class CombatUtils {
|
||||||
|
|
||||||
|
private static final ThreadLocal<Boolean> IN_MCMO_DAMAGE
|
||||||
|
= ThreadLocal.withInitial(() -> false);
|
||||||
|
|
||||||
|
|
||||||
|
public static void safeDealDamage(@NotNull LivingEntity target, double amount) {
|
||||||
|
safeDealDamage(target, amount, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely deals damage to a target entity, preventing recursive mcMMO damage calls.
|
||||||
|
*
|
||||||
|
* @param target The {@link LivingEntity} to damage.
|
||||||
|
* @param amount The amount of damage to deal.
|
||||||
|
* @param attacker The {@link Entity} responsible for the damage, or null if none.
|
||||||
|
*/
|
||||||
|
public static void safeDealDamage(@NotNull LivingEntity target, double amount, @Nullable Entity attacker) {
|
||||||
|
boolean prev = IN_MCMO_DAMAGE.get();
|
||||||
|
|
||||||
|
if (prev || target.isDead()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
IN_MCMO_DAMAGE.set(true);
|
||||||
|
if (!hasIgnoreDamageMetadata(target)) {
|
||||||
|
applyIgnoreDamageMetadata(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attacker != null) {
|
||||||
|
target.damage(amount, attacker);
|
||||||
|
} else {
|
||||||
|
target.damage(amount);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
IN_MCMO_DAMAGE.set(false);
|
||||||
|
if (hasIgnoreDamageMetadata(target)) {
|
||||||
|
removeIgnoreDamageMetadata(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CombatUtils() {}
|
private CombatUtils() {}
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true, since = "2.2.039")
|
||||||
public static boolean isDamageLikelyFromNormalCombat(@NotNull DamageCause damageCause) {
|
public static boolean isDamageLikelyFromNormalCombat(@NotNull DamageCause damageCause) {
|
||||||
return switch (damageCause) {
|
return switch (damageCause) {
|
||||||
case ENTITY_ATTACK, ENTITY_SWEEP_ATTACK, PROJECTILE -> true;
|
case ENTITY_ATTACK, ENTITY_SWEEP_ATTACK, PROJECTILE -> true;
|
||||||
@ -52,6 +94,7 @@ public final class CombatUtils {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true, since = "2.2.039")
|
||||||
public static boolean hasWeakenedDamage(@NotNull LivingEntity livingEntity) {
|
public static boolean hasWeakenedDamage(@NotNull LivingEntity livingEntity) {
|
||||||
return livingEntity.hasPotionEffect(PotionEffectType.WEAKNESS);
|
return livingEntity.hasPotionEffect(PotionEffectType.WEAKNESS);
|
||||||
}
|
}
|
||||||
@ -150,7 +193,10 @@ public final class CombatUtils {
|
|||||||
printFinalDamageDebug(player, event, mcMMOPlayer);
|
printFinalDamageDebug(player, event, mcMMOPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processTridentCombatRanged(@NotNull Trident trident, @NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
|
private static void processTridentCombatRanged(@NotNull Trident trident,
|
||||||
|
@NotNull LivingEntity target,
|
||||||
|
@NotNull Player player,
|
||||||
|
@NotNull EntityDamageByEntityEvent event) {
|
||||||
if (event.getCause() == DamageCause.THORNS) {
|
if (event.getCause() == DamageCause.THORNS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -620,7 +666,8 @@ public final class CombatUtils {
|
|||||||
* @param subSkillType the specific limit break skill for calculations
|
* @param subSkillType the specific limit break skill for calculations
|
||||||
* @return the RAW damage bonus from Limit Break which is applied before reductions
|
* @return the RAW damage bonus from Limit Break which is applied before reductions
|
||||||
*/
|
*/
|
||||||
public static int getLimitBreakDamage(@NotNull Player attacker, @NotNull LivingEntity defender, @NotNull SubSkillType subSkillType) {
|
public static int getLimitBreakDamage(@NotNull Player attacker, @NotNull LivingEntity defender,
|
||||||
|
@NotNull SubSkillType subSkillType) {
|
||||||
if (defender instanceof Player playerDefender) {
|
if (defender instanceof Player playerDefender) {
|
||||||
return getLimitBreakDamageAgainstQuality(attacker, subSkillType, getArmorQualityLevel(playerDefender));
|
return getLimitBreakDamageAgainstQuality(attacker, subSkillType, getArmorQualityLevel(playerDefender));
|
||||||
} else {
|
} else {
|
||||||
@ -636,18 +683,20 @@ public final class CombatUtils {
|
|||||||
* @param armorQualityLevel Armor quality level
|
* @param armorQualityLevel Armor quality level
|
||||||
* @return the RAW damage boost after its been mutated by armor quality
|
* @return the RAW damage boost after its been mutated by armor quality
|
||||||
*/
|
*/
|
||||||
public static int getLimitBreakDamageAgainstQuality(@NotNull Player attacker, @NotNull SubSkillType subSkillType, int armorQualityLevel) {
|
public static int getLimitBreakDamageAgainstQuality(@NotNull Player attacker,
|
||||||
int rawDamageBoost = RankUtils.getRank(attacker, subSkillType);
|
@NotNull SubSkillType subSkillType,
|
||||||
|
int armorQualityLevel) {
|
||||||
|
float rawDamageBoost = RankUtils.getRank(attacker, subSkillType);
|
||||||
|
|
||||||
if (armorQualityLevel <= 4) {
|
if (armorQualityLevel <= 4) {
|
||||||
rawDamageBoost *= .25; //75% Nerf
|
rawDamageBoost *= .25F; //75% Nerf
|
||||||
} else if (armorQualityLevel <= 8) {
|
} else if (armorQualityLevel <= 8) {
|
||||||
rawDamageBoost *= .50; //50% Nerf
|
rawDamageBoost *= .50F; //50% Nerf
|
||||||
} else if (armorQualityLevel <= 12) {
|
} else if (armorQualityLevel <= 12) {
|
||||||
rawDamageBoost *= .75; //25% Nerf
|
rawDamageBoost *= .75F; //25% Nerf
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawDamageBoost;
|
return (int) rawDamageBoost;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -695,9 +744,11 @@ public final class CombatUtils {
|
|||||||
*
|
*
|
||||||
* @param target LivingEntity which to attempt to damage
|
* @param target LivingEntity which to attempt to damage
|
||||||
* @param damage Amount of damage to attempt to do
|
* @param damage Amount of damage to attempt to do
|
||||||
|
* @deprecated use {@link #safeDealDamage(LivingEntity, double, Entity)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "2.2.039")
|
||||||
public static void dealDamage(@NotNull LivingEntity target, double damage) {
|
public static void dealDamage(@NotNull LivingEntity target, double damage) {
|
||||||
dealDamage(target, damage, null);
|
safeDealDamage(target, damage, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -706,53 +757,11 @@ public final class CombatUtils {
|
|||||||
* @param target the entity to attempt to damage
|
* @param target the entity to attempt to damage
|
||||||
* @param damage Amount of damage to attempt to do
|
* @param damage Amount of damage to attempt to do
|
||||||
* @param attacker the responsible entity (nullable)
|
* @param attacker the responsible entity (nullable)
|
||||||
|
* @deprecated use {@link #safeDealDamage(LivingEntity, double, Entity)} instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "2.2.039")
|
||||||
public static void dealDamage(@NotNull LivingEntity target, double damage, @Nullable Entity attacker) {
|
public static void dealDamage(@NotNull LivingEntity target, double damage, @Nullable Entity attacker) {
|
||||||
if (target.isDead()) {
|
safeDealDamage(target, damage, attacker);
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// TODO: Check for Spigot API for DamageSource, if DamageSource is found then send out a damage() with a custom damage source
|
|
||||||
applyIgnoreDamageMetadata(target);
|
|
||||||
if (attacker != null) {
|
|
||||||
target.damage(damage, attacker);
|
|
||||||
} else {
|
|
||||||
target.damage(damage);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
removeIgnoreDamageMetadata(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean processingNoInvulnDamage;
|
|
||||||
public static boolean isProcessingNoInvulnDamage() {
|
|
||||||
return processingNoInvulnDamage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void dealNoInvulnerabilityTickDamage(@NotNull LivingEntity target, double damage, @Nullable Entity attacker) {
|
|
||||||
if (target.isDead()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This is horrible, but there is no cleaner way to do this without potentially breaking existing code right now
|
|
||||||
// calling damage here is a double edged sword: On one hand, without a call, plugins won't see this properly when the entity dies,
|
|
||||||
// potentially mis-attributing the death cause; calling a fake event would partially fix this, but this and setting the last damage
|
|
||||||
// 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 = hasIgnoreDamageMetadata(target);
|
|
||||||
boolean wasProcessing = processingNoInvulnDamage;
|
|
||||||
// set markers
|
|
||||||
processingNoInvulnDamage = true;
|
|
||||||
applyIgnoreDamageMetadata(target);
|
|
||||||
int noDamageTicks = target.getNoDamageTicks();
|
|
||||||
target.setNoDamageTicks(0);
|
|
||||||
target.damage(damage, attacker);
|
|
||||||
target.setNoDamageTicks(noDamageTicks);
|
|
||||||
if (!wasMetaSet)
|
|
||||||
removeIgnoreDamageMetadata(target);
|
|
||||||
if (!wasProcessing)
|
|
||||||
processingNoInvulnDamage = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeIgnoreDamageMetadata(@NotNull LivingEntity target) {
|
public static void removeIgnoreDamageMetadata(@NotNull LivingEntity target) {
|
||||||
@ -767,14 +776,6 @@ public final class CombatUtils {
|
|||||||
return target.hasMetadata(MetadataConstants.METADATA_KEY_CUSTOM_DAMAGE);
|
return target.hasMetadata(MetadataConstants.METADATA_KEY_CUSTOM_DAMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dealNoInvulnerabilityTickDamageRupture(@NotNull LivingEntity target, double damage, Entity attacker, int toolTier) {
|
|
||||||
if (target.isDead()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dealNoInvulnerabilityTickDamage(target, damage, attacker);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply Area-of-Effect ability actions.
|
* Apply Area-of-Effect ability actions.
|
||||||
* @param attacker The attacking player
|
* @param attacker The attacking player
|
||||||
@ -826,7 +827,7 @@ public final class CombatUtils {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dealDamage(livingEntity, damageAmount, attacker);
|
safeDealDamage(livingEntity, damageAmount, attacker);
|
||||||
numberOfTargets--;
|
numberOfTargets--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -860,7 +861,8 @@ public final class CombatUtils {
|
|||||||
if (target instanceof Player defender) {
|
if (target instanceof Player defender) {
|
||||||
if (!ExperienceConfig.getInstance().getExperienceGainsPlayerVersusPlayerEnabled()
|
if (!ExperienceConfig.getInstance().getExperienceGainsPlayerVersusPlayerEnabled()
|
||||||
||
|
||
|
||||||
(mcMMO.p.getPartyConfig().isPartyEnabled() && mcMMO.p.getPartyManager().inSameParty(mcMMOPlayer.getPlayer(), (Player) target))) {
|
(mcMMO.p.getPartyConfig().isPartyEnabled()
|
||||||
|
&& mcMMO.p.getPartyManager().inSameParty(mcMMOPlayer.getPlayer(), (Player) target))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1041,6 +1043,7 @@ public final class CombatUtils {
|
|||||||
MobHealthbarUtils.handleMobHealthbars(target, damage, plugin);
|
MobHealthbarUtils.handleMobHealthbars(target, damage, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true, since = "2.2.039")
|
||||||
public static void modifyMoveSpeed(@NotNull LivingEntity livingEntity, double multiplier) {
|
public static void modifyMoveSpeed(@NotNull LivingEntity livingEntity, double multiplier) {
|
||||||
AttributeInstance attributeInstance = livingEntity.getAttribute(MAPPED_MOVEMENT_SPEED);
|
AttributeInstance attributeInstance = livingEntity.getAttribute(MAPPED_MOVEMENT_SPEED);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user