/// <summary> /// Swaps items between two containers and preserves the item indicies. /// </summary> /// <returns>True on success, false otherwise</returns> public static bool InterManagerSwapPreserveIndex( IItemContainer containerA, int idxA, IItemContainer containerB, int idxB) { // validate indicies if (IsNotInRange(idxA, containerA.Provider.Count)) { return(false); } if (IsNotInRange(idxB, containerB.Provider.Count)) { return(false); } // get items var itemA = containerA.Provider[idxA]; var itemB = containerB.Provider[idxB]; // check ids if (itemA.Id == itemB.Id) { // calc stacking A into B long uncheckedOverflow = itemB.Amount + itemA.Amount; var overflow = itemB.Id.GetOverflow(uncheckedOverflow); if (!SafeDoubleInfoExecute( // stack A into B containerB, new ItemChangeInfo(idxB, new ItemStack(itemB.Id, Convert.ToInt32(uncheckedOverflow - overflow)), 0), // leave overflow for A containerA, new ItemChangeInfo(idxA, new ItemStack(itemA.Id, Convert.ToInt32(overflow)), 0))) { return(false); } } else { // remove A and B if (!SafeDoubleInfoExecute( containerA, ItemChangeInfo.Remove(idxA), containerB, ItemChangeInfo.Remove(idxB))) { return(false); } // exec swap if (!SafeDoubleInfoExecute( containerA, new ItemChangeInfo(idxA, itemB, 0), containerB, new ItemChangeInfo(idxB, itemA, 0))) { // reverse removal GuaranteedExecuteInfo(containerA, new ItemChangeInfo(idxA, itemA, 0)); GuaranteedExecuteInfo(containerB, new ItemChangeInfo(idxB, itemB, 0)); } } return(true); }
public void ClearInv(CommandContext ctx) { var inv = ctx.Callee.Parent.AssertGetInventory(); for (var i = 0; i < inv.Inventory.Provider.Count; i++) { inv.Inventory.ExecuteChangeInfo(ItemChangeInfo.Remove(i)); } }
/* * public static bool RemoveFromA_AddToB( * IItemContainer containerA, int idxA, * IItemContainer containerB) * { * // verify idxA * if (IsNotInRange(idxA, containerA.Size)) return false; * var id = containerA.Provider.GetId(idxA); * * // calc changes * var remFromA = ItemChangeInfo.Remove(idxA); * var addToB = containerB.CalcChangeInfo(id, * containerA.Provider.GetAmount(idxA)); * * // verify add to b * if (!addToB.IsValid && addToB.OverflowAmount != 0) return false; * * // execute * if (!SafeDoubleInfoExecute( * containerA, remFromA, * containerB, addToB)) return false; * * return true; * } */ // TODO : write tests for InterManagerSwap /// <summary> /// Swaps items between two containers without preserving the item indicies. /// </summary> /// <returns>True on success, false otherwise</returns> public static bool InterManagerSwap( IItemContainer containerA, int idxA, IItemContainer containerB, int idxB) { // if idxB is null, find either an item idx with the same id or an empty slot. // validate indicies if (IsNotInRange(idxA, containerA.Provider.Count)) { return(false); } if (IsNotInRange(idxB, containerB.Provider.Count)) { return(false); } // get items var itemA = containerA.Provider[idxA]; var itemB = containerB.Provider[idxB]; // calc change info // add A to containerB var cAtoB = containerB.CalcChangeInfo(itemA); // add B to containerA var cBtoA = containerA.CalcChangeInfo(itemB); // operation is undefinied if any changeInfo's are invalid or have overflow, return false bool IsInvalidChangeInfo(ref ItemChangeInfo info) => !info.IsValid || info.OverflowAmount != 0; if (IsInvalidChangeInfo(ref cAtoB)) { return(false); } if (IsInvalidChangeInfo(ref cBtoA)) { return(false); } // managed remove A and B if (!SafeDoubleInfoExecute( containerA, ItemChangeInfo.Remove(idxA), containerB, ItemChangeInfo.Remove(idxB))) { return(false); } // execute change infos we calculated earlier if (!SafeDoubleInfoExecute( containerA, cBtoA, containerB, cAtoB)) { return(false); } return(true); }
public static IEntityHandle PlayerDropItem(this IItemContainer container, int itemIndex, [NotNull] IPlayerComponent player) { if (player == null) { throw new ArgumentNullException(nameof(player)); } var item = container.GetItem(itemIndex); if (item == null) { return(null); } var itemFactory = (IGroundItemFactory)player.Parent.Server.Services.GetService(typeof(IGroundItemFactory)); if (itemFactory == null) { return(null); } var itemEntityHandle = itemFactory.CreatePlayerDrop(item, player, $"Dropped item {item.Id.Name}x{item.Amount}"); if (itemEntityHandle.IsDead()) { return(null); } var itemEntity = itemEntityHandle.Get(); var itemTransform = itemEntity.GetTransform(); var playerTransform = player.Parent.GetTransform(); itemTransform.SwitchPoE(playerTransform.PoE); itemTransform.Teleport(playerTransform); container.ExecuteChangeInfo(ItemChangeInfo.Remove(itemIndex)); return(itemEntityHandle); }
public ItemChangeInfo CalcChangeInfo(ItemStack delta) { if (delta.IsEmpty()) { return(ItemChangeInfo.Invalid); } // figure out whether an item of the same id exists in provider. // if we find an empty slot during this, store it just in case we don't find an existing item. var(nullExistingIdx, emptySlotIdx) = this.GetExistingOrEmptyIdx(delta.Id.ItemId); // we've either found an existing item idx OR have an empty slot id OR have neither of those. // no existing item found, must operation will result in an new item. if (nullExistingIdx == null) { // because we need to add a new item, inputs that result in a remove operation cannot proceed. // filter out remove operations if (delta.Amount <= 0) { return(ItemChangeInfo.Invalid); } // check if we found an empty slot during our iteration. if (emptySlotIdx != null) { // we did, generate a new item var overflow = delta.Id.GetOverflow(delta.Amount); return(new ItemChangeInfo( emptySlotIdx.Value, new ItemStack(delta.Id, (int)(delta.Amount - overflow)), overflow)); } else // we found no empty slots. in this case, it means that the container is full. { return(ItemChangeInfo.Invalid); } } else // we found an item with the same id. { // attempt to add the given amount of the item to this slot. var existingItem = Provider[nullExistingIdx.Value]; var finalNewAmount = existingItem.Amount + delta.Amount; var overflow = delta.Id.GetOverflow(finalNewAmount); // no carry remove item if (finalNewAmount == 0) { return(ItemChangeInfo.Remove(nullExistingIdx.Value)); } // remove with carry if (finalNewAmount < 0) { return(new ItemChangeInfo( nullExistingIdx.Value, ItemStack.Empty, overflow)); } // add with carry if (finalNewAmount > 0) { return(new ItemChangeInfo( nullExistingIdx.Value, new ItemStack(existingItem.Id, (int)(finalNewAmount - overflow)), overflow)); } // crap return(ItemChangeInfo.Invalid); } }