Deed placement (ObjectActionMsgHandler, PlaceAssetMsgHandler) reads deed_structure_id from DeedTemplate._deeds. The deed, employment contract and charter type checks (PlaceAssetMsgHandler, ActivateNPCMsgHandler, GuildCreationFinalizeHandler, UseCharterMsg, Item.serialize) read item_type through the cache template bridge. Charters go through the shared getter rather than _deeds because template 545 "Charter" is a CHARTER in the ITEM folder. Parity (offline, static_item_templates vs COBJECTS, scripts/p13.py, 881 templates: all 880 DEED plus ITEM 545): 0 differences in item_type and deed_structure_id. Every DB DEED, EMPLOYMENTCONTRACT, PETTOTEM and FURNITUREDEED id is in the DEED folder. No value changes expected. No pet totem or furniture deed consumer reads template fields, so neither changes. JSON-Refactor-Plan Task 1.3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1372 lines
50 KiB
Java
1372 lines
50 KiB
Java
package engine.net.client.handlers;
|
|
|
|
import engine.InterestManagement.InterestManager;
|
|
import engine.InterestManagement.RealmMap;
|
|
import engine.InterestManagement.WorldGrid;
|
|
import engine.db.archive.CityRecord;
|
|
import engine.db.archive.DataWarehouse;
|
|
import engine.gameManager.*;
|
|
import engine.math.Bounds;
|
|
import engine.math.Vector3fImmutable;
|
|
import engine.mbEnums;
|
|
import engine.mbEnums.*;
|
|
import engine.net.Dispatch;
|
|
import engine.net.client.ClientConnection;
|
|
import engine.net.client.msg.CityZoneMsg;
|
|
import engine.net.client.msg.ClientNetMsg;
|
|
import engine.net.client.msg.ErrorPopupMsg;
|
|
import engine.net.client.msg.PlaceAssetMsg;
|
|
import engine.net.client.msg.PlaceAssetMsg.PlacementInfo;
|
|
import engine.objects.*;
|
|
import engine.server.MBServerStatics;
|
|
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;
|
|
|
|
/*
|
|
* @Summary: Processes application protocol message which requests
|
|
* creation of new city / buildings from seeds/deeds in inventory.
|
|
*/
|
|
public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
|
|
|
// Useful constants
|
|
// ActionType 1 = client request
|
|
// 2 = Server confirms open window
|
|
// 3 = Request to place asset
|
|
// 4 = Server confirms/close window
|
|
private static final int CLIENTREQ_UNKNOWN = 1;
|
|
private static final int SERVER_OPENWINDOW = 2;
|
|
private static final int CLIENTREQ_NEWBUILDING = 3; // Request to place asset
|
|
private static final int SERVER_CLOSEWINDOW = 4;
|
|
|
|
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
|
|
|
public PlaceAssetMsgHandler() {
|
|
|
|
super();
|
|
|
|
}
|
|
|
|
private static void closePlaceAssetWindow(ClientConnection origin) {
|
|
|
|
// Action type 4 is the server telling the client to
|
|
// close the asset placement window.
|
|
// This is believed to be a confirmation message to the client
|
|
PlaceAssetMsg pam = new PlaceAssetMsg();
|
|
pam.setActionType(4);
|
|
Dispatch dispatch = Dispatch.borrow(origin.getPlayerCharacter(), pam);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
}
|
|
|
|
// Default method: Validates and places all buildings that do not
|
|
// require special treatment in some fashion.
|
|
|
|
private static boolean validateTreeOfLifePlacement(PlayerCharacter playerCharacter, Realm serverRealm, Zone serverZone,
|
|
ClientConnection origin, PlaceAssetMsg msg) {
|
|
|
|
PlacementInfo placementInfo = msg.getFirstPlacementInfo();
|
|
|
|
// Your guild already owns a tree
|
|
|
|
if (playerCharacter.getGuild().getOwnedCity() != null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "Your guild already owns a tree!");
|
|
return false;
|
|
}
|
|
|
|
// Validate that the player is the leader of a guild
|
|
|
|
if (GuildStatusController.isGuildLeader(playerCharacter.getGuildStatus()) == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 10, ""); // Must be a guild leader
|
|
return false;
|
|
}
|
|
|
|
// Validate that the player is the leader of a guild
|
|
// that is not currently Sovereign *** BUG? Doesn't look right. isGuildLeader()?
|
|
|
|
if ((playerCharacter.getGuild().guildState != GuildState.Sworn
|
|
|| playerCharacter.getGuild().guildState != GuildState.Errant) == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 17, ""); // Your is not an errant or soverign guild
|
|
return false;
|
|
}
|
|
|
|
// All trees must be placed within a continent.
|
|
|
|
if (!serverZone.isContinent()) {
|
|
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 69, ""); // Tree must be within a territory
|
|
return false;
|
|
}
|
|
|
|
if (serverRealm == null || serverRealm.getCanPlaceCities() == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 57, playerCharacter.getName()); // No building may be placed within this territory
|
|
return false;
|
|
}
|
|
|
|
// Cannot place a tree underwater
|
|
|
|
if (ZoneManager.isLocUnderwater(placementInfo.getLoc())) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 6, ""); // Cannot place underwater
|
|
return false;
|
|
}
|
|
|
|
//Test city not too close to any other zone
|
|
|
|
if (!ZoneManager.validTreePlacementLoc(serverZone, placementInfo.getLoc().x, placementInfo.getLoc().z)) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 39, ""); // Too close to another tree
|
|
return false;
|
|
}
|
|
|
|
// Validate that Realm is not at it's city limit
|
|
|
|
if (serverRealm.isRealmFull() == true) {
|
|
int numCities;
|
|
numCities = serverRealm.getNumCities();
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 58, Integer.toString(numCities)); // This territory is full
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static boolean validateBuildingPlacement(Zone serverZone, PlaceAssetMsg msg, ClientConnection origin, PlayerCharacter player, PlacementInfo placementInfo) {
|
|
|
|
Bane bane;
|
|
|
|
if (serverZone.guild_zone == 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;
|
|
}
|
|
|
|
// Retrieve the building details we're placing
|
|
|
|
if (serverZone.isNPCCity == true) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 15, ""); // Cannot place in a peace zone
|
|
return false;
|
|
}
|
|
|
|
// Errant guilds cannot place assets
|
|
|
|
if (player.getGuild().guildState == GuildState.Errant) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "Only sovereign or sworn guilds may place assets.");
|
|
return false;
|
|
}
|
|
|
|
// Player must be GL or IC of a guild to place buildings.
|
|
|
|
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false && GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 10, ""); // You must be a guild leader
|
|
return false;
|
|
}
|
|
|
|
// Cannot place a building underwater
|
|
|
|
if (ZoneManager.isLocUnderwater(placementInfo.getLoc())) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 6, ""); // Cannot place underwater
|
|
return false;
|
|
}
|
|
|
|
// Players cannot place buildings in mob zones.
|
|
|
|
if ((serverZone.isMacroZone() == true)
|
|
|| (serverZone.parent.isMacroZone() == true)) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName()); // No building may be placed within this territory
|
|
return false;
|
|
}
|
|
|
|
Realm serverRealm = RealmMap.getRealmAtLocation(city.getLoc());
|
|
|
|
// Cannot place buildings on seafloor or other restricted realms
|
|
|
|
if (serverRealm == null || serverRealm.getCanPlaceCities() == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 57, player.getName()); // No building may be placed within this territory
|
|
return false;
|
|
}
|
|
|
|
// Cannot place assets on a dead tree
|
|
|
|
if ((serverZone.guild_zone)
|
|
&& (City.getCity(serverZone.playerCityUUID).getTOL().getRank() == -1)) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "Cannot place asset on dead tree until world heals");
|
|
return false;
|
|
}
|
|
|
|
// Siege equipment has its own validation and never reaches here
|
|
|
|
bane = city.getBane();
|
|
|
|
if (bane != null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 74, ""); //"Only buildings of war may be placed during a bane"
|
|
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) {
|
|
|
|
if ((building.getBlueprintUUID() != 0) && (Bounds.collide(placementInfo, building) == true)) {
|
|
|
|
// Ignore and remove from simulation if we are placing over rubble
|
|
|
|
if (building.getRank() == -1) {
|
|
|
|
if ((building.getBlueprintUUID() != 0)
|
|
&& (building.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE)) {
|
|
Shrine.RemoveShrineFromCacheByBuilding(building);
|
|
if (building.getCity() != null) {
|
|
|
|
}
|
|
}
|
|
|
|
building.removeFromCache();
|
|
WorldGrid.RemoveWorldObject(building);
|
|
WorldGrid.removeObject(building);
|
|
building.getParentZone().zoneBuildingSet.remove(building);
|
|
if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup().equals(BuildingGroup.BARRACK)) {
|
|
building.RemoveFromBarracksList();
|
|
}
|
|
continue;
|
|
}
|
|
|
|
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 3, ""); // Conflict between proposed assets
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static boolean validateCityBuildingPlacement(Zone serverZone, PlaceAssetMsg msg, ClientConnection origin, PlayerCharacter player, PlacementInfo buildingInfo) {
|
|
|
|
// Perform shared common validation first
|
|
|
|
if (validateBuildingPlacement(serverZone, msg, origin, player, buildingInfo) == false)
|
|
return false;
|
|
|
|
// Must be a player city
|
|
|
|
if (serverZone.guild_zone == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 41, player.getName()); // Cannot place outside a guild zone
|
|
return false;
|
|
}
|
|
|
|
//Test zone has a city object
|
|
|
|
City city = City.getCity(serverZone.playerCityUUID);
|
|
|
|
if (city == null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 52, ""); //"no city to associate asset with"
|
|
return false;
|
|
}
|
|
|
|
// City assets must be placed on the city grid
|
|
|
|
if (!city.isLocationOnCityGrid(buildingInfo.getLoc())) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 52, "");
|
|
return false;
|
|
}
|
|
|
|
// Make sure it's not an errant tree
|
|
|
|
if ((city.getGuild() == null || city.getGuild().isEmptyGuild() == true)) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 18, ""); //"There are no guild trees to be found"
|
|
return false;
|
|
}
|
|
|
|
//Test player is in correct guild to place buildings
|
|
|
|
if (!player.isCSR)
|
|
if (player.getGuild().getObjectUUID() != city.getGuild().getObjectUUID()) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 9, ""); //You must be a guild member to place this asset
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) {
|
|
|
|
// Member variable declaration
|
|
|
|
PlaceAssetMsg msg;
|
|
Boolean buildingCreated;
|
|
|
|
// Character location and session
|
|
|
|
PlayerCharacter playerCharacter;
|
|
PlacementInfo buildingList;
|
|
Blueprint buildingBlueprint;
|
|
|
|
// Tell compiler it's ok to trust us and parse
|
|
// what we need from the message structure
|
|
|
|
msg = (PlaceAssetMsg) baseMsg;
|
|
|
|
// Action type 3 is a client requesting to place an object
|
|
// For all other action types let's just early exit
|
|
|
|
if (msg.getActionType() != CLIENTREQ_NEWBUILDING)
|
|
return true;
|
|
|
|
// assign our character
|
|
|
|
playerCharacter = SessionManager.getPlayerCharacter(origin);
|
|
|
|
// We need to figure out what exactly the player is attempting
|
|
// to place, as some objects like tol/bane/walls are edge cases.
|
|
// So let's get the first item in their list.
|
|
|
|
buildingList = msg.getFirstPlacementInfo();
|
|
|
|
// Early exit if null building list.
|
|
|
|
if (buildingList == null) {
|
|
Logger.error("Player " + playerCharacter.getCombinedName()
|
|
+ " null building list on deed use");
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
closePlaceAssetWindow(origin);
|
|
return true;
|
|
}
|
|
|
|
Item contract = null;
|
|
|
|
for (Item inventoryItem : playerCharacter.getInventory()) {
|
|
if (inventoryItem.template.cacheTemplate.getItemType().equals(ItemType.DEED) &&
|
|
DeedTemplate._deeds.get(inventoryItem.templateID).deed_structure_id == buildingList.getBlueprintUUID()) {
|
|
contract = inventoryItem;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Grab the blueprint from the uuid in the message
|
|
|
|
buildingBlueprint = Blueprint.getBlueprint(buildingList.getBlueprintUUID());
|
|
|
|
// Early exit if blueprint can't be retrieved for the object.
|
|
|
|
if (buildingBlueprint == null) {
|
|
Logger.error("Player " + playerCharacter.getCombinedName()
|
|
+ " null blueprint UUID: " + buildingList.getBlueprintUUID() + " on deed use");
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
closePlaceAssetWindow(origin);
|
|
return true;
|
|
}
|
|
|
|
// Let's now attempt to place the building
|
|
buildingCreated = false;
|
|
|
|
// Many buildings have particular validation and
|
|
// post-creation cleanup requirements.
|
|
|
|
boolean close = true;
|
|
lock.writeLock().lock();
|
|
boolean isSiege = false;
|
|
try {
|
|
switch (buildingBlueprint.getBuildingGroup()) {
|
|
|
|
case TOL:
|
|
if (contract == null)
|
|
break;
|
|
buildingCreated = placeTreeOfLife(playerCharacter, origin, msg);
|
|
break;
|
|
case WAREHOUSE:
|
|
if (contract == null)
|
|
break;
|
|
if (!playerCharacter.charItemManager.doesCharOwnThisItem(contract.getObjectUUID()))
|
|
break;
|
|
buildingCreated = placeWarehouse(playerCharacter, origin, msg);
|
|
break;
|
|
case SIEGETENT:
|
|
case BULWARK:
|
|
if (contract == null)
|
|
break;
|
|
if (!playerCharacter.charItemManager.doesCharOwnThisItem(contract.getObjectUUID()))
|
|
break;
|
|
buildingCreated = placeSiegeEquip(playerCharacter, origin, msg);
|
|
break;
|
|
case SPIRE:
|
|
if (contract == null)
|
|
break;
|
|
if (!playerCharacter.charItemManager.doesCharOwnThisItem(contract.getObjectUUID()))
|
|
break;
|
|
buildingCreated = placeSpire(playerCharacter, origin, msg);
|
|
break;
|
|
case SHRINE:
|
|
if (contract == null)
|
|
break;
|
|
if (!playerCharacter.charItemManager.doesCharOwnThisItem(contract.getObjectUUID()))
|
|
break;
|
|
buildingCreated = placeShrine(playerCharacter, origin, msg);
|
|
break;
|
|
case BARRACK:
|
|
if (contract == null)
|
|
break;
|
|
if (!playerCharacter.charItemManager.doesCharOwnThisItem(contract.getObjectUUID()))
|
|
break;
|
|
buildingCreated = placeBarrack(playerCharacter, origin, msg);
|
|
break;
|
|
case WALLSTRAIGHT:
|
|
case WALLCORNER:
|
|
case SMALLGATE:
|
|
case ARTYTOWER:
|
|
case WALLSTAIRS:
|
|
case WALLSTRAIGHTTOWER:
|
|
buildingCreated = placeCityWalls(playerCharacter, origin, msg);
|
|
close = false;
|
|
break;
|
|
default:
|
|
if (contract == null)
|
|
break;
|
|
if (!playerCharacter.charItemManager.doesCharOwnThisItem(contract.getObjectUUID()))
|
|
break;
|
|
buildingCreated = placeSingleBuilding(playerCharacter, origin, msg);
|
|
break;
|
|
}
|
|
} catch (Exception e) {
|
|
Logger.error("PlaceAssetHandler", e.getMessage());
|
|
e.printStackTrace();
|
|
} finally {
|
|
lock.writeLock().unlock();
|
|
}
|
|
|
|
// Remove the appropriate deed.
|
|
if (buildingCreated == true)
|
|
if (contract != null) {
|
|
playerCharacter.charItemManager.delete(contract);
|
|
playerCharacter.charItemManager.updateInventory();
|
|
}
|
|
|
|
// Close the window. We're done!
|
|
//DONT CLOSE THE WINDOW IF WALL KTHANX
|
|
|
|
if (close)
|
|
closePlaceAssetWindow(origin);
|
|
return true;
|
|
}
|
|
|
|
private boolean placeSingleBuilding(PlayerCharacter playerCharacter, ClientConnection origin, PlaceAssetMsg msg) {
|
|
|
|
PlacementInfo buildingList;
|
|
Zone serverZone;
|
|
|
|
// Retrieve the building details we're placing
|
|
|
|
buildingList = msg.getFirstPlacementInfo();
|
|
|
|
serverZone = ZoneManager.findSmallestZone(buildingList.getLoc());
|
|
// Early exit if something went horribly wrong
|
|
// with locating the current or zone
|
|
|
|
if (serverZone == null) {
|
|
Logger.error("Null zone in placeSingleBuilding");
|
|
return false;
|
|
}
|
|
|
|
// Method checks validation conditions arising when placing
|
|
// buildings. Player must be on a city grid, must be
|
|
// inner council of the city's guild, etc.
|
|
|
|
if (validateBuildingPlacement(serverZone, msg, origin, playerCharacter, buildingList) == false)
|
|
return false; // Close window here?
|
|
|
|
// Place the building
|
|
if (createStructure(playerCharacter, buildingList, serverZone) == null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private boolean placeWarehouse(PlayerCharacter player, ClientConnection origin, PlaceAssetMsg msg) {
|
|
|
|
Zone serverZone;
|
|
City cityObject;
|
|
PlacementInfo buildingList;
|
|
|
|
// Retrieve the building details we're placing
|
|
|
|
buildingList = msg.getFirstPlacementInfo();
|
|
|
|
// Setup working variables we'll need
|
|
|
|
serverZone = ZoneManager.findSmallestZone(buildingList.getLoc());
|
|
|
|
// Early exit if something went horribly wrong
|
|
|
|
if (serverZone == null)
|
|
return false;
|
|
|
|
cityObject = City.getCity(serverZone.playerCityUUID);
|
|
|
|
// Early exit if something went horribly wrong
|
|
|
|
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
|
|
// inner council of the city's guild, etc.
|
|
|
|
if (validateCityBuildingPlacement(serverZone, msg, origin, player, buildingList) == false)
|
|
return false;
|
|
|
|
if (cityObject.warehouse != null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 50, ""); //"You can only have one warehouse"
|
|
return false;
|
|
}
|
|
|
|
// Create the warehouse object and it's entry in the database
|
|
|
|
if (createWarehouse(player, msg.getFirstPlacementInfo(), serverZone) == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private boolean placeSiegeEquip(PlayerCharacter player, ClientConnection origin, PlaceAssetMsg msg) {
|
|
|
|
Zone serverZone;
|
|
Building siegeBuilding;
|
|
PlacementInfo buildingList;
|
|
City serverCity;
|
|
Bane bane;
|
|
|
|
// Retrieve the building details we're placing
|
|
|
|
buildingList = msg.getFirstPlacementInfo();
|
|
|
|
// Setup working variables we'll need
|
|
|
|
serverZone = ZoneManager.findSmallestZone(buildingList.getLoc());
|
|
|
|
// Early exit if something went horribly wrong
|
|
// with locating the current city and/or zone
|
|
|
|
if (serverZone == null) {
|
|
Logger.error("Error obtaining reference to zone");
|
|
return false;
|
|
}
|
|
|
|
serverCity = ZoneManager.getCityAtLocation(buildingList.getLoc());
|
|
|
|
// No valid player city found
|
|
|
|
if (serverCity == null || serverCity.getParent().guild_zone == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 52, ""); // Cannot place outisde a guild zone
|
|
return false;
|
|
}
|
|
|
|
// No bane no bow
|
|
|
|
bane = serverCity.getBane();
|
|
|
|
if (bane == null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 66, ""); // There is no bane circle to support this building of war
|
|
return false;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// Attackers cannot place on grid until bane is live
|
|
|
|
if (bane.getSiegePhase() != SiegePhase.WAR &&
|
|
player.getGuild().equals(serverCity.getBane().getOwner().getGuild()) &&
|
|
serverCity.isLocationOnCityGrid(buildingList.getLoc())) {
|
|
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)
|
|
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);
|
|
|
|
// Oops something went really wrong
|
|
|
|
if (siegeBuilding == null)
|
|
return false;
|
|
|
|
// passes validation: can assign auto-protection to war asset
|
|
|
|
siegeBuilding.setProtectionState(ProtectionState.PROTECTED);
|
|
|
|
return true;
|
|
}
|
|
|
|
private boolean validateSiegeLimits(PlayerCharacter playerCharacter, ClientConnection origin, Bane bane) {
|
|
|
|
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();
|
|
|
|
// Count bow for attackers and defenders
|
|
|
|
awoList = WorldGrid.getObjectsInRangePartial(serverCity, 1000, MBServerStatics.MASK_BUILDING);
|
|
|
|
for (AbstractWorldObject awo : awoList) {
|
|
Building building = (Building) awo;
|
|
|
|
if (building.getBlueprint() != null)
|
|
if (!building.getBlueprint().isSiegeEquip())
|
|
continue;
|
|
|
|
if (!building.getLoc().isInsideCircle(serverCity.getLoc(), CityBoundsType.ZONE.halfExtents))
|
|
continue;
|
|
|
|
if (building.getGuild() == null)
|
|
continue;
|
|
|
|
if (building.getGuild().isEmptyGuild())
|
|
continue;
|
|
|
|
if (!building.getGuild().equals(serverCity.getGuild()) && !building.getGuild().equals(serverCity.getBane().getOwner().getGuild()))
|
|
continue;
|
|
if (building.getRank() < 0) {
|
|
continue;
|
|
}
|
|
if (building.getGuild().equals(serverCity.getGuild()))
|
|
defenderBuildings.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())) {
|
|
//defender attempting to place asset
|
|
if (defenderBuildings.size() >= maxDefenderAssets) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 62, "");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (playerCharacter.getGuild().equals(serverCity.getBane().getStone().getGuild())) {
|
|
//attacker attempting to place asset
|
|
if (attackerBuildings.size() >= maxAttackerAssets) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 61, "");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Passed validation
|
|
|
|
return true;
|
|
}
|
|
|
|
private boolean placeTreeOfLife(PlayerCharacter playerCharacter, ClientConnection origin, PlaceAssetMsg msg) {
|
|
|
|
Realm serverRealm;
|
|
Zone serverZone;
|
|
ArrayList<AbstractGameObject> cityObjects; // MySql result set
|
|
HashMap<GameObjectType, AbstractGameObject> cityObjectMap = new HashMap<>();
|
|
PlacementInfo treeInfo;
|
|
Guild playerNation;
|
|
PlacementInfo treePlacement = msg.getFirstPlacementInfo();
|
|
Building treeObject;
|
|
City cityObject;
|
|
Zone zoneObject;
|
|
|
|
// Setup working variables we'll need
|
|
|
|
serverRealm = RealmMap.getRealmAtLocation(treePlacement.getLoc());
|
|
serverZone = ZoneManager.findSmallestZone(treePlacement.getLoc());
|
|
|
|
// Early exit if something went horribly wrong
|
|
// with locating the current realm and/or zone
|
|
|
|
if (serverRealm == null || serverZone == null)
|
|
return false;
|
|
|
|
// Method checks validation conditions arising when placing
|
|
// trees
|
|
|
|
if (validateTreeOfLifePlacement(playerCharacter, serverRealm, serverZone, origin, msg) == false)
|
|
return false;
|
|
|
|
// Retrieve tree info for the w value it's passing.
|
|
|
|
treeInfo = msg.getFirstPlacementInfo();
|
|
|
|
if (treeInfo == null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
return false;
|
|
}
|
|
|
|
Vector3fImmutable plantLoc = new Vector3fImmutable(treeInfo.getLoc().x,
|
|
0,
|
|
treeInfo.getLoc().z);
|
|
|
|
cityObjects = DbManager.CityQueries.CREATE_CITY(playerCharacter.getObjectUUID(), serverZone.getObjectUUID(),
|
|
plantLoc.x - serverZone.absX, plantLoc.y,
|
|
plantLoc.z - serverZone.absZ, treeInfo.getRot().y, treeInfo.getW(), playerCharacter.getGuild().getName(), LocalDateTime.now());
|
|
|
|
// Uh oh!
|
|
|
|
if (cityObjects == null || cityObjects.isEmpty()) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
return false;
|
|
}
|
|
|
|
// Assign our worker variables after figuring out what
|
|
// is what in the result set.
|
|
|
|
for (AbstractGameObject gameObject : cityObjects)
|
|
cityObjectMap.put(gameObject.getObjectType(), gameObject);
|
|
|
|
treeObject = (Building) cityObjectMap.get(GameObjectType.Building);
|
|
cityObject = (City) cityObjectMap.get(GameObjectType.City);
|
|
zoneObject = (Zone) cityObjectMap.get(GameObjectType.Zone);
|
|
|
|
// 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 Sovereign guild, configure them as such.
|
|
|
|
playerCharacter.getGuild().setNation(playerCharacter.getGuild());
|
|
playerNation = playerCharacter.getGuild();
|
|
playerNation.guildState = GuildState.Sovereign;
|
|
|
|
// Update guild binds and tags
|
|
|
|
GuildManager.updateAllGuildBinds(playerNation, cityObject);
|
|
GuildManager.updateAllGuildTags(playerNation);
|
|
|
|
//load the new city on the clients
|
|
|
|
CityZoneMsg czm = new CityZoneMsg(1, treeObject.getLoc().x, treeObject.getLoc().y, treeObject.getLoc().z, cityObject.getCityName(), zoneObject, mbEnums.CityBoundsType.ZONE.halfExtents, mbEnums.CityBoundsType.ZONE.halfExtents);
|
|
DispatchManager.dispatchMsgToAll(czm);
|
|
|
|
// Set maintenance date
|
|
|
|
MaintenanceManager.setMaintDateTime(treeObject, LocalDateTime.now().plusDays(7));
|
|
|
|
// Send all the cities to the clients?
|
|
// *** Refactor : figure out how to send like, one?
|
|
|
|
City.lastCityUpdate = System.currentTimeMillis();
|
|
treeObject.setLoc(treeObject.getLoc());
|
|
|
|
// As this is a new static object set it's dirtyFlag
|
|
// so players already near it will have the object loaded.
|
|
|
|
InterestManager.setObjectDirty(treeObject);
|
|
|
|
serverRealm.addCity(cityObject.getObjectUUID());
|
|
playerNation.setCityUUID(cityObject.getObjectUUID());
|
|
|
|
// Bypass warehouse entry if we're an admin
|
|
|
|
if (playerCharacter.getAccount().status.equals(AccountStatus.ADMIN))
|
|
return true;
|
|
|
|
// Push this event to the data warehouse
|
|
|
|
CityRecord cityRecord = CityRecord.borrow(cityObject, RecordEventType.CREATE);
|
|
DataWarehouse.pushToWarehouse(cityRecord);
|
|
|
|
return true;
|
|
}
|
|
|
|
// Method validates the location we have selected for our new city
|
|
|
|
private boolean placeSpire(PlayerCharacter playerCharacter, ClientConnection origin, PlaceAssetMsg msg) {
|
|
|
|
Zone serverZone;
|
|
Building spireBuilding;
|
|
Blueprint blueprint;
|
|
City cityObject;
|
|
PlacementInfo buildingList;
|
|
|
|
// Setup working variables we'll need
|
|
|
|
buildingList = msg.getFirstPlacementInfo();
|
|
|
|
serverZone = ZoneManager.findSmallestZone(buildingList.getLoc());
|
|
|
|
// Early exit if something went horribly wrong
|
|
// with locating the current realm and/or city
|
|
|
|
if (serverZone == null)
|
|
return false;
|
|
|
|
cityObject = City.getCity(serverZone.playerCityUUID);
|
|
|
|
if (cityObject == null)
|
|
return false;
|
|
|
|
// Method checks validation conditions arising when placing
|
|
// buildings. Player must be on a city grid, must be
|
|
// inner council of the city's guild, etc.
|
|
|
|
if (validateCityBuildingPlacement(serverZone, msg, origin, playerCharacter, buildingList) == false)
|
|
return false;
|
|
|
|
// Loop through all buildings in this city looking for a spire of the.
|
|
// same type we are placing. There can be only one of each type
|
|
|
|
int spireCount = 0;
|
|
|
|
blueprint = Blueprint.getBlueprint(msg.getFirstPlacementInfo().getBlueprintUUID());
|
|
|
|
for (Building building : serverZone.zoneBuildingSet) {
|
|
|
|
if (building.getBlueprint().getBuildingGroup() == BuildingGroup.SPIRE) {
|
|
|
|
if (building.getBlueprintUUID() == blueprint.getMeshForRank(0)) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 46, ""); // "Spire of that type exists"
|
|
return false;
|
|
}
|
|
spireCount++;
|
|
}
|
|
}
|
|
|
|
// Too many spires for this tree's rank?
|
|
|
|
if (spireCount >= Blueprint.getMaxShrines(cityObject.getTOL().getRank())) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 45, ""); //Tree cannot support anymore spires
|
|
return false;
|
|
}
|
|
|
|
// Create the spire
|
|
|
|
spireBuilding = createStructure(playerCharacter, msg.getFirstPlacementInfo(), serverZone);
|
|
return spireBuilding != null;
|
|
}
|
|
|
|
private boolean placeShrine(PlayerCharacter playerCharacter, ClientConnection origin, PlaceAssetMsg msg) {
|
|
|
|
Zone serverZone;
|
|
Blueprint blueprint;
|
|
City cityObject;
|
|
PlacementInfo buildingList;
|
|
|
|
// Setup working variables we'll need
|
|
buildingList = msg.getFirstPlacementInfo();
|
|
|
|
serverZone = ZoneManager.findSmallestZone(buildingList.getLoc());
|
|
|
|
// Early exit if something went horribly wrong
|
|
// with locating the current realm and/or zone
|
|
|
|
if (serverZone == null)
|
|
return false;
|
|
|
|
// Method checks validation conditions arising when placing
|
|
// buildings. Player must be on a city grid, must be
|
|
// inner council of the city's guild, etc.
|
|
|
|
if (validateCityBuildingPlacement(serverZone, msg, origin, playerCharacter, buildingList) == false)
|
|
return false;
|
|
|
|
// Loop through all buildings in this city looking for a shrine of the.
|
|
// same type we are placing. There can be only one of each type
|
|
|
|
int shrineCount = 0;
|
|
|
|
cityObject = City.getCity(serverZone.playerCityUUID);
|
|
|
|
// Cannot place shrine in abandoned city. Shrines must be owned
|
|
// by the tol owner not the person placing them.
|
|
|
|
if (cityObject.getTOL().getOwnerUUID() == 0) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 42, ""); //Tree cannot support anymore shrines
|
|
return false;
|
|
}
|
|
|
|
blueprint = Blueprint.getBlueprint(msg.getFirstPlacementInfo().getBlueprintUUID());
|
|
|
|
if (blueprint == null) {
|
|
return false;
|
|
}
|
|
|
|
for (Building building : serverZone.zoneBuildingSet) {
|
|
if (building.getBlueprint() == null)
|
|
continue;
|
|
|
|
if (building.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE) {
|
|
if (building.getBlueprintUUID() == blueprint.getMeshForRank(0)) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 43, ""); // "shrine of that type exists"
|
|
return false;
|
|
}
|
|
shrineCount++;
|
|
}
|
|
}
|
|
|
|
// Too many shrines for this tree's rank?
|
|
|
|
if (shrineCount >= Blueprint.getMaxShrines(cityObject.getTOL().getRank())) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 42, ""); //Tree cannot support anymore shrines
|
|
return false;
|
|
}
|
|
|
|
// Create the shrine
|
|
|
|
return createShrine((PlayerCharacter) cityObject.getTOL().getOwner(), msg.getFirstPlacementInfo(), serverZone);
|
|
}
|
|
|
|
private boolean placeBarrack(PlayerCharacter playerCharacter, ClientConnection origin, PlaceAssetMsg msg) {
|
|
|
|
Zone serverZone;
|
|
City cityObject;
|
|
PlacementInfo buildingList;
|
|
|
|
// Setup working variables
|
|
|
|
buildingList = msg.getFirstPlacementInfo();
|
|
|
|
serverZone = ZoneManager.findSmallestZone(buildingList.getLoc());
|
|
|
|
// Early exit if something went horribly wrong
|
|
// with locating the current realm and/or zone
|
|
|
|
if (serverZone == null)
|
|
return false;
|
|
|
|
// Method checks validation conditions arising when placing
|
|
// buildings. Player must be on a city grid, must be
|
|
// inner council of the city's guild, etc.
|
|
|
|
if (validateCityBuildingPlacement(serverZone, msg, origin, playerCharacter, buildingList) == false)
|
|
return false;
|
|
|
|
// Loop through all buildings in this city counting barracks .
|
|
|
|
int barracksCount = 0;
|
|
|
|
cityObject = City.getCity(serverZone.playerCityUUID);
|
|
|
|
// Cannot place barracks in abandoned city.
|
|
|
|
if (cityObject.getTOL().getOwnerUUID() == 0) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 42, ""); //Tree cannot support anymore shrines
|
|
return false;
|
|
}
|
|
|
|
for (Building building : serverZone.zoneBuildingSet) {
|
|
if (building.getBlueprint().getBuildingGroup() == BuildingGroup.BARRACK)
|
|
barracksCount++;
|
|
}
|
|
|
|
// Too many shrines for this tree's rank?
|
|
|
|
if (barracksCount >= cityObject.getTOL().getRank()) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 47, ""); //Tree cannot support anymore shrines
|
|
return false;
|
|
}
|
|
|
|
// Create the shrine
|
|
|
|
return createBarracks((PlayerCharacter) cityObject.getTOL().getOwner(), msg.getFirstPlacementInfo(), serverZone);
|
|
}
|
|
|
|
private boolean placeCityWalls(PlayerCharacter player, ClientConnection origin, PlaceAssetMsg msg) {
|
|
|
|
// Member variables
|
|
|
|
Zone serverZone;
|
|
City cityObject;
|
|
int placementCost = 0;
|
|
CharacterItemManager itemMan;
|
|
Item goldItem;
|
|
Building wallPiece;
|
|
|
|
// Setup working variables we'll need
|
|
|
|
serverZone = ZoneManager.findSmallestZone(player.getLoc());
|
|
|
|
// Early exit if something went horribly wrong
|
|
|
|
if (serverZone == null)
|
|
return false;
|
|
|
|
|
|
if (player.charItemManager.getGoldTrading() > 0) {
|
|
ErrorPopupMsg.sendErrorPopup(player, 195);
|
|
return false;
|
|
}
|
|
|
|
|
|
// Method checks validation conditions arising when placing
|
|
// buildings. Player must be on a city grid, must be
|
|
// inner council of the city's guild, etc.
|
|
|
|
if (validateCityBuildingPlacement(serverZone, msg, origin, player, msg.getFirstPlacementInfo()) == false)
|
|
return false;
|
|
|
|
cityObject = City.getCity(serverZone.playerCityUUID);
|
|
|
|
// We need to be able to access how much gold a character is carrying
|
|
|
|
itemMan = player.charItemManager;
|
|
|
|
if (itemMan == null)
|
|
|
|
return false;
|
|
|
|
goldItem = itemMan.getGoldInventory();
|
|
|
|
// Grab list of walls we're placing
|
|
|
|
ArrayList<PlacementInfo> walls = msg.getPlacementInfo();
|
|
|
|
// Character must be able to afford walls
|
|
|
|
for (PlacementInfo wall : walls) {
|
|
placementCost += PlaceAssetMsg.getWallCost(wall.getBlueprintUUID());
|
|
}
|
|
|
|
// Early exit if not enough gold in character's inventory to place walls
|
|
|
|
if (placementCost > goldItem.getNumOfItems()) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 28, ""); // Not enough gold
|
|
return false;
|
|
}
|
|
|
|
placementCost = 0; // reset placement cost for fix bug with wall pieces somethings not taking gold out if forced an error.
|
|
|
|
// Overlap check and wall deed verifications
|
|
for (PlacementInfo wall : walls) {
|
|
|
|
if (Blueprint.isMeshWallPiece(wall.getBlueprintUUID()) == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 48, ""); //"Assets (except walls) must be placed one at a time"
|
|
continue;
|
|
}
|
|
|
|
// Ignore wall pieces not on the city grid
|
|
if (cityObject.isLocationOnCityGrid(wall.getLoc()) == false) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "Asset " + cityObject.getName() + " not on citygrid");
|
|
continue;
|
|
}
|
|
|
|
// Does this wall collide with any other building?
|
|
|
|
for (Building building : serverZone.zoneBuildingSet) {
|
|
|
|
//TODO Clean up collision with placementInfo. don't need to create the same placementinfo bounds for collision checks on each building.
|
|
if ((building.getBlueprintUUID() != 0) && (Bounds.collide(wall, building) == true)) {
|
|
|
|
if (building.getRank() == -1) {
|
|
building.removeFromCache();
|
|
WorldGrid.RemoveWorldObject(building);
|
|
WorldGrid.removeObject(building);
|
|
building.getParentZone().parent.zoneBuildingSet.remove(building);
|
|
if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup().equals(BuildingGroup.BARRACK)) {
|
|
building.RemoveFromBarracksList();
|
|
}
|
|
continue;
|
|
}
|
|
// remove gold from walls already placed before returning.
|
|
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 3, building.getName()); //"Conflict between assets"
|
|
return false;
|
|
}
|
|
}
|
|
|
|
placementCost = PlaceAssetMsg.getWallCost(wall.getBlueprintUUID());
|
|
|
|
if (!itemMan.modifyInventoryGold(-placementCost)) {
|
|
ChatManager.chatSystemInfo(player, player.getFirstName() + " can't has free moneys! no for real.. Thor.. seriously... I didnt fix it because you getting laid isnt important enough for me.");
|
|
return false;
|
|
}
|
|
|
|
// Attempt to place wall piece
|
|
|
|
wallPiece = createStructure(player, wall, serverZone);
|
|
|
|
if (wallPiece == null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
continue;
|
|
}
|
|
|
|
// walls are auto protected
|
|
|
|
wallPiece.setProtectionState(ProtectionState.PROTECTED);
|
|
PlaceAssetMsg.sendPlaceAssetConfirmWall(origin, serverZone);
|
|
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private Building createStructure(PlayerCharacter playerCharacter, PlacementInfo buildingInfo, Zone currentZone) {
|
|
|
|
Blueprint blueprint;
|
|
Building newMesh;
|
|
DateTime completionDate;
|
|
float vendorRotation;
|
|
float buildingRotation;
|
|
|
|
blueprint = Blueprint.getBlueprint(buildingInfo.getBlueprintUUID());
|
|
|
|
if (blueprint == null) {
|
|
Logger.error("CreateStructure: DB returned null blueprint.");
|
|
return null;
|
|
}
|
|
|
|
// All siege buildings build in 15 minutes
|
|
|
|
if ((blueprint.getBuildingGroup().equals(BuildingGroup.SIEGETENT))
|
|
|| (blueprint.getBuildingGroup().equals(BuildingGroup.BULWARK)))
|
|
completionDate = DateTime.now().plusMinutes(15);
|
|
else
|
|
completionDate = DateTime.now().plusHours(blueprint.getRankTime(1));
|
|
|
|
Vector3fImmutable localLoc = new Vector3fImmutable(ZoneManager.worldToLocal(buildingInfo.getLoc(), currentZone));
|
|
|
|
buildingRotation = buildingInfo.getRot().y;
|
|
vendorRotation = buildingInfo.getW();
|
|
|
|
// if W return is negative, this is a -90 rotation not a 90?
|
|
|
|
newMesh = DbManager.BuildingQueries.CREATE_BUILDING(
|
|
currentZone.getObjectUUID(), playerCharacter.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0),
|
|
localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.NONE, 0, 0,
|
|
completionDate, blueprint.getMeshForRank(0), vendorRotation, buildingRotation);
|
|
|
|
// Make sure we have a valid mesh
|
|
|
|
if (newMesh == null) {
|
|
Logger.error("CreateStructure: DB returned null object.");
|
|
return null;
|
|
}
|
|
|
|
newMesh.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
|
|
MaintenanceManager.setMaintDateTime(newMesh, LocalDateTime.now().plusDays(7));
|
|
|
|
newMesh.setLoc(newMesh.getLoc());
|
|
InterestManager.setObjectDirty(newMesh);
|
|
return newMesh;
|
|
|
|
}
|
|
|
|
// Validates that player is able to place buildings
|
|
|
|
private boolean createShrine(PlayerCharacter player, PlacementInfo buildingInfo, Zone currentZone) {
|
|
|
|
Blueprint blueprint;
|
|
Building newMesh;
|
|
Shrine newShrine;
|
|
City city;
|
|
ShrineType shrineType;
|
|
|
|
if (player == null)
|
|
return false;
|
|
|
|
blueprint = Blueprint.getBlueprint(buildingInfo.getBlueprintUUID());
|
|
|
|
if (blueprint == null) {
|
|
Logger.error("CreateShrine: DB returned null blueprint.");
|
|
return false;
|
|
}
|
|
|
|
shrineType = Shrine.getShrineTypeByBlueprintUUID(blueprint.getBlueprintUUID());
|
|
|
|
city = City.getCity(currentZone.playerCityUUID);
|
|
|
|
if (city == null)
|
|
return false;
|
|
|
|
if (!city.isLocationOnCityGrid(buildingInfo.getLoc()))
|
|
return false;
|
|
|
|
Vector3fImmutable localLoc = new Vector3fImmutable(ZoneManager.worldToLocal(buildingInfo.getLoc(), currentZone));
|
|
|
|
float buildingRotation = buildingInfo.getRot().y;
|
|
float vendorRotation = buildingInfo.getW();
|
|
|
|
|
|
ArrayList<AbstractGameObject> shrineObjects = DbManager.ShrineQueries.CREATE_SHRINE(
|
|
currentZone.getObjectUUID(), player.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0),
|
|
localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.PROTECTED, 0, 0,
|
|
DateTime.now().plusHours(blueprint.getRankTime(1)), blueprint.getMeshForRank(0), vendorRotation, buildingRotation, shrineType.name());
|
|
|
|
if (shrineObjects == null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
return false;
|
|
}
|
|
|
|
for (AbstractGameObject ago : shrineObjects) {
|
|
|
|
switch (ago.getObjectType()) {
|
|
case Building:
|
|
newMesh = (Building) ago;
|
|
newMesh.runAfterLoad();
|
|
newMesh.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
|
|
MaintenanceManager.setMaintDateTime(newMesh, LocalDateTime.now().plusDays(7));
|
|
newMesh.setLoc(newMesh.getLoc());
|
|
InterestManager.setObjectDirty(newMesh);
|
|
break;
|
|
case Shrine:
|
|
newShrine = (Shrine) ago;
|
|
newShrine.getShrineType().addShrineToServerList(newShrine);
|
|
break;
|
|
default:
|
|
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private boolean createBarracks(PlayerCharacter player, PlacementInfo buildingInfo, Zone currentZone) {
|
|
|
|
Blueprint blueprint;
|
|
Building newMesh;
|
|
Shrine newShrine;
|
|
City city;
|
|
|
|
if (player == null)
|
|
return false;
|
|
|
|
blueprint = Blueprint.getBlueprint(buildingInfo.getBlueprintUUID());
|
|
|
|
if (blueprint == null) {
|
|
Logger.error("CreateShrine: DB returned null blueprint.");
|
|
return false;
|
|
}
|
|
|
|
city = City.getCity(currentZone.playerCityUUID);
|
|
|
|
if (city == null)
|
|
return false;
|
|
|
|
if (!city.isLocationOnCityGrid(buildingInfo.getLoc()))
|
|
return false;
|
|
|
|
Vector3fImmutable localLoc = new Vector3fImmutable(ZoneManager.worldToLocal(buildingInfo.getLoc(), currentZone));
|
|
|
|
float buildingRotation = buildingInfo.getRot().y;
|
|
float vendorRotation = buildingInfo.getW();
|
|
DateTime completionDate = DateTime.now().plusHours(blueprint.getRankTime(1));
|
|
|
|
|
|
newMesh = DbManager.BuildingQueries.CREATE_BUILDING(
|
|
currentZone.getObjectUUID(), player.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0),
|
|
localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.PROTECTED, 0, 0,
|
|
completionDate, blueprint.getMeshForRank(0), vendorRotation, buildingRotation);
|
|
|
|
// Make sure we have a valid mesh
|
|
if (newMesh == null) {
|
|
Logger.error("CreateStructure: DB returned null object.");
|
|
return false;
|
|
}
|
|
|
|
newMesh.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
|
|
MaintenanceManager.setMaintDateTime(newMesh, LocalDateTime.now().plusDays(7));
|
|
newMesh.setLoc(newMesh.getLoc());
|
|
InterestManager.setObjectDirty(newMesh);
|
|
|
|
return true;
|
|
}
|
|
|
|
private boolean createWarehouse(PlayerCharacter player, PlacementInfo buildingInfo, Zone currentZone) {
|
|
|
|
Blueprint blueprint;
|
|
Building newMesh = null;
|
|
Building warehouseBuilding;
|
|
|
|
blueprint = Blueprint.getBlueprint(buildingInfo.getBlueprintUUID());
|
|
|
|
if (blueprint == null) {
|
|
Logger.error("CreateWarehouse: DB returned null blueprint.");
|
|
return false;
|
|
}
|
|
|
|
Vector3fImmutable localLoc = new Vector3fImmutable(ZoneManager.worldToLocal(buildingInfo.getLoc(), currentZone));
|
|
|
|
float buildingRotation = buildingInfo.getRot().y;
|
|
float vendorRotation = buildingInfo.getW();
|
|
|
|
City city = City.getCity(currentZone.playerCityUUID);
|
|
|
|
warehouseBuilding = DbManager.BuildingQueries.CREATE_BUILDING(
|
|
currentZone.getObjectUUID(), player.getObjectUUID(), blueprint.getName(), blueprint.getMeshForRank(0),
|
|
localLoc, 1.0f, blueprint.getMaxHealth(0), ProtectionState.NONE, 0, 0,
|
|
DateTime.now().plusHours(blueprint.getRankTime(1)), blueprint.getMeshForRank(0), vendorRotation, buildingRotation);
|
|
|
|
if (warehouseBuilding == null) {
|
|
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
return false;
|
|
}
|
|
|
|
Warehouse warehouse = new Warehouse(warehouseBuilding);
|
|
Warehouse.destroyedWarehouses.values().removeIf(destroyed -> destroyed.city == city);
|
|
city.warehouse = warehouse;
|
|
DbManager.WarehouseQueries.UPDATE_WAREHOUSE(warehouse);
|
|
|
|
// Load the building into the simulation
|
|
|
|
warehouseBuilding.setObjectTypeMask(MBServerStatics.MASK_BUILDING);
|
|
MaintenanceManager.setMaintDateTime(warehouseBuilding, LocalDateTime.now().plusDays(7));
|
|
warehouseBuilding.setLoc(warehouseBuilding.getLoc());
|
|
InterestManager.setObjectDirty(warehouseBuilding);
|
|
warehouseBuilding.runAfterLoad();
|
|
|
|
if (city == null)
|
|
return true;
|
|
|
|
return true;
|
|
}
|
|
} |