1. I think many of you noticed that the items in plugin Kits and other are not always granted in the first free slot.

    After studying the problem I realized that the developers probably forget to clear the list of inventory items after removal.

    Removed items are stored in inventory and have the item.uid = 0.

    The workaround is to give the function that after removal of the items forcibly clears the list:

    Code:
            private void StripInventory(PlayerInventory inventory)
            {     
                inventory.Strip();
             
                //Temporary fix to the lack of clean list by the developers
                inventory.containerMain.itemList.Clear();
                inventory.containerBelt.itemList.Clear();
                inventory.containerMain.itemList.Clear();
             
                inventory.ServerUpdate(0f);
            }
    

    Possible about this issue, it is necessary to inform developers.
     
  2. For my experience, you just need to wait 0.1f before giving kit, so for me fix:

    Code:
    inventory.Strip();// Variant 1
    nextTick(() => {
        giveItem();
    });// Variant 2
    timer.Every(0.1f, () => {
        giveItem();
    });
     
  3. Why use a timer? Just do item.RemoveFromWorld() then item.RemoveFromContainer() and you're set. Make sure to use ToList() in your foreach loop to prevent collection modified errors.
     
  4. These actions are guaranteed for the items in the inventory. Not only cleanup from the list "inventory.containerMain.itemList" and others.
     
  5. I think my problem is still relevant.

    Look at the method ItemContainer.Kill():
    upload_2018-2-17_2-35-7.png

    Look at the method ItemContainer.Clear():
    upload_2018-2-17_2-35-32.png

    I do not see that in the method Clear() cleared List with itemList: this.itemList.Clear();
     
  6. I may suppose that item removal postponing was done by some special purpose, thats why there's no List.Clear.
    But wait, there's a real bug in rust code. It's located in ItemManager.DoRemoves.
    Due to misusage of element removal during iteration the actual removing process would take up to a few cycles. That's why plugins has to use stupid approaches with timers, next frames and so on.
    We've tried to report about this issue back to developers with details, let's hope this will be fixed.

    Here's my workaround with an insignificant overhead:
    Code:
            private static void StripInventory(ItemContainer ctr)
            {
                if (ctr.itemList.Count == 0)
                    return;
                var buffer = Pool.GetList<Item>();
                try
                {
                    buffer.AddRange(ctr.itemList);
                    for (var i = 0; i < buffer.Count; i++)
                    {
                        buffer[i].Remove();
                        buffer[i].DoRemove();
                    }
                }
                finally
                {
                    Pool.FreeList(ref buffer);
                }
            }
    
     
    Last edited by a moderator: Feb 17, 2018
  7. @VVoid, i think on last line need add: ctr.itemList.Clear();
     
  8. Wulf

    Wulf Community Admin

    So you're just suggesting that inventory.Strip(); have .Clear() added inside of it?
     
  9. Code:
            private void StripInv(BasePlayer player)
            {
                foreach (var item in player.inventory.containerMain.itemList.ToList())
                {
                    item.RemoveFromWorld();
                    item.RemoveFromContainer();
                }
                foreach (var item in player.inventory.containerBelt.itemList.ToList())
                {
                    item.RemoveFromWorld();
                    item.RemoveFromContainer();
                }
                foreach (var item in player.inventory.containerWear.itemList.ToList())
                {
                    item.RemoveFromWorld();
                    item.RemoveFromContainer();
                }
            }
    
     
  10. I think the right thing to do:
    Code:
            private void StripInventory(BasePlayer player)
            {           
                List<Item> itemList = Pool.GetList<Item>();            itemList.AddRange(player.inventory.containerMain.itemList);
                itemList.AddRange(player.inventory.containerBelt.itemList);
                itemList.AddRange(player.inventory.containerWear.itemList);
               
                for(int i = 0; i < itemList.Count; i++)
                {
                    itemList[i].RemoveFromContainer();
                    itemList[i].Remove();
                }            Pool.FreeList(ref itemList);
            }
    
     
    Last edited by a moderator: Feb 18, 2018
  11. See on pale red solid line:

    Green interval: i use player.inventory.Strip();
    Red interval: method in previous post

    On my server, players can not build, so the leak is visible immediately. On the red interval of the chart, the leak stopped.

    krD9onxCEDa7Om[1].png
     
  12. Your results are sorta unclear, but from what I took from it your method of emptying the inventory does not cause an entity leak?
     
  13. Look at the larger version (red - entities, blue - online)

    Before:
    9c3c55a9d3[1].png
    After:
    Y2LqoNkT9B0KnA[1].png
    [DOUBLEPOST=1519050982][/DOUBLEPOST]
    On my server (FUNRUST) before every day leaked about 3K entities