public bool Move(Item item, Pocket target, byte targetX, byte targetY)
{
if (!this.Has(target))
return false;
var source = item.Info.Pocket;
var amount = item.Info.Amount;
Item collidingItem = null;
var collidingItemTarget = source;
lock (_pockets)
{
// Hotfix for #200, ctrl+click-equipping.
// If an item is moved from the inventory to a filled equip
// slot, but there's not enough space in the source pocket
// for the colliding item, it would vanish, because the Add
// failed. ("Toss it in, it should be the cursor.")
//
// The following code tries to prevent that, by explicitly
// checking if this is a ctrl+click-equip move, and whether
// the potentially colliding item fits into the inventory.
//
// Is there a better way to solve this? Maybe a more
// generalized one? *Without* reverting the move on fail?
if (source != Pocket.Cursor && target.IsEquip())
{
//Log.Debug("Inv2EqMove: {0} -> {1}", source, target);
if ((collidingItem = _pockets[target].GetItemAt(0, 0)) != null)
{
var success = false;
// Cursor will work by default, as it will be
// empty after moving the new item out of it.
if (source == Pocket.Cursor)
{
success = true;
collidingItemTarget = Pocket.Cursor;
}
// Try main inv
if (!success)
{
if (_pockets.ContainsKey(Pocket.Inventory))
{
success = _pockets[Pocket.Inventory].HasSpace(collidingItem);
collidingItemTarget = Pocket.Inventory;
}
}
// VIP inv
if (!success)
{
if (_pockets.ContainsKey(Pocket.VIPInventory))
{
success = _pockets[Pocket.VIPInventory].HasSpace(collidingItem);
collidingItemTarget = Pocket.VIPInventory;
}
}
// Try bags
if (_creature.Client.Account.PremiumServices.CanUseBags)
{
for (var i = Pocket.ItemBags; i <= Pocket.ItemBagsMax && !success; ++i)
{
if (_pockets.ContainsKey(i))
{
success = _pockets[i].HasSpace(collidingItem);
collidingItemTarget = i;
}
}
}
if (!success)
{
Send.Notice(_creature, Localization.Get("There is no room in your inventory."));
return false;
}
}
}
if (!_pockets[target].TryAdd(item, targetX, targetY, out collidingItem))
return false;
// If amount differs (item was added to stack)
if (collidingItem != null && (item.Info.Amount != amount || (item.Info.Amount == 0 && item.Data.Type != ItemType.Sac)))
{
Send.ItemAmount(_creature, collidingItem);
// Left overs or sac, update
if (item.Info.Amount > 0 || item.Data.Type == ItemType.Sac)
{
Send.ItemAmount(_creature, item);
}
// All in, remove from cursor.
else
{
_pockets[item.Info.Pocket].Remove(item);
Send.ItemRemove(_creature, item);
}
}
else
{
// Remove the item from the source pocket
_pockets[source].Remove(item);
if (collidingItem != null)
{
// Move colliding item into the pocket ascertained to
// be free in the beginning.
if (!_pockets[collidingItemTarget].Add(collidingItem))
{
// Should never happen, as it was checked above.
Log.Error("CreatureInventory: Inv2EqMove error? Please report. {0} -> {1}", source, target);
}
}
Send.ItemMoveInfo(_creature, item, source, collidingItem);
}
}
// Inform about temp moves (items in temp don't count for quest objectives?)
if (source == Pocket.Temporary && target == Pocket.Cursor)
{
this.OnItemEntersInventory(item);
ChannelServer.Instance.Events.OnPlayerReceivesItem(_creature, item.Info.Id, item.Info.Amount);
}
// Check movement
this.CheckLeftHand(item, source, target);
this.CheckRightHand(item, source, target);
// Equip handling
if (target.IsEquip())
{
this.UpdateEquipReferences();
this.OnEquip(item);
if (collidingItem != null)
this.OnUnequip(collidingItem);
this.UpdateEquipStats();
Send.EquipmentChanged(_creature, item);
}
else if (source.IsEquip())
{
this.UpdateEquipReferences();
this.OnUnequip(item);
this.UpdateEquipStats();
Send.EquipmentMoved(_creature, source);
}
// Update trade window
if (target == Pocket.Trade)
{
if (collidingItem != null)
_creature.Temp.ActiveTrade.RemoveItem(_creature, collidingItem);
_creature.Temp.ActiveTrade.AddItem(_creature, item);
}
if (source == Pocket.Trade) _creature.Temp.ActiveTrade.RemoveItem(_creature, item);
// Update entrustment window
if (target >= Pocket.EntrustmentItem1 && target <= Pocket.EntrustmentReward)
{
if (collidingItem != null)
_creature.Temp.ActiveEntrustment.RemoveItem(collidingItem, target);
_creature.Temp.ActiveEntrustment.AddItem(item, target);
}
if (source >= Pocket.EntrustmentItem1 && source <= Pocket.EntrustmentReward) _creature.Temp.ActiveEntrustment.RemoveItem(item, source);
return true;
}