// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com package engine.net.client.handlers; import engine.exception.MsgSendException; import engine.gameManager.ChatManager; import engine.gameManager.DbManager; import engine.gameManager.ForgeManager; import engine.loot.WorkOrder; import engine.mbEnums; import engine.mbEnums.GameObjectType; import engine.mbEnums.ItemType; import engine.net.Dispatch; import engine.net.DispatchMessage; import engine.net.client.ClientConnection; import engine.net.client.msg.ClientNetMsg; import engine.net.client.msg.ErrorPopupMsg; import engine.net.client.msg.ItemProductionMsg; import engine.net.client.msg.ManageNPCMsg; import engine.objects.*; import org.pmw.tinylog.Logger; import java.util.HashMap; /* * @Summary: Processes application protocol message which modifies * hireling inventory through rolling, junking or depositing. */ public class ItemProductionMsgHandler extends AbstractClientMsgHandler { public ItemProductionMsgHandler() { super(ItemProductionMsg.class); } @Override protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException { // Member variable declaration PlayerCharacter player; NPC vendorNPC; ItemProductionMsg msg; Dispatch dispatch; // Member variable assignment msg = (ItemProductionMsg) baseMsg; player = origin.getPlayerCharacter(); if (player == null) return true; // Grab reference to vendor we are interacting with vendorNPC = (NPC) DbManager.getObject(mbEnums.GameObjectType.NPC, msg.npcUUID); // Oops? if (vendorNPC == null) return true; // Process Request switch (msg.actionType) { case PRODUCE: boolean isRandom = false; if (msg.unknown03 != 0 && msg.pToken == 0 && msg.sToken == 0) isRandom = true; // Create new work order WorkOrder workOrder = new WorkOrder(); workOrder.total_to_produce = msg.total_to_produce; workOrder.vendor = vendorNPC; workOrder.templateID = msg.templateID; workOrder.prefixToken = msg.pToken; workOrder.suffixToken = msg.sToken; workOrder.item_name_override = msg.name; workOrder.multiple_slot_request = msg.size; // Submit workOder to begin rolling items int validation_result = ForgeManager.submit(workOrder); // workOrder cannot be completed if (validation_result != 0) { ErrorPopupMsg.sendErrorPopup(player, validation_result); return true; } //Create Multiple Item Function.. Fill all empty slots if (msg.size > 0) { int emptySlots = vendorNPC.getRank() - vendorNPC.getRolling().size(); if (emptySlots > 0) for (int i = 0; i < emptySlots; i++) vendorNPC.produceItem(player.getObjectUUID(), msg.total_to_produce, isRandom, msg.pToken, msg.sToken, msg.name, msg.templateID); } else vendorNPC.produceItem(player.getObjectUUID(), msg.total_to_produce, isRandom, msg.pToken, msg.sToken, msg.name, msg.templateID); break; case JUNK: junkItem(msg.templateID, vendorNPC, origin); break; case RECYCLE: recycleItem(msg.items, vendorNPC, origin); msg.actionType = mbEnums.ProductionActionType.TAKE; dispatch = Dispatch.borrow(player, msg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); break; case COMPLETE: vendorNPC.completeItem(msg.templateID); break; case DEPOSIT: depositItem(msg.templateID, vendorNPC, origin); break; case SETPRICE: setItemPrice(msg.itemType, msg.templateID, msg.itemPrice, vendorNPC, origin); break; case TAKE: takeItem(msg.items, vendorNPC, origin); dispatch = Dispatch.borrow(player, msg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); break; } return true; } private static void setItemPrice(int itemType, int itemUUID, int itemPrice, NPC vendor, ClientConnection origin) { Item targetItem; ItemProductionMsg outMsg; Dispatch dispatch; PlayerCharacter player = origin.getPlayerCharacter(); if (player == null) return; if (itemType == GameObjectType.Item.ordinal()) targetItem = Item.getFromCache(itemUUID); else if (itemType == GameObjectType.MobLoot.ordinal()) targetItem = MobLoot.getFromCache(itemUUID); else targetItem = null; if (targetItem == null) return; if (targetItem.getObjectType() == GameObjectType.Item) { if (!DbManager.ItemQueries.UPDATE_VALUE(targetItem, itemPrice)) { ChatManager.chatInfoError(origin.getPlayerCharacter(), "Failed to set price! Contact CCR For help."); return; } targetItem.setValue(itemPrice); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.DEPOSIT.ordinal(), true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.SETPRICE.ordinal(), true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); } else if (targetItem.getObjectType() == GameObjectType.MobLoot) { MobLoot mobLoot = (MobLoot) targetItem; if (!DbManager.NPCQueries.UPDATE_ITEM_PRICE(mobLoot.getObjectUUID(), vendor.getObjectUUID(), itemPrice)) { ChatManager.chatInfoError(origin.getPlayerCharacter(), "Failed to set price! Contact CCR For help."); return; } targetItem.setValue(itemPrice); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.DEPOSIT.ordinal(), true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.SETPRICE.ordinal(), true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); } } // Method sets the price on an item in the vendor inventory private static void depositItem(int itemUUID, NPC vendor, ClientConnection origin) { Item targetItem; ItemProductionMsg outMsg; CharacterItemManager itemMan; Dispatch dispatch; PlayerCharacter player = origin.getPlayerCharacter(); if (player == null) return; if (origin.sellLock.tryLock()) { try { targetItem = Item.getFromCache(itemUUID); if (targetItem == null) return; if (targetItem.template.item_type.equals(ItemType.GOLD)) return; if (!vendor.charItemManager.hasRoomInventory(targetItem.template.item_wt)) { ErrorPopupMsg.sendErrorPopup(player, 21); return; } itemMan = origin.getPlayerCharacter().charItemManager; if (itemMan == null) return; if (vendor.charItemManager.getInventoryWeight() > 500) { ErrorPopupMsg.sendErrorPopup(player, 21); return; } if (!targetItem.validForInventory(origin, player, itemMan)) { ErrorPopupMsg.sendErrorPopup(player, 19); return; } // Transfer item from player to vendor's inventory if (!itemMan.sellToNPC(targetItem, vendor)) { ErrorPopupMsg.sendErrorPopup(player, 109); return; } outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.DEPOSIT.ordinal(), true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.CONFIRM_DEPOSIT.ordinal(), true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); origin.getPlayerCharacter().charItemManager.updateInventory(); } catch (Exception e) { Logger.error(e); } finally { origin.sellLock.unlock(); } } } // Method completes an item that has been previously rolled // adding it to the NPC's inventory private static void recycleItem(HashMap itemList, NPC vendor, ClientConnection origin) { Item targetItem; ItemProductionMsg outMsg; int totalValue = 0; Dispatch dispatch; if (vendor.getBuilding() == null) return; PlayerCharacter player = origin.getPlayerCharacter(); if (player == null) return; if (itemList == null) return; if (origin.sellLock.tryLock()) { try { for (int itemUUID : itemList.keySet()) { int itemValue = 0; int type = itemList.get(itemUUID); if (type == GameObjectType.Item.ordinal()) targetItem = Item.getFromCache(itemUUID); else targetItem = MobLoot.getFromCache(itemUUID); if (targetItem == null) continue; if (targetItem.template.item_type.equals(ItemType.GOLD)) return; if (!vendor.charItemManager.doesCharOwnThisItem(targetItem.getObjectUUID())) continue; if (vendor.charItemManager.inventoryContains(targetItem) == false) continue; itemValue = targetItem.template.item_value; if (vendor.getBuilding().getStrongboxValue() + itemValue > vendor.getBuilding().getMaxGold()) { ErrorPopupMsg.sendErrorPopup(player, 201); break; } switch (targetItem.template.item_type) { case EMPLOYMENTCONTRACT: case CHARTER: case DEED: case REALMCHARTER: case SCROLL: case POTION: continue; } totalValue += itemValue; vendor.charItemManager.recycle(targetItem); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.TAKE.ordinal(), true); dispatch = Dispatch.borrow(origin.getPlayerCharacter(), outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); } // Refund a portion of the gold if (!vendor.getBuilding().transferGold(totalValue, false)) return; } catch (Exception e) { Logger.error(e); } finally { origin.sellLock.unlock(); } } } // Method handles recycling of an item private static void junkItem(int itemUUID, NPC vendor, ClientConnection origin) { MobLoot targetItem; ManageNPCMsg outMsg; Dispatch dispatch; if (origin.sellLock.tryLock()) { try { targetItem = MobLoot.getFromCache(itemUUID); PlayerCharacter player = origin.getPlayerCharacter(); if (player == null) return; // junk nothing? if (targetItem == null) return; if (!vendor.charItemManager.forgeContains(targetItem, vendor)) return; // Cannot junk items without a forge! if (vendor.getBuilding() == null) return; // Delete the item and cancel any pending rolling timer jobs targetItem.recycle(vendor); vendor.removeItemFromForge(targetItem); // Refresh vendor's inventory to client outMsg = new ManageNPCMsg(vendor); outMsg.setMessageType(1); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY); } finally { origin.sellLock.unlock(); } } } private static void takeItem(HashMap itemList, NPC vendor, ClientConnection origin) { Item targetItem; PlayerCharacter player = origin.getPlayerCharacter(); if (player == null) return; for (int itemUUID : itemList.keySet()) { int type = itemList.get(itemUUID); if (type == GameObjectType.Item.ordinal()) { targetItem = Item.getFromCache(itemUUID); } else targetItem = MobLoot.getFromCache(itemUUID); if (targetItem == null) return; if (targetItem.template.item_type.equals(ItemType.GOLD)) return; if (vendor.charItemManager.inventoryContains(targetItem) == false) return; if (player.charItemManager.hasRoomInventory(targetItem.template.item_wt) == false) return; player.charItemManager.buyFromNPC(targetItem, vendor); } player.charItemManager.updateInventory(); } }