|
|
|
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
|
|
|
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
|
|
|
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
|
|
|
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
|
|
|
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
|
|
|
// Magicbane Emulator Project © 2013 - 2022
|
|
|
|
// www.magicbane.com
|
|
|
|
|
|
|
|
|
|
|
|
package engine.objects;
|
|
|
|
|
|
|
|
import engine.Enum;
|
|
|
|
import engine.Enum.GameObjectType;
|
|
|
|
import engine.Enum.ItemType;
|
|
|
|
import engine.gameManager.BuildingManager;
|
|
|
|
import engine.gameManager.ChatManager;
|
|
|
|
import engine.gameManager.ConfigManager;
|
|
|
|
import engine.gameManager.DbManager;
|
|
|
|
import engine.math.Vector3fImmutable;
|
|
|
|
import engine.net.Dispatch;
|
|
|
|
import engine.net.DispatchMessage;
|
|
|
|
import engine.net.client.ClientConnection;
|
|
|
|
import engine.net.client.ClientMessagePump;
|
|
|
|
import engine.net.client.msg.*;
|
|
|
|
import engine.server.MBServerStatics;
|
|
|
|
import org.pmw.tinylog.Logger;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
|
|
|
|
|
|
import static engine.math.FastMath.sqr;
|
|
|
|
import static engine.net.client.msg.ErrorPopupMsg.sendErrorPopup;
|
|
|
|
|
|
|
|
|
|
|
|
public class CharacterItemManager {
|
|
|
|
|
|
|
|
private static final byte inventoryVer = (byte) 0;
|
|
|
|
private static final byte bankVer = (byte) 0;
|
|
|
|
private static final byte vaultVer = (byte) 0;
|
|
|
|
private final AbstractCharacter absCharacter;
|
|
|
|
// Mapping of all the items associated with this Manager
|
|
|
|
private final ConcurrentHashMap<Integer, Integer> itemIDtoType = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
|
|
|
// Mapping of all items equipped in this Manager
|
|
|
|
// Key = Item Slot
|
|
|
|
private final ConcurrentHashMap<Integer, Item> equipped = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_LOW);
|
|
|
|
private final HashSet<Item> inventory = new HashSet<>();
|
|
|
|
private final HashSet<Item> bank = new HashSet<>();
|
|
|
|
private final HashSet<Item> vault = new HashSet<>();
|
|
|
|
private final HashSet<Integer> equipOrder = new HashSet<>();
|
|
|
|
public Item goldVault;
|
|
|
|
private Account account;
|
|
|
|
private Item goldInventory;
|
|
|
|
private Item goldBank;
|
|
|
|
private boolean bankOpened;
|
|
|
|
private boolean vaultOpened;
|
|
|
|
private short bankWeight;
|
|
|
|
private short inventoryWeight;
|
|
|
|
private short equipWeight;
|
|
|
|
private short vaultWeight;
|
|
|
|
private ClientConnection tradingWith;
|
|
|
|
private byte tradeCommitted;
|
|
|
|
private boolean tradeSuccess;
|
|
|
|
private HashSet<Integer> trading;
|
|
|
|
private int goldTradingAmount;
|
|
|
|
private int tradeID = 0;
|
|
|
|
/*
|
|
|
|
* Item Manager Version data
|
|
|
|
*/
|
|
|
|
private byte equipVer = (byte) 0;
|
|
|
|
|
|
|
|
public CharacterItemManager(AbstractCharacter ac) {
|
|
|
|
super();
|
|
|
|
this.absCharacter = ac;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static byte getInventoryVer() {
|
|
|
|
return inventoryVer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static byte getBankVer() {
|
|
|
|
return bankVer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static byte getVaultVer() {
|
|
|
|
return vaultVer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void takeFromNPC(NPC npc, PlayerCharacter pc, Item take, ClientMessagePump clientMessagePump) {
|
|
|
|
|
|
|
|
ItemBase ib = take.getItemBase();
|
|
|
|
ItemTemplate template = take.template;
|
|
|
|
|
|
|
|
if (template == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CharacterItemManager itemMan = pc.getCharItemManager();
|
|
|
|
|
|
|
|
if (itemMan == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CharacterItemManager npcCim = npc.getCharItemManager();
|
|
|
|
|
|
|
|
if (npcCim == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!npcCim.inventoryContains(take))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!itemMan.hasRoomInventory(template.item_wt))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (take != null) {
|
|
|
|
itemMan.buyFromNPC(take, npc);
|
|
|
|
itemMan.updateInventory();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void load() {
|
|
|
|
loadForGeneric();
|
|
|
|
|
|
|
|
if (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter))
|
|
|
|
loadForPlayerCharacter();
|
|
|
|
else if (this.absCharacter.getObjectType().equals(GameObjectType.NPC))
|
|
|
|
loadForNPC();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void loadGoldItems() {
|
|
|
|
|
|
|
|
if (ConfigManager.serverType.equals(Enum.ServerType.LOGINSERVER)) {
|
|
|
|
//other server, just make generic
|
|
|
|
this.goldInventory = new MobLoot(this.absCharacter, 0);
|
|
|
|
this.goldBank = new MobLoot(this.absCharacter, 0);
|
|
|
|
this.goldVault = new MobLoot(this.absCharacter, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//create inventory gold if needed
|
|
|
|
if (this.goldInventory == null)
|
|
|
|
if (this.absCharacter != null && (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) || this.absCharacter.getObjectType().equals(GameObjectType.NPC)))
|
|
|
|
this.goldInventory = Item.newGoldItem(this.absCharacter, ItemBase.getItemBase(7), Enum.ItemContainerType.INVENTORY);
|
|
|
|
else
|
|
|
|
this.goldInventory = new MobLoot(this.absCharacter, 0);
|
|
|
|
|
|
|
|
//create bank gold if needed
|
|
|
|
if (this.goldBank == null)
|
|
|
|
if (this.absCharacter != null && this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter))
|
|
|
|
this.goldBank = Item.newGoldItem(this.absCharacter, ItemBase.getItemBase(7), Enum.ItemContainerType.BANK);
|
|
|
|
else
|
|
|
|
this.goldBank = new MobLoot(this.absCharacter, 0);
|
|
|
|
|
|
|
|
//create vault gold if needed
|
|
|
|
if (this.goldVault == null)
|
|
|
|
if (this.absCharacter != null && this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter)) {
|
|
|
|
this.goldVault = this.account.vaultGold;
|
|
|
|
} else
|
|
|
|
this.goldVault = new MobLoot(this.absCharacter, 0);
|
|
|
|
|
|
|
|
this.itemIDtoType.put(this.goldInventory.getObjectUUID(), this.goldInventory.getObjectType().ordinal());
|
|
|
|
this.itemIDtoType.put(this.goldBank.getObjectUUID(), this.goldBank.getObjectType().ordinal());
|
|
|
|
this.itemIDtoType.put(this.goldVault.getObjectUUID(), this.goldVault.getObjectType().ordinal());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private void loadForPlayerCharacter() {
|
|
|
|
ArrayList<Item> al = null;
|
|
|
|
|
|
|
|
// TODO Verify this is an actual account.
|
|
|
|
this.account = ((PlayerCharacter) this.absCharacter).getAccount();
|
|
|
|
|
|
|
|
// Get Items for player and vault
|
|
|
|
if (ConfigManager.serverType.equals(Enum.ServerType.LOGINSERVER)) //login, only need equipped items
|
|
|
|
al = DbManager.ItemQueries.GET_EQUIPPED_ITEMS(this.absCharacter.getObjectUUID());
|
|
|
|
else
|
|
|
|
al = DbManager.ItemQueries.GET_ITEMS_FOR_PC(this.absCharacter.getObjectUUID());
|
|
|
|
|
|
|
|
for (Item i : al) {
|
|
|
|
|
|
|
|
i.validateItemContainer();
|
|
|
|
this.itemIDtoType.put(i.getObjectUUID(), i.getObjectType().ordinal());
|
|
|
|
|
|
|
|
switch (i.containerType) {
|
|
|
|
case EQUIPPED:
|
|
|
|
if (this.equipped.containsValue(i) == false) {
|
|
|
|
this.equipped.put((int) i.getEquipSlot(), i);
|
|
|
|
addEquipOrder((int) i.getEquipSlot());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BANK:
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
this.goldBank = i;
|
|
|
|
else if (this.bank.contains(i) == false)
|
|
|
|
this.bank.add(i);
|
|
|
|
break;
|
|
|
|
case INVENTORY:
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
this.goldInventory = i;
|
|
|
|
else if (this.inventory.contains(i) == false)
|
|
|
|
this.inventory.add(i);
|
|
|
|
break;
|
|
|
|
case VAULT:
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
this.goldVault = i;
|
|
|
|
else if (this.vault.contains(i) == false)
|
|
|
|
this.vault.add(i);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
i.junk();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
this.goldVault = this.account.vaultGold;
|
|
|
|
|
|
|
|
//check all gold is created
|
|
|
|
//loadGoldItems();
|
|
|
|
calculateWeights();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void loadForNPC() {
|
|
|
|
ArrayList<Item> al = null;
|
|
|
|
|
|
|
|
// Get all items related to this NPC:
|
|
|
|
al = DbManager.ItemQueries.GET_ITEMS_FOR_NPC(this.absCharacter.getObjectUUID());
|
|
|
|
|
|
|
|
for (Item i : al) {
|
|
|
|
i.validateItemContainer();
|
|
|
|
this.itemIDtoType.put(i.getObjectUUID(), i.getObjectType().ordinal());
|
|
|
|
|
|
|
|
switch (i.containerType) {
|
|
|
|
case EQUIPPED:
|
|
|
|
if (this.equipped.containsValue(i) == false)
|
|
|
|
this.equipped.put((int) i.getEquipSlot(), i);
|
|
|
|
break;
|
|
|
|
case BANK:
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
this.goldBank = i;
|
|
|
|
else if (this.bank.contains(i) == false)
|
|
|
|
this.bank.add(i);
|
|
|
|
break;
|
|
|
|
case INVENTORY:
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
this.goldInventory = i;
|
|
|
|
else if (this.inventory.contains(i) == false)
|
|
|
|
this.inventory.add(i);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
i.junk();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//check all gold is created
|
|
|
|
//loadGoldItems();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void loadForGeneric() {
|
|
|
|
this.bankWeight = 0;
|
|
|
|
this.inventoryWeight = 0;
|
|
|
|
this.equipWeight = 0;
|
|
|
|
this.vaultWeight = 0;
|
|
|
|
|
|
|
|
//check all gold is created
|
|
|
|
//loadGoldItems();
|
|
|
|
// Always initialize with bank and vault closed
|
|
|
|
bankOpened = false;
|
|
|
|
vaultOpened = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Positve Amount = TO BUILDING; Negative Amount = FROM BUILDING. flip signs for Player inventory.
|
|
|
|
public synchronized boolean transferGoldToFromBuilding(int amount, AbstractWorldObject object) {
|
|
|
|
if (this.absCharacter.getObjectType() != GameObjectType.PlayerCharacter)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
PlayerCharacter player = (PlayerCharacter) this.absCharacter;
|
|
|
|
|
|
|
|
switch (object.getObjectType()) {
|
|
|
|
case Building:
|
|
|
|
Building building = (Building) object;
|
|
|
|
|
|
|
|
if (!this.getGoldInventory().validForInventory(player.getClientConnection(), player, this))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (amount < 0 && amount > building.getStrongboxValue())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Not enough gold in inventory to transfer to tree
|
|
|
|
|
|
|
|
if ((amount > 0) &&
|
|
|
|
(this.getGoldInventory().getNumOfItems() - amount < 0)) {
|
|
|
|
sendErrorPopup(player, 28);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() - amount > MBServerStatics.PLAYER_GOLD_LIMIT) {
|
|
|
|
ErrorPopupMsg.sendErrorPopup(player, 202);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Not enough gold to transfer to inventory from tree
|
|
|
|
|
|
|
|
if ((amount < 0) &&
|
|
|
|
(building.getStrongboxValue() + amount < 0)) {
|
|
|
|
sendErrorPopup(player, 127);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (amount < 0)
|
|
|
|
if (!building.hasFunds(-amount))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
//Verify player can access building to transfer goldItem
|
|
|
|
|
|
|
|
if (!BuildingManager.playerCanManage(player, building))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (building.getStrongboxValue() + amount > building.getMaxGold()) {
|
|
|
|
ErrorPopupMsg.sendErrorPopup(player, 201);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.getOwner().getCharItemManager().getGoldTrading() > 0) {
|
|
|
|
if (this.getOwner().getObjectType().equals(GameObjectType.PlayerCharacter))
|
|
|
|
ErrorPopupMsg.sendErrorPopup((PlayerCharacter) this.getOwner(), 195);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.modifyInventoryGold(-amount)) {
|
|
|
|
|
|
|
|
Logger.error(player.getName() + " transfer amount = " + amount + " ; Gold Inventory = " + this.getGoldInventory().getNumOfItems());
|
|
|
|
|
|
|
|
// ChatManager.chatSystemError(player, "You do not have this Gold.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!building.transferGold(amount, false)) {
|
|
|
|
|
|
|
|
Logger.error(player.getName() + " transfer amount = " + amount + " ; Gold Inventory = " + this.getGoldInventory().getNumOfItems() + "; Building Strongbox = " + building.getStrongboxValue());
|
|
|
|
|
|
|
|
//ChatManager.chatSystemError(player, "Something went terribly wrong. Contact CCR.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case Warehouse:
|
|
|
|
|
|
|
|
Warehouse warehouse = (Warehouse) object;
|
|
|
|
|
|
|
|
if (amount < 0) {
|
|
|
|
if (!Warehouse.deposit((PlayerCharacter) this.absCharacter, this.getGoldInventory(), amount * -1, true, true,warehouse)) {
|
|
|
|
|
|
|
|
ErrorPopupMsg.sendErrorPopup((PlayerCharacter) this.absCharacter, 203);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!Warehouse.withdraw(warehouse, (PlayerCharacter) this.absCharacter, this.getGoldInventory().getItemBase(), amount * -1, true, true)) {
|
|
|
|
|
|
|
|
ErrorPopupMsg.sendErrorPopup((PlayerCharacter) this.absCharacter, 203);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Item Controls
|
|
|
|
*/
|
|
|
|
public synchronized boolean modifyInventoryGold(int modifyValue) {
|
|
|
|
|
|
|
|
Item goldItem;
|
|
|
|
PlayerCharacter player;
|
|
|
|
boolean success = false;
|
|
|
|
|
|
|
|
goldItem = getGoldInventory();
|
|
|
|
|
|
|
|
if (goldItem == null) {
|
|
|
|
Logger.error("ModifyInventoryGold", "Could not create gold item");
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() + modifyValue > MBServerStatics.PLAYER_GOLD_LIMIT) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() + modifyValue < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// No database update for npc's gold values so we use the player object
|
|
|
|
// for flow control later on.
|
|
|
|
|
|
|
|
if (this.absCharacter.getObjectType() == GameObjectType.PlayerCharacter)
|
|
|
|
player = (PlayerCharacter) this.absCharacter;
|
|
|
|
else
|
|
|
|
player = null;
|
|
|
|
|
|
|
|
// If this is an update for a player character update the database
|
|
|
|
|
|
|
|
if (player != null)
|
|
|
|
try {
|
|
|
|
if (!DbManager.ItemQueries.UPDATE_GOLD(this.getGoldInventory(), this.goldInventory.getNumOfItems() + modifyValue)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
success = true;
|
|
|
|
} catch (Exception e) {
|
|
|
|
Logger.error("ModifyInventoryGold", "Error writing to database");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update in-game gold values for character
|
|
|
|
goldItem.setNumOfItems(goldItem.getNumOfItems() + modifyValue);
|
|
|
|
UpdateGoldMsg ugm = new UpdateGoldMsg(this.absCharacter);
|
|
|
|
ugm.configure();
|
|
|
|
|
|
|
|
Dispatch dispatch = Dispatch.borrow(player, ugm);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean tradeRequest(TradeRequestMsg msg) {
|
|
|
|
|
|
|
|
PlayerCharacter source = (PlayerCharacter) this.getOwner();
|
|
|
|
PlayerCharacter target = PlayerCharacter.getFromCache(msg.getPlayerID());
|
|
|
|
Dispatch dispatch;
|
|
|
|
|
|
|
|
if (!canTrade(source, target)) {
|
|
|
|
ChatManager.chatSystemError(source, "Can't currently trade with target player");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO uncomment this block after we determine when we
|
|
|
|
// setBankOpen(false) and setVaultOpen(false)
|
|
|
|
CharacterItemManager cim1 = source.getCharItemManager();
|
|
|
|
CharacterItemManager cim2 = target.getCharItemManager();
|
|
|
|
|
|
|
|
if (cim1 == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (cim2 == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(target, msg);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean invalidTradeRequest(InvalidTradeRequestMsg msg) {
|
|
|
|
PlayerCharacter requester = PlayerCharacter.getFromCache(msg.getRequesterID());
|
|
|
|
Dispatch dispatch;
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(requester, msg);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean canTrade(PlayerCharacter playerA, PlayerCharacter playerB) {
|
|
|
|
|
|
|
|
if (playerA == null || playerB == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
//make sure both are alive
|
|
|
|
if (!playerA.isAlive() || !playerB.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
//distance check
|
|
|
|
Vector3fImmutable aLoc = playerA.getLoc();
|
|
|
|
Vector3fImmutable bLoc = playerB.getLoc();
|
|
|
|
|
|
|
|
if (aLoc.distanceSquared2D(bLoc) > sqr(MBServerStatics.TRADE_RANGE))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
//visibility check
|
|
|
|
if (!playerA.canSee(playerB) || !playerB.canSee(playerA))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (playerA.lastBuildingAccessed != 0) {
|
|
|
|
ManageCityAssetsMsg mca = new ManageCityAssetsMsg();
|
|
|
|
mca.actionType = 4;
|
|
|
|
mca.setTargetType(Enum.GameObjectType.Building.ordinal());
|
|
|
|
mca.setTargetID(playerA.lastBuildingAccessed);
|
|
|
|
Dispatch dispatch = Dispatch.borrow(playerA, mca);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
playerA.lastBuildingAccessed = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean acceptTradeRequest(AcceptTradeRequestMsg msg) {
|
|
|
|
|
|
|
|
PlayerCharacter source = (PlayerCharacter) this.getOwner();
|
|
|
|
PlayerCharacter target = PlayerCharacter.getFromCache(msg.getTargetID());
|
|
|
|
|
|
|
|
Dispatch dispatch;
|
|
|
|
|
|
|
|
if (source == null || !source.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (target == null || !target.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.tradingWith != null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!canTrade(source, target))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// verify characterTarget is in range
|
|
|
|
if (source.getLoc().distanceSquared2D(target.getLoc()) > sqr(MBServerStatics.TRADE_RANGE))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// TODO uncomment this block after we determine when we
|
|
|
|
// setBankOpen(false) and setVaultOpen(false)
|
|
|
|
/*
|
|
|
|
* CharacterItemManager cim1 = source.getCharItemManager();
|
|
|
|
* CharacterItemManager cim2 = characterTarget.getCharItemManager(); if (cim1 ==
|
|
|
|
* null) return false; if (cim2 == null) return false; if (cim1.isBankOpen())
|
|
|
|
* return false; if (cim2.isVaultOpen()) return false;
|
|
|
|
*/
|
|
|
|
ClientConnection sourceConn = source.getClientConnection();
|
|
|
|
ClientConnection targetConn = target.getClientConnection();
|
|
|
|
|
|
|
|
if (sourceConn == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (targetConn == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
CharacterItemManager toTradeWith = target.getCharItemManager();
|
|
|
|
|
|
|
|
if (toTradeWith == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Account sourceAccount = source.getAccount();
|
|
|
|
Account targetAccount = target.getAccount();
|
|
|
|
|
|
|
|
UpdateVaultMsg uvmSource = new UpdateVaultMsg(sourceAccount);
|
|
|
|
UpdateVaultMsg uvmTarget = new UpdateVaultMsg(targetAccount);
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(source, uvmSource);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(target, uvmTarget);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
|
|
|
|
|
|
|
this.setVaultOpen(false);
|
|
|
|
toTradeWith.setVaultOpen(false);
|
|
|
|
this.setBankOpen(false);
|
|
|
|
toTradeWith.setBankOpen(false);
|
|
|
|
|
|
|
|
OpenTradeWindowMsg otwm = new OpenTradeWindowMsg(msg.getUnknown01(), source, target);
|
|
|
|
|
|
|
|
// Only start trade if both players aren't already trading with
|
|
|
|
// someone
|
|
|
|
|
|
|
|
if (this.getTradingWith() != null || toTradeWith.getTradingWith() != null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
this.initializeTrade();
|
|
|
|
toTradeWith.initializeTrade();
|
|
|
|
this.setTradingWith(targetConn);
|
|
|
|
toTradeWith.setTradingWith(sourceConn);
|
|
|
|
this.tradeID = msg.getUnknown01();
|
|
|
|
toTradeWith.tradeID = msg.getUnknown01();
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(source, otwm);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(target, otwm);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean addItemToTradeWindow(AddItemToTradeWindowMsg msg) {
|
|
|
|
PlayerCharacter source = (PlayerCharacter) this.getOwner();
|
|
|
|
Dispatch dispatch;
|
|
|
|
|
|
|
|
if (source == null || !source.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
ClientConnection ccOther = this.getTradingWith();
|
|
|
|
|
|
|
|
if (ccOther == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
PlayerCharacter other = ccOther.getPlayerCharacter();
|
|
|
|
|
|
|
|
if (other == null || !other.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CharacterItemManager tradingWith = other.getCharItemManager();
|
|
|
|
|
|
|
|
if (tradingWith == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!canTrade(source, other))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Item i = Item.getFromCache(msg.getItemID());
|
|
|
|
|
|
|
|
if (i == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!this.doesCharOwnThisItem(i.getObjectUUID()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
//can't add item to trade window twice
|
|
|
|
if (this.tradingContains(i))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
//dupe check
|
|
|
|
if (!i.validForInventory(source.getClientConnection(), source, this))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!tradingWith.hasRoomTrade(i.template.item_wt)) {
|
|
|
|
dispatch = Dispatch.borrow(source, msg);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
UpdateTradeWindowMsg utwm = new UpdateTradeWindowMsg(source, other);
|
|
|
|
|
|
|
|
this.setTradeCommitted((byte) 0);
|
|
|
|
tradingWith.setTradeCommitted((byte) 0);
|
|
|
|
|
|
|
|
this.addItemToTrade(i);
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(other, msg);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
|
|
|
|
|
|
|
modifyCommitToTrade();
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(other, utwm);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.PRIMARY);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean addGoldToTradeWindow(AddGoldToTradeWindowMsg msg) {
|
|
|
|
|
|
|
|
PlayerCharacter source = (PlayerCharacter) this.getOwner();
|
|
|
|
Dispatch dispatch;
|
|
|
|
|
|
|
|
if (source == null || !source.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
ClientConnection ccOther = this.getTradingWith();
|
|
|
|
|
|
|
|
if (ccOther == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
PlayerCharacter other = ccOther.getPlayerCharacter();
|
|
|
|
|
|
|
|
if (other == null || !other.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CharacterItemManager tradingWith = other.getCharItemManager();
|
|
|
|
|
|
|
|
if (tradingWith == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
UpdateTradeWindowMsg utwm = new UpdateTradeWindowMsg(other, source);
|
|
|
|
UpdateTradeWindowMsg utwmOther = new UpdateTradeWindowMsg(source, other);
|
|
|
|
|
|
|
|
if (!canTrade(source, other))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
this.setTradeCommitted((byte) 0);
|
|
|
|
tradingWith.setTradeCommitted((byte) 0);
|
|
|
|
|
|
|
|
int amt = msg.getAmount();
|
|
|
|
|
|
|
|
if (amt <= 0) {
|
|
|
|
Logger.info(source.getFirstName() + " added negative gold to trade window. Dupe attempt FAILED!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (amt > MBServerStatics.PLAYER_GOLD_LIMIT)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() - amt < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
this.addGoldToTrade(amt);
|
|
|
|
|
|
|
|
// BONUS CODE BELOW: Thanks some unknown retard!
|
|
|
|
// sourceItemMan.updateInventory(sourceItemMan.getInventory(), true);
|
|
|
|
|
|
|
|
UpdateGoldMsg ugm = new UpdateGoldMsg(source);
|
|
|
|
ugm.configure();
|
|
|
|
|
|
|
|
modifyCommitToTrade();
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(source, utwm);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(source, ugm);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(other, utwmOther);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean uncommitToTrade(UncommitToTradeMsg msg) {
|
|
|
|
|
|
|
|
PlayerCharacter source = (PlayerCharacter) this.getOwner();
|
|
|
|
|
|
|
|
if (source == null || !source.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CharacterItemManager sourceItemMan = source.getCharItemManager();
|
|
|
|
|
|
|
|
if (sourceItemMan == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
sourceItemMan.setTradeCommitted((byte) 0);
|
|
|
|
|
|
|
|
ClientConnection ccOther = sourceItemMan.getTradingWith();
|
|
|
|
|
|
|
|
if (ccOther == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
PlayerCharacter other = ccOther.getPlayerCharacter();
|
|
|
|
|
|
|
|
if (other == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!canTrade(source, other))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return modifyCommitToTrade();
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean commitToTrade(CommitToTradeMsg msg) {
|
|
|
|
|
|
|
|
PlayerCharacter source = (PlayerCharacter) this.getOwner();
|
|
|
|
|
|
|
|
if (source == null || !source.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
this.setTradeCommitted((byte) 1);
|
|
|
|
|
|
|
|
ClientConnection ccOther = this.getTradingWith();
|
|
|
|
|
|
|
|
if (ccOther == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
PlayerCharacter other = ccOther.getPlayerCharacter();
|
|
|
|
|
|
|
|
if (other == null || !other.isAlive())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CharacterItemManager tradingWith = other.getCharItemManager();
|
|
|
|
|
|
|
|
if (tradingWith == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!canTrade(source, other))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
modifyCommitToTrade();
|
|
|
|
|
|
|
|
if (this.getTradeCommitted() == (byte) 1 && tradingWith.getTradeCommitted() == (byte) 1) {
|
|
|
|
int tradeID = this.tradeID;
|
|
|
|
CloseTradeWindowMsg ctwm1 = new CloseTradeWindowMsg(source, tradeID);
|
|
|
|
CloseTradeWindowMsg ctwm2 = new CloseTradeWindowMsg(other, tradeID);
|
|
|
|
this.commitTrade();
|
|
|
|
this.closeTradeWindow(ctwm1, false);
|
|
|
|
other.getCharItemManager().closeTradeWindow(ctwm2, false);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private synchronized boolean modifyCommitToTrade() {
|
|
|
|
CharacterItemManager man1 = this;
|
|
|
|
|
|
|
|
if (this.getTradingWith() == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.getTradingWith().getPlayerCharacter() == null)
|
|
|
|
return false;
|
|
|
|
CharacterItemManager man2 = this.getTradingWith().getPlayerCharacter().getCharItemManager();
|
|
|
|
Dispatch dispatch;
|
|
|
|
|
|
|
|
if (man1 == null || man2 == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
ModifyCommitToTradeMsg modify = new ModifyCommitToTradeMsg(this.getOwner(), man2.getOwner(), man1.getTradeCommitted(),
|
|
|
|
man2.getTradeCommitted());
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow((PlayerCharacter) this.getOwner(), modify);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow((PlayerCharacter) man2.getOwner(), modify);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean closeTradeWindow(CloseTradeWindowMsg msg, boolean sourceTrade) {
|
|
|
|
|
|
|
|
|
|
|
|
Dispatch dispatch;
|
|
|
|
|
|
|
|
PlayerCharacter source = (PlayerCharacter) this.getOwner();
|
|
|
|
if (source == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CharacterItemManager sourceItemMan = source.getCharItemManager();
|
|
|
|
|
|
|
|
if (sourceItemMan == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
int tradeID = this.tradeID;
|
|
|
|
CloseTradeWindowMsg closeMsg = new CloseTradeWindowMsg(source, tradeID);
|
|
|
|
|
|
|
|
dispatch = Dispatch.borrow(source, closeMsg);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
|
|
|
|
if (!sourceTrade) {
|
|
|
|
sourceItemMan.endTrade();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClientConnection cc2 = sourceItemMan.getTradingWith();
|
|
|
|
|
|
|
|
if (cc2 == null || cc2.getPlayerCharacter() == null) {
|
|
|
|
sourceItemMan.endTrade();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
sourceItemMan.endTrade();
|
|
|
|
|
|
|
|
|
|
|
|
cc2.getPlayerCharacter().getCharItemManager().closeTradeWindow(msg, false);
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Item getGoldInventory() {
|
|
|
|
if (this.goldInventory == null)
|
|
|
|
loadGoldItems();
|
|
|
|
return this.goldInventory;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Item getGoldBank() {
|
|
|
|
if (this.goldBank == null)
|
|
|
|
loadGoldItems();
|
|
|
|
return this.goldBank;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Item getGoldVault() {
|
|
|
|
if (this.goldVault == null)
|
|
|
|
loadGoldItems();
|
|
|
|
return this.goldVault;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addEquipOrder(int slot) {
|
|
|
|
synchronized (this.equipOrder) {
|
|
|
|
Integer iSlot = slot;
|
|
|
|
if (this.equipOrder.contains(iSlot))
|
|
|
|
this.equipOrder.remove(iSlot);
|
|
|
|
this.equipOrder.add(slot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean doesCharOwnThisItem(int itemID) {
|
|
|
|
return this.itemIDtoType.containsKey(itemID);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean junk(Item i) {
|
|
|
|
return junk(i, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean recycle(Item i) {
|
|
|
|
if (i.getObjectType() == GameObjectType.Item)
|
|
|
|
return junk(i, false);
|
|
|
|
else {
|
|
|
|
if (this.removeItemFromInventory(i) == false)
|
|
|
|
return false;
|
|
|
|
((MobLoot) i).recycle((NPC) this.absCharacter);
|
|
|
|
calculateInventoryWeight();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The DeleteItemMsg takes care of updating inventory, so we don't want to do it separately
|
|
|
|
public synchronized boolean delete(Item i) {
|
|
|
|
return junk(i, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//cleanup an item from CharacterItemManager if it doesn't belong here
|
|
|
|
public synchronized boolean cleanupDupe(Item i) {
|
|
|
|
if (i == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD)) {
|
|
|
|
if (this.getGoldInventory() != null) {
|
|
|
|
if (i.getObjectUUID() == this.getGoldInventory().getObjectUUID())
|
|
|
|
this.goldInventory = null;
|
|
|
|
} else if (this.getGoldBank() != null) {
|
|
|
|
if (i.getObjectUUID() == this.getGoldBank().getObjectUUID())
|
|
|
|
this.goldBank = null;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
byte slot = i.getEquipSlot();
|
|
|
|
|
|
|
|
if (this.doesCharOwnThisItem(i.getObjectUUID()) == false)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// remove it from other lists:
|
|
|
|
this.remItemFromLists(i, slot);
|
|
|
|
this.itemIDtoType.remove(i.getObjectUUID());
|
|
|
|
|
|
|
|
calculateWeights();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean consume(Item i) {
|
|
|
|
i.decrementChargesRemaining();
|
|
|
|
if ((byte) i.chargesRemaining > 0)
|
|
|
|
return true;
|
|
|
|
return junk(i, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
private synchronized boolean junk(Item i, boolean updateInventory) {
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD)) {
|
|
|
|
if (this.getGoldInventory().getObjectUUID() == i.getObjectUUID())
|
|
|
|
if (DbManager.ItemQueries.UPDATE_GOLD(i, 0)) {
|
|
|
|
this.getGoldInventory().setNumOfItems(0);
|
|
|
|
if (updateInventory)
|
|
|
|
updateInventory();
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!(this.absCharacter.getObjectType().equals(GameObjectType.Mob)))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
byte slot = i.getEquipSlot();
|
|
|
|
|
|
|
|
if (this.doesCharOwnThisItem(i.getObjectUUID()) == false && this.absCharacter.getObjectType() != GameObjectType.Mob && (i.containerType != Enum.ItemContainerType.FORGE))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// remove it from other lists:
|
|
|
|
this.remItemFromLists(i, slot);
|
|
|
|
this.itemIDtoType.remove(i.getObjectUUID());
|
|
|
|
|
|
|
|
i.junk();
|
|
|
|
|
|
|
|
//Why are we adding junked items?!
|
|
|
|
|
|
|
|
// if (i.getObjectType() != GameObjectType.MobLoot)
|
|
|
|
// CharacterItemManager.junkedItems.add(i);
|
|
|
|
|
|
|
|
|
|
|
|
calculateWeights();
|
|
|
|
|
|
|
|
if (updateInventory)
|
|
|
|
// Send the new inventory
|
|
|
|
//updateInventory(i, false); this line was causing entire inventory to disappear
|
|
|
|
updateInventory(this.getInventory(), true);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean moveItemToInventory(Item i) {
|
|
|
|
|
|
|
|
boolean fromEquip = false;
|
|
|
|
synchronized (this) {
|
|
|
|
byte slot = i.getEquipSlot();
|
|
|
|
|
|
|
|
//Skip if NOT in vault.
|
|
|
|
if (i.containerType != Enum.ItemContainerType.VAULT)
|
|
|
|
if (this.doesCharOwnThisItem(i.getObjectUUID()) == false)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Only valid from bank, equip and vault
|
|
|
|
if (!bankContains(i) && !equippedContains(i) && !vaultContains(i))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (equippedContains(i)) {
|
|
|
|
fromEquip = true;
|
|
|
|
ItemBase ib = i.getItemBase();
|
|
|
|
if (ib != null && ib.getType().equals(ItemType.GOLD))
|
|
|
|
this.absCharacter.cancelOnUnEquip();
|
|
|
|
}
|
|
|
|
|
|
|
|
// check to see what type of AbstractCharacter subclass we have stored
|
|
|
|
if (this.absCharacter.getClass() == PlayerCharacter.class) {
|
|
|
|
if (!i.moveItemToInventory((PlayerCharacter) this.absCharacter))
|
|
|
|
return false;
|
|
|
|
} else if (!i.moveItemToInventory((NPC) this.absCharacter))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// remove it from other lists:
|
|
|
|
this.remItemFromLists(i, slot);
|
|
|
|
|
|
|
|
// add to Inventory
|
|
|
|
this.inventory.add(i);
|
|
|
|
i.addToCache();
|
|
|
|
this.itemIDtoType.put(i.getObjectUUID(), i.getObjectType().ordinal());
|
|
|
|
|
|
|
|
calculateWeights();
|
|
|
|
}
|
|
|
|
|
|
|
|
//Apply bonuses if from equip
|
|
|
|
if (fromEquip && this.absCharacter != null) {
|
|
|
|
this.absCharacter.applyBonuses();
|
|
|
|
if (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter))
|
|
|
|
this.absCharacter.incVer();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean moveItemToBank(Item i) {
|
|
|
|
byte slot = i.getEquipSlot();
|
|
|
|
|
|
|
|
if (this.doesCharOwnThisItem(i.getObjectUUID()) == false)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Item must be in inventory to move to bank
|
|
|
|
if (!this.inventory.contains(i))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// check to see what type of AbstractCharacter subclass we have stored
|
|
|
|
if (this.absCharacter.getClass() == PlayerCharacter.class) {
|
|
|
|
if (!i.moveItemToBank((PlayerCharacter) this.absCharacter))
|
|
|
|
return false;
|
|
|
|
} else if (!i.moveItemToBank((NPC) this.absCharacter))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// remove it from other lists:
|
|
|
|
this.remItemFromLists(i, slot);
|
|
|
|
|
|
|
|
// add to Bank
|
|
|
|
this.bank.add(i);
|
|
|
|
i.addToCache();
|
|
|
|
|
|
|
|
calculateWeights();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean moveGoldToBank(Item from, int amt) {
|
|
|
|
if (from == null)
|
|
|
|
return false;
|
|
|
|
if (from.getNumOfItems() - amt < 0)
|
|
|
|
return false;
|
|
|
|
if (this.goldBank.getNumOfItems() + amt > MBServerStatics.BANK_GOLD_LIMIT) {
|
|
|
|
if (this.absCharacter.getObjectType() == GameObjectType.PlayerCharacter) {
|
|
|
|
PlayerCharacter pc = (PlayerCharacter) this.absCharacter;
|
|
|
|
if (pc.getClientConnection() != null)
|
|
|
|
ErrorPopupMsg.sendErrorPopup(pc, 202);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!DbManager.ItemQueries.MOVE_GOLD(from, this.getGoldBank(), amt))
|
|
|
|
return false;
|
|
|
|
from.setNumOfItems(from.getNumOfItems() - amt);
|
|
|
|
this.goldBank.setNumOfItems(this.goldBank.getNumOfItems() + amt);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean moveGoldToVault(Item from, int amt) {
|
|
|
|
if (from == null)
|
|
|
|
return false;
|
|
|
|
if (from.getNumOfItems() - amt < 0)
|
|
|
|
return false;
|
|
|
|
if (!DbManager.ItemQueries.MOVE_GOLD(from, this.account.vaultGold, amt))
|
|
|
|
return false;
|
|
|
|
from.setNumOfItems(from.getNumOfItems() - amt);
|
|
|
|
this.account.vaultGold.setNumOfItems(this.goldVault.getNumOfItems() + amt);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean moveGoldToInventory(Item from, int amt) {
|
|
|
|
if (from == null)
|
|
|
|
return false;
|
|
|
|
if (from.getNumOfItems() - amt < 0 || amt < 1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.goldInventory.getNumOfItems() + amt > MBServerStatics.PLAYER_GOLD_LIMIT) {
|
|
|
|
if (this.absCharacter.getObjectType() == GameObjectType.PlayerCharacter) {
|
|
|
|
PlayerCharacter pc = (PlayerCharacter) this.absCharacter;
|
|
|
|
if (pc.getClientConnection() != null)
|
|
|
|
ErrorPopupMsg.sendErrorPopup(pc, 202);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (from instanceof MobLoot) {
|
|
|
|
if (!DbManager.ItemQueries.UPDATE_GOLD(this.getGoldInventory(),
|
|
|
|
this.goldInventory.getNumOfItems() + amt))
|
|
|
|
return false;
|
|
|
|
} else if (!DbManager.ItemQueries.MOVE_GOLD(from, this.goldInventory, amt))
|
|
|
|
return false;
|
|
|
|
from.setNumOfItems(from.getNumOfItems() - amt);
|
|
|
|
this.goldInventory.setNumOfItems(this.goldInventory.getNumOfItems() + amt);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//This is called by the addGold devCmd.
|
|
|
|
public synchronized boolean addGoldToInventory(int amt, boolean fromDevCmd) {
|
|
|
|
|
|
|
|
if (this.absCharacter == null || (!(this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter))))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() + amt > MBServerStatics.PLAYER_GOLD_LIMIT) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() + amt < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
boolean worked = DbManager.ItemQueries.UPDATE_GOLD(this.getGoldInventory(), this.goldInventory.getNumOfItems() + amt);
|
|
|
|
if (worked) {
|
|
|
|
//log this since it's technically a dupe. Only use on test server!
|
|
|
|
if (fromDevCmd) {
|
|
|
|
String logString = this.absCharacter.getName() + " added " + amt + " gold to their inventory";
|
|
|
|
Logger.info(logString);
|
|
|
|
}
|
|
|
|
this.goldInventory.setNumOfItems(this.goldInventory.getNumOfItems() + amt);
|
|
|
|
}
|
|
|
|
return worked;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Used to trainsfer gold from one inventory to another, for steal, etc.
|
|
|
|
public boolean transferGoldToMyInventory(AbstractCharacter tar, int amount) {
|
|
|
|
if (tar == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CharacterItemManager tarCim = tar.getCharItemManager();
|
|
|
|
if (tarCim == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() + amount < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() + amount > MBServerStatics.PLAYER_GOLD_LIMIT)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (tarCim.getGoldInventory().getNumOfItems() - amount < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (tarCim.getGoldInventory().getNumOfItems() - amount > MBServerStatics.PLAYER_GOLD_LIMIT)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
synchronized (this) {
|
|
|
|
synchronized (tarCim) {
|
|
|
|
if (!tarCim.addGoldToInventory(0 - amount, false)) //remove gold from target
|
|
|
|
return false;
|
|
|
|
if (!addGoldToInventory(amount, false)) //add to this inventory
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean moveItemToVault(Item i) {
|
|
|
|
byte slot = i.getEquipSlot();
|
|
|
|
|
|
|
|
// if (this.doesCharOwnThisItem(i.getObjectUUID()) == false)
|
|
|
|
// return false;
|
|
|
|
|
|
|
|
// Item must be in inventory to move to vault
|
|
|
|
if (!this.inventory.contains(i))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// check to see what type of AbstractCharacter subclass we have stored
|
|
|
|
if (this.absCharacter.getClass() == PlayerCharacter.class) {
|
|
|
|
if (!i.moveItemToVault(this.account))
|
|
|
|
return false;
|
|
|
|
} else
|
|
|
|
return false; // NPC's dont have vaults!
|
|
|
|
|
|
|
|
// remove it from other lists:
|
|
|
|
this.remItemFromLists(i, slot);
|
|
|
|
|
|
|
|
// add to Vault
|
|
|
|
i.addToCache();
|
|
|
|
|
|
|
|
calculateWeights();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Used for buying MobEquipment from NPC
|
|
|
|
//Handles the gold transfer aspect
|
|
|
|
|
|
|
|
// This removes ingame item from inventory for loot.
|
|
|
|
private synchronized boolean removeItemFromInventory(Item i) {
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD)) {
|
|
|
|
if (i.getObjectUUID() != this.getGoldInventory().getObjectUUID())
|
|
|
|
return false;
|
|
|
|
if (!DbManager.ItemQueries.UPDATE_GOLD(this.goldInventory, 0)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (this.doesCharOwnThisItem(i.getObjectUUID()) == false)
|
|
|
|
return false;
|
|
|
|
if (this.inventory.contains(i)) {
|
|
|
|
this.inventory.remove(i);
|
|
|
|
this.itemIDtoType.remove(i.getObjectUUID());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// tell client we're removing item
|
|
|
|
updateInventory(i, false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This adds item to inventory for loot. Validity checks already handled
|
|
|
|
public synchronized boolean addItemToInventory(Item i) {
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
if (this.absCharacter.getObjectType() == GameObjectType.Mob) {
|
|
|
|
if (this.goldInventory == null)
|
|
|
|
loadGoldItems();
|
|
|
|
this.goldInventory.setNumOfItems(this.goldInventory.getNumOfItems() + i.getNumOfItems());
|
|
|
|
} else {
|
|
|
|
int amt = i.getNumOfItems();
|
|
|
|
if (DbManager.ItemQueries.UPDATE_GOLD(this.goldInventory, this.goldInventory.getNumOfItems() + amt)) {
|
|
|
|
updateInventory();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.inventory.add(i);
|
|
|
|
this.itemIDtoType.put(i.getObjectUUID(), i.getObjectType().ordinal());
|
|
|
|
|
|
|
|
|
|
|
|
if (i.template != null)
|
|
|
|
this.inventoryWeight += i.template.item_wt;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//called for adding gold of a specified amount
|
|
|
|
public synchronized boolean addItemToInventory(Item i, int amount) {
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
return DbManager.ItemQueries.UPDATE_GOLD(this.getGoldInventory(), this.goldInventory.getNumOfItems() + amount);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean equipItem(Item i, byte slot) {
|
|
|
|
|
|
|
|
synchronized (this) {
|
|
|
|
byte curSlot = i.getEquipSlot(); // Should be 0
|
|
|
|
|
|
|
|
if (this.doesCharOwnThisItem(i.getObjectUUID()) == false && this.absCharacter.getObjectType() != GameObjectType.Mob) {
|
|
|
|
Logger.error("Doesnt own item");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Item must be in inventory to equip
|
|
|
|
if (!this.inventory.contains(i) && this.absCharacter.getObjectType() != GameObjectType.Mob)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// make sure player can equip item
|
|
|
|
if (i.getItemBase() == null)
|
|
|
|
return false;
|
|
|
|
if (!i.getItemBase().canEquip(slot, this, absCharacter, i) && this.absCharacter.getObjectType() != GameObjectType.Mob)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// check to see if item is already there.
|
|
|
|
Item old = this.equipped.get((int) slot);
|
|
|
|
if (old != null) {
|
|
|
|
Logger.error("already equipped");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check to see what type of AbstractCharacter subclass we have stored
|
|
|
|
if (this.absCharacter.getClass() == PlayerCharacter.class) {
|
|
|
|
if (!i.equipItem((PlayerCharacter) this.absCharacter, slot))
|
|
|
|
return false;
|
|
|
|
} else if (this.absCharacter.getObjectType() == GameObjectType.Mob) {
|
|
|
|
if (!i.equipItem((Mob) this.absCharacter, slot)) {
|
|
|
|
Logger.error("Failed to set Equip");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (!i.equipItem((NPC) this.absCharacter, slot))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// remove it from other lists:
|
|
|
|
this.remItemFromLists(i, slot);
|
|
|
|
|
|
|
|
// add to Equipped
|
|
|
|
this.equipped.put((int) slot, i);
|
|
|
|
i.addToCache();
|
|
|
|
|
|
|
|
addEquipOrder(i.getEquipSlot());
|
|
|
|
|
|
|
|
//calculateWeights();
|
|
|
|
}
|
|
|
|
|
|
|
|
//Apply Bonuses and update player
|
|
|
|
if (this.absCharacter != null) {
|
|
|
|
this.absCharacter.applyBonuses();
|
|
|
|
if (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter))
|
|
|
|
this.absCharacter.incVer();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean buyFromNPC(Building vendorBuilding, int cost, int buildingDeposit) {
|
|
|
|
|
|
|
|
Item gold = this.getGoldInventory();
|
|
|
|
|
|
|
|
if (cost <= 0 || (gold.getNumOfItems() - cost) < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
if (this.getOwner() != null && this.getOwner().getObjectType().equals(GameObjectType.PlayerCharacter)) {
|
|
|
|
if (this.goldTradingAmount > 0) {
|
|
|
|
ErrorPopupMsg.sendErrorPopup((PlayerCharacter) this.getOwner(), 195);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create gold from screatch instead of building strongbox
|
|
|
|
// if the NPC is not slotted.
|
|
|
|
|
|
|
|
if (vendorBuilding == null) {
|
|
|
|
|
|
|
|
return this.modifyInventoryGold(-cost);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (vendorBuilding.getStrongboxValue() + cost > vendorBuilding.getMaxGold()) {
|
|
|
|
|
|
|
|
if (this.absCharacter.getObjectType() == GameObjectType.PlayerCharacter) {
|
|
|
|
PlayerCharacter pc = (PlayerCharacter) this.absCharacter;
|
|
|
|
if (pc.getClientConnection() != null)
|
|
|
|
ErrorPopupMsg.sendErrorPopup(pc, 206);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Update strongbox and inventory gold
|
|
|
|
if (!this.modifyInventoryGold(-cost))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
City buildingCity = vendorBuilding.getCity();
|
|
|
|
|
|
|
|
if (buildingCity != null) {
|
|
|
|
buildingCity.transactionLock.writeLock().lock();
|
|
|
|
try {
|
|
|
|
if (!vendorBuilding.transferGold(buildingDeposit, true))
|
|
|
|
return false;
|
|
|
|
} catch (Exception e) {
|
|
|
|
Logger.error(e);
|
|
|
|
return false;
|
|
|
|
} finally {
|
|
|
|
buildingCity.transactionLock.writeLock().unlock();
|
|
|
|
}
|
|
|
|
} else if (!vendorBuilding.transferGold(buildingDeposit, true))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Used for selling items to NPC
|
|
|
|
public synchronized boolean sellToNPC(Building building, int cost, Item item) {
|
|
|
|
|
|
|
|
// Create gold from screatch instead of building strongbox
|
|
|
|
// if the NPC is not slotted.
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() + cost < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() + cost > MBServerStatics.PLAYER_GOLD_LIMIT)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
if (this.getOwner().getCharItemManager().getGoldTrading() > 0) {
|
|
|
|
if (this.getOwner().getObjectType().equals(GameObjectType.PlayerCharacter))
|
|
|
|
ErrorPopupMsg.sendErrorPopup((PlayerCharacter) this.getOwner(), 195);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (building == null) {
|
|
|
|
return this.modifyInventoryGold(cost);
|
|
|
|
}
|
|
|
|
|
|
|
|
//make sure strongbox can afford gold.
|
|
|
|
|
|
|
|
if (!building.hasFunds(cost))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if ((building.getStrongboxValue() - cost) < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Update strongbox and inventory gold
|
|
|
|
|
|
|
|
if (!building.transferGold(-cost, false))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return this.modifyInventoryGold(cost);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This sells an item to an npc
|
|
|
|
*
|
|
|
|
* @return True on success
|
|
|
|
*/
|
|
|
|
public synchronized boolean sellToNPC(Item itemToSell, NPC npc) {
|
|
|
|
|
|
|
|
CharacterItemManager itemMan;
|
|
|
|
|
|
|
|
if (itemToSell == null || npc == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
itemMan = npc.getCharItemManager();
|
|
|
|
|
|
|
|
if (itemMan == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
//test npc inventory is not full
|
|
|
|
|
|
|
|
synchronized (this) {
|
|
|
|
synchronized (itemMan) {
|
|
|
|
if (!this.doesCharOwnThisItem(itemToSell.getObjectUUID()))
|
|
|
|
return false;
|
|
|
|
// attempt to transfer item in db
|
|
|
|
|
|
|
|
boolean sdrMerchant = false;
|
|
|
|
|
|
|
|
if (npc.getContractID() >= 1900 && npc.getContractID() <= 1906)
|
|
|
|
sdrMerchant = true;
|
|
|
|
|
|
|
|
if (sdrMerchant) {
|
|
|
|
this.delete(itemToSell);
|
|
|
|
this.updateInventory();
|
|
|
|
|
|
|
|
} else if (!itemToSell.moveItemToInventory(npc))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// db transfer successfull, remove from this character
|
|
|
|
// skip this check if this is a mobLoot item (which is not in any inventory)
|
|
|
|
if (!sdrMerchant)
|
|
|
|
if (!removeItemFromInventory(itemToSell))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// add item to looter.
|
|
|
|
if (!sdrMerchant)
|
|
|
|
if (!itemMan.addItemToInventory(itemToSell))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate new weights
|
|
|
|
calculateInventoryWeight();
|
|
|
|
itemMan.calculateInventoryWeight();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This buys an item from an npc
|
|
|
|
* Handles transfer of item.
|
|
|
|
*
|
|
|
|
* @return True on success
|
|
|
|
*/
|
|
|
|
public synchronized boolean buyFromNPC(Item purchasedItem, NPC npc) {
|
|
|
|
|
|
|
|
CharacterItemManager itemMan;
|
|
|
|
ItemBase itemBase;
|
|
|
|
|
|
|
|
if (purchasedItem == null || npc == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
itemMan = npc.getCharItemManager();
|
|
|
|
|
|
|
|
if (itemMan == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
synchronized (this) {
|
|
|
|
synchronized (itemMan) {
|
|
|
|
ItemTemplate template = purchasedItem.template;
|
|
|
|
|
|
|
|
if (template == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
//test inventory is not full
|
|
|
|
|
|
|
|
if (!hasRoomInventory(template.item_wt))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!itemMan.inventory.contains(purchasedItem))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// attempt to transfer item in db
|
|
|
|
|
|
|
|
if (purchasedItem.getObjectType() == GameObjectType.MobLoot) {
|
|
|
|
|
|
|
|
Item newItem = ((MobLoot) purchasedItem).promoteToItem((PlayerCharacter) this.absCharacter);
|
|
|
|
if (newItem == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!itemMan.removeItemFromInventory(purchasedItem))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!addItemToInventory(newItem))
|
|
|
|
return false;
|
|
|
|
//Item was created and still a mobloot item, remove from npc production list in db.
|
|
|
|
|
|
|
|
DbManager.NPCQueries.REMOVE_FROM_PRODUCTION_LIST(purchasedItem.getObjectUUID(), npc.getObjectUUID());
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (!purchasedItem.moveItemToInventory((PlayerCharacter) this.absCharacter))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (purchasedItem.getValue() != purchasedItem.getMagicValue()) {
|
|
|
|
DbManager.ItemQueries.UPDATE_VALUE(purchasedItem, 0);
|
|
|
|
purchasedItem.setValue(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// db transfer successfull, remove from this character
|
|
|
|
// skip this check if this is a mobLoot item (which is not in any inventory)
|
|
|
|
if (!itemMan.removeItemFromInventory(purchasedItem))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// add item to looter.
|
|
|
|
|
|
|
|
if (!addItemToInventory(purchasedItem))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate new weights
|
|
|
|
calculateInventoryWeight();
|
|
|
|
itemMan.calculateInventoryWeight();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loot an item from an AbstractCharacter. Call this function on
|
|
|
|
* the CharacterItemManager of the current item owner, not the looter.
|
|
|
|
* This method will verify that the looter can receive the item
|
|
|
|
* (e.g. inventory isn't full).
|
|
|
|
*
|
|
|
|
* @param i Item being looted
|
|
|
|
* @param looter Player looting the item
|
|
|
|
* @param origin ClientConnection
|
|
|
|
* @return True on success
|
|
|
|
*/
|
|
|
|
public synchronized Item lootItemFromMe(Item i, PlayerCharacter looter, ClientConnection origin) {
|
|
|
|
return lootItemFromMe(i, looter, origin, false, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
//This function is used for both looting and stealing
|
|
|
|
public synchronized Item lootItemFromMe(Item lootItem, PlayerCharacter lootingPlayer, ClientConnection origin, boolean fromSteal, int amount) {
|
|
|
|
|
|
|
|
//TODO this function should have more logging
|
|
|
|
// make sure lootingPlayer exists
|
|
|
|
if (lootingPlayer == null)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
// get looters item manager
|
|
|
|
CharacterItemManager looterItems = lootingPlayer.getCharItemManager();
|
|
|
|
|
|
|
|
if (looterItems == null)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
if (fromSteal) {
|
|
|
|
if (!this.absCharacter.isAlive())
|
|
|
|
return null;
|
|
|
|
} else if (!this.absCharacter.canBeLooted())
|
|
|
|
return null;
|
|
|
|
|
|
|
|
MobLoot mobLoot = null;
|
|
|
|
if (lootItem instanceof MobLoot) {
|
|
|
|
mobLoot = (MobLoot) lootItem;
|
|
|
|
if (mobLoot.isDeleted())
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Lock both ItemManagers; lower ID first
|
|
|
|
CharacterItemManager lockFirst;
|
|
|
|
CharacterItemManager lockSecond;
|
|
|
|
if (this.absCharacter.getObjectUUID()
|
|
|
|
< looterItems.absCharacter.getObjectUUID()) {
|
|
|
|
lockFirst = this;
|
|
|
|
lockSecond = looterItems;
|
|
|
|
} else {
|
|
|
|
lockFirst = looterItems;
|
|
|
|
lockSecond = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
synchronized (lockFirst) {
|
|
|
|
synchronized (lockSecond) {
|
|
|
|
// make sure current player has item in inventory
|
|
|
|
if (lootItem.getItemBase().getType().equals(ItemType.GOLD) && lootItem.getObjectUUID() != this.getGoldInventory().getObjectUUID() && !(this.absCharacter.getObjectType().equals(GameObjectType.Mob)))
|
|
|
|
return null;
|
|
|
|
else if (!this.inventory.contains(lootItem) && !this.getEquippedList().contains(lootItem) && !lootItem.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
return null;
|
|
|
|
|
|
|
|
// get weight of item
|
|
|
|
|
|
|
|
if (lootItem.template == null)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
int weight = lootItem.template.item_wt;
|
|
|
|
|
|
|
|
// make sure lootingPlayer has room for item
|
|
|
|
if (!lootItem.getItemBase().getType().equals(ItemType.GOLD) && !looterItems.hasRoomInventory(weight))
|
|
|
|
return null;
|
|
|
|
|
|
|
|
if (lootItem.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
if (amount != -1) { //from steal
|
|
|
|
int total = lootItem.getNumOfItems();
|
|
|
|
amount = (amount > total) ? total : amount;
|
|
|
|
if (!looterItems.moveGoldToInventory(lootItem, amount))
|
|
|
|
return null;
|
|
|
|
if (mobLoot != null && amount == total)
|
|
|
|
this.delete(mobLoot);
|
|
|
|
} else { //from loot
|
|
|
|
if (!looterItems.moveGoldToInventory(lootItem, lootItem.getNumOfItems()))
|
|
|
|
return null;
|
|
|
|
if (mobLoot != null) // delete mobloot after it has been looted
|
|
|
|
this.delete(mobLoot);
|
|
|
|
}
|
|
|
|
else { //not Gold item
|
|
|
|
boolean created = false;
|
|
|
|
if (mobLoot != null) {
|
|
|
|
lootItem = mobLoot.promoteToItem(lootingPlayer);
|
|
|
|
|
|
|
|
// delete mobloot after it has been looted
|
|
|
|
this.delete(mobLoot);
|
|
|
|
if (lootItem == null)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
created = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// attempt to transfer item in db
|
|
|
|
|
|
|
|
if (!lootItem.moveItemToInventory(lootingPlayer))
|
|
|
|
return null;
|
|
|
|
|
|
|
|
// db transfer successfull, remove from this character
|
|
|
|
// skip this check if this is a mobLoot item (which is not in any inventory)
|
|
|
|
if (mobLoot == null)
|
|
|
|
if (!removeItemFromInventory(lootItem))
|
|
|
|
return null;
|
|
|
|
|
|
|
|
// add item to lootingPlayer.
|
|
|
|
if (!looterItems.addItemToInventory(lootItem))
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate new weights
|
|
|
|
calculateInventoryWeight();
|
|
|
|
looterItems.calculateInventoryWeight();
|
|
|
|
|
|
|
|
return lootItem;
|
|
|
|
}
|
|
|
|
|
|
|
|
private synchronized void remItemFromLists(Item i, byte slot) {
|
|
|
|
|
|
|
|
this.equipped.remove((int) slot);
|
|
|
|
this.vault.remove(i);
|
|
|
|
this.bank.remove(i);
|
|
|
|
this.inventory.remove(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Delegates
|
|
|
|
*/
|
|
|
|
public synchronized boolean bankContains(Item i) {
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
return (this.getGoldBank() != null && this.goldBank.getObjectUUID() == i.getObjectUUID());
|
|
|
|
return bank.contains(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean inventoryContains(Item i) {
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
return (this.getGoldInventory() != null && this.goldInventory.getObjectUUID() == i.getObjectUUID());
|
|
|
|
return inventory.contains(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean forgeContains(Item i, NPC vendor) {
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
return (this.getGoldInventory() != null && this.goldInventory.getObjectUUID() == i.getObjectUUID());
|
|
|
|
return vendor.getRolling().contains(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean vaultContains(Item i) {
|
|
|
|
if (i.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
return (this.getGoldVault() != null && this.goldVault.getObjectUUID() == i.getObjectUUID());
|
|
|
|
return this.account.getVault().contains(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean vaultContainsType(ItemBase ib) {
|
|
|
|
if (ib.getUUID() == 7)
|
|
|
|
return (this.getGoldVault() != null);
|
|
|
|
for (Item i : vault) {
|
|
|
|
if (i.getItemBase().getUUID() == ib.getUUID())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//for calling from devCmd fill vault. Already synchronized
|
|
|
|
public boolean vaultContainsTypeA(ItemBase ib) {
|
|
|
|
if (ib.getUUID() == 7)
|
|
|
|
return (this.getGoldVault() != null);
|
|
|
|
for (Item i : vault) {
|
|
|
|
if (i.getItemBase().getUUID() == ib.getUUID())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean equippedContains(Item i) {
|
|
|
|
return equipped.containsValue(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized Item getItemFromEquipped(int slot) {
|
|
|
|
return equipped.get(slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized Item getItemByUUID(int objectUUID) {
|
|
|
|
if (this.itemIDtoType.containsKey(objectUUID)) {
|
|
|
|
|
|
|
|
Integer integer = this.itemIDtoType.get(objectUUID);
|
|
|
|
if (integer == GameObjectType.Item.ordinal()) {
|
|
|
|
return Item.getFromCache(objectUUID);
|
|
|
|
} else if (integer == GameObjectType.MobLoot.ordinal()) {
|
|
|
|
return MobLoot.getFromCache(objectUUID);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.getGoldInventory() != null && this.goldInventory.getObjectUUID() == objectUUID)
|
|
|
|
return this.goldInventory;
|
|
|
|
if (this.getGoldBank() != null && this.goldBank.getObjectUUID() == objectUUID)
|
|
|
|
return this.goldBank;
|
|
|
|
if (this.getGoldVault() != null && this.goldVault.getObjectUUID() == objectUUID)
|
|
|
|
return this.goldVault;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean tradingContains(Item i) {
|
|
|
|
if (this.trading == null || i == null)
|
|
|
|
return false;
|
|
|
|
return this.trading.contains(i.getObjectUUID());
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isBankOpen() {
|
|
|
|
return this.bankOpened;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void setBankOpen(boolean bankOpened) {
|
|
|
|
this.bankOpened = bankOpened;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isVaultOpen() {
|
|
|
|
return this.vaultOpened;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void setVaultOpen(boolean vaultOpened) {
|
|
|
|
this.vaultOpened = vaultOpened;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ClientConnection getTradingWith() {
|
|
|
|
return tradingWith;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void setTradingWith(ClientConnection tradingWith) {
|
|
|
|
this.tradingWith = tradingWith;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void clearTradingWith() {
|
|
|
|
this.tradingWith = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getGoldTrading() {
|
|
|
|
return goldTradingAmount;
|
|
|
|
}
|
|
|
|
|
|
|
|
public byte getTradeCommitted() {
|
|
|
|
return tradeCommitted;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void setTradeCommitted(byte tradeCommitted) {
|
|
|
|
this.tradeCommitted = tradeCommitted;
|
|
|
|
}
|
|
|
|
|
|
|
|
public HashSet<Integer> getTrading() {
|
|
|
|
return trading;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* List Copiers
|
|
|
|
*/
|
|
|
|
|
|
|
|
public synchronized void addItemToTrade(Item i) {
|
|
|
|
this.trading.add(i.getObjectUUID());
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean getTradeSuccess() {
|
|
|
|
return tradeSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void setTradeSuccess(boolean tradeSuccess) {
|
|
|
|
this.tradeSuccess = tradeSuccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean RemoveEquipmentFromLackOfSkill(PlayerCharacter pc, boolean initialized) {
|
|
|
|
|
|
|
|
|
|
|
|
if (pc == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.equipped == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
for (int slot : this.equipped.keySet()) {
|
|
|
|
|
|
|
|
if (slot == MBServerStatics.SLOT_HAIRSTYLE || slot == MBServerStatics.SLOT_BEARDSTYLE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Item item = this.equipped.get(slot);
|
|
|
|
|
|
|
|
if (item == null) {
|
|
|
|
this.equipped.remove(slot);
|
|
|
|
pc.applyBonuses();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ItemTemplate.validForSkills(item, pc.getSkills())) {
|
|
|
|
this.forceToInventory(slot, item, pc, initialized);
|
|
|
|
pc.applyBonuses();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Note that this method returns a <b>copy</b> of the internally stored
|
|
|
|
* list.
|
|
|
|
*
|
|
|
|
* @return the equipped
|
|
|
|
*/
|
|
|
|
public ConcurrentHashMap<Integer, Item> getEquipped() {
|
|
|
|
synchronized (this.equipped) {
|
|
|
|
return new ConcurrentHashMap<>(this.equipped);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public ArrayList<Item> getEquippedList() {
|
|
|
|
ArrayList<Item> ret = new ArrayList<>();
|
|
|
|
synchronized (this.equipOrder) {
|
|
|
|
synchronized (this.equipped) {
|
|
|
|
for (int slot : this.equipOrder) {
|
|
|
|
if (this.equipped.containsKey(slot))
|
|
|
|
ret.add(this.equipped.get(slot));
|
|
|
|
}
|
|
|
|
if (ret.size() != this.equipped.size())
|
|
|
|
//missed adding some items, figure out what.
|
|
|
|
for (int slot : this.equipped.keySet()) {
|
|
|
|
if (!(this.equipOrder.contains(slot))) {
|
|
|
|
this.equipOrder.add(slot);
|
|
|
|
ret.add(this.equipped.get(slot));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Item getEquipped(int slot) {
|
|
|
|
synchronized (this.equipped) {
|
|
|
|
return this.equipped.get(slot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Note that this method returns a <b>copy</b> of the internally stored
|
|
|
|
* list.
|
|
|
|
*
|
|
|
|
* @return the inventory
|
|
|
|
*/
|
|
|
|
public ArrayList<Item> getInventory() {
|
|
|
|
return getInventory(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public ArrayList<Item> getInventory(boolean sendGold) {
|
|
|
|
synchronized (this.inventory) {
|
|
|
|
ArrayList<Item> ret = new ArrayList<>(this.inventory);
|
|
|
|
if (sendGold && this.getGoldInventory() != null && this.goldInventory.getNumOfItems() > 0)
|
|
|
|
ret.add(this.goldInventory);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getInventoryCount() {
|
|
|
|
synchronized (this.inventory) {
|
|
|
|
return this.inventory.size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clears ownership of items. Called when player dies, but before
|
|
|
|
* respawning.
|
|
|
|
*
|
|
|
|
* @return the inventory
|
|
|
|
*/
|
|
|
|
public synchronized void orphanInventory() {
|
|
|
|
PlayerCharacter pc = null;
|
|
|
|
if (this.absCharacter != null && this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter))
|
|
|
|
pc = (PlayerCharacter) this.absCharacter;
|
|
|
|
synchronized (this.inventory) {
|
|
|
|
//dupe check, validate player properly owns all items
|
|
|
|
if (pc != null) {
|
|
|
|
Iterator<Item> iter = this.inventory.iterator();
|
|
|
|
while (iter.hasNext()) {
|
|
|
|
Item item = iter.next();
|
|
|
|
//this call may remove the item from this.inventory
|
|
|
|
if (!item.validForInventory(pc.getClientConnection(), pc, this)) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.inventory.size() > 0)
|
|
|
|
DbManager.ItemQueries.ORPHAN_INVENTORY(this.inventory);
|
|
|
|
//make a copy of gold inventory for looting
|
|
|
|
//so we don't remove the goldInventory
|
|
|
|
if (this.getGoldInventory().getNumOfItems() > 0) {
|
|
|
|
int amt = this.goldInventory.getNumOfItems();
|
|
|
|
if (DbManager.ItemQueries.UPDATE_GOLD(this.goldInventory, 0)) {
|
|
|
|
this.goldInventory.setNumOfItems(0);
|
|
|
|
MobLoot gold = new MobLoot(this.absCharacter, amt);
|
|
|
|
this.inventory.add(gold);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This transfers the entire inventory to another list For populating
|
|
|
|
* corpse' inventory when player dies
|
|
|
|
*
|
|
|
|
* @return the inventory
|
|
|
|
*/
|
|
|
|
public synchronized void transferEntireInventory(
|
|
|
|
ArrayList<Item> newInventory, Corpse corpse, boolean enterWorld) {
|
|
|
|
|
|
|
|
PlayerCharacter pc = null;
|
|
|
|
if (this.absCharacter != null && this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter))
|
|
|
|
pc = (PlayerCharacter) this.absCharacter;
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() > 0) {
|
|
|
|
int amt = this.goldInventory.getNumOfItems();
|
|
|
|
if (DbManager.ItemQueries.UPDATE_GOLD(this.goldInventory, 0)) {
|
|
|
|
this.goldInventory.setNumOfItems(0);
|
|
|
|
MobLoot gold = new MobLoot(this.absCharacter, amt);
|
|
|
|
newInventory.add(gold);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Item item : this.inventory) {
|
|
|
|
if (item != null)
|
|
|
|
if (item instanceof MobLoot) {
|
|
|
|
|
|
|
|
//MobLoot
|
|
|
|
item.zeroItem();
|
|
|
|
item.containerType = Enum.ItemContainerType.INVENTORY;
|
|
|
|
|
|
|
|
if (item.getItemBase().getType().equals(ItemType.GOLD))
|
|
|
|
//only add gold item once
|
|
|
|
if (!corpse.hasGold())
|
|
|
|
corpse.setHasGold(true);
|
|
|
|
newInventory.add(item);
|
|
|
|
} else //item
|
|
|
|
if (item.getItemBase().getType().equals(ItemType.GOLD)) {
|
|
|
|
int amt = item.getNumOfItems();
|
|
|
|
item.setNumOfItems(0);
|
|
|
|
MobLoot ml = new MobLoot(this.absCharacter, amt);
|
|
|
|
ml.zeroItem();
|
|
|
|
ml.containerType = Enum.ItemContainerType.INVENTORY;
|
|
|
|
if (!corpse.hasGold()) {
|
|
|
|
corpse.setHasGold(true);
|
|
|
|
newInventory.add(ml);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
boolean transferred = item.moveItemToInventory(corpse);
|
|
|
|
if (!transferred)
|
|
|
|
Logger.error(
|
|
|
|
"CharItemManager.transferEntireInvetory",
|
|
|
|
"DB Error, Failed to transfer item "
|
|
|
|
+ item.getObjectUUID() + " to new owner "
|
|
|
|
+ corpse.getObjectUUID());
|
|
|
|
newInventory.add(item);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// tell client we're clearing inventory
|
|
|
|
|
|
|
|
|
|
|
|
// clear the inventory.
|
|
|
|
this.inventory.clear();
|
|
|
|
|
|
|
|
//re-calculate inventory weight
|
|
|
|
calculateInventoryWeight();
|
|
|
|
if (!enterWorld)
|
|
|
|
updateInventory(this.getInventory(), false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void purgeInventory() {
|
|
|
|
|
|
|
|
if (!this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (this.goldInventory != null)
|
|
|
|
if (this.getGoldInventory().getNumOfItems() > 0) {
|
|
|
|
if (DbManager.ItemQueries.UPDATE_GOLD(this.goldInventory, 0)) {
|
|
|
|
this.goldInventory.setNumOfItems(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.inventory.size() > 0)
|
|
|
|
DbManager.ItemQueries.ORPHAN_INVENTORY(this.inventory);
|
|
|
|
|
|
|
|
// clear the inventory.
|
|
|
|
this.inventory.clear();
|
|
|
|
//re-calculate inventory weight
|
|
|
|
calculateInventoryWeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Note that this method returns a <b>copy</b> of the internally stored
|
|
|
|
* list.
|
|
|
|
*
|
|
|
|
* @return the bank
|
|
|
|
*/
|
|
|
|
public ArrayList<Item> getBank() {
|
|
|
|
synchronized (this.bank) {
|
|
|
|
ArrayList<Item> ret = new ArrayList<>(this.bank);
|
|
|
|
if (this.getGoldBank() != null && this.goldBank.getNumOfItems() > 0)
|
|
|
|
ret.add(this.goldBank);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Note that this method returns a <b>copy</b> of the internally stored
|
|
|
|
* list.
|
|
|
|
*
|
|
|
|
* @return the vault
|
|
|
|
*/
|
|
|
|
public ArrayList<Item> getVault() {
|
|
|
|
synchronized (this.vault) {
|
|
|
|
ArrayList<Item> ret = new ArrayList<>(this.vault);
|
|
|
|
if (this.getGoldVault() != null && this.goldVault.getNumOfItems() > 0)
|
|
|
|
ret.add(this.goldVault);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasRoomInventory(int weight) {
|
|
|
|
if (this.absCharacter == null)
|
|
|
|
return false;
|
|
|
|
if (this.absCharacter.getObjectType() == GameObjectType.PlayerCharacter) {
|
|
|
|
PlayerCharacter pc = (PlayerCharacter) this.absCharacter;
|
|
|
|
int newWeight = this.getCarriedWeight() + weight;
|
|
|
|
return newWeight <= (int) pc.statStrBase * 3;
|
|
|
|
} else if (this.absCharacter.getObjectType() == GameObjectType.NPC) {
|
|
|
|
int newWeight = this.getCarriedWeight() + weight;
|
|
|
|
return newWeight <= 1900 + (this.absCharacter.getLevel() * 3);
|
|
|
|
} else
|
|
|
|
return true; // npc's need checked
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasRoomTrade(int itemWeight) {
|
|
|
|
|
|
|
|
PlayerCharacter playerCharacter;
|
|
|
|
PlayerCharacter tradeCharacter;
|
|
|
|
|
|
|
|
int tradeWeight;
|
|
|
|
|
|
|
|
if (this.absCharacter == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) == false)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
playerCharacter = (PlayerCharacter) this.absCharacter;
|
|
|
|
|
|
|
|
if ((this.tradingWith == null) ||
|
|
|
|
(this.tradingWith.isConnected() == false))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
tradeCharacter = this.tradingWith.getPlayerCharacter();
|
|
|
|
|
|
|
|
tradeWeight = this.getCarriedWeight() + itemWeight;
|
|
|
|
tradeWeight = tradeWeight + tradeCharacter.getCharItemManager().getTradingWeight();
|
|
|
|
tradeWeight = tradeWeight - this.getTradingWeight();
|
|
|
|
|
|
|
|
return tradeWeight <= (int) playerCharacter.statStrBase * 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasRoomBank(int weight) {
|
|
|
|
|
|
|
|
if (this.absCharacter == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return weight <= this.absCharacter.getBankCapacityRemaining();
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasRoomVault(int weight) {
|
|
|
|
if (this.absCharacter == null)
|
|
|
|
return false;
|
|
|
|
return weight <= this.absCharacter.getVaultCapacityRemaining();
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getCarriedWeight() {
|
|
|
|
return getInventoryWeight() + getEquipWeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getInventoryWeight() {
|
|
|
|
return this.inventoryWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getBankWeight() {
|
|
|
|
return this.bankWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getEquipWeight() {
|
|
|
|
return this.equipWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getVaultWeight() {
|
|
|
|
return this.vaultWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getTradingForWeight() {
|
|
|
|
return calculateTradingForWeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getTradingWeight() {
|
|
|
|
|
|
|
|
int weight = 0;
|
|
|
|
Item item;
|
|
|
|
|
|
|
|
for (int i : this.trading) {
|
|
|
|
item = Item.getFromCache(i);
|
|
|
|
|
|
|
|
if (item == null)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
weight += item.template.item_wt;
|
|
|
|
}
|
|
|
|
return weight;
|
|
|
|
}
|
|
|
|
|
|
|
|
public AbstractCharacter getOwner() {
|
|
|
|
return this.absCharacter;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void calculateWeights() {
|
|
|
|
calculateBankWeight();
|
|
|
|
calculateInventoryWeight();
|
|
|
|
calculateEquipWeight();
|
|
|
|
calculateVaultWeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void calculateBankWeight() {
|
|
|
|
this.bankWeight = 0;
|
|
|
|
for (Item item : this.bank) {
|
|
|
|
if (item.template != null)
|
|
|
|
this.bankWeight += item.template.item_value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void calculateEquipWeight() {
|
|
|
|
this.equipWeight = 0;
|
|
|
|
Collection<Item> c = this.equipped.values();
|
|
|
|
Iterator<Item> it = c.iterator();
|
|
|
|
while (it.hasNext()) {
|
|
|
|
Item item = it.next();
|
|
|
|
if (item.template != null)
|
|
|
|
this.equipWeight += item.template.item_wt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void calculateInventoryWeight() {
|
|
|
|
this.inventoryWeight = 0;
|
|
|
|
for (Item item : this.inventory) {
|
|
|
|
if (item.template != null)
|
|
|
|
this.inventoryWeight += item.template.item_wt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void calculateVaultWeight() {
|
|
|
|
this.vaultWeight = 0;
|
|
|
|
for (Item item : this.vault) {
|
|
|
|
if (item.template != null)
|
|
|
|
this.vaultWeight += item.template.item_wt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private int calculateTradingForWeight() {
|
|
|
|
int tradingForWeight = 0;
|
|
|
|
|
|
|
|
return tradingForWeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void updateInventory(Item item, boolean add) {
|
|
|
|
ArrayList<Item> list = new ArrayList<>();
|
|
|
|
list.add(item);
|
|
|
|
updateInventory(list, add);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void updateInventory(ArrayList<Item> inventory, boolean add) {
|
|
|
|
|
|
|
|
if (this.absCharacter == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) == false)
|
|
|
|
return;
|
|
|
|
|
|
|
|
PlayerCharacter pc = (PlayerCharacter) this.absCharacter;
|
|
|
|
|
|
|
|
UpdateInventoryMsg updateInventoryMsg = new UpdateInventoryMsg(inventory, this.getBank(), this.getGoldInventory(), add);
|
|
|
|
Dispatch dispatch = Dispatch.borrow(pc, updateInventoryMsg);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void forceToInventory(int slot, Item item, PlayerCharacter pc, boolean initialized) {
|
|
|
|
if (item == null || pc == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!item.moveItemToInventory(pc)) {
|
|
|
|
//TODO well why did this fail? clean it up
|
|
|
|
}
|
|
|
|
|
|
|
|
// remove it from other lists:
|
|
|
|
this.remItemFromLists(item, (byte) slot);
|
|
|
|
|
|
|
|
// add to Inventory
|
|
|
|
this.inventory.add(item);
|
|
|
|
item.addToCache();
|
|
|
|
|
|
|
|
calculateWeights();
|
|
|
|
|
|
|
|
//Update players with unequipped item
|
|
|
|
if (initialized) {
|
|
|
|
TransferItemFromEquipToInventoryMsg back = new TransferItemFromEquipToInventoryMsg(pc, slot);
|
|
|
|
DispatchMessage.dispatchMsgToInterestArea(pc, back, engine.Enum.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update the player's inventory window by resending the entire contents.
|
|
|
|
*/
|
|
|
|
public void updateInventory() {
|
|
|
|
this.updateInventory(this.getInventory(), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void initializeTrade() {
|
|
|
|
this.trading = new HashSet<>();
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean commitTrade() {
|
|
|
|
int goldFrom1 = 0;
|
|
|
|
int goldFrom2 = 0;
|
|
|
|
|
|
|
|
if (this.getTradingWith() == null || this.getTradingWith().isConnected() == false
|
|
|
|
|| this.getTradingWith().getPlayerCharacter() == null) {
|
|
|
|
this.endTrade();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CharacterItemManager tradingWith = this.getTradingWith().getPlayerCharacter().getCharItemManager();
|
|
|
|
|
|
|
|
if (tradingWith == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (this.goldTradingAmount != 0) {
|
|
|
|
|
|
|
|
if (tradingWith.goldInventory == null) {
|
|
|
|
Logger.error("Null Gold for player " + this.getOwner().getObjectUUID());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
goldFrom1 = this.goldTradingAmount;
|
|
|
|
}
|
|
|
|
if (tradingWith.goldTradingAmount != 0) {
|
|
|
|
|
|
|
|
if (this.getGoldInventory() == null) {
|
|
|
|
Logger.error("Null Gold for player " + this.getOwner().getObjectUUID());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
goldFrom2 = tradingWith.goldTradingAmount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.getGoldInventory().getNumOfItems() + goldFrom2 > 10000000) {
|
|
|
|
PlayerCharacter pc = (PlayerCharacter) this.absCharacter;
|
|
|
|
if (pc.getClientConnection() != null)
|
|
|
|
ErrorPopupMsg.sendErrorPopup(pc, 202);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tradingWith.getGoldInventory().getNumOfItems() + goldFrom1 > 10000000) {
|
|
|
|
PlayerCharacter pc = (PlayerCharacter) tradingWith.absCharacter;
|
|
|
|
if (pc.getClientConnection() != null)
|
|
|
|
ErrorPopupMsg.sendErrorPopup(pc, 202);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.trading.size() > 0 || tradingWith.trading.size() > 0 || goldFrom1 > 0 || goldFrom2 > 0) {
|
|
|
|
if (!DbManager.ItemQueries.DO_TRADE(this.trading, tradingWith.trading, this, tradingWith,
|
|
|
|
this.goldInventory, tradingWith.goldInventory, goldFrom1, goldFrom2))
|
|
|
|
return false;
|
|
|
|
} else
|
|
|
|
return true;
|
|
|
|
|
|
|
|
for (int i : this.trading) {
|
|
|
|
Item item = Item.getFromCache(i);
|
|
|
|
if (item == null)
|
|
|
|
continue;
|
|
|
|
this.trade(item);
|
|
|
|
tradingWith.tradeForItem(item);
|
|
|
|
}
|
|
|
|
for (int i : tradingWith.trading) {
|
|
|
|
Item item = Item.getFromCache(i);
|
|
|
|
if (item == null)
|
|
|
|
continue;
|
|
|
|
tradingWith.trade(item);
|
|
|
|
this.tradeForItem(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
//subtract gold your trading from your inventory.
|
|
|
|
if (this.goldTradingAmount > 0)
|
|
|
|
this.getGoldInventory().setNumOfItems(this.getGoldInventory().getNumOfItems() - this.goldTradingAmount);
|
|
|
|
//subtract gold your trading from your inventory.
|
|
|
|
if (tradingWith.goldTradingAmount > 0)
|
|
|
|
tradingWith.getGoldInventory().setNumOfItems(tradingWith.getGoldInventory().getNumOfItems() - tradingWith.goldTradingAmount);
|
|
|
|
|
|
|
|
if (tradingWith.goldTradingAmount > 0)
|
|
|
|
this.getGoldInventory().setNumOfItems(this.goldInventory.getNumOfItems()
|
|
|
|
+ tradingWith.goldTradingAmount);
|
|
|
|
if (this.goldTradingAmount > 0)
|
|
|
|
tradingWith.getGoldInventory().setNumOfItems(tradingWith.goldInventory.getNumOfItems()
|
|
|
|
+ this.goldTradingAmount);
|
|
|
|
|
|
|
|
this.tradeSuccess = true;
|
|
|
|
tradingWith.tradeSuccess = true;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void endTrade() {
|
|
|
|
updateInventory(this.getInventory(), true);
|
|
|
|
this.tradeCommitted = (byte) 0;
|
|
|
|
this.tradeSuccess = false;
|
|
|
|
this.tradingWith = null;
|
|
|
|
this.trading = null;
|
|
|
|
this.goldTradingAmount = 0;
|
|
|
|
this.tradeID = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void endTrade(boolean fromDeath) {
|
|
|
|
this.tradeCommitted = (byte) 0;
|
|
|
|
this.tradeSuccess = false;
|
|
|
|
this.tradingWith = null;
|
|
|
|
this.trading = null;
|
|
|
|
this.goldTradingAmount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove item from your possession
|
|
|
|
private synchronized boolean trade(Item i) {
|
|
|
|
if (this.doesCharOwnThisItem(i.getObjectUUID()) == false)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Only valid from inventory
|
|
|
|
if (!inventoryContains(i))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// remove from Inventory
|
|
|
|
this.inventory.remove(i);
|
|
|
|
this.itemIDtoType.remove(i.getObjectUUID());
|
|
|
|
i.setOwnerID(0);
|
|
|
|
|
|
|
|
calculateWeights();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Damage an equipped item a specified amount
|
|
|
|
public void damageItem(Item item, int amount) {
|
|
|
|
if (item == null || amount < 1 || amount > 5)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//verify the item is equipped by this player
|
|
|
|
int slot = item.getEquipSlot();
|
|
|
|
if (!this.equipped.containsKey(slot))
|
|
|
|
return;
|
|
|
|
Item verify = this.equipped.get(slot);
|
|
|
|
if (verify == null || item.getObjectUUID() != verify.getObjectUUID())
|
|
|
|
return;
|
|
|
|
|
|
|
|
//don't damage noob gear, hair or beards.
|
|
|
|
if (item.template.item_health_full == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!item.isCanDestroy())
|
|
|
|
return;
|
|
|
|
|
|
|
|
int dur = (int) (short) item.durabilityCurrent;
|
|
|
|
|
|
|
|
if (dur - amount <= 0) {
|
|
|
|
//destroy the item
|
|
|
|
junk(item);
|
|
|
|
|
|
|
|
//TODO remove item from the client
|
|
|
|
//This may not be correct
|
|
|
|
dur = 0;
|
|
|
|
} else {
|
|
|
|
dur -= amount;
|
|
|
|
if (!DbManager.ItemQueries.SET_DURABILITY(item, dur))
|
|
|
|
return;
|
|
|
|
item.setDurabilityCurrent((short) dur);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.absCharacter.getObjectType().equals(GameObjectType.PlayerCharacter) == false)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//send damage item msg to client
|
|
|
|
PlayerCharacter pc = (PlayerCharacter) this.absCharacter;
|
|
|
|
|
|
|
|
ItemHealthUpdateMsg itemHealthUpdateMsg = new ItemHealthUpdateMsg(slot, (float) dur);
|
|
|
|
Dispatch dispatch = Dispatch.borrow(pc, itemHealthUpdateMsg);
|
|
|
|
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//Damage a random piece of armor a specified amount
|
|
|
|
public void damageRandomArmor(int amount) {
|
|
|
|
ArrayList<Item> armor = new ArrayList<>();
|
|
|
|
if (this.equipped.containsKey(MBServerStatics.SLOT_OFFHAND)) {
|
|
|
|
Item item = this.equipped.get(MBServerStatics.SLOT_OFFHAND);
|
|
|
|
ItemBase ib = item.getItemBase();
|
|
|
|
if (ib.isShield())
|
|
|
|
armor.add(item);
|
|
|
|
}
|
|
|
|
if (this.equipped.containsKey(MBServerStatics.SLOT_HELMET))
|
|
|
|
armor.add(this.equipped.get(MBServerStatics.SLOT_HELMET));
|
|
|
|
if (this.equipped.containsKey(MBServerStatics.SLOT_CHEST))
|
|
|
|
armor.add(this.equipped.get(MBServerStatics.SLOT_CHEST));
|
|
|
|
if (this.equipped.containsKey(MBServerStatics.SLOT_ARMS))
|
|
|
|
armor.add(this.equipped.get(MBServerStatics.SLOT_ARMS));
|
|
|
|
if (this.equipped.containsKey(MBServerStatics.SLOT_GLOVES))
|
|
|
|
armor.add(this.equipped.get(MBServerStatics.SLOT_GLOVES));
|
|
|
|
if (this.equipped.containsKey(MBServerStatics.SLOT_GLOVES))
|
|
|
|
armor.add(this.equipped.get(MBServerStatics.SLOT_GLOVES));
|
|
|
|
if (this.equipped.containsKey(MBServerStatics.SLOT_LEGGINGS))
|
|
|
|
armor.add(this.equipped.get(MBServerStatics.SLOT_LEGGINGS));
|
|
|
|
if (this.equipped.containsKey(MBServerStatics.SLOT_FEET))
|
|
|
|
armor.add(this.equipped.get(MBServerStatics.SLOT_FEET));
|
|
|
|
|
|
|
|
if (armor.isEmpty())
|
|
|
|
return; //nothing to damage
|
|
|
|
|
|
|
|
int roll = ThreadLocalRandom.current().nextInt(armor.size());
|
|
|
|
damageItem(armor.get(roll), amount);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Damage all equipped gear a random amount between 1 and 5
|
|
|
|
public void damageAllGear() {
|
|
|
|
for (Item gear : this.equipped.values()) {
|
|
|
|
damageItem(gear, (ThreadLocalRandom.current().nextInt(5) + 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add item to your possession
|
|
|
|
public synchronized boolean tradeForItem(Item i) {
|
|
|
|
// add to Inventory
|
|
|
|
this.inventory.add(i);
|
|
|
|
this.itemIDtoType.put(i.getObjectUUID(), i.getObjectType().ordinal());
|
|
|
|
i.setOwnerID(this.absCharacter.getObjectUUID());
|
|
|
|
|
|
|
|
calculateWeights();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean addGoldToTrade(int amount) {
|
|
|
|
|
|
|
|
if (this.goldTradingAmount + amount > MBServerStatics.PLAYER_GOLD_LIMIT)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
this.goldTradingAmount += amount;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Completely empties inventory, deleting any items. Use with caution!
|
|
|
|
*/
|
|
|
|
public synchronized void clearInventory() {
|
|
|
|
this.getGoldInventory().setNumOfItems(0);
|
|
|
|
Iterator<Item> ii = this.inventory.iterator();
|
|
|
|
while (ii.hasNext()) {
|
|
|
|
Item itm = ii.next();
|
|
|
|
ii.remove();
|
|
|
|
this.delete(itm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized void clearEquip() {
|
|
|
|
|
|
|
|
ArrayList<Item> equipCopy = new ArrayList<>(this.getEquippedList());
|
|
|
|
Iterator<Item> ii = equipCopy.iterator();
|
|
|
|
while (ii.hasNext()) {
|
|
|
|
Item itm = ii.next();
|
|
|
|
this.getEquippedList().remove(itm);
|
|
|
|
this.delete(itm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public byte getEquipVer() {
|
|
|
|
return this.equipVer;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void incEquipVer() {
|
|
|
|
this.equipVer++;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void incInventoryVer() {
|
|
|
|
this.equipVer++;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void incBankVer() {
|
|
|
|
this.equipVer++;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void incVaultVer() {
|
|
|
|
this.equipVer++;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getTradeID() {
|
|
|
|
return tradeID;
|
|
|
|
}
|
|
|
|
|
|
|
|
public synchronized boolean closeTradeWindow() {
|
|
|
|
if (this.getTradingWith() != null || this.getTradeID() != 0)
|
|
|
|
this.closeTradeWindow(new CloseTradeWindowMsg(this.getOwner(), this.getTradeID()), true);
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|