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)
|
||||
! (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 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 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) 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)
|
||||
|
@ -527,7 +527,6 @@ public class EntityListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
BleedTimerTask.remove(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;
|
||||
|
||||
import com.gmail.nossr50.config.AdvancedConfig;
|
||||
import com.gmail.nossr50.datatypes.interactions.NotificationType;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
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.ParticleEffectUtils;
|
||||
import com.gmail.nossr50.util.sounds.SoundManager;
|
||||
@ -11,29 +13,26 @@ import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class BleedTimerTask extends BukkitRunnable {
|
||||
private final static int MAX_BLEED_TICKS = 100; //The cap has been raised :)
|
||||
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<>();
|
||||
private static Map<LivingEntity, BleedContainer> bleedList = new HashMap<LivingEntity, BleedContainer>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
lowerBleedTicks(); //Lower bleed ticks
|
||||
cleanEntities(); //Remove unwanted entities
|
||||
synchronized public void run() {
|
||||
Iterator<Entry<LivingEntity, BleedContainer>> bleedIterator = bleedList.entrySet().iterator();
|
||||
|
||||
for(LivingEntity target : bleedList.keySet())
|
||||
{
|
||||
//mcMMO.p.getServer().broadcastMessage("Entity "+target.getName()+" has "+bleedList.get(target)+" ticks of bleed left");
|
||||
while (bleedIterator.hasNext()) {
|
||||
Entry<LivingEntity, BleedContainer> containerEntry = bleedIterator.next();
|
||||
LivingEntity target = containerEntry.getKey();
|
||||
|
||||
if (bleedList.get(target) <= 0 || !target.isValid()) {
|
||||
cleanupList.add(target);
|
||||
int bleedTicks = containerEntry.getValue().bleedTicks;
|
||||
|
||||
if (containerEntry.getValue().bleedTicks <= 0 || !target.isValid()) {
|
||||
bleedIterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -43,59 +42,49 @@ public class BleedTimerTask extends BukkitRunnable {
|
||||
damage = AdvancedConfig.getInstance().getRuptureDamagePlayer();
|
||||
|
||||
//Above Bleed Rank 3 deals 50% more damage
|
||||
if(bleedDamage.get(target) >= 3)
|
||||
if (containerEntry.getValue().bleedRank >= 3)
|
||||
damage = damage * 1.5;
|
||||
|
||||
Player player = (Player) target;
|
||||
|
||||
if (!player.isOnline()) {
|
||||
cleanupList.add(target);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*if (bleedList.get(target) <= 0) {
|
||||
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Bleeding.Stopped");
|
||||
}*/
|
||||
}
|
||||
else {
|
||||
NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.Bleeding.Stopped");
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
||||
CombatUtils.dealNoInvulnerabilityTickDamage(target, damage, attackerMap.get(target));
|
||||
CombatUtils.dealNoInvulnerabilityTickDamage(target, damage, containerEntry.getValue().damageSource);
|
||||
//Play Bleed Sound
|
||||
SoundManager.worldSendSound(target.getWorld(), target.getLocation(), SoundType.BLEED);
|
||||
|
||||
ParticleEffectUtils.playBleedEffect(target);
|
||||
lowerBleedDurationTicks(target);
|
||||
|
||||
//Lower Bleed Ticks
|
||||
BleedContainer loweredBleedContainer = copyContainer(containerEntry.getValue());
|
||||
loweredBleedContainer.bleedTicks -= 1;
|
||||
containerEntry.setValue(loweredBleedContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private void lowerBleedTicks() {
|
||||
for(LivingEntity lower : lowerList)
|
||||
{
|
||||
if(bleedList.containsKey(lower))
|
||||
bleedList.put(lower, bleedList.get(lower) - 1);
|
||||
}
|
||||
public static BleedContainer copyContainer(BleedContainer container)
|
||||
{
|
||||
LivingEntity target = container.target;
|
||||
LivingEntity source = container.damageSource;
|
||||
int bleedTicks = container.bleedTicks;
|
||||
int bleedRank = container.bleedRank;
|
||||
|
||||
lowerList.clear();
|
||||
}
|
||||
|
||||
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);
|
||||
BleedContainer newContainer = new BleedContainer(target, bleedTicks, bleedRank, source);
|
||||
return newContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,24 +93,12 @@ public class BleedTimerTask extends BukkitRunnable {
|
||||
* @param entity LivingEntity to bleed out
|
||||
*/
|
||||
public static void bleedOut(LivingEntity entity) {
|
||||
if (bleedList.containsKey(entity)) {
|
||||
CombatUtils.dealNoInvulnerabilityTickDamage(entity, bleedList.get(entity) * 2, attackerMap.get(entity));
|
||||
bleedList.remove(entity);
|
||||
bleedDamage.remove(entity);
|
||||
attackerMap.remove(entity);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Don't remove anything from the list outside of run()
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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)) {
|
||||
bleedList.remove(entity);
|
||||
bleedDamage.remove(entity);
|
||||
attackerMap.remove(entity);
|
||||
CombatUtils.dealNoInvulnerabilityTickDamage(entity, bleedList.get(entity).bleedTicks * 2, bleedList.get(entity).damageSource);
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,22 +108,9 @@ public class BleedTimerTask extends BukkitRunnable {
|
||||
* @param entity LivingEntity to add
|
||||
* @param ticks Number of bleeding ticks
|
||||
*/
|
||||
public static void add(LivingEntity entity, LivingEntity attacker, int ticks, int bleedRank) {
|
||||
int newTicks = ticks;
|
||||
|
||||
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 synchronized static void add(LivingEntity entity, LivingEntity attacker, int ticks, int bleedRank) {
|
||||
BleedContainer newBleedContainer = new BleedContainer(entity, ticks, bleedRank, attacker);
|
||||
bleedList.put(entity, newBleedContainer);
|
||||
}
|
||||
|
||||
public static boolean isBleeding(LivingEntity entity) {
|
||||
|
Loading…
Reference in New Issue
Block a user