Use managed typed inventory documents
This commit is contained in:
parent
63c396be42
commit
14a4680c5f
4 changed files with 97 additions and 36 deletions
|
|
@ -90,6 +90,7 @@ RequireEntityDestroyedRequestAuthority(root);
|
|||
RequireDroppedPickupCheckpointState(root);
|
||||
RequireTradePurchaseRequestAuthority(root);
|
||||
RequireInventoryProjectionSlotIdentity(root);
|
||||
RequireInventoryValidationUsesManagedTypedDocuments(root);
|
||||
RequireInventoryLoadoutSaveRequestAuthority(root);
|
||||
RequireInventoryLoadoutRestoreRequestAuthority(root);
|
||||
RequireDockedCurrentShipRequestAuthority(root);
|
||||
|
|
@ -6816,6 +6817,78 @@ static void RequireInventoryProjectionSlotIdentity(string root)
|
|||
}
|
||||
}
|
||||
|
||||
static void RequireInventoryValidationUsesManagedTypedDocuments(string root)
|
||||
{
|
||||
var clientStatePath = Path.Combine(
|
||||
root,
|
||||
"Packages",
|
||||
"org.gamecult.aetheria.state",
|
||||
"Runtime",
|
||||
"AetheriaClientState.cs");
|
||||
var inventoryMenuPath = Path.Combine(root, "Assets", "Scripts", "UI", "Menu", "InventoryMenu.cs");
|
||||
var inventoryPanelPath = Path.Combine(root, "Assets", "Scripts", "UI", "Menu", "InventoryPanel.cs");
|
||||
|
||||
if (!File.Exists(clientStatePath) ||
|
||||
!File.Exists(inventoryMenuPath) ||
|
||||
!File.Exists(inventoryPanelPath))
|
||||
{
|
||||
throw new InvalidOperationException("Cannot verify managed inventory document access; expected client state and inventory UI sources are missing.");
|
||||
}
|
||||
|
||||
var clientState = File.ReadAllText(clientStatePath);
|
||||
if (!clientState.Contains("public Task<AetheriaRuntimeInventoryDocument> LatestInventoryAsync(int entityIndex)", StringComparison.Ordinal) ||
|
||||
!clientState.Contains("public AetheriaRuntimeInventoryDocument LatestInventory(int entityIndex)", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"AetheriaClientDetailState must expose managed typed latest access for indexed inventory documents.");
|
||||
}
|
||||
|
||||
var sources = new Dictionary<string, string>
|
||||
{
|
||||
["InventoryMenu.cs"] = File.ReadAllText(inventoryMenuPath),
|
||||
["InventoryPanel.cs"] = File.ReadAllText(inventoryPanelPath)
|
||||
};
|
||||
foreach (var (name, source) in sources)
|
||||
{
|
||||
var compact = CompactSource(source);
|
||||
var requiredSymbols = new[]
|
||||
{
|
||||
"var state = ResolveClient().Aetheria();",
|
||||
"state.Latest<AetheriaRuntimeCurrentEntityDocument>()",
|
||||
"state.Latest<AetheriaRuntimeStationRefitDocument>()",
|
||||
"state.Details.LatestInventory(entityIndex)"
|
||||
};
|
||||
var missingSymbols = requiredSymbols
|
||||
.Where(symbol => !source.Contains(symbol, StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
if (missingSymbols.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{name} no longer validates inventory slots through managed typed client documents: " +
|
||||
string.Join(", ", missingSymbols));
|
||||
}
|
||||
|
||||
var forbiddenCompactedSymbols = new[]
|
||||
{
|
||||
".Aetheria().Current.Entity.LatestAsync()",
|
||||
".Aetheria().StationRefit.LatestAsync()",
|
||||
".Details.Inventory(entityIndex).LatestAsync()"
|
||||
}
|
||||
.Select(CompactSource)
|
||||
.ToArray();
|
||||
var hits = forbiddenCompactedSymbols
|
||||
.Where(symbol => compact.Contains(symbol, StringComparison.Ordinal))
|
||||
.ToArray();
|
||||
if (hits.Length > 0)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"{name} still walks CultMesh document handles manually instead of using managed typed client state.");
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Inventory validation: cargo/equipment checks read managed typed client documents instead of manual handle walks");
|
||||
}
|
||||
|
||||
static void RequireVerseHostSettingsAuthority(string root)
|
||||
{
|
||||
var settingsPath = Path.Combine(root, "Aetheria.State", "Documents", "AetheriaVerseHostSettings.cs");
|
||||
|
|
@ -14828,7 +14901,7 @@ static void RequireInventoryDoubleClickTransferRequestAuthority(string root)
|
|||
"TryValidateTypedCargoSlot(",
|
||||
"TryValidateTypedEquipmentSlot(",
|
||||
".Details",
|
||||
".Inventory(entityIndex)",
|
||||
".LatestInventory(entityIndex)",
|
||||
"origin.Cargo.TryGetValue(item, out var originPosition)",
|
||||
"SourceIndex == cargoIndex",
|
||||
"SourceIndex == equipmentIndex",
|
||||
|
|
@ -15823,6 +15896,11 @@ static bool ContainsUnitySettingsMember(string source, string memberName)
|
|||
source.Contains($"\nSettings.{memberName}", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
static string CompactSource(string source)
|
||||
{
|
||||
return string.Concat((source ?? "").Where(character => !char.IsWhiteSpace(character)));
|
||||
}
|
||||
|
||||
static string TryReadMethodName(string trimmedLine)
|
||||
{
|
||||
if (!StartsWithMethodAccessModifier(trimmedLine) ||
|
||||
|
|
|
|||
|
|
@ -838,13 +838,8 @@ public class InventoryMenu : MonoBehaviour
|
|||
|
||||
try
|
||||
{
|
||||
var current = ResolveClient()
|
||||
.Aetheria()
|
||||
.Current
|
||||
.Entity
|
||||
.LatestAsync()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
var state = ResolveClient().Aetheria();
|
||||
var current = state.Latest<AetheriaRuntimeCurrentEntityDocument>();
|
||||
if (current != null && string.Equals(current.EntityKey, entityKey, StringComparison.Ordinal))
|
||||
{
|
||||
equipment = current.Equipment ?? Array.Empty<AetheriaRuntimeRtsInventoryItem>();
|
||||
|
|
@ -852,12 +847,7 @@ public class InventoryMenu : MonoBehaviour
|
|||
return true;
|
||||
}
|
||||
|
||||
var refit = ResolveClient()
|
||||
.Aetheria()
|
||||
.StationRefit
|
||||
.LatestAsync()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
var refit = state.Latest<AetheriaRuntimeStationRefitDocument>();
|
||||
var entityIndex = -1;
|
||||
if (refit != null)
|
||||
{
|
||||
|
|
@ -872,13 +862,7 @@ public class InventoryMenu : MonoBehaviour
|
|||
if (entityIndex < 0)
|
||||
return false;
|
||||
|
||||
var inventory = ResolveClient()
|
||||
.Aetheria()
|
||||
.Details
|
||||
.Inventory(entityIndex)
|
||||
.LatestAsync()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
var inventory = state.Details.LatestInventory(entityIndex);
|
||||
if (inventory == null || !string.Equals(inventory.EntityKey, entityKey, StringComparison.Ordinal))
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -1255,13 +1255,8 @@ private void Update()
|
|||
|
||||
try
|
||||
{
|
||||
var current = ResolveClient()
|
||||
.Aetheria()
|
||||
.Current
|
||||
.Entity
|
||||
.LatestAsync()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
var state = ResolveClient().Aetheria();
|
||||
var current = state.Latest<AetheriaRuntimeCurrentEntityDocument>();
|
||||
if (current != null && string.Equals(current.EntityKey, entityKey, StringComparison.Ordinal))
|
||||
{
|
||||
equipment = current.Equipment ?? Array.Empty<AetheriaRuntimeRtsInventoryItem>();
|
||||
|
|
@ -1269,7 +1264,7 @@ private void Update()
|
|||
return true;
|
||||
}
|
||||
|
||||
var refit = ResolveStationRefit();
|
||||
var refit = state.Latest<AetheriaRuntimeStationRefitDocument>();
|
||||
var entityIndex = -1;
|
||||
if (refit != null)
|
||||
{
|
||||
|
|
@ -1284,13 +1279,7 @@ private void Update()
|
|||
if (entityIndex < 0)
|
||||
return false;
|
||||
|
||||
var inventory = ResolveClient()
|
||||
.Aetheria()
|
||||
.Details
|
||||
.Inventory(entityIndex)
|
||||
.LatestAsync()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
var inventory = state.Details.LatestInventory(entityIndex);
|
||||
if (inventory == null || !string.Equals(inventory.EntityKey, entityKey, StringComparison.Ordinal))
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -461,6 +461,16 @@ namespace GameCult.Aetheria.State.Verse
|
|||
{
|
||||
return _inventory(entityIndex);
|
||||
}
|
||||
|
||||
public Task<AetheriaRuntimeInventoryDocument> LatestInventoryAsync(int entityIndex)
|
||||
{
|
||||
return Inventory(entityIndex).LatestAsync();
|
||||
}
|
||||
|
||||
public AetheriaRuntimeInventoryDocument LatestInventory(int entityIndex)
|
||||
{
|
||||
return LatestInventoryAsync(entityIndex).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AetheriaClientStarbridgeState
|
||||
|
|
|
|||
Loading…
Reference in a new issue