diff --git a/src/engine/devcmd/cmds/PurgeObjectsCmd.java b/src/engine/devcmd/cmds/PurgeObjectsCmd.java index c0b318c7..74922c07 100644 --- a/src/engine/devcmd/cmds/PurgeObjectsCmd.java +++ b/src/engine/devcmd/cmds/PurgeObjectsCmd.java @@ -59,22 +59,25 @@ public class PurgeObjectsCmd extends AbstractDevCmd { if (npc != null) { - for (Mob mob : npc.siegeMinionMap.keySet()) { + for (Integer minionUUID : npc.minions) { + Mob mob = Mob.getMob(minionUUID); WorldGrid.RemoveWorldObject(mob); WorldGrid.removeObject(mob, pc); - //Mob.getRespawnMap().remove(mob); + if (mob.getParentZone() != null) mob.getParentZone().zoneMobSet.remove(mob); } + DbManager.NPCQueries.DELETE_NPC(npc); DbManager.removeFromCache(GameObjectType.NPC, npc.getObjectUUID()); WorldGrid.RemoveWorldObject(npc); } else if (mobA != null) { - for (Mob mob : mobA.getSiegeMinionMap().keySet()) { + for (Integer minionUUID : mobA.minions) { + Mob mob = Mob.getMob(minionUUID); WorldGrid.RemoveWorldObject(mob); WorldGrid.removeObject(mob, pc); - //Mob.getRespawnMap().remove(mob); + if (mob.getParentZone() != null) mob.getParentZone().zoneMobSet.remove(mob); } @@ -151,10 +154,11 @@ public class PurgeObjectsCmd extends AbstractDevCmd { if (npc != null) { - for (Mob mob : npc.siegeMinionMap.keySet()) { + for (Integer minionUUID : npc.minions) { + Mob mob = Mob.getMob(minionUUID); WorldGrid.RemoveWorldObject(mob); WorldGrid.removeObject(mob, pc); - //Mob.getRespawnMap().remove(mob); + if (mob.getParentZone() != null) mob.getParentZone().zoneMobSet.remove(mob); } @@ -163,10 +167,11 @@ public class PurgeObjectsCmd extends AbstractDevCmd { npc.getObjectUUID()); WorldGrid.RemoveWorldObject(npc); } else if (mobA != null) { - for (Mob mob : mobA.getSiegeMinionMap().keySet()) { + for (Integer minionUUID : mobA.minions) { + Mob mob = Mob.getMob(minionUUID); WorldGrid.RemoveWorldObject(mob); WorldGrid.removeObject(mob, pc); - //Mob.getRespawnMap().remove(mob); + if (mob.getParentZone() != null) mob.getParentZone().zoneMobSet.remove(mob); } diff --git a/src/engine/devcmd/cmds/RemoveObjectCmd.java b/src/engine/devcmd/cmds/RemoveObjectCmd.java index c1ee4f85..3a6a9fa7 100644 --- a/src/engine/devcmd/cmds/RemoveObjectCmd.java +++ b/src/engine/devcmd/cmds/RemoveObjectCmd.java @@ -154,24 +154,29 @@ public class RemoveObjectCmd extends AbstractDevCmd { mobA = (Mob) ac; if (npc != null) { - for (Mob mob : npc.siegeMinionMap.keySet()) { - WorldGrid.RemoveWorldObject(mob); - WorldGrid.removeObject(mob, pc); - //Mob.getRespawnMap().remove(mob); - if (mob.getParentZone() != null) - mob.getParentZone().zoneMobSet.remove(mob); + + for (Integer minionUUID : npc.minions) { + Mob minionMob = Mob.getMob(minionUUID); + WorldGrid.RemoveWorldObject(minionMob); + WorldGrid.removeObject(minionMob, pc); + + if (minionMob.getParentZone() != null) + minionMob.getParentZone().zoneMobSet.remove(minionMob); } + DbManager.NPCQueries.DELETE_NPC(npc); DbManager.removeFromCache(npc); WorldGrid.RemoveWorldObject(npc); WorldGrid.removeObject(npc, pc); } else if (mobA != null) { - for (Mob mob : mobA.getSiegeMinionMap().keySet()) { - WorldGrid.RemoveWorldObject(mob); - WorldGrid.removeObject(mob, pc); - //Mob.getRespawnMap().remove(mob); - if (mob.getParentZone() != null) - mob.getParentZone().zoneMobSet.remove(mob); + + for (Integer minionUUID : mobA.minions) { + Mob minionMob = Mob.getMob(minionUUID); + WorldGrid.RemoveWorldObject(minionMob); + WorldGrid.removeObject(minionMob, pc); + + if (minionMob.getParentZone() != null) + minionMob.getParentZone().zoneMobSet.remove(minionMob); } DbManager.MobQueries.DELETE_MOB(mobA); DbManager.removeFromCache(mobA); @@ -209,11 +214,13 @@ public class RemoveObjectCmd extends AbstractDevCmd { if (npc.building != null) npc.building.getHirelings().remove(npc); - for (Mob mob : npc.siegeMinionMap.keySet()) { - WorldGrid.RemoveWorldObject(mob); - WorldGrid.removeObject(mob, pc); - if (mob.getParentZone() != null) - mob.getParentZone().zoneMobSet.remove(mob); + for (Integer minionUUID : npc.minions) { + Mob minionMob = Mob.getMob(minionUUID); + WorldGrid.RemoveWorldObject(minionMob); + WorldGrid.removeObject(minionMob, pc); + + if (minionMob.getParentZone() != null) + minionMob.getParentZone().zoneMobSet.remove(minionMob); } DbManager.NPCQueries.DELETE_NPC(npc); diff --git a/src/engine/gameManager/NPCManager.java b/src/engine/gameManager/NPCManager.java index 249befe8..f8c61771 100644 --- a/src/engine/gameManager/NPCManager.java +++ b/src/engine/gameManager/NPCManager.java @@ -122,37 +122,39 @@ public enum NPCManager { public static void removeSiegeMinions(Mob mobile) { - for (Mob toRemove : mobile.siegeMinionMap.keySet()) { + for (Integer minionUUID : mobile.minions) { + + Mob siegeMinion = Mob.getMob(minionUUID); if (mobile.isMoving()) { mobile.stopMovement(mobile.getLoc()); - if (toRemove.parentZone != null) - toRemove.parentZone.zoneMobSet.remove(toRemove); + if (siegeMinion.parentZone != null) + siegeMinion.parentZone.zoneMobSet.remove(siegeMinion); } try { - toRemove.clearEffects(); + siegeMinion.clearEffects(); } catch (Exception e) { Logger.error(e.getMessage()); } - if (toRemove.parentZone != null) - toRemove.parentZone.zoneMobSet.remove(toRemove); + if (siegeMinion.parentZone != null) + siegeMinion.parentZone.zoneMobSet.remove(siegeMinion); - WorldGrid.RemoveWorldObject(toRemove); - WorldGrid.removeObject(toRemove); - DbManager.removeFromCache(toRemove); + WorldGrid.RemoveWorldObject(siegeMinion); + WorldGrid.removeObject(siegeMinion); + DbManager.removeFromCache(siegeMinion); - PlayerCharacter petOwner = (PlayerCharacter) toRemove.guardCaptain; + PlayerCharacter petOwner = (PlayerCharacter) siegeMinion.guardCaptain; if (petOwner != null) { petOwner.setPet(null); - toRemove.guardCaptain = null; + siegeMinion.guardCaptain = null; PetMsg petMsg = new PetMsg(5, null); Dispatch dispatch = Dispatch.borrow(petOwner, petMsg); @@ -263,7 +265,7 @@ public enum NPCManager { if (abstractCharacter.getObjectType().equals(Enum.GameObjectType.Mob) && ((Mob) abstractCharacter).behaviourType.equals(Enum.MobBehaviourType.SiegeEngine)) { Mob siegeMobile = (Mob) abstractCharacter; - buildingSlot = siegeMobile.guardCaptain.siegeMinionMap.size() + 2; + buildingSlot = siegeMobile.guardCaptain.minions.size() + 2; } if (buildingSlot == -1) diff --git a/src/engine/mobileAI/MobAI.java b/src/engine/mobileAI/MobAI.java index 5f451173..e4830aea 100644 --- a/src/engine/mobileAI/MobAI.java +++ b/src/engine/mobileAI/MobAI.java @@ -288,18 +288,22 @@ public class MobAI { MovementUtilities.aiMove(mob, mob.destination, true); if (mob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN)) - for (Entry minion : mob.siegeMinionMap.entrySet()) + for (Integer minionUUUD : mob.minions) { + + Mob minion = Mob.getMob(minionUUUD); //make sure mob is out of combat stance - if (minion.getKey().despawned == false) { - if (MovementUtilities.canMove(minion.getKey())) { - Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3); - minion.getKey().updateLocation(); + if (minion.despawned == false) { + if (MovementUtilities.canMove(minion)) { + Vector3f minionOffset = Formation.getOffset(2, mob.minions.indexOf(minionUUUD) + 3); + minion.updateLocation(); Vector3fImmutable formationPatrolPoint = new Vector3fImmutable(mob.destination.x + minionOffset.x, mob.destination.y, mob.destination.z + minionOffset.z); - MovementUtilities.aiMove(minion.getKey(), formationPatrolPoint, true); + MovementUtilities.aiMove(minion, formationPatrolPoint, true); } } + } + } catch (Exception e) { Logger.info(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget" + " " + e.getMessage()); } @@ -987,9 +991,11 @@ public class MobAI { //guard captain pulls his minions home with him - for (Entry minion : mob.siegeMinionMap.entrySet()) { - PowersManager.useMobPower(minion.getKey(), minion.getKey(), recall, 40); - minion.getKey().setCombatTarget(null); + for (Integer minionUUID : mob.minions) { + Mob minion = Mob.getMob(minionUUID); + + PowersManager.useMobPower(minion, minion, recall, 40); + minion.setCombatTarget(null); } } } @@ -1381,16 +1387,18 @@ public class MobAI { MovementUtilities.aiMove(mob, mob.destination, true); if (mob.agentType.equals(Enum.AIAgentType.GUARDCAPTAIN)) { - for (Entry minion : mob.siegeMinionMap.entrySet()) { + for (Integer minionUUID : mob.minions) { + + Mob minion = Mob.getMob(minionUUID); //make sure mob is out of combat stance - if (minion.getKey().despawned == false) { - if (MovementUtilities.canMove(minion.getKey())) { - Vector3f minionOffset = Formation.getOffset(2, minion.getValue() + 3); - minion.getKey().updateLocation(); + if (minion.despawned == false) { + if (MovementUtilities.canMove(minion)) { + Vector3f minionOffset = Formation.getOffset(2, mob.minions.indexOf(minionUUID) + 3); + minion.updateLocation(); Vector3fImmutable formationPatrolPoint = new Vector3fImmutable(mob.destination.x + minionOffset.x, mob.destination.y, mob.destination.z + minionOffset.z); - MovementUtilities.aiMove(minion.getKey(), formationPatrolPoint, true); + MovementUtilities.aiMove(minion, formationPatrolPoint, true); } } } diff --git a/src/engine/net/client/handlers/MinionTrainingMsgHandler.java b/src/engine/net/client/handlers/MinionTrainingMsgHandler.java index 0d24d133..09356688 100644 --- a/src/engine/net/client/handlers/MinionTrainingMsgHandler.java +++ b/src/engine/net/client/handlers/MinionTrainingMsgHandler.java @@ -58,10 +58,10 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler { Mob toRemove = Mob.getFromCache(minionMsg.getUUID()); - if (!npc.siegeMinionMap.containsKey(toRemove)) + if (!npc.minions.contains(toRemove.getObjectUUID())) return true; - npc.siegeMinionMap.remove(toRemove); + npc.minions.remove(toRemove.getObjectUUID()); WorldGrid.RemoveWorldObject(toRemove); @@ -112,7 +112,7 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler { if (npc.getContractID() == 842) maxSlots = 1; - if (npc.siegeMinionMap.size() == maxSlots) + if (npc.minions.size() == maxSlots) return true; int mobBase; @@ -179,13 +179,13 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler { Mob toRemove = Mob.getFromCache(minionMsg.getUUID()); - if (!npc.getSiegeMinionMap().containsKey(toRemove)) + if (!npc.minions.contains(toRemove.getObjectUUID())) return true; if (!DbManager.MobQueries.REMOVE_FROM_GUARDS(npc.getObjectUUID(), toRemove.firstName)) return true; - npc.getSiegeMinionMap().remove(toRemove); + npc.minions.remove(toRemove.getObjectUUID()); WorldGrid.RemoveWorldObject(toRemove); @@ -258,7 +258,7 @@ public class MinionTrainingMsgHandler extends AbstractClientMsgHandler { break; } - if (npc.getSiegeMinionMap().size() == maxSlots) + if (npc.minions.size() == maxSlots) return true; int mobBase = npc.getMobBaseID(); diff --git a/src/engine/net/client/msg/ManageNPCMsg.java b/src/engine/net/client/msg/ManageNPCMsg.java index d21250ea..53797601 100644 --- a/src/engine/net/client/msg/ManageNPCMsg.java +++ b/src/engine/net/client/msg/ManageNPCMsg.java @@ -27,7 +27,6 @@ import org.pmw.tinylog.Logger; import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -343,14 +342,17 @@ public class ManageNPCMsg extends ClientNetMsg { writer.putInt(0); //runemaster list //artillery captain list - ConcurrentHashMap siegeMinions = npc.siegeMinionMap; - writer.putInt(1 + siegeMinions.size()); + + writer.putInt(1 + npc.minions.size()); serializeBulwarkList(writer, 1); //Trebuchet //serializeBulwarkList(writer, 2); //Ballista - if (siegeMinions != null && siegeMinions.size() > 0) + if (npc.minions != null && npc.minions.size() > 0) + + for (Integer minionUUID : npc.minions) { + + Mob mob = Mob.getMob(minionUUID); - for (Mob mob : siegeMinions.keySet()) { this.unknown83 = mob.getObjectUUID(); writer.putInt(2); writer.putInt(mob.getObjectType().ordinal()); @@ -666,14 +668,15 @@ public class ManageNPCMsg extends ClientNetMsg { writer.putInt(0); //runemaster list //artillery captain list - ConcurrentHashMap siegeMinions = mobA.getSiegeMinionMap(); - writer.putInt(siegeMinions.size() + 1); + writer.putInt(mobA.minions.size() + 1); + serializeGuardList(writer, mobA.getContract().getContractID(), mobA); //Guard - if (siegeMinions != null && siegeMinions.size() > 0) + if (mobA.minions != null && mobA.minions.size() > 0) - for (Mob mob : siegeMinions.keySet()) { + for (Integer minionUUID : mobA.minions) { + Mob mob = Mob.getMob(minionUUID); this.unknown83 = mob.getObjectUUID(); writer.putInt(2); writer.putInt(mob.getObjectType().ordinal()); diff --git a/src/engine/objects/AbstractCharacter.java b/src/engine/objects/AbstractCharacter.java index c14dcd58..c4feef6f 100644 --- a/src/engine/objects/AbstractCharacter.java +++ b/src/engine/objects/AbstractCharacter.java @@ -39,6 +39,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.HashSet; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -121,8 +122,7 @@ public abstract class AbstractCharacter extends AbstractWorldObject { private byte aoecntr = 0; public int hidden = 0; // current rank of hide/sneak/invis - - public final ConcurrentHashMap siegeMinionMap = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); + public CopyOnWriteArrayList minions = new CopyOnWriteArrayList(); public AbstractCharacter() { super(); diff --git a/src/engine/objects/Mob.java b/src/engine/objects/Mob.java index 8fc7ee28..d0cfbb4f 100644 --- a/src/engine/objects/Mob.java +++ b/src/engine/objects/Mob.java @@ -26,7 +26,6 @@ import engine.net.Dispatch; import engine.net.DispatchMessage; import engine.net.client.msg.PetMsg; import engine.net.client.msg.PlaceAssetMsg; -import engine.powers.RuneSkillAdjustEntry; import engine.server.MBServerStatics; import org.joda.time.DateTime; import org.pmw.tinylog.Logger; @@ -489,8 +488,7 @@ public class Mob extends AbstractIntelligenceAgent { minionMobile.setLoc(minionMobile.bindLoc); minionMobile.despawn(); - int slot = guardCaptain.siegeMinionMap.size() + 1; - guardCaptain.siegeMinionMap.put(minionMobile, slot); + guardCaptain.minions.add(minionMobile.getObjectUUID()); return minionMobile; } @@ -520,8 +518,7 @@ public class Mob extends AbstractIntelligenceAgent { siegeMinion.setLoc(siegeMinion.bindLoc); siegeMinion.despawn(); - int slot = artyCaptain.siegeMinionMap.size() + 1; - artyCaptain.siegeMinionMap.put(siegeMinion, slot); + artyCaptain.minions.add(siegeMinion.getObjectUUID()); return siegeMinion; } @@ -1783,10 +1780,6 @@ public class Mob extends AbstractIntelligenceAgent { this.weaponPower = weaponPower; } - public ConcurrentHashMap getSiegeMinionMap() { - return siegeMinionMap; - } - public DateTime getUpgradeDateTime() { lock.readLock().lock(); diff --git a/src/engine/objects/NPC.java b/src/engine/objects/NPC.java index 07775e33..88bb5a11 100644 --- a/src/engine/objects/NPC.java +++ b/src/engine/objects/NPC.java @@ -640,28 +640,31 @@ public class NPC extends AbstractCharacter { public void removeMinions() { - for (Mob toRemove : this.siegeMinionMap.keySet()) { + + for (Integer minionUUID : this.minions) { + + Mob minionMob = Mob.getMob(minionUUID); try { - toRemove.clearEffects(); + minionMob.clearEffects(); } catch (Exception e) { Logger.error(e.getMessage()); } - if (toRemove.getParentZone() != null) - toRemove.getParentZone().zoneMobSet.remove(toRemove); + if (minionMob.getParentZone() != null) + minionMob.getParentZone().zoneMobSet.remove(minionMob); - WorldGrid.RemoveWorldObject(toRemove); - DbManager.removeFromCache(toRemove); + WorldGrid.RemoveWorldObject(minionMob); + DbManager.removeFromCache(minionMob); - PlayerCharacter petOwner = (PlayerCharacter) toRemove.guardCaptain; + PlayerCharacter petOwner = (PlayerCharacter) minionMob.guardCaptain; if (petOwner != null) { petOwner.setPet(null); - toRemove.guardCaptain = null; + minionMob.guardCaptain = null; PetMsg petMsg = new PetMsg(5, null); Dispatch dispatch = Dispatch.borrow(petOwner, petMsg); @@ -669,6 +672,7 @@ public class NPC extends AbstractCharacter { } } + } @Override