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.

427 lines
15 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 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;
1 year ago
if (msg.unknown03 != 0 && msg.pToken == 0 && msg.sToken == 0)
isRandom = true;
1 year ago
// 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.slots_used = 0;
workOrder.msg_size = msg.size;
// Validate vendor can roll this item
if (ForgeManager.validate(player, workOrder) == false)
return true;
// Start rolling the item(s)
ForgeManager.submit(workOrder);
//Create Multiple Item Function.. Fill all empty slots
1 year ago
if (msg.size > 0) {
int emptySlots = vendorNPC.getRank() - vendorNPC.getRolling().size();
1 year ago
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<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.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<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();
}
}