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.

2631 lines
74 KiB

// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// 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 final AbstractCharacter absCharacter;
private Account account;
// 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 Item goldInventory;
private Item goldBank;
public Item goldVault;
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;
private final HashSet<Integer> equipOrder = new HashSet<>();
/*
* Item Manager Version data
*/
private byte equipVer = (byte) 0;
private static final byte inventoryVer = (byte) 0;
private static final byte bankVer = (byte) 0;
private static final byte vaultVer = (byte) 0;
public CharacterItemManager(AbstractCharacter ac) {
super();
this.absCharacter = ac;
}
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)){
ErrorPopupMsg.sendErrorPopup((PlayerCharacter) this.absCharacter, 203);
return false;
}
}else{
if (!warehouse.withdraw((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.getItemBase().getWeight())) {
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 (i.getChargesRemaining() > 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;
}
// 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());
ItemBase ib = i.getItemBase();
if (ib != null)
this.inventoryWeight += ib.getWeight();
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;
}
//Used for buying MobEquipment from NPC
//Handles the gold transfer aspect
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) {
itemBase = purchasedItem.getItemBase();
if (itemBase == null)
return false;
//test inventory is not full
if (!hasRoomInventory(itemBase.getWeight()))
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
ItemBase ib = lootItem.getItemBase();
if (ib == null)
return null;
short weight = ib.getWeight();
// 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 synchronized void setTradeCommitted(byte tradeCommitted) {
this.tradeCommitted = tradeCommitted;
}
public byte getTradeCommitted() {
return tradeCommitted;
}
public HashSet<Integer> getTrading() {
return trading;
}
public synchronized void addItemToTrade(Item i) {
this.trading.add(i.getObjectUUID());
}
public synchronized void setTradeSuccess(boolean tradeSuccess) {
this.tradeSuccess = tradeSuccess;
}
public boolean getTradeSuccess() {
return 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 (!item.getItemBase().validForSkills(pc.getSkills())){
this.forceToInventory(slot, item, pc, initialized);
pc.applyBonuses();
}
}
return true;
}
/*
* List Copiers
*/
/**
* 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(short 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(short 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(short weight) {
if (this.absCharacter == null)
return false;
return weight <= this.absCharacter.getBankCapacityRemaining();
}
public boolean hasRoomVault(short 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;
ItemBase ib = item.getItemBase();
weight += ib.getWeight();
}
return weight;
}
public AbstractCharacter getOwner() {
return this.absCharacter;
}
public void calculateWeights() {
calculateBankWeight();
calculateInventoryWeight();
calculateEquipWeight();
calculateVaultWeight();
}
public void calculateBankWeight() {
this.bankWeight = 0;
for (Item i : this.bank) {
ItemBase ib = i.getItemBase();
if (ib != null)
this.bankWeight += ib.getWeight();
}
}
public void calculateEquipWeight() {
this.equipWeight = 0;
Collection<Item> c = this.equipped.values();
Iterator<Item> it = c.iterator();
while (it.hasNext()) {
Item i = it.next();
ItemBase ib = i.getItemBase();
if (ib != null)
this.equipWeight += ib.getWeight();
}
}
public void calculateInventoryWeight() {
this.inventoryWeight = 0;
for (Item i : this.inventory) {
ItemBase ib = i.getItemBase();
if (ib != null)
this.inventoryWeight += ib.getWeight();
}
}
public void calculateVaultWeight() {
this.vaultWeight = 0;
for (Item i : this.vault) {
ItemBase ib = i.getItemBase();
if (ib != null)
this.vaultWeight += ib.getWeight();
}
}
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.getDurabilityMax() == 0)
return;
if (!item.isCanDestroy())
return;
int dur = (int) item.getDurabilityCurrent();
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 static byte getInventoryVer() {
return inventoryVer;
}
public static byte getBankVer() {
return bankVer;
}
public static byte getVaultVer() {
return vaultVer;
}
public void incEquipVer() {
this.equipVer++;
}
public void incInventoryVer() {
this.equipVer++;
}
public void incBankVer() {
this.equipVer++;
}
public void incVaultVer() {
this.equipVer++;
}
public static void takeFromNPC(NPC npc, PlayerCharacter pc, Item take, ClientMessagePump clientMessagePump) {
ItemBase ib = take.getItemBase();
if (ib == 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(ib.getWeight()))
return;
if (take != null) {
itemMan.buyFromNPC(take, npc);
itemMan.updateInventory();
}
}
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;
}
}