fix: Optimizes FindItemsByType by removing allocations. (#1515)
### Summary Container enumeration is in dire need of optimization. Thanks to @stefanomerotta for initiating this work with PR #1443. This PR handles a small part of what Stefan started. Also included are some bug fixes. ### Method Signatures ```cs // Use with foreach without moving/deleting items FindItemsByTypeEnumerator<T> FindItemsByType<T>(bool recurse = true, Predicate<T> predicate = null) // Use with foreach when moving/deleting items QueuedItemsEnumerator<T> EnumerateItemsByType<T>(bool recurse = true, Predicate<T> predicate = null) // Use when iterating multiple times or queuing PooledRefQueue<T> QueueItemsByType<T>(bool recurse = true, Predicate<T> predicate = null) // Use when iterating multiples times or manipulating elements without traversing PooledRefList<T> ListItemsByType<T>(bool recurse = true, Predicate<T> predicate = null) ``` * `FindItemsByType<T>` has changed from returning `List<T>` to `FindItemsByTypeEnumerator<T>` - This method is not safe to use in situations where an item may get consumed, deleted, or moved. * `EnumerateItemsByType<T>` was added as a safe way to iterate and manipulate items. * **Note**: EnumerateItemsByType will _completely traverse the container_ before iteration starts because it uses `QueueItemsByType` under the hood. * `QueueItemsByType<T>` and `ListItemsByType<T>` was added to return a queue or list of items to iterate multiple times and manipulate the items. This isn't the most efficient since it uses a predicate and can result in 2 or 3 total iterations unnecessarily. ### Bug Fixes - [X] Fishing had an error in the random check that may have caused slight bias.
This commit is contained in:
parent
146abad36e
commit
a4cabe2fa4
23 changed files with 655 additions and 390 deletions
|
|
@ -2393,9 +2393,14 @@ namespace Server.Mobiles
|
|||
|
||||
DropHolding();
|
||||
|
||||
// During AOS+, insured/blessed items are moved out of their child containers and put directly into the backpack.
|
||||
// This fixes a "bug" where players put blessed items in nested bags and they were dropped on death
|
||||
if (Core.AOS && Backpack?.Deleted == false)
|
||||
{
|
||||
Backpack.FindItemsByType<Item>(FindItems_Callback).ForEach(item => Backpack.AddItem(item));
|
||||
foreach (var item in Backpack.EnumerateItemsByType<Item>(predicate: FindItems_Callback))
|
||||
{
|
||||
Backpack.AddItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
EquipSnapshot = new List<Item>(Items);
|
||||
|
|
@ -3910,13 +3915,13 @@ namespace Server.Mobiles
|
|||
return;
|
||||
}
|
||||
|
||||
var items = new List<Item>();
|
||||
using var queue = PooledRefQueue<Item>.Create(128);
|
||||
|
||||
foreach (var item in Items)
|
||||
{
|
||||
if (DisplayInItemInsuranceGump(item))
|
||||
{
|
||||
items.Add(item);
|
||||
queue.Enqueue(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3924,20 +3929,26 @@ namespace Server.Mobiles
|
|||
|
||||
if (pack != null)
|
||||
{
|
||||
items.AddRange(pack.FindItemsByType<Item>(DisplayInItemInsuranceGump));
|
||||
foreach (var item in pack.FindItemsByType())
|
||||
{
|
||||
if (DisplayInItemInsuranceGump(item))
|
||||
{
|
||||
queue.Enqueue(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Investigate item sorting
|
||||
|
||||
CloseGump<ItemInsuranceMenuGump>();
|
||||
|
||||
if (items.Count == 0)
|
||||
if (queue.Count == 0)
|
||||
{
|
||||
SendLocalizedMessage(1114915, "", 0x35); // None of your current items meet the requirements for insurance.
|
||||
}
|
||||
else
|
||||
{
|
||||
SendGump(new ItemInsuranceMenuGump(this, items.ToArray()));
|
||||
SendGump(new ItemInsuranceMenuGump(this, queue.ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Accounting;
|
||||
using Server.ContextMenus;
|
||||
using Server.Items;
|
||||
|
|
@ -47,32 +46,36 @@ namespace Server.Mobiles
|
|||
|
||||
if (bank != null)
|
||||
{
|
||||
var gold = bank.FindItemsByType<Gold>();
|
||||
var checks = bank.FindItemsByType<BankCheck>();
|
||||
foreach (var gold in bank.FindItemsByType<Gold>())
|
||||
{
|
||||
balance += gold.Amount;
|
||||
}
|
||||
|
||||
balance += gold.Aggregate(0L, (c, t) => c + t.Amount);
|
||||
if (balance >= int.MaxValue)
|
||||
{
|
||||
return int.MaxValue;
|
||||
}
|
||||
|
||||
balance += checks.Aggregate(0L, (c, t) => c + t.Worth);
|
||||
foreach (var check in bank.FindItemsByType<BankCheck>())
|
||||
{
|
||||
balance += check.Worth;
|
||||
}
|
||||
}
|
||||
|
||||
return Math.Max(0, (int)Math.Min(int.MaxValue, balance));
|
||||
return (int)Math.Clamp(balance, 0, int.MaxValue);
|
||||
}
|
||||
|
||||
public static int GetBalance(Mobile m, out List<Item> gold, out List<Item> checks)
|
||||
{
|
||||
long balance = 0;
|
||||
gold = checks = new List<Item>();
|
||||
|
||||
if (AccountGold.Enabled && m.Account != null)
|
||||
{
|
||||
balance = m.Account.GetTotalGold();
|
||||
|
||||
if (balance > int.MaxValue)
|
||||
if (balance >= int.MaxValue)
|
||||
{
|
||||
gold = checks = new List<Item>();
|
||||
return int.MaxValue;
|
||||
}
|
||||
}
|
||||
|
|
@ -81,23 +84,25 @@ namespace Server.Mobiles
|
|||
|
||||
if (bank != null)
|
||||
{
|
||||
gold = bank.FindItemsByType(typeof(Gold));
|
||||
checks = bank.FindItemsByType(typeof(BankCheck));
|
||||
foreach (var g in bank.FindItemsByType<Gold>())
|
||||
{
|
||||
balance += g.Amount;
|
||||
gold.Add(g);
|
||||
}
|
||||
|
||||
balance += gold.OfType<Gold>().Aggregate(0L, (c, t) => c + t.Amount);
|
||||
if (balance >= int.MaxValue)
|
||||
{
|
||||
return int.MaxValue;
|
||||
}
|
||||
|
||||
balance += checks.OfType<BankCheck>().Aggregate(0L, (c, t) => c + t.Worth);
|
||||
}
|
||||
else
|
||||
{
|
||||
gold = checks = new List<Item>();
|
||||
foreach (var bc in bank.FindItemsByType<BankCheck>())
|
||||
{
|
||||
balance += bc.Worth;
|
||||
checks.Add(bc);
|
||||
}
|
||||
}
|
||||
|
||||
return Math.Max(0, (int)Math.Min(int.MaxValue, balance));
|
||||
return (int)Math.Clamp(balance, 0, int.MaxValue);
|
||||
}
|
||||
|
||||
public static bool Withdraw(Mobile from, int amount)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue