// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com package engine.gameManager; import engine.loot.WorkOrder; import engine.mbEnums; import engine.objects.Item; import engine.objects.ItemTemplate; import engine.objects.PlayerCharacter; import engine.powers.EffectsBase; import org.pmw.tinylog.Logger; import java.util.HashMap; import java.util.concurrent.BlockingQueue; import java.util.concurrent.DelayQueue; import java.util.concurrent.atomic.AtomicInteger; public enum ForgeManager implements Runnable { FORGE_MANAGER; private static final BlockingQueue workOrders = new DelayQueue(); public static final AtomicInteger wordOrderCounter = new AtomicInteger(0); public static HashMap oven = new HashMap(); @Override public void run() { while (true) { try { WorkOrder workOrder = workOrders.take(); // Completed or canceled work orders are not re-enqueued if (workOrder.runCanceled || workOrder.runCompleted) continue; // Create negative ID items to add to collections for (int i = 0; i < workOrder.slotCount; ++i) { // Create workOrder items; one for each slot // assigned to this workOrder. // if Prefix and suffix are null random roll item // otherwise roll what was asked for workOrder.total_produced = workOrder.total_produced + 1; } Logger.info("item forged:" + workOrder.workOrderID + " (" + workOrder.total_produced + "/" + workOrder.total_to_produce + ")"); if (workOrder.total_produced >= workOrder.total_to_produce) { Logger.info("Workorder has completed: " + workOrder.workOrderID); workOrder.runCompleted = true; workOrder.vendor.workOrders.remove(workOrder); continue; } // Persist current items that are cooking // after removing the negative id item from all collections. // Add new item to the vendors inventory // Resubmit workOrder workOrder.completionTime = System.currentTimeMillis() + workOrder.rollingDuration; workOrders.add(workOrder); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void start() { Thread forgeManager; forgeManager = new Thread(FORGE_MANAGER); forgeManager.setName("Forge Manager"); forgeManager.start(); } public static void submit(WorkOrder workOrder) { workOrder.workOrderID = wordOrderCounter.incrementAndGet(); workOrder.completionTime = System.currentTimeMillis() + workOrder.rollingDuration; workOrder.slotCount = calcAvailableSlots(workOrder); workOrder.rollingDuration = ForgeManager.calcRollingDuration(workOrder); // Cost to execute this workOrder workOrder.production_cost = calcProductionCost(workOrder); for (mbEnums.ResourceType resourceType : workOrder.production_cost.keySet()) workOrder.production_cost.compute(resourceType, (k, resourceValue) -> resourceValue * workOrder.total_to_produce); // Single item rolls are total_to_produce of 0; if (workOrder.slotCount > 0 && workOrder.total_to_produce == 0) workOrder.slotCount = 1; // Create negative ID items to add to collections for (int i = 0; i < workOrder.slotCount; ++i) { // Create workOrder items; one for each slot // assigned to this workOrder. // if Prefix and suffix are null random roll item // otherwise roll what was asked for workOrder.total_produced = workOrder.total_produced + 1; } Logger.info(workOrder.toString()); workOrder.vendor.workOrders.add(workOrder); workOrders.add(workOrder); } public static boolean validate(PlayerCharacter playerCharacter, WorkOrder workOrder) { // use Warehouse.caclulateOverdraft(workorder) method return true; } public static long calcRollingDuration(WorkOrder workOrder) { long rollingDuration; float rate = (float) (2.5 * (workOrder.vendor.getBuilding().getRank() - 1)); float baseTime = (20 - rate) * 60000; ItemTemplate template = ItemTemplate.templates.get(workOrder.templateID); // Bane circles if (template.item_bane_rank > 0) baseTime = template.item_bane_rank * 60 * 60 * 3 * 1000; rollingDuration = (long) (baseTime * Float.parseFloat(ConfigManager.MB_PRODUCTION_RATE.getValue())); return rollingDuration; } public static int calcAvailableSlots(WorkOrder workOrder) { // Slots available in a forge are based on the npc rank int availableSlots = workOrder.vendor.getRank(); // Slots currently used up by the npc workOrders for (WorkOrder npcWorkOrder : workOrder.vendor.workOrders) availableSlots = availableSlots - npcWorkOrder.slotCount; // Slot count override for single item production if (workOrder.total_to_produce == 0 && availableSlots > 1) availableSlots = 1; return availableSlots; } public static HashMap calcProductionCost(WorkOrder workOrder) { // Calculate the production cost for a single run of this workOrder HashMap production_cost = new HashMap<>(); ItemTemplate template = ItemTemplate.templates.get(workOrder.templateID); // Add gold and resource costs from template production_cost.put(mbEnums.ResourceType.GOLD, template.item_value); production_cost.putAll(template.item_resource_cost); // Calculate cost of prefix and suffix if (workOrder.prefixToken != 0) { EffectsBase prefix = PowersManager.getEffectByToken(workOrder.prefixToken); EffectsBase prefixValue = PowersManager.getEffectByIDString(prefix.getIDString() + 'A'); production_cost.putAll(prefixValue.getResourcesForEffect()); } if (workOrder.suffixToken != 0) { EffectsBase suffix = PowersManager.getEffectByToken(workOrder.suffixToken); EffectsBase suffixValue = PowersManager.getEffectByIDString(suffix.getIDString() + 'A'); production_cost.putAll(suffixValue.getResourcesForEffect()); } return production_cost; } }