fix: Changes Map.Sector.Items to link list. (#1547)

### Summary

Eliminates `IPooledEnumerable<T>` and `eable.Free()` from `Map` for items. This drastically simplifies code that iterates in range, for example:

```cs
foreach (var item in m.GetItemsInRange(5))
{
}
```
The code above no longer requires an eable and calling `Free()`.
This commit is contained in:
Kamron Batman 2023-10-16 20:51:02 -07:00 • committed by GitHub
parent 1330c4a830
commit 24858f3989
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 577 additions and 419 deletions

View file

@ -467,10 +467,8 @@ namespace Server.Engines.ConPVP
if (landTile.ID == 0x244 && statics.Length == 0) // 0x244 = invalid land tile
{
var eable = Map.GetItemsInRange(point, 0);
var empty = true;
foreach (var item in eable)
foreach (var item in Map.GetItemsInRange(point, 0))
{
if (item != this)
{
@ -513,8 +511,7 @@ namespace Server.Engines.ConPVP
var rect = new Rectangle2D(pTop.X, pTop.Y, pBottom.X - pTop.X + 1, pBottom.Y - pTop.Y + 1);
var area = Map.GetItemsInBounds(rect);
foreach (var i in area)
foreach (var i in Map.GetItemsInBounds(rect))
{
if (i == this || i.ItemID >= 0x4000)
{
@ -567,6 +564,7 @@ namespace Server.Engines.ConPVP
{
continue;
}
if (i is BRGoal goal)
{
var oldLoc = new Point3D(GetWorldLocation());
@ -662,8 +660,7 @@ namespace Server.Engines.ConPVP
}
}
var eable = GetItemsInRange(0);
foreach (var item in eable)
foreach (var item in GetItemsInRange(0))
{
if (item.Visible && item != this)
{

View file

@ -387,8 +387,7 @@ namespace Server.Engines.Craft
return false;
}
var eable = map.GetItemsInRange(from.Location, 2);
foreach (var item in eable)
foreach (var item in map.GetItemsInRange(from.Location, 2))
{
if (item.Z + 16 > item.Z && item.Z + 16 > item.Z && Find(item.ItemID, itemIDs))
{

View file

@ -39,9 +39,7 @@ public class DefBlacksmithy : CraftSystem
return;
}
var eable = map.GetItemsInRange(from.Location, range);
foreach (var item in eable)
foreach (var item in map.GetItemsInRange(from.Location, range))
{
var type = item.GetType();

View file

@ -197,9 +197,7 @@ public partial class LeverPuzzleController : Item
[Usage("GenLeverPuzzle"), Description("Generates lamp room and lever puzzle in doom.")]
public static void GenLampPuzzle_OnCommand(CommandEventArgs e)
{
var eable = Map.Malas.GetItemsInRange(lp_Center, 0);
foreach (var item in eable)
foreach (var item in Map.Malas.GetItemsInRange(lp_Center, 0))
{
if (item is LeverPuzzleController)
{

View file

@ -155,10 +155,9 @@ namespace Server.Ethics
continue;
}
var eable = e.Mobile.GetItemsInRange(2);
var found = false;
foreach (var item in eable)
foreach (var item in e.Mobile.GetItemsInRange(2))
{
if (item is AnkhNorth or AnkhWest)
{

View file

@ -78,14 +78,14 @@ namespace Server.Factions
private static bool CheckExistence(Point3D loc, Map facet, Type type)
{
var eable = facet.GetItemsInRange(loc, 0);
foreach (var item in eable)
foreach (var item in facet.GetItemsInRange(loc, 0))
{
if (type.IsInstanceOfType(item))
{
return true;
}
}
return false;
}
}

View file

@ -307,8 +307,7 @@ namespace Server.Engines.Harvest
return false;
}
var eable = m.GetItemsInRange(0);
foreach (var i in eable)
foreach (var i in m.GetItemsInRange(0))
{
if (i.StackWith(m, i, false))
{

View file

@ -1,5 +1,4 @@
using System;
using System.Linq;
using Server.Items;
namespace Server.Commands
@ -15,10 +14,8 @@ namespace Server.Commands
public static bool FindMorphItem(int x, int y, int z, int inactiveItemID, int activeItemID)
{
var eable = Map.Felucca.GetItemsInRange(new Point3D(x, y, z), 0);
var found = false;
foreach (var item in eable)
foreach (var item in Map.Felucca.GetItemsInRange(new Point3D(x, y, z), 0))
{
if (item is MorphItem morphItem && morphItem.Z == z && morphItem.InactiveItemId == inactiveItemID && morphItem.ActiveItemId == activeItemID)
{
@ -26,15 +23,14 @@ namespace Server.Commands
break;
}
}
return found;
}
public static bool FindEffectController(int x, int y, int z)
{
var eable = Map.Felucca.GetItemsInRange(new Point3D(x, y, z), 0);
var found = false;
foreach (var item in eable)
foreach (var item in Map.Felucca.GetItemsInRange(new Point3D(x, y, z), 0))
{
if (item is EffectController && item.Z == z)
{
@ -42,22 +38,20 @@ namespace Server.Commands
break;
}
}
return found;
}
public static T TryCreateItem<T>(int x, int y, int z, T srcItem) where T : Item
{
var eable = Map.Felucca.GetItemsInBounds<T>(new Rectangle2D(x, y, 1, 1));
var t = eable.FirstOrDefault(item => item.GetType() == srcItem.GetType());
if (t != null)
foreach (var item in Map.Felucca.GetItemsInBounds<T>(new Rectangle2D(x, y, 1, 1)))
{
srcItem.Delete();
return t;
return item;
}
srcItem.MoveToWorld(new Point3D(x, y, z), Map.Felucca);
m_Count++;
return srcItem;
}

View file

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Collections;
using Server.Engines.MLQuests.Gumps;
using Server.Engines.MLQuests.Objectives;
using Server.Engines.MLQuests.Rewards;
@ -266,25 +266,39 @@ namespace Server.Engines.MLQuests
{
var name = $"MLQS-{GetType().Name}";
var toDelete = map.GetItemsInRange(loc, 0).Where(item => item is BaseSpawner && item.Name == name);
foreach (var item in toDelete)
using var queue = PooledRefQueue<Item>.Create();
foreach (var item in map.GetItemsInRange(loc, 0))
{
item.Delete();
// This predates GUIDs. Let's build these spawners and export them so we can delete this code!
if (item is BaseSpawner spawner && spawner.Name == name)
{
queue.Enqueue(item);
}
}
while (queue.Count > 0)
{
queue.Dequeue().Delete();
}
s.Name = name;
s.MoveToWorld(loc, map);
}
public void PutDeco(Item deco, Point3D loc, Map map)
public static void PutDeco(Item deco, Point3D loc, Map map)
{
// Auto cleanup on regeneration
var toDelete = map.GetItemsInRange(loc, 0).Where(item => item.ItemID == deco.ItemID && item.Z == loc.Z);
foreach (var item in toDelete)
using var queue = PooledRefQueue<Item>.Create();
foreach (var item in map.GetItemsInRange(loc, 0))
{
item.Delete();
if (item.ItemID == deco.ItemID && item.Z == loc.Z)
{
queue.Enqueue(item);
}
}
while (queue.Count > 0)
{
queue.Dequeue().Delete();
}
deco.MoveToWorld(loc, map);

View file

@ -98,10 +98,8 @@ namespace Server.Movement
foreach (var sector in _sectors)
{
for (var j = 0; j < sector.Items.Count; ++j)
foreach (var item in sector.Items)
{
var item = sector.Items[j];
if (ignoreMovableImpassables && item.Movable && item.ItemData.ImpassableSurface)
{
continue;
@ -167,10 +165,8 @@ namespace Server.Movement
if (!sectorStartIsForward)
{
for (var i = 0; i < sectorForward.Items.Count; ++i)
foreach (var item in sectorForward.Items)
{
var item = sectorForward.Items[i];
if (ignoreMovableImpassables && item.Movable && item.ItemData.ImpassableSurface)
{
continue;
@ -193,10 +189,8 @@ namespace Server.Movement
}
}
for (var i = 0; i < sectorStart.Items.Count; ++i)
foreach (var item in sectorStart.Items)
{
var item = sectorStart.Items[i];
if (ignoreMovableImpassables && item.Movable && item.ItemData.ImpassableSurface)
{
continue;

View file

@ -147,8 +147,7 @@ namespace Server.Engines.Spawners
// Delete all spawners at this location.
// Probably shouldn't do this outside of migrations? Is there a better way to find/fix spawners?
var eable = map.GetItemsInRange<BaseSpawner>(location, 0);
foreach (var spawner in eable)
foreach (var spawner in map.GetItemsInRange<BaseSpawner>(location, 0))
{
if (spawner.GetType() == type)
{