// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . // ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· // ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ // ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ // ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ // Magicbane Emulator Project © 2013 - 2022 // www.magicbane.com package engine.net.client.handlers; import engine.Enum; import engine.Enum.GameObjectType; import engine.Enum.ItemType; import engine.exception.MsgSendException; import engine.gameManager.ChatManager; import engine.gameManager.DbManager; 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 { private static final int ACTION_PRODUCE = 1; private static final int ACTION_JUNK = 2; private static final int ACTION_RECYCLE = 3; private static final int ACTION_COMPLETE = 4; private static final int ACTION_DEPOSIT = 6; private static final int ACTION_SETPRICE = 5; private static final int ACTION_TAKE = 7; private static final int ACTION_CONFIRM_SETPRICE = 9; // Unsure. Sent by client private static final int ACTION_CONFIRM_DEPOSIT = 10; // Unsure. Sent by client private static final int ACTION_CONFIRM_TAKE = 11; // Unsure. Sent by client public ItemProductionMsgHandler() { super(ItemProductionMsg.class); } 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, ACTION_DEPOSIT, true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_SETPRICE, true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.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, ACTION_DEPOSIT, true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_SETPRICE, true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); } // Set item's price } // 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.getItemBase().getType() == ItemType.GOLD) return; if (!vendor.getCharItemManager().hasRoomInventory(targetItem.template.item_wt)) { ErrorPopupMsg.sendErrorPopup(player, 21); return; } itemMan = origin.getPlayerCharacter().getCharItemManager(); if (itemMan == null) return; if (vendor.getCharItemManager().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, ACTION_DEPOSIT, true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_CONFIRM_DEPOSIT, true); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); origin.getPlayerCharacter().getCharItemManager().updateInventory(); } catch (Exception e) { Logger.error(e); } finally { origin.sellLock.unlock(); } } } // Method adds an item from the players inventory to the vendor. private static void completeItem(int itemUUID, NPC vendor, ClientConnection origin, ItemProductionMsg msg) { Item targetItem; ManageNPCMsg outMsg; Dispatch dispatch; PlayerCharacter player = origin.getPlayerCharacter(); if (player == null) return; if (origin.buyLock.tryLock()) { try { targetItem = Item.getFromCache(itemUUID); if (targetItem == null) return; if (!vendor.getCharItemManager().forgeContains(targetItem, vendor)) return; boolean worked = DbManager.ItemQueries.UPDATE_FORGE_TO_INVENTORY(targetItem); if (!worked) { Guild guild = vendor.getGuild(); if (guild == null) return; //ChatManager.chatGuildInfo(guild, "Failed to complete Item " + targetItem.getName()); return; } targetItem.containerType = Enum.ItemContainerType.INVENTORY; targetItem.setOwner(vendor); vendor.getCharItemManager().addItemToInventory(targetItem); vendor.removeItemFromForge(targetItem); outMsg = new ManageNPCMsg(vendor); outMsg.setMessageType(ACTION_PRODUCE); dispatch = Dispatch.borrow(player, outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); } finally { origin.buyLock.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; int currentStrongbox; 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.getItemBase().getType() == ItemType.GOLD) return; if (!vendor.getCharItemManager().doesCharOwnThisItem(targetItem.getObjectUUID())) continue; if (vendor.getCharItemManager().inventoryContains(targetItem) == false) continue; itemValue = targetItem.template.item_value; if (vendor.getBuilding().getStrongboxValue() + itemValue > vendor.getBuilding().getMaxGold()) { ErrorPopupMsg.sendErrorPopup(player, 201); break; } switch (targetItem.getItemBase().getType()) { case CONTRACT: case GUILDCHARTER: case DEED: case REALMCHARTER: case SCROLL: case TEARS: itemValue = 0; continue; } totalValue += itemValue; long start = System.currentTimeMillis(); vendor.getCharItemManager().recycle(targetItem); long end = System.currentTimeMillis(); long timetook = end - start; // ChatManager.chatSystemInfo(player, "Took " + timetook + " ms to finish"); outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_TAKE, true); dispatch = Dispatch.borrow(origin.getPlayerCharacter(), outMsg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.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(); } } // Refresh vendor's inventory to client } // 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; // Can't junk nothing! if (targetItem == null) return; if (!vendor.getCharItemManager().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, Enum.DispatchChannel.SECONDARY); ; } finally { origin.sellLock.unlock(); } } } // Method junks an item that has been rolled but not completed 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.getItemBase().getType() == ItemType.GOLD) return; if (vendor.getCharItemManager().inventoryContains(targetItem) == false) return; if (player.getCharItemManager().hasRoomInventory(targetItem.template.item_wt) == false) return; player.getCharItemManager().buyFromNPC(targetItem, vendor); } player.getCharItemManager().updateInventory(); // Update NPC inventory to client } // Method removes item from an NPC's inventory and transferes it to a player @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(engine.Enum.GameObjectType.NPC, msg.getNpcUUID()); // Oops? if (vendorNPC == null) return true; // Process Request switch (msg.getActionType()) { case ACTION_PRODUCE: boolean isRandom = false; if (msg.getUnknown03() != 0 && msg.getpToken() == 0 && msg.getsToken() == 0) isRandom = true; //Create Multiple Item Function.. Fill all empty slots if (msg.isMultiple()) { int emptySlots = vendorNPC.getRank() - vendorNPC.getRolling().size(); if (emptySlots > 0) { for (int i = 0; i < emptySlots; i++) { vendorNPC.produceItem(player.getObjectUUID(), msg.getTotalProduction(), isRandom, msg.getpToken(), msg.getsToken(), msg.getName(), msg.getItemUUID()); } } } else vendorNPC.produceItem(player.getObjectUUID(), msg.getTotalProduction(), isRandom, msg.getpToken(), msg.getsToken(), msg.getName(), msg.getItemUUID()); break; case ACTION_JUNK: junkItem(msg.getItemUUID(), vendorNPC, origin); break; case ACTION_RECYCLE: recycleItem(msg.getItemIDtoTypeMap(), vendorNPC, origin); msg.setActionType(7); dispatch = Dispatch.borrow(player, msg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); break; case ACTION_COMPLETE: vendorNPC.completeItem(msg.getItemUUID()); // ManageNPCMsg outMsg = new ManageNPCMsg(vendorNPC); // outMsg.setMessageType(1); // // dispatch = Dispatch.borrow(player, outMsg); // DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); break; case ACTION_DEPOSIT: depositItem(msg.getItemUUID(), vendorNPC, origin); break; case ACTION_SETPRICE: setItemPrice(msg.getItemType(), msg.getItemUUID(), msg.getItemPrice(), vendorNPC, origin); break; case ACTION_TAKE: takeItem(msg.getItemIDtoTypeMap(), vendorNPC, origin); dispatch = Dispatch.borrow(player, msg); DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY); break; } return true; } // Method handles rolling item requests from the client }