Index runtime catalog item lookup
This commit is contained in:
parent
c0528ec6b0
commit
ee3fb2092b
2 changed files with 47 additions and 2 deletions
|
|
@ -101,6 +101,7 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
RunCheck(StableEntityIdentitySurvivesCrossZoneReindex);
|
||||
RunCheck(TractorRampsAndPullsThroughYmirWithoutTeleportingCargo);
|
||||
RunCheck(PickupProximityPrecedesYmirCollisionShell);
|
||||
RunCheck(CatalogItemIndexPreservesSnapshotLookupSemantics);
|
||||
RunCheck(PickupIsCapacityCheckedExactlyOnceAndExpires);
|
||||
RunCheck(StationBodiesCannotConsumePickups);
|
||||
RunCheck(PickupProximityCollectsOrBounces);
|
||||
|
|
@ -8286,6 +8287,22 @@ internal sealed class AetheriaDaemonYmirSmokeChecks
|
|||
"a proximity-collected pickup must leave authoritative world state exactly once");
|
||||
}
|
||||
|
||||
private static void CatalogItemIndexPreservesSnapshotLookupSemantics()
|
||||
{
|
||||
var first = CatalogItem("Indexed-Item");
|
||||
var duplicate = CatalogItem("indexed-item");
|
||||
var catalog = new AetheriaRuntimeCatalogSnapshot([first, duplicate], [], []);
|
||||
|
||||
Require(ReferenceEquals(first, catalog.FindItem("INDEXED-ITEM")),
|
||||
"the derived catalog index must preserve first case-insensitive match semantics");
|
||||
|
||||
var replacement = CatalogItem("replacement-item");
|
||||
catalog.Items = [replacement];
|
||||
Require(catalog.FindItem("indexed-item") == null &&
|
||||
ReferenceEquals(replacement, catalog.FindItem("REPLACEMENT-ITEM")),
|
||||
"replacing snapshot items must invalidate the derived lookup index");
|
||||
}
|
||||
|
||||
private static void PickupIsCapacityCheckedExactlyOnceAndExpires()
|
||||
{
|
||||
var hull = CatalogItem("pickup-hull"); hull.HullCapacity = PerformanceStat(1);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ namespace GameCult.Aetheria.State.Verse
|
|||
[MessagePackObject]
|
||||
public sealed class AetheriaRuntimeCatalogSnapshot
|
||||
{
|
||||
private IReadOnlyList<AetheriaRuntimeCatalogItem> _items = Array.Empty<AetheriaRuntimeCatalogItem>();
|
||||
private Dictionary<string, AetheriaRuntimeCatalogItem>? _itemsByKey;
|
||||
|
||||
public const string SchemaId = "gamecult.aetheria.runtime_catalog.v1";
|
||||
public const string DocumentName = "aetheria.runtime_catalog";
|
||||
|
||||
|
|
@ -36,7 +39,15 @@ namespace GameCult.Aetheria.State.Verse
|
|||
public string CatalogId { get; set; } = DocumentName;
|
||||
|
||||
[Key(1)]
|
||||
public IReadOnlyList<AetheriaRuntimeCatalogItem> Items { get; set; } = Array.Empty<AetheriaRuntimeCatalogItem>();
|
||||
public IReadOnlyList<AetheriaRuntimeCatalogItem> Items
|
||||
{
|
||||
get => _items;
|
||||
set
|
||||
{
|
||||
_items = value ?? Array.Empty<AetheriaRuntimeCatalogItem>();
|
||||
_itemsByKey = null;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreMember]
|
||||
public IReadOnlyList<AetheriaRuntimeCatalogItem> TradeItems =>
|
||||
|
|
@ -57,7 +68,11 @@ namespace GameCult.Aetheria.State.Verse
|
|||
|
||||
public AetheriaRuntimeCatalogItem? FindItem(string itemKey)
|
||||
{
|
||||
return TryGet(Items, itemKey, item => item.ItemKey);
|
||||
if (string.IsNullOrWhiteSpace(itemKey))
|
||||
return null;
|
||||
|
||||
_itemsByKey ??= BuildItemIndex(Items);
|
||||
return _itemsByKey.TryGetValue(itemKey, out var item) ? item : null;
|
||||
}
|
||||
|
||||
public AetheriaRuntimeCatalogItem? FindItem<T>(T? item, Func<T, string?> itemKey) where T : class
|
||||
|
|
@ -108,6 +123,19 @@ namespace GameCult.Aetheria.State.Verse
|
|||
? null
|
||||
: values.FirstOrDefault(value => string.Equals(getKey(value), key, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private static Dictionary<string, AetheriaRuntimeCatalogItem> BuildItemIndex(
|
||||
IEnumerable<AetheriaRuntimeCatalogItem> items)
|
||||
{
|
||||
var index = new Dictionary<string, AetheriaRuntimeCatalogItem>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var item in items ?? Enumerable.Empty<AetheriaRuntimeCatalogItem>())
|
||||
{
|
||||
if (item == null || string.IsNullOrWhiteSpace(item.ItemKey))
|
||||
continue;
|
||||
index.TryAdd(item.ItemKey, item);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
[CultDocument("gamecult.aetheria.loadout_templates", "gamecult.aetheria.loadout_templates.v1")]
|
||||
|
|
|
|||
Loading…
Reference in a new issue