Exemplo n.º 1
0
        /// <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));
            }
        }
Exemplo n.º 3
0
        /*
         * 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);
            }
        }