fix: Cleans up FindItems and removes allocations (#1516)
This commit is contained in:
parent
a4cabe2fa4
commit
d77dac9516
17 changed files with 105 additions and 127 deletions
|
|
@ -23,8 +23,8 @@ namespace Server.Items;
|
|||
public partial class Container
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public FindItemsByTypeEnumerator<Item> FindItemsByType(bool recurse = true, Predicate<Item> predicate = null)
|
||||
=> FindItemsByType<Item>(recurse, predicate);
|
||||
public FindItemsByTypeEnumerator<Item> FindItems(bool recurse = true, Predicate<Item> predicate = null)
|
||||
=> FindItemsByType(recurse, predicate);
|
||||
|
||||
/// <summary>
|
||||
/// Performs a breadth-first search through all the <see cref="Item" />s and
|
||||
|
|
@ -61,8 +61,8 @@ public partial class Container
|
|||
where T : Item => new(this, recurse, predicate);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public QueuedItemsEnumerator<Item> EnumerateItemsByType(bool recurse = true, Predicate<Item> predicate = null)
|
||||
=> EnumerateItemsByType<Item>(recurse, predicate);
|
||||
public QueuedItemsEnumerator<Item> EnumerateItems(bool recurse = true, Predicate<Item> predicate = null)
|
||||
=> EnumerateItemsByType(recurse, predicate);
|
||||
|
||||
/// <summary>
|
||||
/// Safely enumerates items using a breadth-first search through all the <see cref="Item" />s and
|
||||
|
|
@ -102,8 +102,8 @@ public partial class Container
|
|||
where T : Item => new(QueueItemsByType(recurse, predicate));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public PooledRefQueue<Item> QueueItemsByType(bool recurse = true, Predicate<Item> predicate = null) =>
|
||||
QueueItemsByType<Item>(recurse, predicate);
|
||||
public PooledRefQueue<Item> QueueItems(bool recurse = true, Predicate<Item> predicate = null) =>
|
||||
QueueItemsByType(recurse, predicate);
|
||||
|
||||
public PooledRefQueue<T> QueueItemsByType<T>(bool recurse = true, Predicate<T> predicate = null) where T : Item
|
||||
{
|
||||
|
|
@ -117,8 +117,8 @@ public partial class Container
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public PooledRefList<Item> ListItemsByType(bool recurse = true, Predicate<Item> predicate = null) =>
|
||||
ListItemsByType<Item>(recurse, predicate);
|
||||
public PooledRefList<Item> ListItems(bool recurse = true, Predicate<Item> predicate = null) =>
|
||||
ListItemsByType(recurse, predicate);
|
||||
|
||||
public PooledRefList<T> ListItemsByType<T>(bool recurse = true, Predicate<T> predicate = null) where T : Item
|
||||
{
|
||||
|
|
|
|||
|
|
@ -273,21 +273,6 @@ public partial class Container : Item
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool InTypeList(Item item, Type[] types)
|
||||
{
|
||||
var t = item.GetType();
|
||||
|
||||
for (var i = 0; i < types.Length; ++i)
|
||||
{
|
||||
if (types[i].IsAssignableFrom(t))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf)
|
||||
{
|
||||
if (setIf)
|
||||
|
|
@ -816,7 +801,7 @@ public partial class Container : Item
|
|||
}
|
||||
|
||||
using var typedItems = PooledRefList<Item>.Create();
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (type.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
@ -936,7 +921,7 @@ public partial class Container : Item
|
|||
{
|
||||
var type = types[i];
|
||||
using var typedItems = PooledRefList<Item>.Create();
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (type.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
@ -1270,7 +1255,7 @@ public partial class Container : Item
|
|||
using var items = PooledRefQueue<Item>.Create();
|
||||
|
||||
// First pass, compute total
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (type.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
@ -1380,7 +1365,7 @@ public partial class Container : Item
|
|||
var best = 0;
|
||||
|
||||
using var typedItems = PooledRefList<Item>.Create();
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (type.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
@ -1565,7 +1550,7 @@ public partial class Container : Item
|
|||
public int GetAmount(Type type, bool recurse = true)
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (type.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
@ -1579,9 +1564,9 @@ public partial class Container : Item
|
|||
public int GetAmount(Type[] types, bool recurse = true)
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (InTypeList(item, types))
|
||||
if (item.InTypeList(types))
|
||||
{
|
||||
total += item.Amount;
|
||||
}
|
||||
|
|
@ -1593,7 +1578,7 @@ public partial class Container : Item
|
|||
public List<Item> FindItemsByType(Type type, bool recurse = true)
|
||||
{
|
||||
var items = new List<Item>();
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (type.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
@ -1607,9 +1592,9 @@ public partial class Container : Item
|
|||
public List<Item> FindItemsByType(Type[] types, bool recurse = true)
|
||||
{
|
||||
var items = new List<Item>();
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (InTypeList(item, types))
|
||||
if (item.InTypeList(types))
|
||||
{
|
||||
items.Add(item);
|
||||
}
|
||||
|
|
@ -1620,7 +1605,7 @@ public partial class Container : Item
|
|||
|
||||
public Item FindItemByType(Type type, bool recurse = true)
|
||||
{
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (type.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
@ -1633,9 +1618,9 @@ public partial class Container : Item
|
|||
|
||||
public Item FindItemByType(Type[] types, bool recurse = true)
|
||||
{
|
||||
foreach (var item in FindItemsByType(recurse))
|
||||
foreach (var item in FindItems(recurse))
|
||||
{
|
||||
if (InTypeList(item, types))
|
||||
if (item.InTypeList(types))
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ public static class TileData
|
|||
bin.Read(buffer);
|
||||
var terminator = buffer.IndexOfTerminator(1);
|
||||
var name = Encoding.ASCII.GetString(buffer[..(terminator < 0 ? buffer.Length : terminator)]);
|
||||
LandTable[i] = new LandData(Utility.Intern(name), flags);
|
||||
LandTable[i] = new LandData(name.Intern(), flags);
|
||||
}
|
||||
|
||||
for (var i = 0; i < itemLength; i++)
|
||||
|
|
@ -367,7 +367,7 @@ public static class TileData
|
|||
var terminator = buffer.IndexOfTerminator(1);
|
||||
var name = Encoding.ASCII.GetString(buffer[..(terminator < 0 ? buffer.Length : terminator)]);
|
||||
ItemTable[i] = new ItemData(
|
||||
Utility.Intern(name),
|
||||
name.Intern(),
|
||||
flags,
|
||||
weight,
|
||||
quality,
|
||||
|
|
|
|||
|
|
@ -1761,4 +1761,20 @@ public static class Utility
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNullOrWhiteSpace(this ReadOnlySpan<char> span) =>
|
||||
span == default || span.IsEmpty || span.IsWhiteSpace();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool InTypeList(this Item item, Type[] types) => item.GetType().InTypeList(types);
|
||||
|
||||
public static bool InTypeList(this Type t, Type[] types)
|
||||
{
|
||||
for (var i = 0; i < types.Length; ++i)
|
||||
{
|
||||
if (types[i].IsAssignableFrom(t))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ namespace Server.Commands.Generic
|
|||
|
||||
var list = new List<object>();
|
||||
|
||||
foreach (var item in cont.FindItemsByType())
|
||||
foreach (var item in cont.FindItems())
|
||||
{
|
||||
if (ext.IsValid(item))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ namespace Server.Engines.Craft
|
|||
|
||||
if (from.Backpack != null)
|
||||
{
|
||||
foreach (var item in from.Backpack.FindItemsByType())
|
||||
foreach (var item in from.Backpack.FindItems())
|
||||
{
|
||||
if (resourceType.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
@ -186,7 +186,7 @@ namespace Server.Engines.Craft
|
|||
|
||||
if (from.Backpack != null)
|
||||
{
|
||||
foreach (var item in from.Backpack.FindItemsByType())
|
||||
foreach (var item in from.Backpack.FindItems())
|
||||
{
|
||||
if (resourceType.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
@ -266,7 +266,7 @@ namespace Server.Engines.Craft
|
|||
if (from.Backpack != null)
|
||||
{
|
||||
var type = subResource.ItemType;
|
||||
foreach (var item in from.Backpack.FindItemsByType())
|
||||
foreach (var item in from.Backpack.FindItems())
|
||||
{
|
||||
if (type.IsInstanceOfType(item))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -530,23 +530,20 @@ namespace Server.Engines.Craft
|
|||
|
||||
public int GetQuantity(Container cont, Type[] types)
|
||||
{
|
||||
var items = cont.FindItemsByType(types);
|
||||
|
||||
var amount = 0;
|
||||
|
||||
for (var i = 0; i < items.Count; ++i)
|
||||
foreach (var item in cont.FindItems())
|
||||
{
|
||||
if (items[i] is not IHasQuantity hq)
|
||||
if (!item.InTypeList(types))
|
||||
{
|
||||
amount += items[i].Amount;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((hq as BaseBeverage)?.Content != RequiredBeverage)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item is not IHasQuantity hq)
|
||||
{
|
||||
amount += item.Amount;
|
||||
}
|
||||
else if ((hq as BaseBeverage)?.Content == RequiredBeverage)
|
||||
{
|
||||
amount += hq.Quantity;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ namespace Server.Engines.MLQuests.Objectives
|
|||
}
|
||||
|
||||
var total = 0;
|
||||
foreach (var item in pack.FindItemsByType(false))
|
||||
foreach (var item in pack.FindItems(false))
|
||||
{
|
||||
if (ClaimTypePredicate(item) && item.QuestItem && Objective.CheckItem(item))
|
||||
{
|
||||
|
|
@ -135,7 +135,7 @@ namespace Server.Engines.MLQuests.Objectives
|
|||
return;
|
||||
}
|
||||
|
||||
foreach (var item in pack.FindItemsByType(false))
|
||||
foreach (var item in pack.FindItems(false))
|
||||
{
|
||||
// does another quest still need this item? (OSI just unmarks everything)
|
||||
if (ClaimTypePredicate(item) &&
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ namespace Server.Engines.MLQuests.Objectives
|
|||
}
|
||||
|
||||
var total = 0;
|
||||
foreach (var item in pack.FindItemsByType(false))
|
||||
foreach (var item in pack.FindItems(false))
|
||||
{
|
||||
if (ClaimTypePredicate(item))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -430,9 +430,7 @@ namespace Server.Engines.Plants
|
|||
return null;
|
||||
}
|
||||
|
||||
var items = from.Backpack.FindItemsByType(new[] { typeof(BasePotion), typeof(PotionKeg) });
|
||||
|
||||
foreach (var item in items)
|
||||
foreach (var item in from.Backpack.FindItems())
|
||||
{
|
||||
if (item is BasePotion potion)
|
||||
{
|
||||
|
|
@ -441,14 +439,9 @@ namespace Server.Engines.Plants
|
|||
return potion;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (item is PotionKeg keg && keg.Held > 0 && Array.IndexOf(effects, keg.Type) >= 0)
|
||||
{
|
||||
var keg = (PotionKeg)item;
|
||||
|
||||
if (keg.Held > 0 && Array.IndexOf(effects, keg.Type) >= 0)
|
||||
{
|
||||
return keg;
|
||||
}
|
||||
return keg;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -225,32 +225,19 @@ namespace Server.Items
|
|||
return true;
|
||||
}
|
||||
|
||||
return IsInTypeList(t, TreasuresOfTokuno.TokunoDyable)
|
||||
|| IsInTypeList(t, TreasuresOfTokuno.LesserArtifactsTotal)
|
||||
|| IsInTypeList(t, TreasuresOfTokuno.GreaterArtifacts)
|
||||
|| IsInTypeList(t, DemonKnight.ArtifactRarity10)
|
||||
|| IsInTypeList(t, DemonKnight.ArtifactRarity11)
|
||||
|| IsInTypeList(t, MondainsLegacy.Artifacts)
|
||||
|| IsInTypeList(t, StealableArtifacts.TypesOfEntries)
|
||||
|| IsInTypeList(t, Paragon.Artifacts)
|
||||
|| IsInTypeList(t, Leviathan.Artifacts)
|
||||
|| IsInTypeList(t, TreasureMapChest.Artifacts)
|
||||
|| IsInTypeList(t, m_Replicas)
|
||||
|| IsInTypeList(t, m_DyableHeritageItems)
|
||||
|| IsInTypeList(t, m_Glasses);
|
||||
}
|
||||
|
||||
private static bool IsInTypeList(Type t, Type[] list)
|
||||
{
|
||||
for (var i = 0; i < list.Length; i++)
|
||||
{
|
||||
if (list[i].IsAssignableFrom(t))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return t.InTypeList(TreasuresOfTokuno.TokunoDyable)
|
||||
|| t.InTypeList(TreasuresOfTokuno.LesserArtifactsTotal)
|
||||
|| t.InTypeList(TreasuresOfTokuno.GreaterArtifacts)
|
||||
|| t.InTypeList(DemonKnight.ArtifactRarity10)
|
||||
|| t.InTypeList(DemonKnight.ArtifactRarity11)
|
||||
|| t.InTypeList(MondainsLegacy.Artifacts)
|
||||
|| t.InTypeList(StealableArtifacts.TypesOfEntries)
|
||||
|| t.InTypeList(Paragon.Artifacts)
|
||||
|| t.InTypeList(Leviathan.Artifacts)
|
||||
|| t.InTypeList(TreasureMapChest.Artifacts)
|
||||
|| t.InTypeList(m_Replicas)
|
||||
|| t.InTypeList(m_DyableHeritageItems)
|
||||
|| t.InTypeList(m_Glasses);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ namespace Server.Mobiles
|
|||
|
||||
var buttons = ToTTurnInGump.FindRedeemableItems(pm);
|
||||
|
||||
if (buttons.Count > 0 && !pm.HasGump<ToTTurnInGump>())
|
||||
if (buttons?.Count > 0 && !pm.HasGump<ToTTurnInGump>())
|
||||
{
|
||||
pm.SendGump(new ToTTurnInGump(this, buttons));
|
||||
}
|
||||
|
|
@ -344,16 +344,17 @@ namespace Server.Gumps
|
|||
var pack = m.Backpack;
|
||||
if (pack == null)
|
||||
{
|
||||
return new List<ImageTileButtonInfo>();
|
||||
return null;
|
||||
}
|
||||
|
||||
var buttons = new List<ImageTileButtonInfo>();
|
||||
|
||||
var items = pack.FindItemsByType(TreasuresOfTokuno.LesserArtifactsTotal);
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
foreach (var item in pack.FindItems())
|
||||
{
|
||||
var item = items[i];
|
||||
if (!item.InTypeList(TreasuresOfTokuno.LesserArtifactsTotal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item is ChestOfHeirlooms heirlooms && (!heirlooms.Locked || heirlooms.TrapLevel != 10))
|
||||
{
|
||||
continue;
|
||||
|
|
@ -407,7 +408,7 @@ namespace Server.Gumps
|
|||
|
||||
pm.CloseGump<ToTTurnInGump>(); // Sanity
|
||||
|
||||
if (buttons.Count > 0)
|
||||
if (buttons?.Count > 0)
|
||||
{
|
||||
pm.SendGump(new ToTTurnInGump(m_Collector, buttons));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ public partial class SalvageBag : Bag
|
|||
var salvaged = 0;
|
||||
var notSalvaged = 0;
|
||||
|
||||
foreach (var item in FindItemsByType())
|
||||
foreach (var item in EnumerateItems())
|
||||
{
|
||||
if (item?.Deleted != false)
|
||||
{
|
||||
|
|
@ -271,11 +271,12 @@ public partial class SalvageBag : Bag
|
|||
// Salvaged: ~1_COUNT~/~2_NUM~ tailored items
|
||||
from.SendLocalizedMessage(1079974, $"{salvaged}\t{salvaged + notSalvaged}");
|
||||
|
||||
var items = FindItemsByType(_clothTypes);
|
||||
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
foreach (var item in EnumerateItems())
|
||||
{
|
||||
from.AddToBackpack(items[i]);
|
||||
if (item.InTypeList(_clothTypes))
|
||||
{
|
||||
from.AddToBackpack(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using ModernUO.Serialization;
|
||||
using Server.Network;
|
||||
using Server.Prompts;
|
||||
|
|
@ -74,9 +75,7 @@ public partial class Key : Item
|
|||
return;
|
||||
}
|
||||
|
||||
var items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) });
|
||||
|
||||
foreach (var item in items)
|
||||
foreach (var item in cont.EnumerateItems())
|
||||
{
|
||||
if (item is Key key)
|
||||
{
|
||||
|
|
@ -85,10 +84,8 @@ public partial class Key : Item
|
|||
key.Delete();
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (item is KeyRing keyRing)
|
||||
{
|
||||
var keyRing = (KeyRing)item;
|
||||
|
||||
keyRing.RemoveKey(keyValue);
|
||||
}
|
||||
}
|
||||
|
|
@ -101,9 +98,7 @@ public partial class Key : Item
|
|||
return false;
|
||||
}
|
||||
|
||||
var items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) });
|
||||
|
||||
foreach (var item in items)
|
||||
foreach (var item in cont.EnumerateItems())
|
||||
{
|
||||
if (item is Key key)
|
||||
{
|
||||
|
|
@ -112,10 +107,8 @@ public partial class Key : Item
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (item is KeyRing keyRing)
|
||||
{
|
||||
var keyRing = (KeyRing)item;
|
||||
|
||||
if (keyRing.ContainsKey(keyValue))
|
||||
{
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ namespace Server.Items
|
|||
{
|
||||
public class PileOfGlacialSnow : Item
|
||||
{
|
||||
private static Type[] _snowPileTypes = { typeof(SnowPile), typeof(PileOfGlacialSnow) };
|
||||
|
||||
[Constructible]
|
||||
public PileOfGlacialSnow() : base(0x913)
|
||||
{
|
||||
|
|
@ -112,7 +114,7 @@ namespace Server.Items
|
|||
{
|
||||
from.SendMessage("You may not throw snow here.");
|
||||
}
|
||||
else if (pack?.FindItemByType(new[] { typeof(SnowPile), typeof(PileOfGlacialSnow) }) != null)
|
||||
else if (pack?.FindItemByType(_snowPileTypes) != null)
|
||||
{
|
||||
if (from.BeginAction<SnowPile>())
|
||||
{
|
||||
|
|
@ -134,16 +136,14 @@ namespace Server.Items
|
|||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
1005577
|
||||
); // You can only throw a snowball at something that can throw one back.
|
||||
// You can only throw a snowball at something that can throw one back.
|
||||
from.SendLocalizedMessage(1005577);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
1005577
|
||||
); // You can only throw a snowball at something that can throw one back.
|
||||
// You can only throw a snowball at something that can throw one back.
|
||||
from.SendLocalizedMessage(1005577);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3929,7 +3929,7 @@ namespace Server.Mobiles
|
|||
|
||||
if (pack != null)
|
||||
{
|
||||
foreach (var item in pack.FindItemsByType())
|
||||
foreach (var item in pack.FindItems())
|
||||
{
|
||||
if (DisplayInItemInsuranceGump(item))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1049,8 +1049,13 @@ namespace Server.Mobiles
|
|||
|
||||
foreach (var ssi in info)
|
||||
{
|
||||
foreach (var item in pack.FindItemsByType(ssi.Types))
|
||||
foreach (var item in pack.FindItems())
|
||||
{
|
||||
if (!item.InTypeList(ssi.Types))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item is Container container && container.Items.Count != 0)
|
||||
{
|
||||
continue;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue