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.
Bug with inventory.Strip()
Discussion in 'Rust Development' started by miRror, Nov 11, 2017.
-
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(); });
-
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.
-
-
I think my problem is still relevant.
Look at the method ItemContainer.Kill():
Look at the method ItemContainer.Clear():
I do not see that in the method Clear() cleared List with itemList: this.itemList.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 -
@VVoid, i think on last line need add: ctr.itemList.Clear();
-
Wulf Community Admin
So you're just suggesting that inventory.Strip(); have .Clear() added inside of it?
-
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(); } }
-
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 -
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.
-
-
Before:
After:
[DOUBLEPOST=1519050982][/DOUBLEPOST]