destroyOrDerank nulled city.warehouse on destruction, so the loot click found no warehouse and returned silently. The destroyed Warehouse is now held in Warehouse.destroyedWarehouses keyed by the rubble building UUID until it is looted empty, the rubble is destroyed, or the city places a new warehouse. Contents are not persisted across a reboot. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
332 lines
13 KiB
Java
332 lines
13 KiB
Java
package engine.net.client.handlers;
|
|
|
|
import engine.gameManager.BuildingManager;
|
|
import engine.gameManager.DispatchManager;
|
|
import engine.gameManager.SessionManager;
|
|
import engine.gameManager.ZoneManager;
|
|
import engine.math.Bounds;
|
|
import engine.mbEnums;
|
|
import engine.mbEnums.DispatchChannel;
|
|
import engine.mbEnums.GameObjectType;
|
|
import engine.net.Dispatch;
|
|
import engine.net.client.ClientConnection;
|
|
import engine.net.client.msg.ClientNetMsg;
|
|
import engine.net.client.msg.ErrorPopupMsg;
|
|
import engine.net.client.msg.ManageCityAssetsMsg;
|
|
import engine.net.client.msg.PlaceAssetMsg;
|
|
import engine.objects.*;
|
|
import org.joda.time.DateTime;
|
|
|
|
/*
|
|
* @Author:
|
|
* @Summary: Processes application protocol message which opens
|
|
* and processes the various building asset management windows.
|
|
*/
|
|
public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
|
|
|
|
public ManageCityAssetMsgHandler() {
|
|
super();
|
|
}
|
|
|
|
@Override
|
|
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) {
|
|
|
|
ManageCityAssetsMsg msg;
|
|
PlayerCharacter player;
|
|
ManageCityAssetsMsg outMsg;
|
|
Building building;
|
|
|
|
msg = (ManageCityAssetsMsg) baseMsg;
|
|
|
|
player = SessionManager.getPlayerCharacter(origin);
|
|
|
|
if (player == null)
|
|
return true;
|
|
|
|
building = BuildingManager.getBuildingFromCache(msg.getTargetID());
|
|
|
|
if (building == null) {
|
|
if (msg.actionType == 14) {
|
|
|
|
Zone zone = ZoneManager.findSmallestZone(player.getLoc());
|
|
|
|
if (!zone.guild_zone) {
|
|
ErrorPopupMsg.sendErrorMsg(player, "Unable to find city to command.");
|
|
return true;
|
|
}
|
|
|
|
City city = City.GetCityFromCache(zone.playerCityUUID);
|
|
|
|
if (city == null) {
|
|
ErrorPopupMsg.sendErrorMsg(player, "Unable to find city to command.");
|
|
return true;
|
|
}
|
|
|
|
if (!city.getGuild().equals(player.getGuild())) {
|
|
ErrorPopupMsg.sendErrorMsg(player, "You are not in the correct guild to command this city.");
|
|
return true;
|
|
}
|
|
|
|
if (!GuildStatusController.isInnerCouncil(player.getGuildStatus()) && !GuildStatusController.isGuildLeader(player.getGuildStatus())) {
|
|
ErrorPopupMsg.sendErrorMsg(player, "You must be an Inner Council or Guild leader to access city commands.");
|
|
return true;
|
|
}
|
|
ManageCityAssetsMsg mca = new ManageCityAssetsMsg(player, building);
|
|
mca.actionType = 15;
|
|
Dispatch dispatch = Dispatch.borrow(player, mca);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
outMsg = new ManageCityAssetsMsg(player, building);
|
|
|
|
if (player.isSafeMode()) {
|
|
outMsg.actionType = 4;
|
|
outMsg.setTargetType(building.getObjectType().ordinal());
|
|
outMsg.setTargetID(building.getObjectUUID());
|
|
outMsg.setAssetName(building.getName());
|
|
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
return true;
|
|
}
|
|
|
|
if (msg.actionType == 2 || msg.actionType == 22) {
|
|
|
|
if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup() == mbEnums.BuildingGroup.BANESTONE) {
|
|
|
|
outMsg.actionType = 18;
|
|
outMsg.setTargetType(building.getObjectType().ordinal());
|
|
outMsg.setTargetID(building.getObjectUUID());
|
|
|
|
} else if (BuildingManager.playerCanManage(player, building)) { //TODO allow Friends list.
|
|
configWindowState(player, building, outMsg);
|
|
outMsg.actionType = 3;
|
|
outMsg.setTargetType(building.getObjectType().ordinal());
|
|
outMsg.setTargetID(building.getObjectUUID());
|
|
outMsg.setTargetType3(building.getObjectType().ordinal());
|
|
outMsg.setTargetID3(building.getObjectUUID());
|
|
outMsg.setUnknown54(1);
|
|
|
|
} else {
|
|
|
|
if (building.getBlueprintUUID() != 0)
|
|
switch (building.getBlueprint().getBuildingGroup()) {
|
|
case SHRINE:
|
|
if (building.getRank() == -1) {
|
|
if (!Bounds.collide(player.getLoc(), building)) {
|
|
ErrorPopupMsg.sendErrorPopup(player, 64);
|
|
return true;
|
|
}
|
|
|
|
Shrine shrine = Shrine.shrinesByBuildingUUID.get(building.getObjectUUID());
|
|
|
|
if (shrine == null)
|
|
return true;
|
|
|
|
if (shrine.getFavors() == 0) {
|
|
ErrorPopupMsg.sendErrorPopup(player, 166); // There is no more favor in this shrine to loot
|
|
return true;
|
|
}
|
|
|
|
BuildingManager.lootBuilding(player, building);
|
|
return true;
|
|
}
|
|
break;
|
|
case WAREHOUSE:
|
|
//TODO check
|
|
if (building.getRank() == -1) {
|
|
if (!Bounds.collide(player.getLoc(), building)) {
|
|
ErrorPopupMsg.sendErrorPopup(player, 64);
|
|
return true;
|
|
}
|
|
|
|
Warehouse warehouse = Warehouse.destroyedWarehouses.get(building.getObjectUUID());
|
|
|
|
if (warehouse == null || Warehouse.isEmpty(warehouse)) {
|
|
ErrorPopupMsg.sendErrorPopup(player, 167); // no more resources.
|
|
return true;
|
|
}
|
|
|
|
BuildingManager.lootBuilding(player, building);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (building.getRank() == -1)
|
|
return true;
|
|
|
|
AbstractCharacter owner = building.getOwner();
|
|
|
|
//no owner, send building info
|
|
if (owner == null) {
|
|
msg.actionType = 4;
|
|
|
|
Dispatch dispatch = Dispatch.borrow(player, msg);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
return true;
|
|
}
|
|
outMsg.actionType = 4;
|
|
outMsg.setTargetType(building.getObjectType().ordinal());
|
|
outMsg.setTargetID(building.getObjectUUID());
|
|
outMsg.setAssetName(building.getName());
|
|
|
|
}
|
|
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
return true;
|
|
}
|
|
|
|
if (msg.actionType == 13) {
|
|
outMsg.actionType = 13;
|
|
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
return true;
|
|
}
|
|
|
|
|
|
//Rename Building.
|
|
|
|
if (msg.actionType == 5) {
|
|
|
|
//TODO we need to check names before allowing
|
|
building.setName(msg.getAssetName());
|
|
configWindowState(player, building, outMsg);
|
|
|
|
outMsg.actionType = 3;
|
|
outMsg.setTargetType(building.getObjectType().ordinal());
|
|
outMsg.setTargetID(building.getObjectUUID());
|
|
outMsg.setTargetType3(GameObjectType.Building.ordinal());
|
|
outMsg.setTargetID3(building.getObjectUUID());
|
|
outMsg.setAssetName1(building.getName());
|
|
outMsg.setUnknown54(1);
|
|
|
|
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
|
|
return true;
|
|
|
|
//TOL, update city name also
|
|
//TODO update city and zone in database
|
|
//TODO update city map data in game server
|
|
}
|
|
|
|
if (msg.actionType == 14) {
|
|
ManageCityAssetsMsg mca = new ManageCityAssetsMsg(player, building);
|
|
mca.actionType = 15;
|
|
Dispatch dispatch = Dispatch.borrow(player, mca);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
return true;
|
|
}
|
|
|
|
if (msg.actionType == 20) {
|
|
|
|
Zone baneZone = building.getParentZone();
|
|
|
|
if (baneZone == null)
|
|
return true;
|
|
|
|
City banedCity = City.getCity(baneZone.playerCityUUID);
|
|
|
|
if (banedCity == null)
|
|
return true;
|
|
|
|
Bane bane = banedCity.getBane();
|
|
|
|
if (bane == null || bane.getLiveDate() != null || player.getGuild() != banedCity.getGuild() || GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
|
|
return true;
|
|
|
|
int baneHour = msg.getBaneHour();
|
|
|
|
if (baneHour < 16 || baneHour > 24) {
|
|
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
|
return true;
|
|
}
|
|
|
|
DateTime baneLive = new DateTime(bane.getPlacementDate());
|
|
baneLive = baneHour == 24 ? baneLive.plusDays(3) : baneLive.plusDays(2);
|
|
baneLive = baneHour == 24 ? baneLive.hourOfDay().setCopy(0) : baneLive.hourOfDay().setCopy(baneHour);
|
|
baneLive = baneLive.minuteOfHour().setCopy(0);
|
|
baneLive = baneLive.secondOfMinute().setCopy(1);
|
|
bane.setLiveDate(baneLive);
|
|
outMsg.actionType = 18;
|
|
|
|
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
|
DispatchManager.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void configWindowState(PlayerCharacter player, Building building, ManageCityAssetsMsg manageCityAssetsMsg) {
|
|
|
|
// Tests to turn on upgrade button if a building is not
|
|
// at it's maximum allowed rank or currently ranking
|
|
|
|
|
|
// Owner is obviously allowed to upgrade his own buildings
|
|
|
|
if (building.getOwner().equals(player)) {
|
|
|
|
// Players cannot destroy or transfer a TOL.
|
|
|
|
if (building.getBlueprint() == null) {
|
|
manageCityAssetsMsg.buttonDestroy = 0;
|
|
manageCityAssetsMsg.buttonTransfer = 0;
|
|
manageCityAssetsMsg.buttonAbandon = 0;
|
|
manageCityAssetsMsg.buttonUpgrade = 0;
|
|
} else if (building.getBlueprint().getBuildingGroup() == mbEnums.BuildingGroup.TOL) {
|
|
manageCityAssetsMsg.buttonDestroy = 0;
|
|
manageCityAssetsMsg.buttonTransfer = 0;
|
|
manageCityAssetsMsg.buttonAbandon = 1;
|
|
manageCityAssetsMsg.buttonUpgrade = 1;
|
|
} else if (building.getBlueprint().getBuildingGroup() == mbEnums.BuildingGroup.MINE) {
|
|
manageCityAssetsMsg.buttonDestroy = 0;
|
|
manageCityAssetsMsg.buttonTransfer = 0;
|
|
manageCityAssetsMsg.buttonAbandon = 0;
|
|
manageCityAssetsMsg.buttonUpgrade = 0; // Cannot upgrade a mine
|
|
} else {
|
|
manageCityAssetsMsg.buttonDestroy = 1;
|
|
manageCityAssetsMsg.buttonTransfer = 1;
|
|
manageCityAssetsMsg.buttonAbandon = 1;
|
|
manageCityAssetsMsg.buttonUpgrade = 1;
|
|
}
|
|
}
|
|
|
|
// Inner Council of the same guild can also upgrade
|
|
|
|
if ((player.getGuild().equals(building.getGuild())) &&
|
|
GuildStatusController.isInnerCouncil(player.getGuildStatus()))
|
|
manageCityAssetsMsg.buttonUpgrade = 1;
|
|
|
|
// Disable upgrade button if at max rank.
|
|
|
|
if (building.getBlueprint() == null)
|
|
manageCityAssetsMsg.buttonUpgrade = 0;
|
|
else if (building.getRank() >= building.getBlueprint().getMaxRank())
|
|
manageCityAssetsMsg.buttonUpgrade = 0;
|
|
;
|
|
|
|
// If a building is not protected we can exit here
|
|
|
|
if (building.assetIsProtected() == false)
|
|
return;
|
|
|
|
// Protection is displayed as "UNDER SIEGE" if
|
|
// an active bane is invalidating the protection
|
|
// contracts of the city.
|
|
|
|
if ((building.getCity() != null) &&
|
|
(building.getCity().protectionEnforced == false)) {
|
|
manageCityAssetsMsg.labelProtected = 0;
|
|
manageCityAssetsMsg.labelSiege = 1;
|
|
manageCityAssetsMsg.labelCeaseFire = 0;
|
|
return;
|
|
}
|
|
|
|
// Building is currently protected by a TOL
|
|
|
|
manageCityAssetsMsg.labelProtected = 1;
|
|
}
|
|
}
|