diff --git a/src/engine/gameManager/MaintenanceManager.java b/src/engine/gameManager/MaintenanceManager.java index c657b124..5a3a8505 100644 --- a/src/engine/gameManager/MaintenanceManager.java +++ b/src/engine/gameManager/MaintenanceManager.java @@ -5,327 +5,206 @@ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com - package engine.gameManager; - // Defines static methods which comprise the magicbane // building maintenance system. - import engine.Enum; import engine.objects.*; import org.pmw.tinylog.Logger; - import java.time.LocalDateTime; import java.util.ArrayList; - +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; public enum MaintenanceManager { - MAINTENANCEMANAGER; - public static void setMaintDateTime(Building building, LocalDateTime maintDate) { - building.maintDateTime = maintDate; DbManager.BuildingQueries.updateMaintDate(building); - } - - public static void processBuildingMaintenance() { - - ArrayList buildingList; - ArrayList maintList; - ArrayList derankList = new ArrayList<>(); - - Logger.info("Starting Maintenance on Player Buildings"); - - // Build list of buildings to apply maintenance on. - - buildingList = new ArrayList(DbManager.getList(Enum.GameObjectType.City)); - maintList = buildMaintList(buildingList); - - // Deduct upkeep and build list of buildings - // which did not have funds available - - for (Building building : maintList) { - - if (chargeUpkeep(building) == false) - derankList.add(building); - } - // Reset maintenance dates for these buildings - - for (Building building : maintList) { - if(derankList.contains(building) == false) - setMaintDateTime(building, LocalDateTime.now().plusDays(7)); - else - setMaintDateTime(building, LocalDateTime.now().plusDays(1)); - + public static void dailyMaintenance() { + Logger.info("Maintenance has started"); + // Run maintenance on player buildings + if (ConfigManager.MB_WORLD_MAINTENANCE.getValue().equalsIgnoreCase("true")) + processMaintenance(); + else + Logger.info("Maintenance Costings: DISABLED"); + Logger.info("Maintenance has completed!"); + } + public static void processMaintenance() { + //create list of all cities + ConcurrentHashMap worldCities = DbManager.getMap(Enum.GameObjectType.City); + //loop all cities + for (AbstractGameObject ago : worldCities.values()) { + if (ago.getObjectType().equals(Enum.GameObjectType.City)) { + City city = (City) ago; + if(city == null || !city.getParent().isPlayerCity()) + continue; + Building tol = city.getTOL(); + if(tol == null) + continue; + LocalDateTime maintenanceDueDate = tol.maintDateTime.withHour(1).withMinute(0).withSecond(0); + LocalDateTime now = LocalDateTime.now(); + if(now.isAfter(maintenanceDueDate)) + processTolMaintenance(tol, city.getWarehouse()); + } } - // Derak or destroy buildings that did not - // have funds available. - - for (Building building : derankList) - building.destroyOrDerank(null); - - Logger.info("Structures: " + buildingList.size() + " Maint: " + maintList.size() + " Derank: " + derankList.size()); } - - // Iterate over all buildings in game and apply exclusion rules - // returning a list of building for which maintenance is due. - - private static ArrayList buildMaintList(ArrayList buildingList) { - - ArrayList maintList = new ArrayList<>(); - - for (AbstractGameObject gameObject : buildingList) { - - Building building = ((City)gameObject).getTOL();//(Building) gameObject; - - if(building == null) - continue; - - // No maintenance on NPC owned buildings (Cache loaded) - - if (building.getProtectionState() == Enum.ProtectionState.NPC) - continue; - - // No maintenance on constructing meshes - - if (building.getRank() < 1) - continue; - - // No Maintenance on furniture - - if (building.parentBuildingID != 0) - continue; - - // No Blueprint? - - if (building.getBlueprint() == null) { - Logger.error("Blueprint missing for uuid: " + building.getObjectUUID()); - continue; + public static void processTolMaintenance(Building tol, Warehouse warehouse){ + if(tol == null) + return; + if(tol.getRank() == 8) + handleR8(tol,warehouse); + else + handleNormal(tol,warehouse); + } + public static void handleNormal(Building tol, Warehouse warehouse){ + //handle r7 and lower ToL maintenance + int goldDue = 3000000; + //enough on strongbox alone to pay + if (tol.getStrongboxValue() >= goldDue) { + tol.maintDateTime = LocalDateTime.now().plusDays(7); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.setStrongboxValue(tol.getStrongboxValue() - goldDue); } - - // No maintenance on banestones omfg - - if (building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.BANESTONE)) - continue; - - // no maintenance on Mines omfg - - if (building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.MINE)) - continue; - - // Null Maintenance date? - - if (building.maintDateTime == null) { - Logger.error("Null maint date for building UUID: " + building.getObjectUUID()); - continue; + return; + } + int newStrongboxValue = tol.getStrongboxValue(); + int newWarehouseGold = 0; + if(warehouse != null && warehouse.getResources().get(ItemBase.getItemBase(7)) != null) { + newWarehouseGold = warehouse.getResources().get(ItemBase.getItemBase(7)); + } else{ + //wasnt enough on strongbox and gold in warehouse is empty + tol.maintDateTime = LocalDateTime.now().plusDays(1); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.destroyOrDerank(null); } - - // Maintenance date is in the future - - if (building.maintDateTime.isAfter(LocalDateTime.now())) - continue; - - - //no maintenance if day of week doesnt match - if (LocalDateTime.now().getDayOfWeek().ordinal() != building.maintDateTime.getDayOfWeek().ordinal()) { - continue; + return; + } + //some on strongbox to pay + if (tol.getStrongboxValue() > 0) { + newStrongboxValue = 0; + goldDue -= tol.getStrongboxValue(); + } + if(newWarehouseGold < goldDue){ + //not enough gold to pay, you miss maintenance + tol.maintDateTime = LocalDateTime.now().plusDays(1); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.destroyOrDerank(null); } - // Add building to maintenance queue - - maintList.add(building); + return; } - - return maintList; - } - - // Method removes the appropriate amount of gold/resources from - // a building according to it's maintenance schedule. True/False - // is returned indicating if the building had enough funds to cover. - - public static boolean chargeUpkeep(Building building) { - - City city = null; - Warehouse warehouse = null; - int maintCost = 0; - int overDraft = 0; - boolean hasFunds = false; - boolean hasResources = false; - int resourceValue = 0; - - city = building.getCity(); - - if (city != null) - warehouse = city.getWarehouse(); - - // Cache maintenance cost value - - //maintCost = building.getMaintCost(); - maintCost = 3000000; - - // Something went wrong. Missing buildinggroup from switch? - - if (maintCost == 0) { - Logger.error("chargeUpkeep", "Error retrieving rankcost for " + building.getName() + " uuid:" + building.getObjectUUID() + "buildinggroup:" + building.getBlueprint().getBuildingGroup().name()); - // check if there is enough gold on the building - return true; + newWarehouseGold -= goldDue; + tol.maintDateTime = LocalDateTime.now().plusDays(7); + if(DbManager.BuildingQueries.updateMaintDate(tol) && DbManager.WarehouseQueries.updateGold(warehouse,newWarehouseGold)) { + warehouse.getResources().put(ItemBase.getItemBase(7), newWarehouseGold); + tol.setStrongboxValue(newStrongboxValue); } - - if (building.getStrongboxValue() >= maintCost) - hasFunds = true; - - // If we cannot cover with just the strongbox - // see if there is a warehouse that will cover - // the overdraft for us. - - - if (hasFunds == false && (building.assetIsProtected() || building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.WAREHOUSE)) { - overDraft = maintCost - building.getStrongboxValue(); + } + public static void handleR8(Building tol, Warehouse warehouse){ + //handle r8 ToL maintenance + //cannot pay r8 maintenance without a warehouse + if(warehouse == null && DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.destroyOrDerank(null); + tol.maintDateTime = LocalDateTime.now().plusDays(1); + return; } - - if ((overDraft > 0)) - if ((building.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.SHRINE) == false) && - (warehouse != null) && building.assetIsProtected() == true && - (warehouse.getResources().get(ItemBase.GOLD_ITEM_BASE)) >= overDraft) { - hasFunds = true; + //handle resource processing + int goldDue = 3000000; + int galvorDue = 5; + int wormwoodDue = 5; + int stoneDue = 5000; + int lumberDue = 5000; + int goldStrongBox = tol.getStrongboxValue(); + int goldWarehouse = 0; + int galvorWarehouse; + int wormwoodWarehouse; + int stoneWarehouse; + int lumberWarehouse; + if(warehouse.getResources().get(Warehouse.galvorIB) != null) { + galvorWarehouse = warehouse.getResources().get(Warehouse.galvorIB); + }else { + tol.maintDateTime = LocalDateTime.now().plusDays(1); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.destroyOrDerank(null); } - - // If this is an R8 tree, validate that we can - // cover the resources required - - if (building.getRank() == 8) { - - hasResources = true; - - if (warehouse == null) - hasResources = false; - else { - - resourceValue = warehouse.getResources().get(Warehouse.stoneIB); - - if (resourceValue < 1500) - hasResources = false; - - resourceValue = warehouse.getResources().get(Warehouse.lumberIB); - - if (resourceValue < 1500) - hasResources = false; - - resourceValue = warehouse.getResources().get(Warehouse.galvorIB); - - if (resourceValue < 5) - hasResources = false; - - resourceValue = warehouse.getResources().get(Warehouse.wormwoodIB); - - if (resourceValue < 5) - hasResources = false; - + return; + } + if(warehouse.getResources().get(Warehouse.stoneIB) != null) { + stoneWarehouse = warehouse.getResources().get(Warehouse.stoneIB); + }else { + tol.maintDateTime = LocalDateTime.now().plusDays(1); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.destroyOrDerank(null); } + return; } - // Validation completed but has failed. We can derank - // the target building and early exit - - if ((hasFunds == false) || - ((building.getRank() == 8) && !hasResources)) { - - // Add cash back to strongbox for lost rank if the building isn't being destroyed - // and it's not an R8 deranking - - //if ((building.getRank() > 1) && (building.getRank() < 8)) { - // building.setStrongboxValue(building.getStrongboxValue() + building.getBlueprint().getRankCost(Math.min(building.getRank(), 7))); - //} - - return false; // Early exit for having failed to meet maintenance + if(warehouse.getResources().get(Warehouse.wormwoodIB) != null) { + wormwoodWarehouse = warehouse.getResources().get(Warehouse.wormwoodIB); + }else { + tol.maintDateTime = LocalDateTime.now().plusDays(1); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.destroyOrDerank(null); + } + return; } - - // Remove cash and resources - - // withdraw what we can from the building - - building.setStrongboxValue(building.getStrongboxValue() - (maintCost - overDraft)); - - // withdraw overdraft from the whorehouse - - if (overDraft > 0) { - - resourceValue = warehouse.getResources().get(Warehouse.goldIB); - - if (DbManager.WarehouseQueries.updateGold(warehouse, resourceValue - overDraft) == true) { - warehouse.getResources().put(Warehouse.goldIB, resourceValue - overDraft); - warehouse.AddTransactionToWarehouse(Enum.GameObjectType.Building, building.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.GOLD, overDraft); - } else { - Logger.error("gold update failed for warehouse of UUID:" + warehouse.getObjectUUID()); - return true; + if(warehouse.getResources().get(Warehouse.lumberIB) != null) { + lumberWarehouse = warehouse.getResources().get(Warehouse.lumberIB); + }else { + tol.maintDateTime = LocalDateTime.now().plusDays(1); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.destroyOrDerank(null); } + return; } - - // Early exit as we're done if we're not an R8 tree - - if (building.getRank() < 8) - return true; - - // Now for the resources if it's an R8 tree - - // Withdraw Stone - - resourceValue = warehouse.getResources().get(Warehouse.stoneIB); - - if (DbManager.WarehouseQueries.updateStone(warehouse, resourceValue - 1500) == true) { - warehouse.getResources().put(Warehouse.stoneIB, resourceValue - 1500); - warehouse.AddTransactionToWarehouse(Enum.GameObjectType.Building, building.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.STONE, 1500); - } else { - Logger.error("stone update failed for warehouse of UUID:" + warehouse.getObjectUUID()); - return true; + boolean canPay = true; + if(goldStrongBox >= goldDue){ + goldStrongBox -= goldDue; + goldDue = 0; } - - // Withdraw Lumber - - resourceValue = warehouse.getResources().get(Warehouse.lumberIB); - - if (DbManager.WarehouseQueries.updateLumber(warehouse, resourceValue - 1500) == true) { - warehouse.getResources().put(Warehouse.lumberIB, resourceValue - 1500); - warehouse.AddTransactionToWarehouse(Enum.GameObjectType.Building, building.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.LUMBER, 1500); - } else { - Logger.error("lumber update failed for warehouse of UUID:" + warehouse.getObjectUUID()); - return true; + if (tol.getStrongboxValue() > 0) { + goldStrongBox = 0; + goldDue -= tol.getStrongboxValue(); } - - // Withdraw Galvor - - resourceValue = warehouse.getResources().get(Warehouse.galvorIB); - - if (DbManager.WarehouseQueries.updateGalvor(warehouse, resourceValue - 5) == true) { - warehouse.getResources().put(Warehouse.galvorIB, resourceValue - 5); - warehouse.AddTransactionToWarehouse(Enum.GameObjectType.Building, building.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.GALVOR, 5); - } else { - Logger.error("galvor update failed for warehouse of UUID:" + warehouse.getObjectUUID()); - return true; + if(warehouse.getResources().get(Warehouse.goldIB) != null) { + goldWarehouse = warehouse.getResources().get(Warehouse.goldIB); + }else if(goldDue > 0){ + tol.maintDateTime = LocalDateTime.now().plusDays(1); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.destroyOrDerank(null); + } + return; } - - resourceValue = warehouse.getResources().get(Warehouse.wormwoodIB); - - if (DbManager.WarehouseQueries.updateWormwood(warehouse, resourceValue - 5) == true) { - warehouse.getResources().put(Warehouse.wormwoodIB, resourceValue - 5); - warehouse.AddTransactionToWarehouse(Enum.GameObjectType.Building, building.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.WORMWOOD, 5); - } else { - Logger.error("wyrmwood update failed for warehouse of UUID:" + warehouse.getObjectUUID()); + if(wormwoodDue > wormwoodWarehouse) + canPay = false; + if(galvorDue > galvorWarehouse) + canPay = false; + if(lumberDue > lumberWarehouse) + canPay = false; + if(stoneDue > stoneWarehouse) + canPay = false; + if(goldDue > goldWarehouse) + canPay = false; + if(!canPay){ + tol.maintDateTime = LocalDateTime.now().plusDays(1); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + tol.destroyOrDerank(null); + } + return; + } + tol.setStrongboxValue(goldStrongBox); + if(DbManager.WarehouseQueries.updateGold(warehouse,goldWarehouse - goldDue)){ + if(DbManager.WarehouseQueries.updateStone(warehouse,stoneWarehouse - stoneDue)){ + if(DbManager.WarehouseQueries.updateLumber(warehouse,lumberWarehouse - lumberDue)){ + if(DbManager.WarehouseQueries.updateGalvor(warehouse,galvorWarehouse - galvorDue)){ + if(DbManager.WarehouseQueries.updateWormwood(warehouse,wormwoodWarehouse - wormwoodDue)){ + tol.maintDateTime = LocalDateTime.now().plusDays(1); + if(DbManager.BuildingQueries.updateMaintDate(tol)) { + return; + } + } + } + } + } } - - return true; - } - - public static void dailyMaintenance() { - - Logger.info("Maintenance has started"); - - // Run maintenance on player buildings - - if (ConfigManager.MB_WORLD_MAINTENANCE.getValue().equalsIgnoreCase("true")) - processBuildingMaintenance(); - else - Logger.info("Maintenance Costings: DISABLED"); - - Logger.info("Maintenance has completed!"); } -} +} \ No newline at end of file