diff --git a/src/engine/devcmd/cmds/InfoCmd.java b/src/engine/devcmd/cmds/InfoCmd.java index c023bec6..c8523d6f 100644 --- a/src/engine/devcmd/cmds/InfoCmd.java +++ b/src/engine/devcmd/cmds/InfoCmd.java @@ -225,11 +225,11 @@ public class InfoCmd extends AbstractDevCmd { output += newline; output += "Hirelings List: name / slot / floor"; - for (AbstractCharacter npc : targetBuilding.hirelings.keySet()) { + for (AbstractCharacter npc : targetBuilding.hirelings) { if (npc.getObjectType() != GameObjectType.NPC) continue; - output += newline + npc.getName() + " slot " + targetBuilding.hirelings.get(npc); + output += newline + npc.getName() + " slot " + targetBuilding.hirelings.indexOf(npc) + 1; output += newline + "location " + npc.getLoc(); } } diff --git a/src/engine/devcmd/cmds/PurgeObjectsCmd.java b/src/engine/devcmd/cmds/PurgeObjectsCmd.java index 53077bf0..418e2cd8 100644 --- a/src/engine/devcmd/cmds/PurgeObjectsCmd.java +++ b/src/engine/devcmd/cmds/PurgeObjectsCmd.java @@ -48,7 +48,7 @@ public class PurgeObjectsCmd extends AbstractDevCmd { for (Building building : zone.zoneBuildingSet) { if (!BuildingManager.IsWallPiece(building)) continue; - for (AbstractCharacter ac : building.hirelings.keySet()) { + for (AbstractCharacter ac : building.hirelings) { NPC npc = null; Mob mobA = null; @@ -143,7 +143,7 @@ public class PurgeObjectsCmd extends AbstractDevCmd { if ((building.getBlueprint() != null) && (building.getBlueprint().getBuildingGroup() == BuildingGroup.SPIRE)) building.disableSpire(false); - for (AbstractCharacter ac : building.hirelings.keySet()) { + for (AbstractCharacter ac : building.hirelings) { NPC npc = null; Mob mobA = null; diff --git a/src/engine/devcmd/cmds/RemoveObjectCmd.java b/src/engine/devcmd/cmds/RemoveObjectCmd.java index 6f54a0b9..eb7fbb84 100644 --- a/src/engine/devcmd/cmds/RemoveObjectCmd.java +++ b/src/engine/devcmd/cmds/RemoveObjectCmd.java @@ -144,7 +144,7 @@ public class RemoveObjectCmd extends AbstractDevCmd { // Remove hirelings for this building - for (AbstractCharacter abstractCharacter : building.hirelings.keySet()) + for (AbstractCharacter abstractCharacter : building.hirelings) BuildingManager.removeHireling(building, abstractCharacter); Zone zone = building.getParentZone(); diff --git a/src/engine/devcmd/cmds/SlotTestCmd.java b/src/engine/devcmd/cmds/SlotTestCmd.java index 347d603c..23fc695a 100644 --- a/src/engine/devcmd/cmds/SlotTestCmd.java +++ b/src/engine/devcmd/cmds/SlotTestCmd.java @@ -70,8 +70,8 @@ public class SlotTestCmd extends AbstractDevCmd { outString += "\r\n\r\n"; outString += "Hirelings List:"; - for (AbstractCharacter hireling : building.hirelings.keySet()) - outString += "\r\n" + hireling.getName() + " slot : " + building.hirelings.get(hireling); + for (AbstractCharacter hireling : building.hirelings) + outString += "\r\n" + hireling.getName() + " slot : " + building.hirelings.indexOf(hireling) + 1; } diff --git a/src/engine/gameManager/BuildingManager.java b/src/engine/gameManager/BuildingManager.java index a96686c2..adfc3c53 100644 --- a/src/engine/gameManager/BuildingManager.java +++ b/src/engine/gameManager/BuildingManager.java @@ -53,9 +53,9 @@ public enum BuildingManager { int numOfSlots = _slotLocations.get(building.meshUUID).size(); - for (int i = 1; i <= numOfSlots; i++) { + for (int i = 0; i < numOfSlots; i++) { - if (!building.hirelings.containsValue(i)) + if (!building.hirelings.contains(i)) return i; } return -1; @@ -73,9 +73,9 @@ public enum BuildingManager { int numOfSlots = _slotLocations.get(building.meshUUID).size(); - for (int i = numOfSlots; i > 0; i--) { + for (int i = numOfSlots - 1; i >= 0; i--) { - if (!building.hirelings.containsValue(i)) + if (!building.hirelings.contains(i)) return i; } return -1; @@ -103,9 +103,9 @@ public enum BuildingManager { // for the current mesh. The position and region can change // such as when upgrading a TOL to R8. - for (AbstractCharacter hireling : building.hirelings.keySet()) { + for (AbstractCharacter hireling : building.hirelings) { - hireling.setLoc(getSlotLocation(building, building.hirelings.get(hireling)).getLocation()); + hireling.setLoc(getSlotLocation(building, building.hirelings.indexOf(hireling) + 1).getLocation()); InterestManager.setObjectDirty(hireling); } @@ -314,7 +314,7 @@ public enum BuildingManager { else newGuild = building.getOwner().getGuild(); - for (AbstractCharacter hireling : building.hirelings.keySet()) { + for (AbstractCharacter hireling : building.hirelings) { hireling.setGuild(newGuild); WorldGrid.updateObject(hireling); } @@ -399,7 +399,7 @@ public enum BuildingManager { if (building.getRank() < 1) { - for (AbstractCharacter slottedNPC : building.hirelings.keySet()) + for (AbstractCharacter slottedNPC : building.hirelings) BuildingManager.removeHireling(building, slottedNPC); return; @@ -407,9 +407,9 @@ public enum BuildingManager { // Delete hireling if building has deranked. - for (AbstractCharacter hireling : building.hirelings.keySet()) { + for (AbstractCharacter hireling : building.hirelings) { - if (building.hirelings.get(hireling) > building.getBlueprint().getSlotsForRank(building.getRank())) + if (building.hirelings.indexOf(hireling) + 1 > building.getBlueprint().getSlotsForRank(building.getRank())) BuildingManager.removeHireling(building, hireling); } diff --git a/src/engine/gameManager/NPCManager.java b/src/engine/gameManager/NPCManager.java index 8d62b28f..5b41750e 100644 --- a/src/engine/gameManager/NPCManager.java +++ b/src/engine/gameManager/NPCManager.java @@ -197,7 +197,7 @@ public enum NPCManager { // Pets are regular mobiles not hirelings (Siege engines) if (abstractCharacter.contract != null) - abstractCharacter.building.hirelings.put(abstractCharacter, buildingSlot); + abstractCharacter.building.hirelings.addIfAbsent(abstractCharacter); // Override bind and location for this npc derived // from BuildingManager slot location data. diff --git a/src/engine/net/client/handlers/OrderNPCMsgHandler.java b/src/engine/net/client/handlers/OrderNPCMsgHandler.java index 2936dfac..739dd854 100644 --- a/src/engine/net/client/handlers/OrderNPCMsgHandler.java +++ b/src/engine/net/client/handlers/OrderNPCMsgHandler.java @@ -54,7 +54,7 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler { return; } - if (!building.hirelings.containsKey(hireling)) + if (!building.hirelings.contains(hireling)) return; BuildingManager.removeHireling(building, hireling); @@ -402,7 +402,7 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler { if (building == null) return true; - if (building.hirelings.containsKey(npc) == false) + if (building.hirelings.contains(npc) == false) return true; @@ -421,7 +421,7 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler { if (ManageCityAssetMsgHandler.playerCanManageNotFriends(player, building) == false) return true; - if (building.hirelings.containsKey(npc) == false) + if (building.hirelings.contains(npc) == false) return true; if (npc.remove() == false) { @@ -515,7 +515,7 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler { if (building == null) return true; - if (!building.hirelings.containsKey(mob)) + if (!building.hirelings.contains(mob)) return true; if (player.getCharItemManager().getTradingWith() != null) { @@ -531,7 +531,7 @@ public class OrderNPCMsgHandler extends AbstractClientMsgHandler { if (BuildingManager.playerCanManage(player, building) == false) return true; - if (building.hirelings.containsKey(mob) == false) + if (building.hirelings.contains(mob) == false) return true; BuildingManager.removeHireling(building, mob); diff --git a/src/engine/net/client/msg/ManageCityAssetsMsg.java b/src/engine/net/client/msg/ManageCityAssetsMsg.java index 7d27e30c..fba33f55 100644 --- a/src/engine/net/client/msg/ManageCityAssetsMsg.java +++ b/src/engine/net/client/msg/ManageCityAssetsMsg.java @@ -24,7 +24,6 @@ import org.joda.time.Period; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; /** * Open manage city asset window @@ -230,7 +229,7 @@ public class ManageCityAssetsMsg extends ClientNetMsg { writer.putInt(0); writer.putInt(0); writer.putInt(asset.hirelings.size()); - for (AbstractCharacter hireling : asset.hirelings.keySet()) { + for (AbstractCharacter hireling : asset.hirelings) { if (!hireling.getObjectType().equals(GameObjectType.NPC)) writer.putString(hireling.getName()); else { @@ -264,7 +263,7 @@ public class ManageCityAssetsMsg extends ClientNetMsg { writer.putInt(asset.hirelings.size()); - for (AbstractCharacter npcHire : asset.hirelings.keySet()) { + for (AbstractCharacter npcHire : asset.hirelings) { writer.putInt(npcHire.getObjectType().ordinal()); writer.putInt(npcHire.getObjectUUID()); if (npcHire.getObjectType() == GameObjectType.NPC) @@ -668,11 +667,11 @@ public class ManageCityAssetsMsg extends ClientNetMsg { writer.putInt(1); } + writer.putInt(building.hirelings.size()); - ConcurrentHashMap npcList = building.hirelings; - writer.putInt(npcList.size()); - if (npcList.size() > 0) { - for (AbstractCharacter npcHire : npcList.keySet()) { + if (building.hirelings.size() > 0) { + + for (AbstractCharacter npcHire : building.hirelings) { writer.putInt(npcHire.getObjectType().ordinal()); if (npcHire.getObjectType() == GameObjectType.Mob) writer.putInt(((Mob) npcHire).getDBID()); diff --git a/src/engine/objects/Building.java b/src/engine/objects/Building.java index 7ee5fb23..a3fe0f2e 100644 --- a/src/engine/objects/Building.java +++ b/src/engine/objects/Building.java @@ -41,6 +41,7 @@ import java.time.ZoneId; import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -51,7 +52,7 @@ public class Building extends AbstractWorldObject { // Used for thread safety private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - public ConcurrentHashMap hirelings = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW); + public CopyOnWriteArrayList hirelings = new CopyOnWriteArrayList<>(); private final HashMap doorJobs = new HashMap<>(); public int meshUUID; public Zone parentZone; @@ -647,12 +648,11 @@ public class Building extends AbstractWorldObject { // Add costs associated with hirelings - for (AbstractCharacter npc : this.hirelings.keySet()) { + for (AbstractCharacter npc : this.hirelings) { if (npc.getObjectType() != GameObjectType.NPC) continue; - maintCost += Blueprint.getNpcMaintCost(npc.getRank()); } diff --git a/src/engine/objects/City.java b/src/engine/objects/City.java index fe654a0d..b589ecf7 100644 --- a/src/engine/objects/City.java +++ b/src/engine/objects/City.java @@ -656,7 +656,7 @@ public class City extends AbstractWorldObject { if (this.getTOL() == null) return outNPC; - for (AbstractCharacter npc : getTOL().hirelings.keySet()) { + for (AbstractCharacter npc : getTOL().hirelings) { if (npc.getObjectType() == GameObjectType.NPC) if (((NPC) npc).getContract().isRuneMaster() == true) outNPC = (NPC) npc; diff --git a/src/engine/objects/Mine.java b/src/engine/objects/Mine.java index b0274b4a..125ec376 100644 --- a/src/engine/objects/Mine.java +++ b/src/engine/objects/Mine.java @@ -550,7 +550,7 @@ public class Mine extends AbstractGameObject { Building mineBuilding = BuildingManager.getBuilding(this.buildingID); if (mineBuilding == null) return this.production.baseProduction; - for (AbstractCharacter harvester : mineBuilding.hirelings.keySet()) { + for (AbstractCharacter harvester : mineBuilding.hirelings) { totalModded += baseModValue; totalModded += rankModValue * harvester.getRank(); }