Exemple #1
0
 public static bool DrawItemChangeInfo(ItemChangeInfo info)
 {
     if (info.item != null)
     {
         int max = info.item.maxAmount;
         if (max == -1)
         {
             info.amountToAdd = EditorGUILayout.IntField("Amount to add ", info.amountToAdd);
         }
         else
         {
             info.amountToAdd = EditorGUILayout.IntSlider(info.amountToAdd, -info.item.maxAmount, info.item.maxAmount);
         }
         info.newDescription = EditorGUILayout.TextField("New Description", info.newDescription);
         info.historyString  = EditorGUILayout.TextField("History String", info.historyString);
     }
     if (GUILayout.Button("X"))
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
    /// <summary>
    /// 修改道具数量
    /// </summary>
    /// <param name="uid"></param>
    /// <param name="count"></param>
    public void ChangeStackCount(ulong uid, long count)
    {
        if (m_Items.TryGetValue(uid, out ItemContainer item))
        {
            long oldCount = item.Count;

            item.Count = count;
            if (item.MainType == Category.Currency)
            {
                SendNotification(NotificationName.MSG_CURRENCY_CHANGED);
            }
            if (oldCount != count)
            {
                ItemChangeInfo info = new ItemChangeInfo()
                {
                    Category         = item.MainType,
                    UID              = item.UID,
                    TID              = item.TID,
                    ItemPos          = item.Position,
                    ParentUID        = item.ParentUID,
                    ChangeType       = ItemChangeInfo.Type.CountChange,
                    CountChangeDelta = count - oldCount
                };

                SendNotification(NotificationName.MSG_PACKAGE_ITEM_CHANGE, info);
            }
        }
    }
        /// <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);
        }
        private static void GuaranteedExecuteInfo(
            IItemContainer container, ItemChangeInfo info)
        {
            // make sure we're in range.
            if (0 > info.Index || info.Index >= container.Provider.Count)
            {
                return;
            }

            // try managed
            if (!container.ExecuteChangeInfo(info))
            {
                // it failed, force it
                container.Provider[info.Index] = info.NewItem;
            }
        }
Exemple #7
0
    /// <summary>
    /// 添加条目
    /// </summary>
    /// <param name="itemGetting">条目数据</param>
    private void OnGettingItem(ItemChangeInfo itemGetting)
    {
        if (itemGetting.CountChangeDelta > 0 && itemGetting.TID > 0)
        {
            if (itemGetting.Category != 0 && itemGetting.Category != Category.Package)
            {
                ItemData data = new ItemData();
                data.Name       = TableUtil.GetItemName(itemGetting.TID);
                data.Quality    = TableUtil.GetItemQuality(itemGetting.TID);
                data.Count      = itemGetting.CountChangeDelta;
                data.IconBundle = TableUtil.GetItemIconBundle(itemGetting.TID);
                data.IconName   = TableUtil.GetItemSquareIconImage(itemGetting.TID);

                m_WaitingQueue.Add(data);
            }
        }
    }
        public bool ExecuteChangeInfo(ItemChangeInfo info)
        {
            if (!info.IsValid)
            {
                return(false);
            }

            if (info.Index < 0 || info.Index >= Provider.Count)
            {
                return(false);
            }

            Provider[info.Index] = info.NewItem;

            Parent.SendMessage(ItemChangeMessage.InventoryChange(this, info));

            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);
        }
Exemple #10
0
    /// <summary>
    /// 添加道具
    /// </summary>
    /// <param name="holdInit"></param>
    /// <param name="uid"></param>
    /// <param name="tid"></param>
    /// <param name="parentUid"></param>
    /// <param name="pos"></param>
    /// <param name="count"></param>
    /// <param name="capacity"></param>
    public Category AddItem(bool holdInit, ulong uid, uint tid, ulong parentUid, int pos, long count, uint capacity, ulong reference, ulong createTime)
    {
        ItemContainer item = CreateItem(uid, tid, parentUid, pos, count, capacity, reference, createTime);

        m_Items.Add(uid, item);
        if (m_PlayerItem == null && item.MainType == Category.Player)
        {
            m_PlayerItem = item;
            return(Category.Player);
        }
        else if (m_HeroItem == null && item.MainType == Category.Hero)
        {
            m_HeroItem = item;
            return(Category.Hero);
        }
        else if (m_SpaceStation == null && item.MainType == Category.WarehousePackage)
        {
            m_SpaceStation = item;
        }

        if (!holdInit)
        {
            LinkData(uid, parentUid);
        }
        if (item.MainType != Category.Skill)
        {
            ItemChangeInfo info = new ItemChangeInfo();
            info.ChangeType       = ItemChangeInfo.Type.Add;
            info.Category         = item.MainType;
            info.UID              = uid;
            info.TID              = item.TID;
            info.ParentUID        = parentUid;
            info.ItemPos          = pos;
            info.CountChangeDelta = count;
            SendNotification(NotificationName.MSG_PACKAGE_ITEM_CHANGE, info);
        }
        return(item.MainType);
    }
        /// <summary>
        /// Executes two ItemChangeInfo's in such a way that change will only occur if the two of them are successful.
        /// </summary>
        /// <returns>True if both infos were executed succesfully, false otherwise.</returns>
        private static bool SafeDoubleInfoExecute(
            IItemContainer managerA, ItemChangeInfo infoA,
            IItemContainer managerB, ItemChangeInfo infoB)
        {
            // cache state of A.
            var idx    = infoA.Index;
            var cacheA = new ItemChangeInfo(idx, managerA.Provider[idx], 0);

            // execute
            if (!managerA.ExecuteChangeInfo(infoA))
            {
                return(false);
            }
            if (!managerB.ExecuteChangeInfo(infoB))
            {
                // A succeeded, B didn't. Revert changes to A.
                GuaranteedExecuteInfo(managerA, cacheA);

                return(false);
            }

            return(true);
        }
