Resolve item stat refs in runtime reader
This commit is contained in:
parent
4eb5712e36
commit
fd3f945341
4 changed files with 294 additions and 68 deletions
|
|
@ -4287,10 +4287,23 @@ static void RequireInventoryCargoItemDetailsUseEveSurface(string root)
|
|||
throw new InvalidOperationException("InventoryMenu cargo click path no longer routes item inspection through the Eve surface.");
|
||||
}
|
||||
|
||||
if (!source.Contains("ResolveInventorySurfaceStateRef", StringComparison.Ordinal) ||
|
||||
!source.Contains("AetheriaRuntimeDaemonItemStatQueries.TryReadItemStatRef(", StringComparison.Ordinal) ||
|
||||
!source.Contains("AetheriaRuntimeDaemonItemStatQueries.EvaluatePerformanceStat(", StringComparison.Ordinal) ||
|
||||
var runtimeStateReaderPath = Path.Combine(
|
||||
root,
|
||||
"Packages",
|
||||
"org.gamecult.aetheria.state",
|
||||
"Runtime",
|
||||
"AetheriaRuntimeStateReader.cs");
|
||||
var runtimeStateReader = File.Exists(runtimeStateReaderPath)
|
||||
? File.ReadAllText(runtimeStateReaderPath)
|
||||
: throw new InvalidOperationException("Cannot verify item stat state-ref authority; AetheriaRuntimeStateReader.cs is missing.");
|
||||
|
||||
if (!runtimeStateReader.Contains("TryResolveDaemonItemStatRef(", StringComparison.Ordinal) ||
|
||||
!runtimeStateReader.Contains("AetheriaRuntimeDaemonItemStatQueries.TryReadItemStatRef(", StringComparison.Ordinal) ||
|
||||
!runtimeStateReader.Contains("AetheriaRuntimeDaemonItemStatQueries.EvaluatePerformanceStat(", StringComparison.Ordinal) ||
|
||||
!runtimeStateReader.Contains("FindDaemonItem(", StringComparison.Ordinal) ||
|
||||
!cargoItemSurfaceBuilder.Contains("AetheriaRuntimeDaemonItemStatQueries.ItemStatRef(", StringComparison.Ordinal) ||
|
||||
source.Contains("ResolveInventorySurfaceStateRef", StringComparison.Ordinal) ||
|
||||
source.Contains("TryResolveInventorySurfaceStateRef", StringComparison.Ordinal) ||
|
||||
source.Contains("private static bool TryReadItemStatRef(", StringComparison.Ordinal) ||
|
||||
source.Contains("DecodeRefToken", StringComparison.Ordinal) ||
|
||||
source.Contains("GameManager.ItemManager.GetTier", StringComparison.Ordinal) ||
|
||||
|
|
@ -9708,7 +9721,9 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root)
|
|||
"ResolveEveSurfaceStateRef",
|
||||
"TryResolveEveSurfaceStateRef",
|
||||
"TryResolveDaemonStateRef",
|
||||
"TryResolveDaemonItemStatRef",
|
||||
"AetheriaRuntimeDaemonStateRefs.Prefix",
|
||||
"AetheriaRuntimeDaemonItemStatQueries.StateRefPrefix",
|
||||
"AetheriaRuntimeDaemonStateRefs.CurrentEntityName",
|
||||
"AetheriaRuntimeDaemonPublicationStore.TryReadGameSurface",
|
||||
"AetheriaRuntimeDaemonPublicationStore.TryReadGameTuiSurface",
|
||||
|
|
@ -9722,6 +9737,7 @@ static void RequireRuntimeStateReaderOwnsUnityStateAcquisition(string root)
|
|||
"ResolveSurfaceStateRefs(stateFilePath, surface)",
|
||||
"public static Func<string, string> CreateEveSurfaceStateRefResolver(string stateFilePath)",
|
||||
"CreateStateRefResolver(string stateFilePath)",
|
||||
"FindDaemonItem(",
|
||||
"AetheriaRuntimeEveSurfaceAdapter.ResolveStateRefs(",
|
||||
"AetheriaRuntimeEveSurfaceAdapter.EmptySurface(surfaceId)"
|
||||
};
|
||||
|
|
|
|||
|
|
@ -406,6 +406,82 @@ public class DaemonRuntimeDocumentTests
|
|||
AetheriaRuntimeDaemonStateRefs.CurrentTargetName));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RuntimeStateReaderResolvesItemStatRefsFromDaemonFrame()
|
||||
{
|
||||
var frame = new AetheriaRuntimeDaemonFrameDocument
|
||||
{
|
||||
Run = new AetheriaRuntimeRunCheckpointCommit
|
||||
{
|
||||
Zones = new[]
|
||||
{
|
||||
new AetheriaRuntimeZoneSnapshotCommit
|
||||
{
|
||||
Entities = new[]
|
||||
{
|
||||
new AetheriaRuntimeEntitySnapshotCommit
|
||||
{
|
||||
Equipment = new[]
|
||||
{
|
||||
new AetheriaRuntimeLoadoutItemSlotCommit
|
||||
{
|
||||
Item = new AetheriaRuntimeLoadoutItemCommit
|
||||
{
|
||||
ItemKey = "test-laser",
|
||||
Quality = 0.5,
|
||||
Durability = 1.0,
|
||||
Enabled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var statValue = new AetheriaRuntimeBehaviorValue(
|
||||
"performance-stat",
|
||||
"",
|
||||
0,
|
||||
false,
|
||||
"",
|
||||
"",
|
||||
new[]
|
||||
{
|
||||
NumberValue(10),
|
||||
NumberValue(20),
|
||||
NumberValue(0),
|
||||
NumberValue(0),
|
||||
NumberValue(1),
|
||||
EmptyBehaviorValue("stat-recipe")
|
||||
},
|
||||
Array.Empty<AetheriaRuntimeBehaviorMapEntry>());
|
||||
var catalog = new AetheriaRuntimeCatalogSnapshot(
|
||||
new[]
|
||||
{
|
||||
CatalogItem(
|
||||
"test-laser",
|
||||
new[]
|
||||
{
|
||||
new AetheriaRuntimeBehaviorPayload(
|
||||
0,
|
||||
"Weapon",
|
||||
2,
|
||||
new[] { new AetheriaRuntimeBehaviorField(7, statValue) })
|
||||
})
|
||||
},
|
||||
Array.Empty<AetheriaRuntimeCorporation>(),
|
||||
Array.Empty<AetheriaRuntimeNameFile>());
|
||||
|
||||
Assert.IsTrue(AetheriaRuntimeStateReader.TryResolveDaemonItemStatRef(
|
||||
frame,
|
||||
catalog,
|
||||
AetheriaRuntimeDaemonItemStatQueries.ItemStatRef("test-laser", "Weapon", 2, 7),
|
||||
out var value));
|
||||
Assert.AreEqual("15", value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TickRunnerSkipsPreviouslyAccountedObservedCommands()
|
||||
{
|
||||
|
|
@ -3501,6 +3577,87 @@ public class DaemonRuntimeDocumentTests
|
|||
"state.cc.daemon.soa.cc");
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeCatalogItem CatalogItem(
|
||||
string itemKey,
|
||||
IReadOnlyList<AetheriaRuntimeBehaviorPayload> behaviorPayloads)
|
||||
{
|
||||
return new AetheriaRuntimeCatalogItem(
|
||||
itemKey,
|
||||
itemKey,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Array.Empty<AetheriaRuntimeShapeCell>(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
Array.Empty<AetheriaRuntimeShapeCell>(),
|
||||
Array.Empty<AetheriaRuntimeHardpoint>(),
|
||||
behaviorPayloads,
|
||||
"",
|
||||
"",
|
||||
behaviorPayloads.Select(payload => payload.Kind).ToArray(),
|
||||
1,
|
||||
false,
|
||||
0,
|
||||
1,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
Array.Empty<AetheriaRuntimeCurveKey>(),
|
||||
"",
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
Array.Empty<AetheriaRuntimeAudioStat>(),
|
||||
Array.Empty<AetheriaRuntimeCurveKey>(),
|
||||
"",
|
||||
"");
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeBehaviorValue NumberValue(double value)
|
||||
{
|
||||
return new AetheriaRuntimeBehaviorValue(
|
||||
"",
|
||||
"",
|
||||
value,
|
||||
false,
|
||||
"",
|
||||
"",
|
||||
Array.Empty<AetheriaRuntimeBehaviorValue>(),
|
||||
Array.Empty<AetheriaRuntimeBehaviorMapEntry>());
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeBehaviorValue EmptyBehaviorValue(string kind)
|
||||
{
|
||||
return new AetheriaRuntimeBehaviorValue(
|
||||
kind,
|
||||
"",
|
||||
0,
|
||||
false,
|
||||
"",
|
||||
"",
|
||||
Array.Empty<AetheriaRuntimeBehaviorValue>(),
|
||||
Array.Empty<AetheriaRuntimeBehaviorMapEntry>());
|
||||
}
|
||||
|
||||
private static bool ContainsSurfaceMetric(
|
||||
AetheriaRuntimeSurfaceComponent component,
|
||||
string label,
|
||||
|
|
|
|||
|
|
@ -261,7 +261,6 @@ public class InventoryMenu : MonoBehaviour
|
|||
AetheriaRuntimeCargoItemDetailsSurfaceBuilder.Build(ProjectCargoItemDetailsSurface(item, typedItem)),
|
||||
HandleCargoItemDetailsSurfaceCommand,
|
||||
_cargoItemDetailsSurfaceChrome,
|
||||
ResolveInventorySurfaceStateRef,
|
||||
sortingOrder: 1001);
|
||||
}
|
||||
|
||||
|
|
@ -304,7 +303,6 @@ public class InventoryMenu : MonoBehaviour
|
|||
AetheriaRuntimeEquippedItemDetailsSurfaceBuilder.Build(ProjectEquippedItemDetailsSurface(item, typedItem)),
|
||||
HandleEquippedItemDetailsSurfaceCommand,
|
||||
_equippedItemDetailsSurfaceChrome,
|
||||
ResolveInventorySurfaceStateRef,
|
||||
sortingOrder: 1002);
|
||||
}
|
||||
|
||||
|
|
@ -539,15 +537,6 @@ public class InventoryMenu : MonoBehaviour
|
|||
: "";
|
||||
}
|
||||
|
||||
private static string FormatCurrentItemStat(AetheriaRuntimeBehaviorValue stat, EquippableItem item)
|
||||
{
|
||||
return ActionGameManager.RuntimePlayerSettings.Format(
|
||||
AetheriaRuntimeDaemonItemStatQueries.EvaluatePerformanceStat(
|
||||
stat,
|
||||
ToRuntimeLoadoutItem(item),
|
||||
item?.Temperature ?? 0));
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeLoadoutItemCommit ToRuntimeLoadoutItem(EquippableItem item)
|
||||
{
|
||||
return AetheriaRuntimeDaemonItemStatQueries.ItemCommit(
|
||||
|
|
@ -558,51 +547,6 @@ public class InventoryMenu : MonoBehaviour
|
|||
overrideShutdown: item != null && item.OverrideShutdown);
|
||||
}
|
||||
|
||||
private string ResolveInventorySurfaceStateRef(string stateRef)
|
||||
{
|
||||
return TryResolveInventorySurfaceStateRef(stateRef, out var value) ? value : "";
|
||||
}
|
||||
|
||||
private bool TryResolveInventorySurfaceStateRef(string stateRef, out string value)
|
||||
{
|
||||
value = "";
|
||||
if (!AetheriaRuntimeDaemonItemStatQueries.TryReadItemStatRef(
|
||||
stateRef,
|
||||
out var itemKey,
|
||||
out var behaviorKind,
|
||||
out var behaviorGroup,
|
||||
out var fieldKey))
|
||||
return false;
|
||||
|
||||
var item = ResolveSelectedEquippableItem(itemKey);
|
||||
var typedItem = FindTypedInventoryItem(item);
|
||||
var behavior = typedItem?.BehaviorPayloads?.FirstOrDefault(candidate =>
|
||||
string.Equals(candidate.Kind, behaviorKind, StringComparison.Ordinal) &&
|
||||
candidate.Group == behaviorGroup);
|
||||
var field = behavior?.Fields?.FirstOrDefault(candidate => candidate.Key == fieldKey);
|
||||
if (item == null || field == null)
|
||||
return false;
|
||||
|
||||
value = FormatCurrentItemStat(field.Value, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
private EquippableItem ResolveSelectedEquippableItem(string itemKey)
|
||||
{
|
||||
var equipped = _selectedEquippedItem?.EquippableItem;
|
||||
if (ItemKeyMatches(equipped, itemKey))
|
||||
return equipped;
|
||||
|
||||
var cargo = _selectedItem as EquippableItem;
|
||||
return ItemKeyMatches(cargo, itemKey) ? cargo : null;
|
||||
}
|
||||
|
||||
private static bool ItemKeyMatches(EquippableItem item, string itemKey)
|
||||
{
|
||||
return item != null &&
|
||||
string.Equals(item.ItemKey ?? "", itemKey ?? "", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static bool IsWeaponGroupAssigned(EquippedItem item, int groupIndex)
|
||||
{
|
||||
return item?.Entity?.WeaponGroups != null &&
|
||||
|
|
|
|||
|
|
@ -121,13 +121,24 @@ namespace GameCult.Aetheria.State.Verse
|
|||
if (string.IsNullOrWhiteSpace(stateRef))
|
||||
return false;
|
||||
|
||||
if (!stateRef.StartsWith(AetheriaRuntimeDaemonStateRefs.Prefix + "/", StringComparison.Ordinal))
|
||||
return false;
|
||||
|
||||
TryReadDaemonFrame(stateFilePath, out var frame);
|
||||
AetheriaRuntimeDaemonPublicationStore.TryReadHealth(stateFilePath, out var health);
|
||||
AetheriaRuntimeDaemonPublicationStore.TryReadCommandBoundary(stateFilePath, out var commandBoundary);
|
||||
return TryResolveDaemonStateRef(frame, health, commandBoundary, stateRef, out value);
|
||||
if (stateRef.StartsWith(AetheriaRuntimeDaemonStateRefs.Prefix + "/", StringComparison.Ordinal))
|
||||
{
|
||||
AetheriaRuntimeDaemonPublicationStore.TryReadHealth(stateFilePath, out var health);
|
||||
AetheriaRuntimeDaemonPublicationStore.TryReadCommandBoundary(stateFilePath, out var commandBoundary);
|
||||
return TryResolveDaemonStateRef(frame, health, commandBoundary, stateRef, out value);
|
||||
}
|
||||
|
||||
if (stateRef.StartsWith(AetheriaRuntimeDaemonItemStatQueries.StateRefPrefix + "/", StringComparison.Ordinal))
|
||||
{
|
||||
return TryResolveDaemonItemStatRef(
|
||||
frame,
|
||||
OpenRuntimeCatalog(stateFilePath),
|
||||
stateRef,
|
||||
out value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool TryResolveDaemonStateRef(
|
||||
|
|
@ -211,6 +222,42 @@ namespace GameCult.Aetheria.State.Verse
|
|||
}
|
||||
}
|
||||
|
||||
public static bool TryResolveDaemonItemStatRef(
|
||||
AetheriaRuntimeDaemonFrameDocument? frame,
|
||||
AetheriaRuntimeCatalogSnapshot? catalog,
|
||||
string stateRef,
|
||||
out string value)
|
||||
{
|
||||
value = "";
|
||||
if (!AetheriaRuntimeDaemonItemStatQueries.TryReadItemStatRef(
|
||||
stateRef,
|
||||
out var itemKey,
|
||||
out var behaviorKind,
|
||||
out var behaviorGroup,
|
||||
out var fieldKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var item = FindDaemonItem(frame?.Run, itemKey);
|
||||
var typedItem = catalog?.FindItem(itemKey);
|
||||
var field = typedItem?.BehaviorPayloads?
|
||||
.FirstOrDefault(candidate =>
|
||||
string.Equals(candidate.Kind, behaviorKind, StringComparison.Ordinal) &&
|
||||
candidate.Group == behaviorGroup)
|
||||
?.Fields?
|
||||
.FirstOrDefault(candidate => candidate.Key == fieldKey);
|
||||
if (item == null || field == null)
|
||||
return false;
|
||||
|
||||
value = AetheriaRuntimeDaemonItemStatQueries.EvaluatePerformanceStat(
|
||||
field.Value,
|
||||
item,
|
||||
heat: 0)
|
||||
.ToString("0.###", CultureInfo.InvariantCulture);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryReadDaemonGameSurface(
|
||||
string stateFilePath,
|
||||
out EveSurfaceDocument document)
|
||||
|
|
@ -303,9 +350,71 @@ namespace GameCult.Aetheria.State.Verse
|
|||
AetheriaRuntimeDaemonPublicationStore.TryReadHealth(stateFilePath, out var health);
|
||||
AetheriaRuntimeDaemonPublicationStore.TryReadCommandBoundary(stateFilePath, out var commandBoundary);
|
||||
|
||||
return stateRef => TryResolveDaemonStateRef(frame, health, commandBoundary, stateRef, out var value)
|
||||
? value
|
||||
: "";
|
||||
return stateRef =>
|
||||
{
|
||||
if (TryResolveDaemonStateRef(frame, health, commandBoundary, stateRef, out var value))
|
||||
return value;
|
||||
|
||||
return stateRef.StartsWith(AetheriaRuntimeDaemonItemStatQueries.StateRefPrefix + "/", StringComparison.Ordinal) &&
|
||||
TryResolveDaemonItemStatRef(frame, OpenRuntimeCatalog(stateFilePath), stateRef, out value)
|
||||
? value
|
||||
: "";
|
||||
};
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeLoadoutItemCommit? FindDaemonItem(
|
||||
AetheriaRuntimeRunCheckpointCommit? run,
|
||||
string itemKey)
|
||||
{
|
||||
if (run == null || string.IsNullOrWhiteSpace(itemKey))
|
||||
return null;
|
||||
|
||||
foreach (var zone in run.Zones ?? Array.Empty<AetheriaRuntimeZoneSnapshotCommit>())
|
||||
foreach (var entity in zone.Entities ?? Array.Empty<AetheriaRuntimeEntitySnapshotCommit>())
|
||||
{
|
||||
var item = FindDaemonItem(entity.Equipment, itemKey)
|
||||
?? FindDaemonItem(entity.CargoBays, itemKey)
|
||||
?? FindDaemonItem(entity.DockingBays, itemKey)
|
||||
?? FindDaemonItem(entity.CargoContents, itemKey)
|
||||
?? FindDaemonItem(entity.DockingBayContents, itemKey);
|
||||
if (item != null)
|
||||
return item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeLoadoutItemCommit? FindDaemonItem(
|
||||
IReadOnlyList<AetheriaRuntimeLoadoutItemSlotCommit>? slots,
|
||||
string itemKey)
|
||||
{
|
||||
foreach (var slot in slots ?? Array.Empty<AetheriaRuntimeLoadoutItemSlotCommit>())
|
||||
{
|
||||
if (IsItemMatch(slot?.Item, itemKey))
|
||||
return slot?.Item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeLoadoutItemCommit? FindDaemonItem(
|
||||
IReadOnlyList<AetheriaRuntimeCargoBayLoadoutCommit>? cargoBays,
|
||||
string itemKey)
|
||||
{
|
||||
foreach (var cargoBay in cargoBays ?? Array.Empty<AetheriaRuntimeCargoBayLoadoutCommit>())
|
||||
{
|
||||
var item = FindDaemonItem(cargoBay?.Items, itemKey);
|
||||
if (item != null)
|
||||
return item;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool IsItemMatch(AetheriaRuntimeLoadoutItemCommit? item, string itemKey)
|
||||
{
|
||||
return item != null &&
|
||||
string.Equals(item.ItemKey ?? "", itemKey ?? "", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeZoneSnapshotCommit FindCurrentZone(AetheriaRuntimeRunCheckpointCommit run)
|
||||
|
|
|
|||
Loading…
Reference in a new issue