From 325c8b8254e18d86d6a79ecdb078eb1d14fd7949 Mon Sep 17 00:00:00 2001
From: FatBoy-DOTC <justin.chucksinsulating@gmail.com>
Date: Sat, 14 Jan 2023 11:57:30 -0600
Subject: [PATCH 01/13] siege asset placement reliant on attcker/defender
 maximums

---
 .../client/handlers/PlaceAssetMsgHandler.java | 49 ++++++++++++-------
 1 file changed, 32 insertions(+), 17 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index d7b12aef..4e65d5b6 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -23,6 +23,7 @@ import engine.objects.*;
 import engine.server.MBServerStatics;
 import org.joda.time.DateTime;
 import org.pmw.tinylog.Logger;
+import sun.util.calendar.ZoneInfo;
 
 import java.time.LocalDateTime;
 import java.util.ArrayList;
@@ -122,7 +123,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		}
 
 		// Let's now attempt to place the building
-
 		buildingCreated = false;
 
 		// Many buildings have particular validation and
@@ -394,12 +394,11 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 			return true;
 
 		// If there is an bane placed, we protect 2x the stone rank's worth of attacker assets
+
 		// and 1x the tree rank's worth of assets automatically
 
 		HashSet<AbstractWorldObject> awoList = WorldGrid.getObjectsInRangePartial(serverCity, 1000, MBServerStatics.MASK_BUILDING);
 
