Public Repository for the Magicbane Shadowbane Emulator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

443 lines
16 KiB

// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// 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 vendor;
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
vendor = (NPC) DbManager.getObject(mbEnums.GameObjectType.NPC, msg.npcUUID);
// Oops?
if (vendor == null)
return true;
// Process Request
switch (msg.actionType) {
case PRODUCE:
1 year ago
// Create new work order
WorkOrder workOrder = new WorkOrder();
workOrder.total_to_produce = msg.total_to_produce;
workOrder.vendor = vendor;
workOrder.templateID = msg.itemUUID;
workOrder.prefixToken = msg.pToken;
workOrder.suffixToken = msg.sToken;
workOrder.item_name_override = msg.name;
workOrder.multiple_slot_request = (msg.size != 0);
// Submit workOder to begin rolling items
int validation_result = ForgeManager.submit(workOrder);
12 months ago
// workOrder could not be completed
// Report back to the user the reason why
if (validation_result != 0) {
ErrorPopupMsg.sendErrorPopup(player, validation_result);
return true;
}
12 months ago
break;
case JUNK:
junkItem(msg.itemUUID, vendor, origin);
break;
case RECYCLE:
recycleItem(msg.items, vendor, origin);
msg.actionType = mbEnums.ProductionActionType.TAKE;
dispatch = Dispatch.borrow(player, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
break;
case COMPLETE:
completeItem(msg.itemUUID, vendor);
break;
case DEPOSIT:
depositItem(msg.itemUUID, vendor, origin);
break;
case SETPRICE:
setItemPrice(msg.itemType, msg.itemUUID, msg.itemPrice, vendor, origin);
break;
case TAKE:
takeItem(msg.items, vendor, origin);
dispatch = Dispatch.borrow(player, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
break;
}
return true;
}
private static void completeItem(int itemUUID, NPC vendor) {
Item virtualItem = ForgeManager.inMemoryItemLookup.get(itemUUID);
if (virtualItem == null)
return;
//remove from client forge window
ItemProductionMsg outMsg = new ItemProductionMsg(vendor.building, vendor, virtualItem, mbEnums.ProductionActionType.SETPRICE, true);
DispatchMessage.dispatchMsgToInterestArea(vendor, outMsg, mbEnums.DispatchChannel.SECONDARY, 700, false, false);
// Add to NPC inventory
vendor.charItemManager.addItemToInventory(virtualItem);
// Remove from collections
WorkOrder workOrder = ForgeManager.itemWorkOrderLookup.get(virtualItem);
workOrder.cooking.remove(virtualItem);
ForgeManager.vendorItemLookup.get(vendor).remove(virtualItem);
ForgeManager.itemWorkOrderLookup.remove(virtualItem);
}
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, true);
dispatch = Dispatch.borrow(player, outMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.SETPRICE, 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, true);
dispatch = Dispatch.borrow(player, outMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.SETPRICE, 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, true);
dispatch = Dispatch.borrow(player, outMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.SECONDARY);
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, mbEnums.ProductionActionType.CONFIRM_DEPOSIT, 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<Integer, Integer> 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, 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) {
Item targetItem;
ManageNPCMsg outMsg;
Dispatch dispatch;
if (origin.sellLock.tryLock()) {
try {
targetItem = ForgeManager.inMemoryItemLookup.get(itemUUID);
PlayerCharacter player = origin.getPlayerCharacter();
if (player == null)
return;
// junk nothing?
if (targetItem == null)
return;
// Cannot junk items without a forge!
if (vendor.getBuilding() == null)
return;
// Delete the item
ForgeManager.inMemoryItemLookup.remove(targetItem.objectUUID);
WorkOrder workOrder = ForgeManager.itemWorkOrderLookup.get(targetItem);
workOrder.cooking.remove(targetItem);
ForgeManager.vendorItemLookup.get(workOrder.vendor).remove(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<Integer, Integer> 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();
}
}