package engine.net.client.handlers; import engine.Enum; import engine.Enum.GameObjectType; import engine.exception.MsgSendException; import engine.gameManager.BuildingManager; import engine.gameManager.DbManager; import engine.gameManager.SessionManager; import engine.net.Dispatch; import engine.net.DispatchMessage; import engine.net.client.ClientConnection; import engine.net.client.msg.*; import engine.objects.Building; import engine.objects.PlayerCharacter; import org.pmw.tinylog.Logger; import java.time.LocalDateTime; import static engine.net.client.msg.ErrorPopupMsg.sendErrorPopup; /* * * @Summary: Processes application protocol message where a * client requests that a building be upgraded. */ public class UpgradeAssetMsgHandler extends AbstractClientMsgHandler { // Constructor public UpgradeAssetMsgHandler() { super(UpgradeAssetMessage.class); } @Override protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException { // Member variable declaration UpgradeAssetMessage msg; ManageCityAssetsMsg outMsg; PlayerCharacter player; int buildingUUID; Building buildingToRank; LocalDateTime dateToUpgrade; int nextRank; int rankCost; Dispatch dispatch; // Assign member variables msg = (UpgradeAssetMessage) baseMsg; // Grab pointer to the requesting player player = SessionManager.getPlayerCharacter(origin); // Grab pointer to the building from the cache buildingUUID = msg.getBuildingUUID(); buildingToRank = (Building) DbManager.getObject(GameObjectType.Building, buildingUUID); // Early exit if building not in cache. if (buildingToRank == null) { Logger.error("Attempt to upgrade null building by " + player.getName()); return true; } // Early exit for building that is already ranking if (buildingToRank.isRanking()) { Logger.error("Attempt to upgrade a building already ranking by " + player.getName()); return true; } // Calculate and set time/cost to upgrade nextRank = (buildingToRank.getRank() + 1); if (buildingToRank.getBlueprint() == null) return true; if (buildingToRank.getBlueprint().getMaxRank() < nextRank || nextRank == 8){ ErrorPopupMsg.sendErrorMsg(player, "Building is already at it's Max rank."); return true; } rankCost = buildingToRank.getBlueprint().getRankCost(nextRank); // SEND NOT ENOUGH GOLD ERROR if (!buildingToRank.hasFunds(rankCost)){ ErrorPopupMsg.sendErrorPopup(player, 127); // Not enough gold in strongbox return true; } if (rankCost > buildingToRank.getStrongboxValue()) { sendErrorPopup(player, 127); return true; } // Validation appears good. Let's now process the upgrade try { if (buildingToRank.getCity() != null){ buildingToRank.getCity().transactionLock.writeLock().lock(); try{ if (!buildingToRank.transferGold(-rankCost,false)) { sendErrorPopup(player, 127); return true; } }catch(Exception e){ Logger.error(e); }finally{ buildingToRank.getCity().transactionLock.writeLock().unlock(); } }else if (!buildingToRank.transferGold(-rankCost,false)) { sendErrorPopup(player, 127); return true; } dateToUpgrade = LocalDateTime.now().plusHours(buildingToRank.getBlueprint().getRankTime(nextRank)); BuildingManager.setUpgradeDateTime(buildingToRank, dateToUpgrade, 0); // Schedule upgrade job BuildingManager.submitUpgradeJob(buildingToRank); // Refresh the client's manage asset window // *** Refactor : We have some of these unknowns outMsg = new ManageCityAssetsMsg(player, buildingToRank); // Action TYPE outMsg.actionType = 3; outMsg.setTargetType(buildingToRank.getObjectType().ordinal()); outMsg.setTargetID(buildingToRank.getObjectUUID()); outMsg.setTargetType3(buildingToRank.getObjectType().ordinal()); outMsg.setTargetID3(buildingToRank.getObjectUUID()); outMsg.setAssetName1(buildingToRank.getName()); outMsg.setUnknown54(1); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); } catch (Exception e) { PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity"); } return true; } }