diff --git a/Projects/Server/Items/Container.cs b/Projects/Server/Items/Container.cs index 65b910e95..d258d3e45 100644 --- a/Projects/Server/Items/Container.cs +++ b/Projects/Server/Items/Container.cs @@ -430,8 +430,8 @@ public partial class Container : Item public virtual bool TryDropItems(Mobile from, bool sendFullMessage, params ReadOnlySpan droppedItems) { - var dropItems = new List(); - var stackItems = new List(); + using var dropItems = PooledRefQueue.Create(); + using var stackItems = PooledRefQueue.Create(); var extraItems = 0; var extraWeight = 0; @@ -451,7 +451,7 @@ public partial class Container : Item if (item is not Container && CheckHold(from, dropped, false, false, 0, extraWeight) && item.CanStackWith(dropped)) { - stackItems.Add(new ItemStackEntry(item, dropped)); + stackItems.Enqueue(new ItemStackEntry(item, dropped)); extraWeight += (int)Math.Ceiling(item.Weight * (item.Amount + dropped.Amount)) - item.PileWeight; // extra weight delta, do not need TotalWeight as we do not have hybrid stackable container types stacked = true; @@ -461,7 +461,7 @@ public partial class Container : Item if (!stacked && CheckHold(from, dropped, false, true, extraItems, extraWeight)) { - dropItems.Add(dropped); + dropItems.Enqueue(dropped); extraItems++; extraWeight += dropped.TotalWeight + dropped.PileWeight; } @@ -469,14 +469,15 @@ public partial class Container : Item if (dropItems.Count + stackItems.Count == droppedItems.Length) // All good { - for (var i = 0; i < dropItems.Count; i++) + while (dropItems.Count > 0) { - DropItem(dropItems[i]); + DropItem(dropItems.Dequeue()); } - for (var i = 0; i < stackItems.Count; i++) + while (stackItems.Count > 0) { - stackItems[i].m_StackItem.StackWith(from, stackItems[i].m_DropItem, false); + var stackItem = stackItems.Dequeue(); + stackItem.m_StackItem.StackWith(from, stackItem.m_DropItem, false); } return true; diff --git a/Projects/Server/Regions/Region.cs b/Projects/Server/Regions/Region.cs index a53e6466f..1c71756a4 100644 --- a/Projects/Server/Regions/Region.cs +++ b/Projects/Server/Regions/Region.cs @@ -547,10 +547,29 @@ public class Region : IComparable, IValueLinkListNode public virtual bool AcceptsSpawnsFrom(Region region) => AllowSpawn() && (region == this || Parent?.AcceptsSpawnsFrom(region) == true); + public PooledRefList GetPlayersPooled() + { + var list = PooledRefList.Create(); + for (var i = 0; i < Sectors?.Length; i++) + { + var sector = Sectors[i]; + + foreach (var ns in sector.Clients) + { + var player = ns.Mobile; + if (player?.Deleted == false && player.Region.IsPartOf(this)) + { + list.Add(ns.Mobile); + } + } + } + + return list; + } + public List GetPlayers() { - var list = new List(); - + List list = []; for (var i = 0; i < Sectors?.Length; i++) { var sector = Sectors[i]; @@ -609,6 +628,25 @@ public class Region : IComparable, IValueLinkListNode return list; } + public PooledRefList GetMobilesPooled() + { + var list = PooledRefList.Create(); + for (var i = 0; i < Sectors?.Length; i++) + { + var sector = Sectors[i]; + + foreach (var mobile in sector.Mobiles) + { + if (mobile.Region.IsPartOf(this)) + { + list.Add(mobile); + } + } + } + + return list; + } + public int GetMobileCount() { var count = 0; @@ -649,6 +687,26 @@ public class Region : IComparable, IValueLinkListNode return list; } + public PooledRefList GetItemsPooled() + { + var list = PooledRefList.Create(); + + for (var i = 0; i < Sectors?.Length; i++) + { + var sector = Sectors[i]; + + foreach (var item in sector.Items) + { + if (Find(item.Location, item.Map).IsPartOf(this)) + { + list.Add(item); + } + } + } + + return list; + } + public int GetItemCount() { var count = 0; diff --git a/Projects/Server/Utilities/Html.cs b/Projects/Server/Utilities/Html.cs index 9377c7014..944e2e025 100644 --- a/Projects/Server/Utilities/Html.cs +++ b/Projects/Server/Utilities/Html.cs @@ -16,7 +16,6 @@ using System; using System.Buffers; using System.Runtime.CompilerServices; -using System.Text; using Server.Buffers; using Server.Text; diff --git a/Projects/UOContent/Accounting/Account.cs b/Projects/UOContent/Accounting/Account.cs index c9e85de2c..c33e459f2 100644 --- a/Projects/UOContent/Accounting/Account.cs +++ b/Projects/UOContent/Accounting/Account.cs @@ -850,40 +850,6 @@ public partial class Account : IAccount, IComparable return true; } - /// - /// Deserializes a list of string values from an xml element. Null values are not added to the list. - /// - /// The XmlElement from which to deserialize. - /// String list. Value will never be null. - private static string[] LoadAccessCheck(XmlElement node) - { - string[] stringList; - var accessCheck = node["accessCheck"]; - - if (accessCheck != null) - { - var list = new List(); - - foreach (XmlElement ip in accessCheck.GetElementsByTagName("ip")) - { - var text = Utility.GetText(ip, null); - - if (text != null) - { - list.Add(text); - } - } - - stringList = list.ToArray(); - } - else - { - stringList = []; - } - - return stringList; - } - /// /// Deserializes a list of IPAddress values from an xml element. /// diff --git a/Projects/UOContent/Commands/Generic/Commands/DesignInsert.cs b/Projects/UOContent/Commands/Generic/Commands/DesignInsert.cs index 345ff37c9..c8d294a8f 100644 --- a/Projects/UOContent/Commands/Generic/Commands/DesignInsert.cs +++ b/Projects/UOContent/Commands/Generic/Commands/DesignInsert.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Server.Collections; using Server.Gumps; using Server.Items; using Server.Multis; @@ -112,7 +113,7 @@ namespace Server.Commands.Generic if (okay) { - var foundations = new List(); + using var foundations = PooledRefQueue.Create(); flushToLog = list.Count > 20; for (var i = 0; i < list.Count; ++i) @@ -127,7 +128,7 @@ namespace Server.Commands.Generic if (!foundations.Contains(house)) { - foundations.Add(house); + foundations.Enqueue(house); } break; @@ -146,9 +147,9 @@ namespace Server.Commands.Generic } } - foreach (var house in foundations) + while (foundations.Count > 0) { - house.Delta(ItemDelta.Update); + foundations.Dequeue().Delta(ItemDelta.Update); } } else diff --git a/Projects/UOContent/Commands/Generic/Implementors/RegionCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/RegionCommandImplementor.cs index c866e41dc..eb4a3f8d9 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/RegionCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/RegionCommandImplementor.cs @@ -33,8 +33,10 @@ namespace Server.Commands.Generic if (mobiles) { - foreach (var mob in reg.GetMobiles()) + using var mobileList = reg.GetMobilesPooled(); + for (var i = 0; i < mobileList.Count; i++) { + var mob = mobileList[i]; if (BaseCommand.IsAccessible(from, mob) && ext.IsValid(mob)) { list.Add(mob); @@ -44,7 +46,8 @@ namespace Server.Commands.Generic if (items) { - foreach (var item in reg.GetItems()) + using var itemList = reg.GetItemsPooled(); + foreach (var item in itemList) { if (BaseCommand.IsAccessible(from, item) && ext.IsValid(item)) { diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs b/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs index 1aca46e31..032ece7f0 100755 --- a/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs @@ -1364,6 +1364,8 @@ public class ChampionSpawnRegion : BaseRegion global = Math.Max(global, 1 + Spawn.Level); //This is a guesstimate. TODO: Verify & get exact values // OSI testing: at 2 red skulls, light = 0x3 ; 1 red = 0x3.; 3 = 8; 9 = 0xD 8 = 0xD 12 = 0x12 10 = 0xD } + private static readonly HashSet _addresses = []; + public override void OnEnter(Mobile m) { if (!m.Player || m.AccessLevel != AccessLevel.Player || Spawn.Active) @@ -1371,8 +1373,6 @@ public class ChampionSpawnRegion : BaseRegion return; } - Region parent = Parent ?? this; - if (Spawn.ReadyToActivate) { Spawn.Start(); @@ -1384,27 +1384,29 @@ public class ChampionSpawnRegion : BaseRegion return; } - List players = parent.GetPlayers(); - List addresses = new List(); + using var players = (Parent ?? this).GetPlayersPooled(); + for (var i = 0; i < players.Count; i++) { - if (players[i].AccessLevel == AccessLevel.Player && players[i].NetState != null && - !addresses.Contains(players[i].NetState.Address) && !((PlayerMobile)players[i]).Young) + var player = players[i]; + if (player.AccessLevel == AccessLevel.Player && player.NetState != null && !((PlayerMobile)player).Young) { - addresses.Add(players[i].NetState.Address); + _addresses.Add(player.NetState.Address); } } - if (addresses.Count >= 15) + if (_addresses.Count >= 15) { - foreach (Mobile player in players) + for (var i = 0; i < players.Count; i++) { - player.SendMessage(0x20, Spawn.BroadcastMessage); + players[i].SendMessage(0x20, Spawn.BroadcastMessage); } Spawn.ActivatedByProximity = true; Spawn.BeginRestart(TimeSpan.FromMinutes(5.0)); } + + _addresses.Clear(); } public override bool OnMoveInto(Mobile m, Direction d, Point3D newLocation, Point3D oldLocation) diff --git a/Projects/UOContent/Engines/CannedEvil/GenChamps.cs b/Projects/UOContent/Engines/CannedEvil/GenChamps.cs index 22a7f03a0..3d94a9fc3 100644 --- a/Projects/UOContent/Engines/CannedEvil/GenChamps.cs +++ b/Projects/UOContent/Engines/CannedEvil/GenChamps.cs @@ -14,7 +14,7 @@ *************************************************************************/ using System; -using System.Collections.Generic; +using Server.Collections; using Server.Logging; namespace Server.Engines.CannedEvil; @@ -67,18 +67,18 @@ public static class ChampionGenerator */ //We assume that all champion spawns are generated here. - List spawns = []; + using var spawns = PooledRefQueue.Create(); foreach (Item item in World.Items.Values) { if (item is ChampionSpawn spawn) { - spawns.Add(spawn); + spawns.Enqueue(spawn); } } - for (int i = spawns.Count - 1; i >= 0; i--) + while (spawns.Count > 0) { - spawns[i].Delete(); + spawns.Dequeue().Delete(); } Process(DungeonLocations); diff --git a/Projects/UOContent/Engines/Doom/GenGauntlet.cs b/Projects/UOContent/Engines/Doom/GenGauntlet.cs index 5c4c4edf2..96c7a6f74 100644 --- a/Projects/UOContent/Engines/Doom/GenGauntlet.cs +++ b/Projects/UOContent/Engines/Doom/GenGauntlet.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using Server.Collections; using Server.Items; using Server.Mobiles; @@ -272,18 +272,23 @@ namespace Server.Engines.Doom FacialHairHue = 0x482 }; - var items = new List(dealer.Items); + using var toDelete = PooledRefQueue.Create(); - for (var i = 0; i < items.Count; ++i) + for (var i = 0; i < dealer.Items.Count; ++i) { - var item = items[i]; + var item = dealer.Items[i]; if (item.Layer is not Layer.ShopBuy and not Layer.ShopResale and not Layer.ShopSell) { - item.Delete(); + toDelete.Enqueue(item); } } + while (toDelete.Count > 0) + { + toDelete.Dequeue().Delete(); + } + dealer.AddItem(new FloppyHat(1)); dealer.AddItem(new Robe(1)); dealer.AddItem(new LanternOfSouls()); diff --git a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs index 05d5dc6dc..9f4e9c028 100644 --- a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs +++ b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs @@ -667,12 +667,13 @@ public partial class LeverPuzzleController : Item protected override void OnTick() { ticks++; - var mobiles = m_Controller._lampRoom.GetMobiles(); + using var mobiles = m_Controller._lampRoom.GetMobilesPooled(); if (ticks >= 71 || m_Controller._lampRoom.GetPlayerCount() == 0) { - foreach (var mobile in mobiles) + for (var i = 0; i < mobiles.Count; i++) { + var mobile = mobiles[i]; if (mobile?.Deleted == false && !mobile.IsDeadBondedPet) { mobile.Kill(); @@ -689,33 +690,36 @@ public partial class LeverPuzzleController : Item level++; } - foreach (var mobile in mobiles) + for (var i = 0; i < mobiles.Count; i++) { - if (IsValidDamagable(mobile)) + var mobile = mobiles[i]; + if (!IsValidDamagable(mobile)) { - if (ticks % 2 == 0 && level == 5) + continue; + } + + if (ticks % 2 == 0 && level == 5) + { + if (mobile.Player) { - if (mobile.Player) + mobile.Say(1062092); + if (AniSafe(mobile)) { - mobile.Say(1062092); - if (AniSafe(mobile)) - { - mobile.Animate(32, 5, 1, true, false, 0); - } + mobile.Animate(32, 5, 1, true, false, 0); } - - DoDamage(mobile, 15, 20, true); } - if (Utility.Random((int)(level & ~0xfffffffc), 3) == 3) - { - mobile.ApplyPoison(mobile, PA2[level]); - } + DoDamage(mobile, 15, 20, true); + } - if (ticks % 12 == 0 && level > 0 && mobile.Player) - { - mobile.SendLocalizedMessage(PA[level][0], null, PA[level][1]); - } + if (Utility.Random((int)(level & ~0xfffffffc), 3) == 3) + { + mobile.ApplyPoison(mobile, PA2[level]); + } + + if (ticks % 12 == 0 && level > 0 && mobile.Player) + { + mobile.SendLocalizedMessage(PA[level][0], null, PA[level][1]); } } diff --git a/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs b/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs index 91bde7a24..6caaf9dfc 100644 --- a/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs +++ b/Projects/UOContent/Engines/Factions/Mobiles/Guards/GuardAI.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using Server.Collections; using Server.Factions.AI; using Server.Items; using Server.Mobiles; @@ -692,41 +692,42 @@ namespace Server.Factions var dexMod = GetStatMod(m_Guard, StatType.Dex); var intMod = GetStatMod(m_Guard, StatType.Int); - var types = new List(); + using var spellTypes = PooledRefQueue.Create(); if (strMod <= 0) { - types.Add(typeof(StrengthSpell)); + spellTypes.Enqueue(typeof(StrengthSpell)); } if (dexMod <= 0 && IsAllowed(GuardAI.Melee)) { - types.Add(typeof(AgilitySpell)); + spellTypes.Enqueue(typeof(AgilitySpell)); } if (intMod <= 0 && IsAllowed(GuardAI.Magic)) { - types.Add(typeof(CunningSpell)); + spellTypes.Enqueue(typeof(CunningSpell)); } if (IsAllowed(GuardAI.Bless)) { - if (types.Count > 1) + if (spellTypes.Count > 1) { spell = new BlessSpell(m_Guard); } - else if (types.Count == 1) + else if (spellTypes.Count == 1) { - spell = types[0].CreateInstance(m_Guard, null); + spell = spellTypes.Dequeue().CreateInstance(m_Guard, null); } } - else if (types.Count > 0) + else if (spellTypes.Count > 0) { - if (types[0] == typeof(StrengthSpell)) + var spellType = spellTypes.Dequeue(); + if (spellType == typeof(StrengthSpell)) { UseItemByType(typeof(BaseStrengthPotion)); } - else if (types[0] == typeof(AgilitySpell)) + else if (spellType == typeof(AgilitySpell)) { UseItemByType(typeof(BaseAgilityPotion)); } @@ -746,30 +747,30 @@ namespace Server.Factions var dexMod = GetStatMod(combatant, StatType.Dex); var intMod = GetStatMod(combatant, StatType.Int); - var types = new List(); + using var spellTypes = PooledRefQueue.Create(); if (strMod >= 0) { - types.Add(typeof(WeakenSpell)); + spellTypes.Enqueue(typeof(WeakenSpell)); } if (dexMod >= 0 && IsAllowed(GuardAI.Melee)) { - types.Add(typeof(ClumsySpell)); + spellTypes.Enqueue(typeof(ClumsySpell)); } if (intMod >= 0 && IsAllowed(GuardAI.Magic)) { - types.Add(typeof(FeeblemindSpell)); + spellTypes.Enqueue(typeof(FeeblemindSpell)); } - if (types.Count > 1) + if (spellTypes.Count > 1) { spell = new CurseSpell(m_Guard); } - else if (types.Count == 1) + else if (spellTypes.Count == 1) { - spell = types[0].CreateInstance(m_Guard, null); + spell = spellTypes.Dequeue().CreateInstance(m_Guard, null); } } } diff --git a/Projects/UOContent/Engines/ML Quests/Mobiles/BoonCollector.cs b/Projects/UOContent/Engines/ML Quests/Mobiles/BoonCollector.cs index 6dd4e4782..86754c5e5 100644 --- a/Projects/UOContent/Engines/ML Quests/Mobiles/BoonCollector.cs +++ b/Projects/UOContent/Engines/ML Quests/Mobiles/BoonCollector.cs @@ -118,8 +118,7 @@ public abstract partial class DoneQuestCollector : BaseCreature, IRaceChanger } else { - var conversation = new List(); - conversation.AddRange(Incomplete); + List conversation = [..Incomplete]; var context = MLQuestSystem.GetContext(pm); diff --git a/Projects/UOContent/Engines/ML Quests/Objectives/DeliverObjective.cs b/Projects/UOContent/Engines/ML Quests/Objectives/DeliverObjective.cs index e8d689028..c50ed99e7 100644 --- a/Projects/UOContent/Engines/ML Quests/Objectives/DeliverObjective.cs +++ b/Projects/UOContent/Engines/ML Quests/Objectives/DeliverObjective.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using Server.Collections; using Server.Gumps; using Server.Items; using Server.Logging; @@ -46,7 +46,7 @@ namespace Server.Engines.MLQuests.Objectives return; } - var delivery = new List(); + using var delivery = PooledRefQueue.Create(); for (var i = 0; i < Amount; ++i) { @@ -54,7 +54,7 @@ namespace Server.Engines.MLQuests.Objectives if (item != null) { - delivery.Add(item); + delivery.Enqueue(item); if (item.Stackable && Amount > 1) { @@ -64,9 +64,9 @@ namespace Server.Engines.MLQuests.Objectives } } - foreach (var item in delivery) + while (delivery.Count > 0) { - pack.DropItem(item); // Confirmed: on OSI items are added even if your pack is full + pack.DropItem(delivery.Dequeue()); // Confirmed: on OSI items are added even if your pack is full } } diff --git a/Projects/UOContent/Gumps/Houses/HouseGumpAOS.cs b/Projects/UOContent/Gumps/Houses/HouseGumpAOS.cs index 3a159286f..bd4a6ce7b 100644 --- a/Projects/UOContent/Gumps/Houses/HouseGumpAOS.cs +++ b/Projects/UOContent/Gumps/Houses/HouseGumpAOS.cs @@ -870,7 +870,7 @@ namespace Server.Gumps } var items = house.GetItems(); - var mobiles = house.GetMobiles(); + using var mobiles = house.GetMobilesPooled(); newHouse.MoveToWorld( new Point3D( @@ -1216,7 +1216,7 @@ namespace Server.Gumps ); var r = m_House.Region; - var list = r.GetMobiles(); + using var list = r.GetMobilesPooled(); for (var i = 0; i < list.Count; ++i) { @@ -1258,7 +1258,7 @@ namespace Server.Gumps } var r = m_House.Region; - var list = r.GetMobiles(); + using var list = r.GetMobilesPooled(); for (var i = 0; i < list.Count; ++i) { diff --git a/Projects/UOContent/Items/Books/BaseBook.cs b/Projects/UOContent/Items/Books/BaseBook.cs index b70dcf854..47f368754 100644 --- a/Projects/UOContent/Items/Books/BaseBook.cs +++ b/Projects/UOContent/Items/Books/BaseBook.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using ModernUO.Serialization; using Server.Collections; using Server.ContextMenus; @@ -141,11 +140,14 @@ namespace Server.Items { get { - var lines = new List(); - - foreach (var bpi in Pages) + using var lines = PooledRefQueue.Create(256); + for (var i = 0; i < Pages.Length; i++) { - lines.AddRange(bpi.Lines); + var bpi = Pages[i]; + for (var j = 0; j < bpi.Lines.Length; j++) + { + lines.Enqueue(bpi.Lines[j]); + } } return lines.ToArray(); diff --git a/Projects/UOContent/Items/Bulletin Boards/BulletinMessage.cs b/Projects/UOContent/Items/Bulletin Boards/BulletinMessage.cs index 2e4500d10..8fa3ddd05 100644 --- a/Projects/UOContent/Items/Bulletin Boards/BulletinMessage.cs +++ b/Projects/UOContent/Items/Bulletin Boards/BulletinMessage.cs @@ -1,6 +1,6 @@ using System; -using System.Collections.Generic; using ModernUO.Serialization; +using Server.Collections; using Server.Targeting; namespace Server.Items @@ -22,7 +22,7 @@ namespace Server.Items PostedHue = Poster.Hue; Lines = lines; - var list = new List(); + using var list = PooledRefQueue.Create(poster.Items.Count); for (var i = 0; i < poster.Items.Count; ++i) { @@ -30,7 +30,7 @@ namespace Server.Items if (item.Layer >= Layer.OneHanded && item.Layer <= Layer.Mount) { - list.Add(new BulletinEquip(item.ItemID, item.Hue)); + list.Enqueue(new BulletinEquip(item.ItemID, item.Hue)); } } diff --git a/Projects/UOContent/Items/Containers/Strongbox.cs b/Projects/UOContent/Items/Containers/Strongbox.cs index 6e937ff9c..aa5e63925 100644 --- a/Projects/UOContent/Items/Containers/Strongbox.cs +++ b/Projects/UOContent/Items/Containers/Strongbox.cs @@ -1,6 +1,6 @@ using System; -using System.Collections.Generic; using ModernUO.Serialization; +using Server.Collections; using Server.Multis; namespace Server.Items; @@ -102,15 +102,15 @@ public partial class StrongBox : BaseContainer, IChoppable public Container ConvertToStandardContainer() { var metalBox = new MetalBox(); - var subItems = new List(Items); + using var subItems = PooledRefList.Create(Items.Count); + subItems.AddRange(Items); - foreach (var subItem in subItems) + for (var i = 0; i < subItems.Count; i++) { - metalBox.AddItem(subItem); + metalBox.AddItem(subItems[i]); } Delete(); - return metalBox; } } diff --git a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs index 4c2f1ff26..92504888e 100644 --- a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs +++ b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs @@ -824,25 +824,28 @@ public partial class Corpse : Container, ICarvable } var pack = from.Backpack; + using var items = PooledRefList.Create(128); if (RestoreEquip != null && pack != null) { - var packItems = new List(pack.Items); // Only items in the top-level pack are re-equipped + items.AddRange(pack.Items); - for (var i = 0; i < packItems.Count; i++) + // Only items in the top-level pack are re-equipped + for (var i = 0; i < items.Count; i++) { - var packItem = packItems[i]; + var packItem = items[i]; if (RestoreEquip.Contains(packItem) && packItem.Movable) { from.EquipItem(packItem); } } + + items.Clear(); } - var items = new List(Items); - var didntFit = false; + items.AddRange(Items); for (var i = 0; !didntFit && i < items.Count; ++i) { diff --git a/Projects/UOContent/Items/Skill Items/Fishing/Misc/ShipwreckedItem.cs b/Projects/UOContent/Items/Skill Items/Fishing/Misc/ShipwreckedItem.cs index c4f7945ac..962b8752d 100644 --- a/Projects/UOContent/Items/Skill Items/Fishing/Misc/ShipwreckedItem.cs +++ b/Projects/UOContent/Items/Skill Items/Fishing/Misc/ShipwreckedItem.cs @@ -1,4 +1,3 @@ -using System; using ModernUO.Serialization; namespace Server.Items; diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index fe2e6a05b..1da9656cd 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -986,67 +986,71 @@ namespace Server.Mobiles from.TargetLocked = false; } - public static void EquipMacro(Mobile m, List list) + public static void EquipMacro(Mobile m, ref PooledRefList list) { - if (m is PlayerMobile { Alive: true } pm && pm.Backpack != null) + if (m is not PlayerMobile { Alive: true } pm || pm.Backpack == null) { - var pack = pm.Backpack; + return; + } - foreach (var serial in list) + var pack = pm.Backpack; + + foreach (var serial in list) + { + Item item = null; + foreach (var i in pack.Items) { - Item item = null; - foreach (var i in pack.Items) + if (i.Serial == serial) { - if (i.Serial == serial) - { - item = i; - break; - } + item = i; + break; } + } - if (item == null) + if (item == null) + { + continue; + } + + var toMove = pm.FindItemOnLayer(item.Layer); + + if (toMove != null) + { + // pack.DropItem(toMove); + toMove.Internalize(); + + if (!pm.EquipItem(item)) { - continue; - } - - var toMove = pm.FindItemOnLayer(item.Layer); - - if (toMove != null) - { - // pack.DropItem(toMove); - toMove.Internalize(); - - if (!pm.EquipItem(item)) - { - pm.EquipItem(toMove); - } - else - { - pack.DropItem(toMove); - } + pm.EquipItem(toMove); } else { - pm.EquipItem(item); + pack.DropItem(toMove); } } + else + { + pm.EquipItem(item); + } } } - public static void UnequipMacro(Mobile m, List layers) + public static void UnequipMacro(Mobile m, ref PooledRefList layers) { - if (m is PlayerMobile { Alive: true } pm && pm.Backpack != null) + if (m is not PlayerMobile { Alive: true } pm || pm.Backpack == null) { - var pack = pm.Backpack; - var eq = m.Items; + return; + } - for (var i = eq.Count - 1; i >= 0; i--) + var pack = pm.Backpack; + var eq = m.Items; + + for (var i = eq.Count - 1; i >= 0; i--) + { + var item = eq[i]; + if (layers.Contains(item.Layer)) { - var item = eq[i]; - if (layers.Contains(item.Layer)) - { - pack.TryDropItem(pm, item, false); - } + pack.TryDropItem(pm, item, false); } } } @@ -1547,13 +1551,17 @@ namespace Server.Mobiles // Eject all from house from.RevealingAction(); - foreach (var item in context.Foundation.GetItems()) + var list = context.Foundation.GetItems(); + for (var i = 0; i < list.Count; i++) { + var item = list[i]; item.Location = context.Foundation.BanLocation; } - foreach (var mobile in context.Foundation.GetMobiles()) + using var mobiles = context.Foundation.GetMobilesPooled(); + for (var i = 0; i < mobiles.Count; i++) { + var mobile = mobiles[i]; mobile.Location = context.Foundation.BanLocation; } diff --git a/Projects/UOContent/Multis/Houses/BaseHouse.cs b/Projects/UOContent/Multis/Houses/BaseHouse.cs index f1d3954d9..4be71dc51 100644 --- a/Projects/UOContent/Multis/Houses/BaseHouse.cs +++ b/Projects/UOContent/Multis/Houses/BaseHouse.cs @@ -1235,24 +1235,24 @@ namespace Server.Multis return list; } - public List GetMobiles() + public PooledRefList GetMobilesPooled() { if (Map == null || Map == Map.Internal) { - return new List(); + return PooledRefList.Create(0); } - var list = new List(); - - foreach (var mobile in Region.GetMobiles()) + var mobileList = Region.GetMobilesPooled(); + for (var i = mobileList.Count - 1; i >= 0; i--) { - if (IsInside(mobile)) + var mobile = mobileList[i]; + if (!IsInside(mobile)) { - list.Add(mobile); + mobileList.Remove(mobile); } } - return list; + return mobileList; } public virtual bool CheckAosLockdowns(int need) => GetAosCurLockdowns() + need <= GetAosMaxLockdowns(); diff --git a/Projects/UOContent/Multis/Houses/HouseFoundation.cs b/Projects/UOContent/Multis/Houses/HouseFoundation.cs index 46be9fdfa..2c12373e0 100644 --- a/Projects/UOContent/Multis/Houses/HouseFoundation.cs +++ b/Projects/UOContent/Multis/Houses/HouseFoundation.cs @@ -901,8 +901,10 @@ namespace Server.Multis item.Location = BanLocation; } - foreach (var mobile in GetMobiles()) + using var mobiles = GetMobilesPooled(); + for (var i = 0; i < mobiles.Count; i++) { + var mobile = mobiles[i]; if (mobile != m) { mobile.Location = BanLocation; @@ -1294,13 +1296,18 @@ namespace Server.Multis // Eject all from house from.RevealingAction(); - foreach (var item in GetItems()) + var items = GetItems(); + for (var i = 0; i < items.Count; i++) { + var item = items[i]; item.Location = BanLocation; } - foreach (var mobile in GetMobiles()) + using var mobiles = GetMobilesPooled(); + var list = GetMobilesPooled(); + for (var i = 0; i < list.Count; i++) { + var mobile = list[i]; mobile.Location = BanLocation; } @@ -1760,13 +1767,17 @@ namespace Server.Multis // Eject all from house from.RevealingAction(); - foreach (var item in context.Foundation.GetItems()) + var list = context.Foundation.GetItems(); + for (var i = 0; i < list.Count; i++) { + var item = list[i]; item.Location = context.Foundation.BanLocation; } - foreach (var mobile in context.Foundation.GetMobiles()) + using var mobiles = context.Foundation.GetMobilesPooled(); + for (var i = 0; i < mobiles.Count; i++) { + var mobile = mobiles[i]; mobile.Location = context.Foundation.BanLocation; } diff --git a/Projects/UOContent/Network/Packets/IncomingItemPackets.cs b/Projects/UOContent/Network/Packets/IncomingItemPackets.cs index f2ad7fd8f..db47dbb31 100644 --- a/Projects/UOContent/Network/Packets/IncomingItemPackets.cs +++ b/Projects/UOContent/Network/Packets/IncomingItemPackets.cs @@ -14,8 +14,8 @@ *************************************************************************/ using System.Buffers; -using System.Collections.Generic; using System.IO; +using Server.Collections; using Server.Items; using Server.Mobiles; @@ -112,24 +112,25 @@ public static class IncomingItemPackets public static void EquipMacro(NetState state, SpanReader reader) { int count = reader.ReadByte(); - var serialList = new List(count); + var serialList = PooledRefList.Create(count); for (var i = 0; i < count; ++i) { serialList.Add((Serial)reader.ReadUInt32()); } - PlayerMobile.EquipMacro(state.Mobile, serialList); + PlayerMobile.EquipMacro(state.Mobile, ref serialList); + serialList.Dispose(); } public static void UnequipMacro(NetState state, SpanReader reader) { int count = reader.ReadByte(); - var layers = new List(count); + var layers = PooledRefList.Create(count); for (var i = 0; i < count; ++i) { layers.Add((Layer)reader.ReadUInt16()); } - PlayerMobile.UnequipMacro(state.Mobile, layers); + PlayerMobile.UnequipMacro(state.Mobile, ref layers); } }