-
-
 		for (AbstractWorldObject awo : awoList) {
 			Building building = (Building)awo;
 
@@ -426,28 +425,44 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 			if (building.getGuild().equals(serverCity.getGuild()))
 				numDefenderBuildings++;
-			else
-			if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
+			else if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
 				numAttackerBuildings++;
 
-
-		}
-
-		// Validate bane limits on siege assets
-
-		if (serverCity.getBane() != null)
-			if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild())) &&
-					(numAttackerBuildings >= serverCity.getBane().getStone().getRank() * 2)) {
+// Validate bane limits on siege assets
+			//if (serverCity.getBane() != null)
+			//	if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild())) &&
+			//			(numAttackerBuildings >= serverCity.getBane().getStone().getRank() * 2)) {
+			//		return true;
+			//	}
+
+			//if ((player.getGuild().equals(serverCity.getGuild())) &&
+			//		(numDefenderBuildings >= serverCity.getTOL().getRank())) {
+			//	return true;
+			//}
+			int maxAttackerAssets = serverCity.getBane().getStone().getRank() * 2;
+			int maxDefenderAssets = serverCity.getRank();
+			if(player.getGuild() == serverCity.getGuild()){
+				//defender attempting to place asset
+				if(numDefenderBuildings == maxDefenderAssets){
+					return true;
+				}
+			}
+			else if(player.getGuild() == serverCity.getBane().getStone().getGuild()){
+				//attacker attempting to place asset
+				if(numAttackerBuildings == maxAttackerAssets){
+					return true;
+				}
+			}
+			else{
+				//third party attempting to place asset, early exit
 				return true;
 			}
-
-		if ((player.getGuild().equals(serverCity.getGuild())) &&
-				(numDefenderBuildings >= serverCity.getTOL().getRank())) {
-			return true;
 		}
 
 
 
+
+
 		// passes validation: can assign auto-protection to war asset
 
 		if (serverCity.getBane() != null)

From 7a670ffdbfa237c7062d009f7adf9993ab82a413 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sat, 14 Jan 2023 13:35:37 -0500
Subject: [PATCH 02/13] Appropriate error messages for BOW limits.

---
 .../client/handlers/PlaceAssetMsgHandler.java | 34 +++++--------------
 1 file changed, 9 insertions(+), 25 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 4e65d5b6..f983bfeb 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -415,7 +415,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 			if (building.getGuild().isErrant())
 				continue;
 
-
 			if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
 				continue;
 
@@ -428,28 +427,22 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 			else if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
 				numAttackerBuildings++;
 
-// Validate bane limits on siege assets
-			//if (serverCity.getBane() != null)
-			//	if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild())) &&
-			//			(numAttackerBuildings >= serverCity.getBane().getStone().getRank() * 2)) {
-			//		return true;
-			//	}
-
-			//if ((player.getGuild().equals(serverCity.getGuild())) &&
-			//		(numDefenderBuildings >= serverCity.getTOL().getRank())) {
-			//	return true;
-			//}
+			// Validate bane limits on siege assets
+
 			int maxAttackerAssets = serverCity.getBane().getStone().getRank() * 2;
 			int maxDefenderAssets = serverCity.getRank();
-			if(player.getGuild() == serverCity.getGuild()){
+
+			if(player.getGuild().equals(serverCity.getGuild())){
 				//defender attempting to place asset
-				if(numDefenderBuildings == maxDefenderAssets){
+				if(numDefenderBuildings >= maxDefenderAssets){
+					PlaceAssetMsg.sendPlaceAssetError(origin,62, "");
 					return true;
 				}
 			}
-			else if(player.getGuild() == serverCity.getBane().getStone().getGuild()){
+			else if(player.getGuild().equals(serverCity.getBane().getStone().getGuild())){
 				//attacker attempting to place asset
-				if(numAttackerBuildings == maxAttackerAssets){
+				if(numAttackerBuildings >= maxAttackerAssets){
+					PlaceAssetMsg.sendPlaceAssetError(origin,61, "");
 					return true;
 				}
 			}
@@ -459,10 +452,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 			}
 		}
 
-
-
-
-
 		// passes validation: can assign auto-protection to war asset
 
 		if (serverCity.getBane() != null)
@@ -470,11 +459,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 				if (player.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
 					return true;
 
-
-
-
-
-
 		siegeBuilding.setProtectionState(ProtectionState.PROTECTED);
 		// No bane placed.  We're done!
 

From d8dad9f08769c3bc2bf85b277905845399d8ef91 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sat, 14 Jan 2023 15:07:35 -0500
Subject: [PATCH 03/13] Extract siege limits validation method.

---
 .../client/handlers/PlaceAssetMsgHandler.java | 127 +++++++++---------
 1 file changed, 66 insertions(+), 61 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index f983bfeb..02334ea6 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -308,8 +308,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		Building siegeBuilding;
 		PlacementInfo buildingList;
 		City serverCity;
-		int numAttackerBuildings = 0;
-		int numDefenderBuildings = 0;
 
 		// Retrieve the building details we're placing
 
@@ -359,8 +357,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 					serverCity = player.getGuild().getOwnedCity();
 		}
 
-
-
 		if ((serverCity != null) &&
 				(serverCity.getBane() != null)) {
 
@@ -377,95 +373,104 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		}
 
 		// cant place siege equipment off city zone.
-
-
+		
 		// Create the siege Building
 
 		siegeBuilding = createStructure(player, msg.getFirstPlacementInfo(), serverZone);
-		if (serverCity == null)
-			return true;
+		
 		// Oops something went really wrong
 
 		if (siegeBuilding == null)
 			return false;
 
-
-		if (serverCity.getBane() == null)
+		// If there is a bane placed, we limit placement to  2x the stone rank's worth of attacker assets
+		// and 1x the tree rank for defenders
+		
+		if (validateSiegeLimits(player, origin, serverCity.getBane()) == false)
 			return true;
+		
+		// passes validation: can assign auto-protection to war asset
 
-		// If there is an bane placed, we protect 2x the stone rank's worth of attacker assets
+		if (serverCity.getBane() != null)
+			if (serverCity.isLocationOnCityGrid(siegeBuilding.getBounds()))
+				if (player.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
+					return true;
 
-		// and 1x the tree rank's worth of assets automatically
+		siegeBuilding.setProtectionState(ProtectionState.PROTECTED);
+		
+		// No bane placed.  We're done!
+		
+		return true;
+	}
 
-		HashSet<AbstractWorldObject> awoList = WorldGrid.getObjectsInRangePartial(serverCity, 1000, MBServerStatics.MASK_BUILDING);
+	private  boolean validateSiegeLimits(PlayerCharacter playerCharacter, ClientConnection origin, Bane bane) {
 
-		for (AbstractWorldObject awo : awoList) {
-			Building building = (Building)awo;
+		City serverCity = bane.getCity();
+		HashSet<AbstractWorldObject> awoList;
+		
+		int maxAttackerAssets = serverCity.getBane().getStone().getRank() * 2;
+		int maxDefenderAssets = serverCity.getRank();
+		int numDefenderBuildings = 0;
+		int numAttackerBuildings = 0;
+		
+		// Count bow for attackers and defenders
 
-			if (building.getBlueprint() != null)
-				if (!building.getBlueprint().isSiegeEquip())
-					continue;
+		awoList =  WorldGrid.getObjectsInRangePartial(serverCity, 1000, MBServerStatics.MASK_BUILDING);
 
-			if (!building.getLoc().isInsideCircle(serverCity.getLoc(), Enum.CityBoundsType.SIEGE.extents))
-				continue;
+		for (AbstractWorldObject awo : awoList) {
+			Building building = (Building) awo;
 
-			if (building.getGuild() == null)
+		if (building.getBlueprint() != null)
+			if (!building.getBlueprint().isSiegeEquip())
 				continue;
 
-			if (building.getGuild().isErrant())
-				continue;
+		if (!building.getLoc().isInsideCircle(serverCity.getLoc(), Enum.CityBoundsType.SIEGE.extents))
+			continue;
 
-			if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
-				continue;
+		if (building.getGuild() == null)
+			continue;
 
-			// Only count auto protected buildings
-			if (building.getProtectionState() != ProtectionState.PROTECTED)
-				continue;
+		if (building.getGuild().isErrant())
+			continue;
 
-			if (building.getGuild().equals(serverCity.getGuild()))
-				numDefenderBuildings++;
-			else if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
-				numAttackerBuildings++;
+		if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
+			continue;
 
-			// Validate bane limits on siege assets
+		// Only count auto protected buildings
+		if (building.getProtectionState() != ProtectionState.PROTECTED)
+			continue;
 
-			int maxAttackerAssets = serverCity.getBane().getStone().getRank() * 2;
-			int maxDefenderAssets = serverCity.getRank();
+		if (building.getGuild().equals(serverCity.getGuild()))
+			numDefenderBuildings++;
+		
+		if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
+			numAttackerBuildings++;
+	
+			// Validate bane limits on siege assets
 
-			if(player.getGuild().equals(serverCity.getGuild())){
+			if (playerCharacter.getGuild().equals(serverCity.getGuild())) {
 				//defender attempting to place asset
-				if(numDefenderBuildings >= maxDefenderAssets){
-					PlaceAssetMsg.sendPlaceAssetError(origin,62, "");
-					return true;
+				if (numDefenderBuildings >= maxDefenderAssets) {
+					PlaceAssetMsg.sendPlaceAssetError(origin, 62, "");
+					return false;
 				}
 			}
-			else if(player.getGuild().equals(serverCity.getBane().getStone().getGuild())){
+			
+			if (playerCharacter.getGuild().equals(serverCity.getBane().getStone().getGuild())) {
 				//attacker attempting to place asset
-				if(numAttackerBuildings >= maxAttackerAssets){
-					PlaceAssetMsg.sendPlaceAssetError(origin,61, "");
-					return true;
+				if (numAttackerBuildings >= maxAttackerAssets) {
+					PlaceAssetMsg.sendPlaceAssetError(origin, 61, "");
+					return false;
 				}
 			}
-			else{
-				//third party attempting to place asset, early exit
-				return true;
-			}
+			
 		}
-
-		// passes validation: can assign auto-protection to war asset
-
-		if (serverCity.getBane() != null)
-			if (serverCity.isLocationOnCityGrid(siegeBuilding.getBounds()))
-				if (player.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
-					return true;
-
-		siegeBuilding.setProtectionState(ProtectionState.PROTECTED);
-		// No bane placed.  We're done!
-
-
-		return true;
+		// Passed validation
+		
+		return  true;
 	}
-
+	
+			
 	private boolean placeTreeOfLife(PlayerCharacter playerCharacter, ClientConnection origin, PlaceAssetMsg msg) {
 
 		Realm serverRealm;

From c84fb601774e0fdbe132b601817cfb1bf9681b56 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sat, 14 Jan 2023 15:08:18 -0500
Subject: [PATCH 04/13] Errant import removed.

---
 src/engine/net/client/handlers/PlaceAssetMsgHandler.java | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 02334ea6..520d0741 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -23,8 +23,6 @@ import engine.objects.*;
 import engine.server.MBServerStatics;
 import org.joda.time.DateTime;
 import org.pmw.tinylog.Logger;
-import sun.util.calendar.ZoneInfo;
-
 import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.HashSet;

From 29c6d6cd8ec3fdd8525ca9f7e9b3aa1c0cb69003 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sat, 14 Jan 2023 15:23:02 -0500
Subject: [PATCH 05/13] Counter scope issue resolved.

---
 .../net/client/handlers/PlaceAssetMsgHandler.java | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 520d0741..a3b2e789 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -405,11 +405,11 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		City serverCity = bane.getCity();
 		HashSet<AbstractWorldObject> awoList;
-		
+		HashSet<AbstractWorldObject> attackerBuildings = new HashSet<>();
+		HashSet<AbstractWorldObject> defenderBuildings = new HashSet<>();
+		;
 		int maxAttackerAssets = serverCity.getBane().getStone().getRank() * 2;
 		int maxDefenderAssets = serverCity.getRank();
-		int numDefenderBuildings = 0;
-		int numAttackerBuildings = 0;
 		
 		// Count bow for attackers and defenders
 
@@ -439,16 +439,15 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 			continue;
 
 		if (building.getGuild().equals(serverCity.getGuild()))
-			numDefenderBuildings++;
+			defenderBuildings.add(building);
 		
 		if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
-			numAttackerBuildings++;
-	
+			attackerBuildings.add(building);
 			// Validate bane limits on siege assets
 
 			if (playerCharacter.getGuild().equals(serverCity.getGuild())) {
 				//defender attempting to place asset
-				if (numDefenderBuildings >= maxDefenderAssets) {
+				if (defenderBuildings.size() >= maxDefenderAssets) {
 					PlaceAssetMsg.sendPlaceAssetError(origin, 62, "");
 					return false;
 				}
@@ -456,7 +455,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 			
 			if (playerCharacter.getGuild().equals(serverCity.getBane().getStone().getGuild())) {
 				//attacker attempting to place asset
-				if (numAttackerBuildings >= maxAttackerAssets) {
+				if (attackerBuildings.size() >= maxAttackerAssets) {
 					PlaceAssetMsg.sendPlaceAssetError(origin, 61, "");
 					return false;
 				}

From 2643be456ed14de07d68350a16458ee1a77ffac0 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sat, 14 Jan 2023 15:34:23 -0500
Subject: [PATCH 06/13] Moved validation check to before asset creation.

---
 .../client/handlers/PlaceAssetMsgHandler.java | 23 ++++++-------------
 1 file changed, 7 insertions(+), 16 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index a3b2e789..132d2198 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -371,7 +371,13 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		}
 
 		// cant place siege equipment off city zone.
-		
+
+		// If there is a bane placed, we limit placement to  2x the stone rank's worth of attacker assets
+		// and 1x the tree rank for defenders
+
+		if (validateSiegeLimits(player, origin, serverCity.getBane()) == false)
+			return true;
+
 		// Create the siege Building
 
 		siegeBuilding = createStructure(player, msg.getFirstPlacementInfo(), serverZone);
@@ -380,20 +386,9 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		if (siegeBuilding == null)
 			return false;
-
-		// If there is a bane placed, we limit placement to  2x the stone rank's worth of attacker assets
-		// and 1x the tree rank for defenders
-		
-		if (validateSiegeLimits(player, origin, serverCity.getBane()) == false)
-			return true;
 		
 		// passes validation: can assign auto-protection to war asset
 
-		if (serverCity.getBane() != null)
-			if (serverCity.isLocationOnCityGrid(siegeBuilding.getBounds()))
-				if (player.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
-					return true;
-
 		siegeBuilding.setProtectionState(ProtectionState.PROTECTED);
 		
 		// No bane placed.  We're done!
@@ -434,10 +429,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
 			continue;
 
-		// Only count auto protected buildings
-		if (building.getProtectionState() != ProtectionState.PROTECTED)
-			continue;
-
 		if (building.getGuild().equals(serverCity.getGuild()))
 			defenderBuildings.add(building);
 		

From 8ef5cb4e22774e7805ee8c2c0c6445b950b76666 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sat, 14 Jan 2023 16:31:58 -0500
Subject: [PATCH 07/13] Rework of validation checks.

---
 .../client/handlers/PlaceAssetMsgHandler.java | 77 ++++++++-----------
 1 file changed, 33 insertions(+), 44 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 132d2198..2cc539c3 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -335,42 +335,30 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		serverCity = ZoneManager.getCityAtLocation(buildingList.getLoc());
 
 		//no city found
-		//check if attacker city.
-		if (serverCity == null){
-			Bane bane = Bane.getBaneByAttackerGuild(player.getGuild());
-			City attackerCity = null;
-			if (bane != null)
-				attackerCity = bane.getCity();
-
-			if (attackerCity != null)
-				if (buildingList.getLoc().isInsideCircle(attackerCity.getLoc(), Enum.CityBoundsType.SIEGE.extents))
-					serverCity = attackerCity;
+
+		if (serverCity == null) {
+			PlaceAssetMsg.sendPlaceAssetError(origin, 41, ""); // Cannot place outisde a guild zone
+			return false;
 		}
-		//no city found for attacker city,
-		//check if defender city
 
-		if (serverCity == null){
-			if (player.getGuild().getOwnedCity() != null)
-				if (buildingList.getLoc().isInsideCircle(player.getGuild().getOwnedCity().getLoc(), Enum.CityBoundsType.SIEGE.extents))
-					serverCity = player.getGuild().getOwnedCity();
+		// No bane no bow
+
+		if (serverCity.getBane() == null) {
+			PlaceAssetMsg.sendPlaceAssetError(origin, 66, ""); // There is no bane circle to support this building of war
+			return false;
 		}
 
-		if ((serverCity != null) &&
-				(serverCity.getBane() != null)) {
 
-			// Set the server zone to the city zone in order to account for being inside
-			// the siege bounds buffer area
+		// Set the server zone to the city zone in order to account for being inside
+		// the siege bounds buffer area
 
-			serverZone = serverCity.getParent();
+		serverZone = serverCity.getParent();
 
-			if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild()) == false)
+		if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild()) == false)
 					&& (player.getGuild().equals(serverCity.getGuild()) == false)) {
-				PlaceAssetMsg.sendPlaceAssetError(origin, 54, ""); // Must belong to attacker or defender
-				return false;
+			PlaceAssetMsg.sendPlaceAssetError(origin, 54, ""); // Must belong to attacker or defender
+			return false;
 			}
-		}
-
-		// cant place siege equipment off city zone.
 
 		// If there is a bane placed, we limit placement to  2x the stone rank's worth of attacker assets
 		// and 1x the tree rank for defenders
@@ -413,27 +401,29 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		for (AbstractWorldObject awo : awoList) {
 			Building building = (Building) awo;
 
-		if (building.getBlueprint() != null)
-			if (!building.getBlueprint().isSiegeEquip())
+			if (building.getBlueprint() != null)
+				if (!building.getBlueprint().isSiegeEquip())
+					continue;
+
+			if (!building.getLoc().isInsideCircle(serverCity.getLoc(), Enum.CityBoundsType.SIEGE.extents))
 				continue;
 
-		if (!building.getLoc().isInsideCircle(serverCity.getLoc(), Enum.CityBoundsType.SIEGE.extents))
-			continue;
+			if (building.getGuild() == null)
+				continue;
 
-		if (building.getGuild() == null)
-			continue;
+			if (building.getGuild().isErrant())
+				continue;
 
-		if (building.getGuild().isErrant())
-			continue;
+			if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
+				continue;
 
-		if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
-			continue;
+			if (building.getGuild().equals(serverCity.getGuild()))
+				defenderBuildings.add(building);
 
-		if (building.getGuild().equals(serverCity.getGuild()))
-			defenderBuildings.add(building);
-		
-		if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
-			attackerBuildings.add(building);
+			if (building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
+				attackerBuildings.add(building);
+
+		}
 			// Validate bane limits on siege assets
 
 			if (playerCharacter.getGuild().equals(serverCity.getGuild())) {
@@ -451,8 +441,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 					return false;
 				}
 			}
-			
-		}
+
 		// Passed validation
 		
 		return  true;

From 313c13c588131e858178f0506425b8e3d782f27e Mon Sep 17 00:00:00 2001
From: FatBoy-DOTC <justin.chucksinsulating@gmail.com>
Date: Sat, 14 Jan 2023 18:36:51 -0600
Subject: [PATCH 08/13] corrected error message ID numbers

---
 .../client/handlers/PlaceAssetMsgHandler.java | 29 ++++++++++---------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 2cc539c3..6c7d5014 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -275,8 +275,9 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		// Early exit if something went horribly wrong
 
-		if (cityObject == null)
-			return false;
+		if (cityObject == null){
+			PlaceAssetMsg.sendPlaceAssetError(origin, 52, "");
+			return false;}
 
 		// Method checks validation conditions arising when placing
 		// buildings.  Player must be on a city grid, must be
@@ -337,7 +338,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		//no city found
 
 		if (serverCity == null) {
-			PlaceAssetMsg.sendPlaceAssetError(origin, 41, ""); // Cannot place outisde a guild zone
+			PlaceAssetMsg.sendPlaceAssetError(origin, 52, ""); // Cannot place outisde a guild zone
 			return false;
 		}
 
@@ -1232,17 +1233,17 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		if(Blueprint.getBlueprint(placementInfo.getBlueprintUUID()).isSiegeEquip() == false)
 		{
 			if (serverZone.isPlayerCity() == false) {
-				PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+				PlaceAssetMsg.sendPlaceAssetError(origin, 52, player.getName());
 				return false;
 			}
 			City city = ZoneManager.getCityAtLocation(placementInfo.getLoc());
 
 			if (player.getGuild().equals(city.getGuild()) == false) {
-				PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+				PlaceAssetMsg.sendPlaceAssetError(origin, 40, player.getName());
 				return false;
 			}
 			if (city.isLocationOnCityGrid(placementInfo.getLoc()) == false) {
-				PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+				PlaceAssetMsg.sendPlaceAssetError(origin, 41, player.getName());
 				return false;
 			}
 		}
@@ -1252,7 +1253,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 			if(city == null)
 			{
-				PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+				PlaceAssetMsg.sendPlaceAssetError(origin, 52, player.getName());
 				return false;
 			}
 			Bane bane = city.getBane();
@@ -1272,38 +1273,38 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 				if(bane == null)
 				{
 					//bane was null
-					PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+					PlaceAssetMsg.sendPlaceAssetError(origin, 66, player.getName());
 					return false;
 				}
 				if(city == null)
 				{
 					//city was null
-					PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+					PlaceAssetMsg.sendPlaceAssetError(origin, 67, player.getName());
 					return false;
 				}
 				//check if player is from siege guild
 				if(player.getGuild().equals(bane.getOwner().getGuild()) == false)
 				{
-					PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+					PlaceAssetMsg.sendPlaceAssetError(origin, 54, player.getName());
 					return false;
 				}
 
 				//check if player is GL or IC of the bane guild
 				if(GuildStatusController.isGuildLeader(player.getGuildStatus()) == false && GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
 				{
-					PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+					PlaceAssetMsg.sendPlaceAssetError(origin, 71, player.getName());
 					return false;
 				}
 
 				//cannot place on grid until bane is live
 				if(bane.getSiegePhase() != SiegePhase.WAR && city.isLocationOnCityGrid(placementInfo.getLoc()) == true)
 				{
-					PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+					PlaceAssetMsg.sendPlaceAssetError(origin, 71, player.getName());
 					return false;
 				}
 				if(city.isLocationWithinSiegeBounds(placementInfo.getLoc()) == false && city.isLocationOnCityZone(placementInfo.getLoc()) == false)
 				{
-					PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
+					PlaceAssetMsg.sendPlaceAssetError(origin, 66, player.getName());
 					return false;
 				}
 			}
@@ -1421,7 +1422,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		// City assets must be placed on the city grid
 
 		if (!city.isLocationOnCityGrid(buildingInfo.getLoc())) {
-			PlaceAssetMsg.sendPlaceAssetError(origin, 1, "Assset must be placed on a City Grid");
+			PlaceAssetMsg.sendPlaceAssetError(origin, 52, "");
 			return false;
 		}
 

From e0af139b2437a37af833b1388a658bf1453ec83f Mon Sep 17 00:00:00 2001
From: FatBoy-DOTC <justin.chucksinsulating@gmail.com>
Date: Sat, 14 Jan 2023 18:56:43 -0600
Subject: [PATCH 09/13] deed no longer is taken after failed placement

---
 src/engine/net/client/handlers/PlaceAssetMsgHandler.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 6c7d5014..7d327dc4 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -365,7 +365,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		// and 1x the tree rank for defenders
 
 		if (validateSiegeLimits(player, origin, serverCity.getBane()) == false)
-			return true;
+			return false;
 
 		// Create the siege Building
 

From f3fee3140aece4845d3c5bee0b157585573ee80a Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sun, 15 Jan 2023 08:18:23 -0500
Subject: [PATCH 10/13] Move siege validation out of the generic
 ValidateBuildingPlacement method.

---
 .../client/handlers/PlaceAssetMsgHandler.java | 109 +++++-------------
 1 file changed, 29 insertions(+), 80 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 7d327dc4..218ceea1 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -307,6 +307,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		Building siegeBuilding;
 		PlacementInfo buildingList;
 		City serverCity;
+		Bane bane;
 
 		// Retrieve the building details we're placing
 
@@ -324,44 +325,56 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 			return false;
 		}
 
-		// Checks validation conditions arising when placing
-		// generic structures.
-
-		if (validateBuildingPlacement(serverZone, msg, origin, player, buildingList) == false)
-			return false;
-
-		// If there is a bane placed, only the attackers and defenders can
-		// place siege assets
-
 		serverCity = ZoneManager.getCityAtLocation(buildingList.getLoc());
 
-		//no city found
+		// No valid player city found
 
-		if (serverCity == null) {
+		if (serverCity == null || serverZone.isPlayerCity() == false) {
 			PlaceAssetMsg.sendPlaceAssetError(origin, 52, ""); // Cannot place outisde a guild zone
 			return false;
 		}
 
 		// No bane no bow
 
-		if (serverCity.getBane() == null) {
+		bane = serverCity.getBane();
+
+		if (bane == null) {
 			PlaceAssetMsg.sendPlaceAssetError(origin, 66, ""); // There is no bane circle to support this building of war
 			return false;
 		}
 
-
 		// Set the server zone to the city zone in order to account for being inside
 		// the siege bounds buffer area
 
 		serverZone = serverCity.getParent();
 
+		// Must belong to either attacker or defenders.
+
 		if ((player.getGuild().equals(serverCity.getBane().getOwner().getGuild()) == false)
 					&& (player.getGuild().equals(serverCity.getGuild()) == false)) {
 			PlaceAssetMsg.sendPlaceAssetError(origin, 54, ""); // Must belong to attacker or defender
 			return false;
 			}
 
-		// If there is a bane placed, we limit placement to  2x the stone rank's worth of attacker assets
+		// Player must be  GL or IC of the bane guild to place bow.
+
+		if(GuildStatusController.isGuildLeader(player.getGuildStatus()) == false
+				&& GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
+		{
+			PlaceAssetMsg.sendPlaceAssetError(origin, 10, player.getName());  // You must be a guild leader to place this asset
+			return false;
+		}
+
+		//cannot place on grid until bane is live
+
+		if(bane.getSiegePhase() != SiegePhase.WAR &&
+				serverCity.isLocationOnCityGrid(buildingList.getLoc()) == true)
+		{
+			PlaceAssetMsg.sendPlaceAssetError(origin, 53, player.getName()); // Buildings of war cannot be placed around a city grid unless there is an active bane
+			return false;
+		}
+
+		// If there is a bane placed, we limit bow placement to 2x the stone rank's worth of attacker assets
 		// and 1x the tree rank for defenders
 
 		if (validateSiegeLimits(player, origin, serverCity.getBane()) == false)
@@ -380,8 +393,6 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		siegeBuilding.setProtectionState(ProtectionState.PROTECTED);
 		
-		// No bane placed.  We're done!
-		
 		return true;
 	}
 
@@ -1230,85 +1241,23 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		RealmType currentRealm;
 
-		if(Blueprint.getBlueprint(placementInfo.getBlueprintUUID()).isSiegeEquip() == false)
-		{
 			if (serverZone.isPlayerCity() == false) {
 				PlaceAssetMsg.sendPlaceAssetError(origin, 52, player.getName());
 				return false;
 			}
+
 			City city = ZoneManager.getCityAtLocation(placementInfo.getLoc());
 
 			if (player.getGuild().equals(city.getGuild()) == false) {
 				PlaceAssetMsg.sendPlaceAssetError(origin, 40, player.getName());
 				return false;
 			}
+
 			if (city.isLocationOnCityGrid(placementInfo.getLoc()) == false) {
 				PlaceAssetMsg.sendPlaceAssetError(origin, 41, player.getName());
 				return false;
 			}
-		}
-		else
-		{
-			City city = ZoneManager.getCityAtLocation(placementInfo.getLoc());
 
-			if(city == null)
-			{
-				PlaceAssetMsg.sendPlaceAssetError(origin, 52, player.getName());
-				return false;
-			}
-			Bane bane = city.getBane();
-			//check if player is owner/IC of tree or bane
-			if (player.getGuild().equals(city.getGuild()) == true)
-			{
-				//is from owners guild
-				if(GuildStatusController.isGuildLeader(player.getGuildStatus()) == false && GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
-				{
-					PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName());
-					return false;
-				}
-			}
-			else
-			{
-				//is not from owners guild
-				if(bane == null)
-				{
-					//bane was null
-					PlaceAssetMsg.sendPlaceAssetError(origin, 66, player.getName());
-					return false;
-				}
-				if(city == null)
-				{
-					//city was null
-					PlaceAssetMsg.sendPlaceAssetError(origin, 67, player.getName());
-					return false;
-				}
-				//check if player is from siege guild
-				if(player.getGuild().equals(bane.getOwner().getGuild()) == false)
-				{
-					PlaceAssetMsg.sendPlaceAssetError(origin, 54, player.getName());
-					return false;
-				}
-
-				//check if player is GL or IC of the bane guild
-				if(GuildStatusController.isGuildLeader(player.getGuildStatus()) == false && GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
-				{
-					PlaceAssetMsg.sendPlaceAssetError(origin, 71, player.getName());
-					return false;
-				}
-
-				//cannot place on grid until bane is live
-				if(bane.getSiegePhase() != SiegePhase.WAR && city.isLocationOnCityGrid(placementInfo.getLoc()) == true)
-				{
-					PlaceAssetMsg.sendPlaceAssetError(origin, 71, player.getName());
-					return false;
-				}
-				if(city.isLocationWithinSiegeBounds(placementInfo.getLoc()) == false && city.isLocationOnCityZone(placementInfo.getLoc()) == false)
-				{
-					PlaceAssetMsg.sendPlaceAssetError(origin, 66, player.getName());
-					return false;
-				}
-			}
-		}
 		// Retrieve the building details we're placing
 
 		if (serverZone.isNPCCity() == true) {

From 526c078978fc37a93ae91466c57c1c1fc97b9655 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sun, 15 Jan 2023 08:31:56 -0500
Subject: [PATCH 11/13] Collision check extracted to method.

---
 .../client/handlers/PlaceAssetMsgHandler.java | 21 ++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 218ceea1..71701c61 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -380,6 +380,13 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		if (validateSiegeLimits(player, origin, serverCity.getBane()) == false)
 			return false;
 
+		// Collision check (Removes rubble side effect)
+
+		if (placementCollisionCheck(serverZone, origin, buildingList)){
+			PlaceAssetMsg.sendPlaceAssetError(origin, 3, ""); // Conflict between proposed assets
+			return false;
+		}
+
 		// Create the siege Building
 
 		siegeBuilding = createStructure(player, msg.getFirstPlacementInfo(), serverZone);
@@ -1311,6 +1318,15 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 			return false;
 		}
 
+		if (placementCollisionCheck(serverZone, origin, placementInfo)){
+			PlaceAssetMsg.sendPlaceAssetError(origin, 3, ""); // Conflict between proposed assets
+			return false;
+		}
+
+		return true;
+	}
+
+	private static boolean placementCollisionCheck(Zone serverZone, ClientConnection origin, PlacementInfo placementInfo) {
 		// Overlap check
 
 		for (Building building : serverZone.zoneBuildingSet) {
@@ -1338,11 +1354,10 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 
 				PlaceAssetMsg.sendPlaceAssetError(origin, 3, "");  // Conflict between proposed assets
-				return false;
+				return true;
 			}
 		}
-
-		return true;
+		return false;
 	}
 
 	private static boolean validateCityBuildingPlacement(Zone serverZone, PlaceAssetMsg msg, ClientConnection origin, PlayerCharacter player, PlacementInfo buildingInfo) {

From 68294baae6ef99ad9d087c8b76c37ef0f4c66e61 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sun, 15 Jan 2023 08:57:54 -0500
Subject: [PATCH 12/13] Cleanup of scope issue when creating city objects.

---
 .../client/handlers/PlaceAssetMsgHandler.java | 74 +++++++++----------
 1 file changed, 33 insertions(+), 41 deletions(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 71701c61..7bd11983 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -25,6 +25,7 @@ import org.joda.time.DateTime;
 import org.pmw.tinylog.Logger;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -200,7 +201,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		playerCharacter.setLastContract(msg.getContractID());
 
-		// Remove the appropiate deed.
+		// Remove the appropriate deed.
 		if (buildingCreated == true)
 			if (contract != null) {
 				playerCharacter.getCharItemManager().delete(contract);
@@ -472,12 +473,13 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		Realm serverRealm;
 		Zone serverZone;
 		ArrayList<AbstractGameObject> cityObjects; // MySql result set
+		HashMap<GameObjectType, AbstractGameObject> cityObjectMap = new HashMap<>();
 		PlacementInfo treeInfo;
-		Building treeObject = null;
-		City cityObject = null;
-		Zone cityZone = null;
 		Guild playerNation;
 		PlacementInfo treePlacement = msg.getFirstPlacementInfo();
+		Building treeObject;
+		City cityObject;
+		Zone zoneObject;
 
 		// Setup working variables we'll need
 
@@ -523,59 +525,49 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		// Assign our worker variables after figuring out what
 		// is what in the result set.
 
-		for (AbstractGameObject gameObject : cityObjects) {
+		for (AbstractGameObject gameObject : cityObjects)
+			cityObjectMap.put(gameObject.getObjectType(), gameObject);
 
-			switch (gameObject.getObjectType()) {
-				case Building:
-					treeObject = (Building) gameObject;
-					treeObject.runAfterLoad();
-					break;
-				case City:
-					cityObject = (City) gameObject;
-					break;
-				case Zone:
-					cityZone = (Zone) gameObject;
-					break;
-				default:
-					// log some error here? *** Refactor
-			}
-		}
+		treeObject = (Building) cityObjectMap.get(GameObjectType.Building);
+		treeObject.runAfterLoad();;
+		cityObject = (City) cityObjectMap.get(GameObjectType.City);
+		zoneObject = (Zone) cityObjectMap.get(GameObjectType.Zone);
 
-		//?? your not allowed to plant a tree if ur not an errant guild.
+		// not allowed to plant a tree if ur not an errant guild.
 		// Desub from any previous nation.
 		// This should be done automatically in a method inside Guild *** Refactor
-		// Player is now a Soverign guild, configure them as such.
+		// Player is now a Sovereign guild, configure them as such.
 
 		playerCharacter.getGuild().setNation(playerCharacter.getGuild());
 		playerNation = playerCharacter.getGuild();
 		playerNation.setGuildState(GuildState.Sovereign);
 
 		// Link the zone with the city and then add
-		// to the appropritae hash tables and cache
+		// to the appropriate hash tables and cache
 
-		cityZone.setPlayerCity(true);
+		zoneObject.setPlayerCity(true);
 
-		if (cityZone.getParent() != null)
-			cityZone.getParent().addNode(cityZone); //add as child to parent
+		if (zoneObject.getParent() != null)
+			zoneObject.getParent().addNode(zoneObject); //add as child to parent
 
-		ZoneManager.addZone(cityZone.getObjectUUID(), cityZone);
-		ZoneManager.addPlayerCityZone(cityZone);
-		serverZone.addNode(cityZone);
+		ZoneManager.addZone(zoneObject.getObjectUUID(), zoneObject);
+		ZoneManager.addPlayerCityZone(zoneObject);
+		serverZone.addNode(zoneObject);
 
-		cityZone.generateWorldAltitude();
+		zoneObject.generateWorldAltitude();
 
-		cityObject.setParent(cityZone);
+		cityObject.setParent(zoneObject);
 		cityObject.setObjectTypeMask(MBServerStatics.MASK_CITY); // *** Refactor : should have it already
 		//Link the tree of life with the new zone
 
 		treeObject.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
-		treeObject.setParentZone(cityZone);
+		treeObject.setParentZone(zoneObject);
 		MaintenanceManager.setMaintDateTime(treeObject, LocalDateTime.now().plusDays(7));
 
 		// Update guild binds and tags
 		//load the new city on the clients
 
-		CityZoneMsg czm = new CityZoneMsg(1, treeObject.getLoc().x, treeObject.getLoc().y, treeObject.getLoc().z, cityObject.getCityName(), cityZone, Enum.CityBoundsType.ZONE.extents, Enum.CityBoundsType.ZONE.extents);
+		CityZoneMsg czm = new CityZoneMsg(1, treeObject.getLoc().x, treeObject.getLoc().y, treeObject.getLoc().z, cityObject.getCityName(), zoneObject, Enum.CityBoundsType.ZONE.extents, Enum.CityBoundsType.ZONE.extents);
 		DispatchMessage.dispatchMsgToAll(czm);
 
 		GuildManager.updateAllGuildBinds(playerNation, cityObject);
@@ -698,7 +690,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		cityObject = City.getCity(serverZone.getPlayerCityUUID());
 
-		// Cannot place shrine in abanadoned city.  Shrines must be owned
+		// Cannot place shrine in abandoned city.  Shrines must be owned
 		// by the tol owner not the person placing them.
 
 		if (cityObject.getTOL().getOwnerUUID() == 0) {
@@ -767,7 +759,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		cityObject = City.getCity(serverZone.getPlayerCityUUID());
 
-		// Cannot place barracks in abanadoned city.
+		// Cannot place barracks in abandoned city.
 
 		if (cityObject.getTOL().getOwnerUUID() == 0) {
 			PlaceAssetMsg.sendPlaceAssetError(origin, 42, "");  //Tree cannot support anymore shrines
@@ -1036,11 +1028,11 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		blueprint = Blueprint.getBlueprint(buildingInfo.getBlueprintUUID());
 
 		if (blueprint == null) {
-			Logger.error("CreateStucture: DB returned null blueprint.");
+			Logger.error("CreateStructure: DB returned null blueprint.");
 			return null;
 		}
 
-		// All seige buildings build in 15 minutes
+		// All siege buildings build in 15 minutes
 		if ((blueprint.getBuildingGroup().equals(BuildingGroup.SIEGETENT))
 				|| (blueprint.getBuildingGroup().equals(BuildingGroup.BULWARK)))
 			completionDate = DateTime.now().plusMinutes(15);
@@ -1061,7 +1053,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		// Make sure we have a valid mesh
 		if (newMesh == null) {
-			Logger.error("CreateStucture: DB returned null object.");
+			Logger.error("CreateStructure: DB returned null object.");
 			return null;
 		}
 
@@ -1179,7 +1171,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		// Make sure we have a valid mesh
 		if (newMesh == null) {
-			Logger.error("CreateStucture: DB returned null object.");
+			Logger.error("CreateStructure: DB returned null object.");
 			return false;
 		}
 
@@ -1362,7 +1354,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 	private static boolean validateCityBuildingPlacement(Zone serverZone, PlaceAssetMsg msg, ClientConnection origin, PlayerCharacter player, PlacementInfo buildingInfo) {
 
-		// Peform shared common validation first
+		// Perform shared common validation first
 
 		if (validateBuildingPlacement(serverZone, msg, origin, player, buildingInfo) == false)
 			return false;
@@ -1370,7 +1362,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 		// Must be a player city
 
 		if (serverZone.isPlayerCity() == false) {
-			PlaceAssetMsg.sendPlaceAssetError(origin, 41, player.getName()); // Cannot place outisde a guild zone
+			PlaceAssetMsg.sendPlaceAssetError(origin, 41, player.getName()); // Cannot place outside a guild zone
 			return false;
 		}
 

From 0469754d5d28c1b49674549deebc67cc4bb76389 Mon Sep 17 00:00:00 2001
From: MagicBot <MagicBot@magicbane.com>
Date: Sun, 15 Jan 2023 13:00:26 -0500
Subject: [PATCH 13/13] Bugfix: needs city parent not current zone to pick up
 siege bounds.

---
 src/engine/net/client/handlers/PlaceAssetMsgHandler.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
index 7bd11983..79cc7aa8 100644
--- a/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
+++ b/src/engine/net/client/handlers/PlaceAssetMsgHandler.java
@@ -330,7 +330,7 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
 
 		// No valid player city found
 
-		if (serverCity == null || serverZone.isPlayerCity() == false) {
+		if (serverCity == null || serverCity.getParent().isPlayerCity() == false) {
 			PlaceAssetMsg.sendPlaceAssetError(origin, 52, ""); // Cannot place outisde a guild zone
 			return false;
 		}