Exemple #12
0
    /// <summary>
    /// 删除道具
    /// </summary>
    /// <param name="uid"></param>
    public void RemoveItem(ulong uid)
    {
        if (m_Items.TryGetValue(uid, out ItemContainer item))
        {
            ItemChangeInfo info = new ItemChangeInfo();
            info.ChangeType = ItemChangeInfo.Type.Del;
            info.Category   = item.MainType;
            info.UID        = uid;
            info.ParentUID  = item.ParentUID;
            info.ItemPos    = item.Position;
            info.TID        = item.TID;
            if (item.Reference != 0 && m_Items.TryGetValue(item.Reference, out ItemContainer original))
            {
                original.Replicas.Remove(uid);
            }
            DeLinkData(uid);
            m_Items.Remove(uid);

            if (item.MainType != Category.Skill)
            {
                SendNotification(NotificationName.MSG_PACKAGE_ITEM_CHANGE, info);
            }
        }
    }
 private ItemChangeMessage([NotNull] IItemContainer container, ItemChangeInfo info, MessageId id)
 {
     Container = container ?? throw new ArgumentNullException(nameof(container));
     Info      = info;
     EventId   = (int)id;
 }
Exemple #14
0
 int toInt(ItemChangeInfo pItemChangeInfo)
 {
     var lBitData = new zz.IntBitIO();
     lBitData.write(pItemChangeInfo.count, 14);
     lBitData.write(pItemChangeInfo.itemId, 14);
     lBitData.write(pItemChangeInfo.index, 4);
     return lBitData.date;
 }
        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);
            }
        }
 public static ItemChangeMessage EquipmentChange([NotNull] IItemContainer container, ItemChangeInfo info)
 => new ItemChangeMessage(container, info, MessageId.EquipmentChange);
 public static ItemChangeMessage InventoryChange([NotNull] IItemContainer container, ItemChangeInfo info)
 => new ItemChangeMessage(container, info, MessageId.ItemChange);
Exemple #18
0
 private void HandleItemChange(ItemChangeInfo info)
 {
     _dirtyBuffer.Add(info.Index);
 }
Exemple #19
0
 public void ItemBagChange(ItemChangeInfo[] pItemChangeInfo)
 {
     if (Network.isClient)
     {
         switch (pItemChangeInfo.Length)
         {
             case 1: networkView.RPC("ItemBagChange", RPCMode.Server,
                 toInt(pItemChangeInfo[0]));
                 break;
             case 2: networkView.RPC("ItemBagChange2", RPCMode.Server,
                 toInt(pItemChangeInfo[0]),
                 toInt(pItemChangeInfo[1]));
                 break;
             case 3: networkView.RPC("ItemBagChange3", RPCMode.Server,
                 toInt(pItemChangeInfo[0]),
                 toInt(pItemChangeInfo[1]),
                 toInt(pItemChangeInfo[2]));
                 break;
             case 4: networkView.RPC("ItemBagChange4", RPCMode.Server,
                 toInt(pItemChangeInfo[0]),
                 toInt(pItemChangeInfo[1]),
                 toInt(pItemChangeInfo[2]),
                 toInt(pItemChangeInfo[3]));
                 break;
             case 5: networkView.RPC("ItemBagChange5", RPCMode.Server,
                 toInt(pItemChangeInfo[0]),
                 toInt(pItemChangeInfo[1]),
                 toInt(pItemChangeInfo[2]),
                 toInt(pItemChangeInfo[3]),
                 toInt(pItemChangeInfo[4]));
                 break;
             default:
                 Debug.LogError("error pItemChangeInfo.Length:" + pItemChangeInfo.Length);
                 break;
         }
     }
     else
     {
         foreach (var lInfo in pItemChangeInfo)
         {
             ItemBagChange(lInfo.index, lInfo.itemId, lInfo.count);
         }
     }
 }