diff --git a/Aetheria.State.Daemon/Program.cs b/Aetheria.State.Daemon/Program.cs index 9c678830c..28f237312 100644 --- a/Aetheria.State.Daemon/Program.cs +++ b/Aetheria.State.Daemon/Program.cs @@ -937,15 +937,16 @@ static async Task PublishRuntimeSessionAsync( static async Task EnsureWorldDocumentAsync(AetheriaStateNode node) { var now = DateTimeOffset.UtcNow.ToString("O"); - var existing = await node.GetWorldAsync().ConfigureAwait(false); + var world = node.World(); + var existing = await world.ReadAsync().ConfigureAwait(false); if (existing != null) { existing.UpdatedAtUtc = now; - await node.PutWorldAsync(existing).ConfigureAwait(false); + await world.ReplaceAsync(existing).ConfigureAwait(false); return; } - await node.PutWorldAsync(new AetheriaWorldState + await world.ReplaceAsync(new AetheriaWorldState { Name = "Aetheria", WorldId = "aetheria", @@ -957,11 +958,12 @@ static async Task EnsureWorldDocumentAsync(AetheriaStateNode node) static async Task EnsureTradeValuePolicyAsync(AetheriaStateNode node, string now) { - var existing = await node.GetTradeValuePolicyAsync().ConfigureAwait(false); + var tradeValuePolicy = node.TradeValuePolicy(); + var existing = await tradeValuePolicy.ReadAsync().ConfigureAwait(false); if (existing != null) return; - await node.PutTradeValuePolicyAsync( + await tradeValuePolicy.ReplaceAsync( AetheriaRuntimeStateMapper.ToTradeValuePolicy( AetheriaRuntimeTradeValueSettings.Default, now)).ConfigureAwait(false); @@ -993,7 +995,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string .ReplaceAsync(settings) .ConfigureAwait(false); - await node.PutRunStateAsync(runKey, new AetheriaRunState + await node.RunState(runKey).ReplaceAsync(new AetheriaRunState { RunId = runId, EntranceZoneIndex = 0, @@ -1006,7 +1008,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string UpdatedAtUtc = now }).ConfigureAwait(false); - await node.PutZoneStateAsync(zoneKey, new AetheriaZoneState + await node.ZoneState(zoneKey).ReplaceAsync(new AetheriaZoneState { Name = "Daemon Local Testbed", Position = Vec2(0, 0), @@ -1084,7 +1086,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string GravityTerrainWaveFrequency = 0.6 }).ConfigureAwait(false); - await node.PutEntitySnapshotAsync(new CultRecordKey(entityKeys[0]), SeedEntity( + await node.EntitySnapshot(new CultRecordKey(entityKeys[0])).ReplaceAsync(SeedEntity( "Anchor Station", "station", Vec3(-220, 0, -90), @@ -1103,7 +1105,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string Contact(entityKeys[7], 0.6, false) ], ["repair-parts", "reactor-fuel", "drone-core"])).ConfigureAwait(false); - await node.PutEntitySnapshotAsync(new CultRecordKey(entityKeys[1]), SeedEntity( + await node.EntitySnapshot(new CultRecordKey(entityKeys[1])).ReplaceAsync(SeedEntity( "Vanguard One", "ship", Vec3(-60, 0, -40), @@ -1120,7 +1122,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string Contact(entityKeys[5], 0.85, true) ], ["coilgun-ammo", "field-rations"])).ConfigureAwait(false); - await node.PutEntitySnapshotAsync(new CultRecordKey(entityKeys[2]), SeedEntity( + await node.EntitySnapshot(new CultRecordKey(entityKeys[2])).ReplaceAsync(SeedEntity( "Wing Two", "ship", Vec3(180, 0, 120), @@ -1137,7 +1139,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string Contact(entityKeys[6], 0.6, true) ], ["sensor-buoy", "shield-cell"])).ConfigureAwait(false); - await node.PutEntitySnapshotAsync(new CultRecordKey(entityKeys[3]), SeedEntity( + await node.EntitySnapshot(new CultRecordKey(entityKeys[3])).ReplaceAsync(SeedEntity( "Torch Three", "ship", Vec3(-160, 0, 210), @@ -1153,7 +1155,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string Contact(entityKeys[5], 0.9, true) ], ["micro-missile", "coolant-pack"])).ConfigureAwait(false); - await node.PutEntitySnapshotAsync(new CultRecordKey(entityKeys[4]), SeedEntity( + await node.EntitySnapshot(new CultRecordKey(entityKeys[4])).ReplaceAsync(SeedEntity( "Ash Raider", "ship", Vec3(420, 0, 180), @@ -1169,7 +1171,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string Contact(entityKeys[2], 0.5, true) ], ["scrap-metal", "stolen-capacitor"])).ConfigureAwait(false); - await node.PutEntitySnapshotAsync(new CultRecordKey(entityKeys[5]), SeedEntity( + await node.EntitySnapshot(new CultRecordKey(entityKeys[5])).ReplaceAsync(SeedEntity( "Cinder Knife", "ship", Vec3(560, 0, -110), @@ -1184,7 +1186,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string Contact(entityKeys[3], 1, true) ], ["volatile-fuel"])).ConfigureAwait(false); - await node.PutEntitySnapshotAsync(new CultRecordKey(entityKeys[6]), SeedEntity( + await node.EntitySnapshot(new CultRecordKey(entityKeys[6])).ReplaceAsync(SeedEntity( "Blackwake", "ship", Vec3(680, 0, 260), @@ -1198,7 +1200,7 @@ static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string Contact(entityKeys[2], 0.8, true) ], ["ore-cache", "burned-relay-core"])).ConfigureAwait(false); - await node.PutEntitySnapshotAsync(new CultRecordKey(entityKeys[7]), SeedEntity( + await node.EntitySnapshot(new CultRecordKey(entityKeys[7])).ReplaceAsync(SeedEntity( "Derelict Relay", "station", Vec3(-260, 0, 260), @@ -1378,7 +1380,7 @@ static async Task ReadRuntimeRunCheckpointA if (string.IsNullOrWhiteSpace(settings?.ActiveRunKey)) return null; - var run = await node.GetRunStateAsync(new CultRecordKey(settings.ActiveRunKey)).ConfigureAwait(false); + var run = await node.RunState(new CultRecordKey(settings.ActiveRunKey)).ReadAsync().ConfigureAwait(false); if (run == null) return null; @@ -1386,7 +1388,7 @@ static async Task ReadRuntimeRunCheckpointA var zoneKeys = run.ZoneKeys ?? Array.Empty(); for (var zoneIndex = 0; zoneIndex < zoneKeys.Length; zoneIndex++) { - var zone = await node.GetZoneStateAsync(new CultRecordKey(zoneKeys[zoneIndex])).ConfigureAwait(false); + var zone = await node.ZoneState(new CultRecordKey(zoneKeys[zoneIndex])).ReadAsync().ConfigureAwait(false); if (zone == null) continue; @@ -1429,7 +1431,7 @@ static async Task ToRuntimeZoneAsync( var entities = new List(); for (var entityIndex = 0; entityIndex < entityKeys.Length; entityIndex++) { - var entity = await node.GetEntitySnapshotAsync(new CultRecordKey(entityKeys[entityIndex])).ConfigureAwait(false); + var entity = await node.EntitySnapshot(new CultRecordKey(entityKeys[entityIndex])).ReadAsync().ConfigureAwait(false); if (entity != null) entities.Add(ToRuntimeEntity(entity, entityIndex, entityIndices)); } diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index 17b8f287b..8d8e56887 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -111,7 +111,7 @@ var corporations = node.Cache.GetAll().ToArray(); var nameFiles = node.Cache.GetAll().ToArray(); var catalog = await node.RuntimeCatalog().LatestAsync().ConfigureAwait(false); var surface = AetheriaCatalogSurfaceProjector.Build(catalog, DateTimeOffset.UtcNow.ToString("O")); -var tradeValuePolicy = await node.GetTradeValuePolicyAsync() +var tradeValuePolicy = await node.TradeValuePolicy().ReadAsync() ?? throw new InvalidOperationException("Missing authored trade value policy document."); await RequireTradeValuePolicyEveCommandPersistsAsync(); var runtimeCatalog = catalog; @@ -9945,7 +9945,7 @@ static void RequireTypedEveCommandBodies(string root) "command.TradeValuePolicy.Value", "command.TradeValuePolicy.TierIndex", "ExecuteTradeValuePolicyCommandAsync(", - "PutTradeValuePolicyAsync(", + "TradeValuePolicy()", "SubmitInputSettingsCommandAsync(", "SubmitLoadoutTemplateCommandAsync(", "SubmitKnownSurfaceCommandAsync(", @@ -12826,7 +12826,9 @@ static async Task RequireTradeValuePolicyEveCommandPersistsAsync() var policy = AetheriaRuntimeStateMapper.ToTradeValuePolicy( AetheriaRuntimeTradeValueSettings.Default, DateTimeOffset.UtcNow.ToString("O")); - await commandNode.PutTradeValuePolicyAsync(policy).ConfigureAwait(false); + await commandNode.TradeValuePolicy() + .ReplaceAsync(policy) + .ConfigureAwait(false); var originalMinimum = policy.QualityPriceModifier?.Minimum ?? 0; var editedMinimum = originalMinimum + 0.125; @@ -12847,7 +12849,7 @@ static async Task RequireTradeValuePolicyEveCommandPersistsAsync() "Trade value policy Eve command was not accepted by the typed command bridge."); } - var editedPolicy = await commandNode.GetTradeValuePolicyAsync().ConfigureAwait(false) + var editedPolicy = await commandNode.TradeValuePolicy().ReadAsync().ConfigureAwait(false) ?? throw new InvalidOperationException("Trade value policy disappeared after typed Eve command."); var actualMinimum = editedPolicy.QualityPriceModifier?.Minimum ?? 0; if (Math.Abs(actualMinimum - editedMinimum) > 0.000001) diff --git a/Aetheria.State/AetheriaEveCommandBridge.cs b/Aetheria.State/AetheriaEveCommandBridge.cs index 6fb3e039a..9c4dadd62 100644 --- a/Aetheria.State/AetheriaEveCommandBridge.cs +++ b/Aetheria.State/AetheriaEveCommandBridge.cs @@ -298,16 +298,17 @@ public static class AetheriaEveCommandBridge var commit = command.LoadoutTemplate ?? throw new InvalidOperationException( $"Loadout template command '{command.CommandId}' is missing its typed payload."); var loadout = AetheriaRuntimeStateMapper.ToLoadoutTemplate(commit, command.IssuedAtUtc); - await node.PutLoadoutTemplateAsync( - AetheriaRuntimeStateMapper.LoadoutKey(loadout.Name), - loadout).ConfigureAwait(false); + await node.LoadoutTemplate(AetheriaRuntimeStateMapper.LoadoutKey(loadout.Name)) + .ReplaceAsync(loadout) + .ConfigureAwait(false); } private static async Task ExecuteTradeValuePolicyCommandAsync( AetheriaStateNode node, AetheriaRuntimeEveCommandDocument command) { - var policy = await node.GetTradeValuePolicyAsync().ConfigureAwait(false) ?? + var tradeValuePolicy = node.TradeValuePolicy(); + var policy = await tradeValuePolicy.ReadAsync().ConfigureAwait(false) ?? AetheriaRuntimeStateMapper.ToTradeValuePolicy( AetheriaRuntimeTradeValueSettings.Default, command.IssuedAtUtc); @@ -343,7 +344,7 @@ public static class AetheriaEveCommandBridge if (persistPolicy) { policy.UpdatedAtUtc = command.IssuedAtUtc; - await node.PutTradeValuePolicyAsync(policy).ConfigureAwait(false); + await tradeValuePolicy.ReplaceAsync(policy).ConfigureAwait(false); } } diff --git a/Aetheria.State/AetheriaStateNode.cs b/Aetheria.State/AetheriaStateNode.cs index 2d7d92a30..046b12a05 100644 --- a/Aetheria.State/AetheriaStateNode.cs +++ b/Aetheria.State/AetheriaStateNode.cs @@ -225,6 +225,37 @@ public sealed class AetheriaStateNode : IAsyncDisposable, IDisposable return MutableDocumentPointer(EveCommandAcceptanceStatusKey); } + public CultMeshMutableStatePointer World() + { + return MutableDocumentPointer(new CultRecordKey("global:aetheria.world_state.v1")); + } + + public CultMeshMutableStatePointer TradeValuePolicy() + { + return MutableDocumentPointer( + new CultRecordKey(AetheriaTradeValuePolicy.RecordKey)); + } + + public CultMeshMutableStatePointer LoadoutTemplate(CultRecordKey key) + { + return MutableDocumentPointer(key); + } + + public CultMeshMutableStatePointer RunState(CultRecordKey key) + { + return MutableDocumentPointer(key); + } + + public CultMeshMutableStatePointer ZoneState(CultRecordKey key) + { + return MutableDocumentPointer(key); + } + + public CultMeshMutableStatePointer EntitySnapshot(CultRecordKey key) + { + return MutableDocumentPointer(key); + } + public Task> PutWorldAsync(AetheriaWorldState world) { return Database.PutAsync(new CultRecordKey("global:aetheria.world_state.v1"), world);