mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-25 22:56:45 +01:00
Fixing Rupture (Bleed) ConcurrentModificationException
Removed the internal limit on ticks for Rupture Rupture no longer adds new ticks when applying bleed to an existing target, it instead refreshes the duration
This commit is contained in:
parent
a421bd7e4c
commit
c22a1a0dd2
@ -37,8 +37,10 @@ Version 2.1.0
|
|||||||
+ (MySQL) Added support for SSL for MySQL/MariaDB (On by default)
|
+ (MySQL) Added support for SSL for MySQL/MariaDB (On by default)
|
||||||
! (Skills) Taming's Gore now uses Rupture Rank 1 for its DoT calculations
|
! (Skills) Taming's Gore now uses Rupture Rank 1 for its DoT calculations
|
||||||
! (Skills) Sword's Bleed has been renamed to Rupture
|
! (Skills) Sword's Bleed has been renamed to Rupture
|
||||||
|
! (Skills) Sword's Rupture no longer has an internal hard coded limit
|
||||||
! (Skills) Sword's Serrated Strikes now uses your Rupture rank to determine the damage/ticks for its bleed effect.
|
! (Skills) Sword's Serrated Strikes now uses your Rupture rank to determine the damage/ticks for its bleed effect.
|
||||||
! (Skills) Sword's Rupture now ticks four times as fast
|
! (Skills) Sword's Rupture now ticks four times as fast
|
||||||
|
! (Skills) Sword's Rupture now refreshes bleed duration instead of adding duration when applying bleed to the same target
|
||||||
! (Skills) Sword's Rupture will now deal lethal damage
|
! (Skills) Sword's Rupture will now deal lethal damage
|
||||||
= (Skills) Fixed a bug where Rupture would apply an incorrect amount of bleed ticks
|
= (Skills) Fixed a bug where Rupture would apply an incorrect amount of bleed ticks
|
||||||
! (Skills) Sword's Rupture now reaches its max proc chance at level 20 (200 in Retro)
|
! (Skills) Sword's Rupture now reaches its max proc chance at level 20 (200 in Retro)
|
||||||
|
@ -527,7 +527,6 @@ public class EntityListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BleedTimerTask.remove(entity);
|
|
||||||
Archery.arrowRetrievalCheck(entity);
|
Archery.arrowRetrievalCheck(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.gmail.nossr50.runnables.skills;
|
||||||
|
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
|
||||||
|
public class BleedContainer {
|
||||||
|
public int bleedTicks;
|
||||||
|
public int bleedRank;
|
||||||
|
public LivingEntity target;
|
||||||
|
public LivingEntity damageSource;
|
||||||
|
|
||||||
|
public BleedContainer(LivingEntity target, int bleedTicks, int bleedRank, LivingEntity damageSource)
|
||||||
|
{
|
||||||
|
this.target = target;
|
||||||
|
this.bleedTicks = bleedTicks;
|
||||||
|
this.bleedRank = bleedRank;
|
||||||
|
this.damageSource = damageSource;
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,10 @@
|
|||||||
package com.gmail.nossr50.runnables.skills;
|
package com.gmail.nossr50.runnables.skills;
|
||||||
|
|
||||||
import com.gmail.nossr50.config.AdvancedConfig;
|
import com.gmail.nossr50.config.AdvancedConfig;
|
||||||
|
import com.gmail.nossr50.datatypes.interactions.NotificationType;
|
||||||
import com.gmail.nossr50.mcMMO;
|
import com.gmail.nossr50.mcMMO;
|
||||||
import com.gmail.nossr50.util.MobHealthbarUtils;
|
import com.gmail.nossr50.util.MobHealthbarUtils;
|
||||||
|
import com.gmail.nossr50.util.player.NotificationManager;
|
||||||
import com.gmail.nossr50.util.skills.CombatUtils;
|
import com.gmail.nossr50.util.skills.CombatUtils;
|
||||||
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
|
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
|
||||||
import com.gmail.nossr50.util.sounds.SoundManager;
|
import com.gmail.nossr50.util.sounds.SoundManager;
|
||||||
@ -11,29 +13,26 @@ import org.bukkit.entity.LivingEntity;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class BleedTimerTask extends BukkitRunnable {
|
public class BleedTimerTask extends BukkitRunnable {
|
||||||
private final static int MAX_BLEED_TICKS = 100; //The cap has been raised :)
|
private static Map<LivingEntity, BleedContainer> bleedList = new HashMap<LivingEntity, BleedContainer>();
|
||||||
private static Map<LivingEntity, Integer> bleedList = new HashMap<LivingEntity, Integer>();
|
|
||||||
private static Map<LivingEntity, Integer> bleedDamage = new HashMap<LivingEntity, Integer>();
|
|
||||||
private static Map<LivingEntity, LivingEntity> attackerMap = new HashMap<>();
|
|
||||||
private static ArrayList<LivingEntity> cleanupList = new ArrayList<>();
|
|
||||||
private static ArrayList<LivingEntity> lowerList = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
synchronized public void run() {
|
||||||
lowerBleedTicks(); //Lower bleed ticks
|
Iterator<Entry<LivingEntity, BleedContainer>> bleedIterator = bleedList.entrySet().iterator();
|
||||||
cleanEntities(); //Remove unwanted entities
|
|
||||||
|
|
||||||
for(LivingEntity target : bleedList.keySet())
|
while (bleedIterator.hasNext()) {
|
||||||
{
|
Entry<LivingEntity, BleedContainer> containerEntry = bleedIterator.next();
|
||||||
//mcMMO.p.getServer().broadcastMessage("Entity "+target.getName()+" has "+bleedList.get(target)+" ticks of bleed left");
|
LivingEntity target = containerEntry.getKey();
|
||||||
|
|
||||||
if (bleedList.get(target) <= 0 || !target.isValid()) {
|
int bleedTicks = containerEntry.getValue().bleedTicks;
|
||||||
cleanupList.add(target);
|
|
||||||
|
if (containerEntry.getValue().bleedTicks <= 0 || !target.isValid()) {
|
||||||
|
bleedIterator.remove();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,59 +42,49 @@ public class BleedTimerTask extends BukkitRunnable {
|
|||||||
damage = AdvancedConfig.getInstance().getRuptureDamagePlayer();
|
damage = AdvancedConfig.getInstance().getRuptureDamagePlayer();
|
||||||
|
|
||||||
//Above Bleed Rank 3 deals 50% more damage
|
//Above Bleed Rank 3 deals 50% more damage
|
||||||
if(bleedDamage.get(target) >= 3)
|
if (containerEntry.getValue().bleedRank >= 3)
|
||||||
damage = damage * 1.5;
|
damage = damage * 1.5;
|
||||||
|
|
||||||
Player player = (Player) target;
|
Player player = (Player) target;
|
||||||
|
|
||||||
if (!player.isOnline()) {
|
if (!player.isOnline()) {
|
||||||
cleanupList.add(target);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (bleedList.get(target) <= 0) {
|
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Bleeding.Stopped");
|
||||||
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Bleeding.Stopped");
|
} else {
|
||||||
}*/
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
damage = AdvancedConfig.getInstance().getRuptureDamageMobs();
|
damage = AdvancedConfig.getInstance().getRuptureDamageMobs();
|
||||||
|
|
||||||
|
//Above Bleed Rank 3 deals 50% more damage
|
||||||
|
if (containerEntry.getValue().bleedRank >= 3)
|
||||||
|
damage = damage * 1.5;
|
||||||
|
|
||||||
|
|
||||||
MobHealthbarUtils.handleMobHealthbars(target, damage, mcMMO.p); //Update health bars
|
MobHealthbarUtils.handleMobHealthbars(target, damage, mcMMO.p); //Update health bars
|
||||||
}
|
}
|
||||||
|
|
||||||
CombatUtils.dealNoInvulnerabilityTickDamage(target, damage, attackerMap.get(target));
|
CombatUtils.dealNoInvulnerabilityTickDamage(target, damage, containerEntry.getValue().damageSource);
|
||||||
//Play Bleed Sound
|
//Play Bleed Sound
|
||||||
SoundManager.worldSendSound(target.getWorld(), target.getLocation(), SoundType.BLEED);
|
SoundManager.worldSendSound(target.getWorld(), target.getLocation(), SoundType.BLEED);
|
||||||
|
|
||||||
ParticleEffectUtils.playBleedEffect(target);
|
ParticleEffectUtils.playBleedEffect(target);
|
||||||
lowerBleedDurationTicks(target);
|
|
||||||
|
//Lower Bleed Ticks
|
||||||
|
BleedContainer loweredBleedContainer = copyContainer(containerEntry.getValue());
|
||||||
|
loweredBleedContainer.bleedTicks -= 1;
|
||||||
|
containerEntry.setValue(loweredBleedContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lowerBleedTicks() {
|
public static BleedContainer copyContainer(BleedContainer container)
|
||||||
for(LivingEntity lower : lowerList)
|
{
|
||||||
{
|
LivingEntity target = container.target;
|
||||||
if(bleedList.containsKey(lower))
|
LivingEntity source = container.damageSource;
|
||||||
bleedList.put(lower, bleedList.get(lower) - 1);
|
int bleedTicks = container.bleedTicks;
|
||||||
}
|
int bleedRank = container.bleedRank;
|
||||||
|
|
||||||
lowerList.clear();
|
BleedContainer newContainer = new BleedContainer(target, bleedTicks, bleedRank, source);
|
||||||
}
|
return newContainer;
|
||||||
|
|
||||||
private void cleanEntities() {
|
|
||||||
for(LivingEntity cleanTarget : cleanupList)
|
|
||||||
{
|
|
||||||
if(bleedList.containsKey(cleanTarget))
|
|
||||||
{
|
|
||||||
remove(cleanTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanupList.clear(); //Reset List
|
|
||||||
}
|
|
||||||
|
|
||||||
private void lowerBleedDurationTicks(LivingEntity target) {
|
|
||||||
if(bleedList.get(target) != null)
|
|
||||||
lowerList.add(target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,24 +93,12 @@ public class BleedTimerTask extends BukkitRunnable {
|
|||||||
* @param entity LivingEntity to bleed out
|
* @param entity LivingEntity to bleed out
|
||||||
*/
|
*/
|
||||||
public static void bleedOut(LivingEntity entity) {
|
public static void bleedOut(LivingEntity entity) {
|
||||||
if (bleedList.containsKey(entity)) {
|
/*
|
||||||
CombatUtils.dealNoInvulnerabilityTickDamage(entity, bleedList.get(entity) * 2, attackerMap.get(entity));
|
* Don't remove anything from the list outside of run()
|
||||||
bleedList.remove(entity);
|
*/
|
||||||
bleedDamage.remove(entity);
|
|
||||||
attackerMap.remove(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a LivingEntity from the bleedList if it is in it
|
|
||||||
*
|
|
||||||
* @param entity LivingEntity to remove
|
|
||||||
*/
|
|
||||||
public static void remove(LivingEntity entity) {
|
|
||||||
if (bleedList.containsKey(entity)) {
|
if (bleedList.containsKey(entity)) {
|
||||||
bleedList.remove(entity);
|
CombatUtils.dealNoInvulnerabilityTickDamage(entity, bleedList.get(entity).bleedTicks * 2, bleedList.get(entity).damageSource);
|
||||||
bleedDamage.remove(entity);
|
|
||||||
attackerMap.remove(entity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,22 +108,9 @@ public class BleedTimerTask extends BukkitRunnable {
|
|||||||
* @param entity LivingEntity to add
|
* @param entity LivingEntity to add
|
||||||
* @param ticks Number of bleeding ticks
|
* @param ticks Number of bleeding ticks
|
||||||
*/
|
*/
|
||||||
public static void add(LivingEntity entity, LivingEntity attacker, int ticks, int bleedRank) {
|
public synchronized static void add(LivingEntity entity, LivingEntity attacker, int ticks, int bleedRank) {
|
||||||
int newTicks = ticks;
|
BleedContainer newBleedContainer = new BleedContainer(entity, ticks, bleedRank, attacker);
|
||||||
|
bleedList.put(entity, newBleedContainer);
|
||||||
if (bleedList.containsKey(entity)) {
|
|
||||||
newTicks += bleedList.get(entity);
|
|
||||||
bleedList.put(entity, Math.min(MAX_BLEED_TICKS, newTicks));
|
|
||||||
|
|
||||||
//Override the current bleed rank only if this one is higher
|
|
||||||
if(bleedDamage.get(entity) < bleedRank)
|
|
||||||
bleedDamage.put(entity, bleedRank);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bleedList.put(entity, Math.min(MAX_BLEED_TICKS, newTicks));
|
|
||||||
bleedDamage.put(entity, bleedRank);
|
|
||||||
attackerMap.put(entity, attacker);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isBleeding(LivingEntity entity) {
|
public static boolean isBleeding(LivingEntity entity) {
|
||||||
|
Loading…
Reference in New Issue
Block a user