Publish daemon menu Eve surfaces
This commit is contained in:
parent
f13f70d92b
commit
59e783f6a0
5 changed files with 261 additions and 6 deletions
|
|
@ -795,6 +795,189 @@ static async Task PublishDaemonApiDocumentsAsync(
|
|||
await node.MutableDocument<EveSurfaceDocument>(AetheriaRuntimeVerseRecordKeys.DaemonEditorTuiSurface)
|
||||
.ReplaceAsync(AetheriaRuntimeSurfaceDocuments.ToPortableSurface(result.EditorTuiSurface))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
await PublishDaemonMenuSurfacesAsync(node, result.Frame).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
static async Task PublishDaemonMenuSurfacesAsync(
|
||||
AetheriaStateNode node,
|
||||
AetheriaRuntimeDaemonFrameDocument frame)
|
||||
{
|
||||
if (frame == null)
|
||||
return;
|
||||
|
||||
var updatedAtUtc = string.IsNullOrWhiteSpace(frame.PublishedAtUtc)
|
||||
? DateTimeOffset.UtcNow.ToString("O")
|
||||
: frame.PublishedAtUtc;
|
||||
var catalog = AetheriaRuntimeCatalogStore.OpenReadOnly(node.StatePath);
|
||||
var loadoutTemplates = AetheriaRuntimeCatalogStore.ReadLoadoutTemplates(node.StatePath);
|
||||
var playerSettings = await ReadRuntimePlayerSettingsAsync(node).ConfigureAwait(false);
|
||||
var currentEntity = AetheriaRuntimeRtsDocuments.CurrentEntity(frame);
|
||||
var stationRefit = AetheriaRuntimeRtsDocuments.StationRefit(frame, loadoutTemplates, catalog);
|
||||
var dropdownRequest = new AetheriaRuntimeInventoryDropdownSurfaceRequest
|
||||
{
|
||||
CurrentView = "Current Entity",
|
||||
DisplayedEntityKey = currentEntity.EntityKey,
|
||||
DisplayedCargoEntityKey = currentEntity.EntityKey,
|
||||
DisplayedCargoIndex = 0,
|
||||
CanSaveLoadout = !string.IsNullOrWhiteSpace(currentEntity.EntityKey)
|
||||
};
|
||||
var inventoryRequest = new AetheriaRuntimeInventoryPanelSurfaceRequest
|
||||
{
|
||||
ViewTitle = string.IsNullOrWhiteSpace(currentEntity.Entity?.DisplayName)
|
||||
? "Current Entity Inventory"
|
||||
: currentEntity.Entity.DisplayName,
|
||||
DisplayedEntityKey = currentEntity.EntityKey,
|
||||
DisplayedEntityIndex = currentEntity.EntityIndex,
|
||||
DisplayedCargoEntityKey = currentEntity.EntityKey,
|
||||
DisplayedCargoEntityIndex = currentEntity.EntityIndex,
|
||||
DisplayedCargoIndex = 0
|
||||
};
|
||||
var inventory = currentEntity.EntityIndex < 0
|
||||
? new AetheriaRuntimeInventoryDocument()
|
||||
: AetheriaRuntimeRtsDocuments.Inventory(frame, currentEntity.EntityIndex);
|
||||
|
||||
var mainMenu = AetheriaRuntimeMainMenuSurfaceBuilder.BuildRoot(
|
||||
AetheriaRuntimeStateBoot.Inspect(
|
||||
new DirectoryInfo(Path.GetDirectoryName(node.StatePath) ?? "."),
|
||||
node.StatePath),
|
||||
playerSettings,
|
||||
canOpenRuntimeInputScreen: true,
|
||||
inGame: true,
|
||||
updatedAtUtc);
|
||||
var inventoryPanel = AetheriaRuntimeInventoryPanelSurfaceBuilder.BuildFromDocuments(
|
||||
currentEntity,
|
||||
stationRefit,
|
||||
inventory,
|
||||
catalog,
|
||||
playerSettings,
|
||||
inventoryRequest,
|
||||
AetheriaRuntimeVerseRecordKeys.InventoryDropdownSurface.ToString(),
|
||||
updatedAtUtc);
|
||||
var inventoryDropdown = AetheriaRuntimeInventoryDropdownSurfaceBuilder.BuildFromDocuments(
|
||||
stationRefit,
|
||||
dropdownRequest,
|
||||
updatedAtUtc);
|
||||
var mapMenu = AetheriaRuntimeZoneDetailsSurfaceBuilder.BuildFromDocuments(
|
||||
AetheriaRuntimeRtsDocuments.ZoneDetails(frame, currentEntity.ZoneIndex),
|
||||
AetheriaRuntimeRtsDocuments.SectorMap(frame),
|
||||
catalog,
|
||||
playerSettings,
|
||||
updatedAtUtc);
|
||||
var tradeMenu = BuildTradeMenuSurface(stationRefit, catalog, updatedAtUtc, frame.FrameId);
|
||||
|
||||
await node.MutableDocument<EveSurfaceDocument>(AetheriaRuntimeVerseRecordKeys.MainMenuSurface)
|
||||
.ReplaceAsync(AetheriaRuntimeSurfaceDocuments.ToPortableSurface(mainMenu))
|
||||
.ConfigureAwait(false);
|
||||
await node.MutableDocument<EveSurfaceDocument>(AetheriaRuntimeVerseRecordKeys.InventoryPanelSurface)
|
||||
.ReplaceAsync(AetheriaRuntimeSurfaceDocuments.ToPortableSurface(inventoryPanel))
|
||||
.ConfigureAwait(false);
|
||||
await node.MutableDocument<EveSurfaceDocument>(AetheriaRuntimeVerseRecordKeys.InventoryDropdownSurface)
|
||||
.ReplaceAsync(AetheriaRuntimeSurfaceDocuments.ToPortableSurface(inventoryDropdown))
|
||||
.ConfigureAwait(false);
|
||||
await node.MutableDocument<EveSurfaceDocument>(AetheriaRuntimeVerseRecordKeys.MapMenuSurface)
|
||||
.ReplaceAsync(AetheriaRuntimeSurfaceDocuments.ToPortableSurface(mapMenu))
|
||||
.ConfigureAwait(false);
|
||||
await node.MutableDocument<EveSurfaceDocument>(AetheriaRuntimeVerseRecordKeys.TradeMenuSurface)
|
||||
.ReplaceAsync(AetheriaRuntimeSurfaceDocuments.ToPortableSurface(tradeMenu))
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
static async Task<AetheriaRuntimePlayerSettingsDocument> ReadRuntimePlayerSettingsAsync(AetheriaStateNode node)
|
||||
{
|
||||
var settings = await node.MutableDocument<AetheriaPlayerSettings>(AetheriaStateNode.PlayerSettingsKey)
|
||||
.ReadAsync()
|
||||
.ConfigureAwait(false);
|
||||
settings ??= new AetheriaPlayerSettings();
|
||||
return new AetheriaRuntimePlayerSettingsDocument
|
||||
{
|
||||
PlayerName = settings.PlayerName ?? "",
|
||||
TutorialPassed = settings.TutorialPassed,
|
||||
TemperatureUnit = settings.Gameplay?.TemperatureUnit ?? "",
|
||||
SignificantDigits = settings.Gameplay?.SignificantDigits ?? 3,
|
||||
DefaultShutdownPerformance = settings.Gameplay?.DefaultShutdownPerformance ?? 0,
|
||||
NebulaQuality = settings.Graphics?.NebulaQuality ?? "",
|
||||
ShowAsteroidsInMinimap = settings.Graphics?.ShowAsteroidsInMinimap ?? false,
|
||||
BindingOverrides = Array.Empty<AetheriaRuntimeInputBindingOverrideDocument>(),
|
||||
ActionBarInputs = settings.Input?.ActionBarInputs ?? Array.Empty<string>()
|
||||
};
|
||||
}
|
||||
|
||||
static AetheriaRuntimeSurfaceDocument BuildTradeMenuSurface(
|
||||
AetheriaRuntimeStationRefitDocument stationRefit,
|
||||
AetheriaRuntimeCatalogSnapshot catalog,
|
||||
string updatedAtUtc,
|
||||
long version)
|
||||
{
|
||||
stationRefit ??= new AetheriaRuntimeStationRefitDocument();
|
||||
var rows = (stationRefit.StationStock ?? Array.Empty<AetheriaRuntimeStationStockItem>())
|
||||
.Take(12)
|
||||
.Select((item, index) =>
|
||||
{
|
||||
var typedItem = catalog?.FindItem(item.ItemKey);
|
||||
return SurfaceLeaf(
|
||||
$"aetheria.trade.menu.stock.{index}",
|
||||
"row",
|
||||
("item", typedItem?.Name ?? item.ItemKey),
|
||||
("key", item.ItemKey ?? ""),
|
||||
("qty", item.Quantity.ToString(CultureInfo.InvariantCulture)),
|
||||
("price", item.Price.ToString("N0", CultureInfo.InvariantCulture)),
|
||||
("owned", item.OwnedQuantity.ToString(CultureInfo.InvariantCulture)),
|
||||
("afford", item.CanAfford ? "yes" : "no"));
|
||||
})
|
||||
.DefaultIfEmpty(SurfaceLeaf(
|
||||
"aetheria.trade.menu.stock.empty",
|
||||
"text",
|
||||
("value", "No station stock is available in the current daemon frame.")))
|
||||
.ToArray();
|
||||
|
||||
return new AetheriaRuntimeSurfaceDocument(
|
||||
providerId: "aetheria.daemon",
|
||||
providerKind: "trade.menu",
|
||||
title: "Trade Menu",
|
||||
version: version,
|
||||
updatedAtUtc: updatedAtUtc ?? "",
|
||||
surface: new AetheriaRuntimeSurfaceTree(
|
||||
"aetheria.trade.menu",
|
||||
SurfaceNode(
|
||||
"aetheria.trade.menu.root",
|
||||
"surface",
|
||||
Array.Empty<(string Key, string Value)>(),
|
||||
SurfaceNode(
|
||||
"aetheria.trade.menu.summary",
|
||||
"card",
|
||||
new[] { ("title", "Station Trade") },
|
||||
SurfaceLeaf("aetheria.trade.menu.summary.docked", "metric", ("label", "Docked"), ("value", stationRefit.IsDocked ? "yes" : "no")),
|
||||
SurfaceLeaf("aetheria.trade.menu.summary.station", "metric", ("label", "Station"), ("value", stationRefit.DockParent?.DisplayName ?? stationRefit.DockParentEntityKey ?? "")),
|
||||
SurfaceLeaf("aetheria.trade.menu.summary.credits", "metric", ("label", "Credits"), ("value", stationRefit.Credits.ToString("N0", CultureInfo.InvariantCulture)))),
|
||||
SurfaceNode(
|
||||
"aetheria.trade.menu.stock",
|
||||
"card",
|
||||
new[] { ("title", "Station Stock") },
|
||||
rows)),
|
||||
Array.Empty<AetheriaRuntimeSurfaceStyleToken>()),
|
||||
commands: Array.Empty<AetheriaRuntimeSurfaceCommandTemplate>());
|
||||
}
|
||||
|
||||
static AetheriaRuntimeSurfaceComponent SurfaceLeaf(
|
||||
string id,
|
||||
string kind,
|
||||
params (string Key, string Value)[] props)
|
||||
{
|
||||
return SurfaceNode(id, kind, props, Array.Empty<AetheriaRuntimeSurfaceComponent>());
|
||||
}
|
||||
|
||||
static AetheriaRuntimeSurfaceComponent SurfaceNode(
|
||||
string id,
|
||||
string kind,
|
||||
(string Key, string Value)[] props,
|
||||
params AetheriaRuntimeSurfaceComponent[] children)
|
||||
{
|
||||
return new AetheriaRuntimeSurfaceComponent(
|
||||
id,
|
||||
kind,
|
||||
props.ToDictionary(prop => prop.Key, prop => prop.Value),
|
||||
children);
|
||||
}
|
||||
|
||||
static async Task AcceptEveCommandsAsync(AetheriaStateNode node, AetheriaDaemonHostOptions options)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
payload);
|
||||
}
|
||||
|
||||
private static byte[] WriteRuntimeSurfaceDocument(AetheriaRuntimeSurfaceDocument document)
|
||||
internal static byte[] WriteRuntimeSurfaceDocument(AetheriaRuntimeSurfaceDocument document)
|
||||
{
|
||||
var buffer = new ArrayBufferWriter<byte>();
|
||||
var writer = new MessagePackWriter(buffer);
|
||||
|
|
@ -173,7 +173,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
}
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeSurfaceDocument ReadRuntimeSurfaceDocument(byte[] payload)
|
||||
internal static AetheriaRuntimeSurfaceDocument ReadRuntimeSurfaceDocument(byte[] payload)
|
||||
{
|
||||
var reader = new MessagePackReader(payload);
|
||||
var fields = reader.ReadArrayHeader();
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
Surface(AetheriaRuntimeDaemonGameSurfaceBuilder.TuiSurfaceId, "Aetheria Daemon TUI", AetheriaRuntimeVerseRecordKeys.DaemonGameTuiSurface.ToString(), "agent", "Compact daemon game surface for dense inspection.", providerId: "aetheria.daemon", providerKind: "game.daemon", transport: "cultmesh-record"),
|
||||
Surface(AetheriaRuntimeDaemonEditorSurfaceBuilder.SurfaceId, "Aetheria Daemon Editor", AetheriaRuntimeVerseRecordKeys.DaemonEditorSurface.ToString(), "operator", "Daemon editor and surface inventory.", providerId: "aetheria.daemon", providerKind: "editor.daemon", transport: "cultmesh-record"),
|
||||
Surface(AetheriaRuntimeDaemonEditorSurfaceBuilder.TuiSurfaceId, "Aetheria Daemon Editor TUI", AetheriaRuntimeVerseRecordKeys.DaemonEditorTuiSurface.ToString(), "agent", "Compact daemon editor and surface inventory.", providerId: "aetheria.daemon", providerKind: "editor.daemon", transport: "cultmesh-record"),
|
||||
Surface(AetheriaRuntimeMainMenuCommands.RootSurfaceId, "Main Menu", "", "player", "Runtime main menu root.", status: "client-contextual"),
|
||||
Surface(AetheriaRuntimeMainMenuCommands.RootSurfaceId, "Main Menu", AetheriaRuntimeVerseRecordKeys.MainMenuSurface.ToString(), "player", "Runtime main menu root.", transport: "cultmesh-record"),
|
||||
Surface(AetheriaRuntimeMainMenuCommands.SettingsSurfaceId, "Main Menu Settings", "", "player", "Runtime main menu settings shell.", status: "client-contextual"),
|
||||
Surface(AetheriaRuntimeMainMenuCommands.InputSettingsSurfaceId, "Main Menu Input Settings", "", "player", "Main menu input settings handoff shell.", status: "client-contextual"),
|
||||
Surface(AetheriaRuntimeMainMenuCommands.PlayerSettingsShellSurfaceId, "Main Menu Player Settings", "", "player", "Main menu player settings shell.", status: "client-contextual"),
|
||||
|
|
@ -73,12 +73,13 @@ namespace GameCult.Aetheria.State.Verse
|
|||
Surface(AetheriaRuntimeLoadoutTemplateCommands.SurfaceId, "Loadout Templates", "", "player", "Loadout template save surface.", status: "client-contextual"),
|
||||
Surface(AetheriaRuntimeClientTargetCommands.SurfaceId, "Client Target", "", "operator", "Local client target and Verse discovery surface.", status: "client-contextual"),
|
||||
Surface(AetheriaRuntimeLocalStorySurfaceBuilder.SurfaceId, "Local Story", "", "player", "Local runtime story/menu surface.", status: "client-contextual"),
|
||||
Surface(AetheriaRuntimeZoneDetailsSurfaceBuilder.SurfaceId, "Zone Details", "", "player", "Selected zone details surface.", status: "contextual"),
|
||||
Surface(AetheriaRuntimeInventoryPanelSurfaceBuilder.SurfaceId, "Inventory Panel", "", "player", "Current inventory panel surface.", status: "contextual"),
|
||||
Surface(AetheriaRuntimeInventoryDropdownSurfaceBuilder.SurfaceId, "Inventory Dropdown", "", "player", "Inventory navigation dropdown surface.", status: "contextual"),
|
||||
Surface(AetheriaRuntimeZoneDetailsSurfaceBuilder.SurfaceId, "Map Menu", AetheriaRuntimeVerseRecordKeys.MapMenuSurface.ToString(), "player", "Current-zone map details surface.", transport: "cultmesh-record"),
|
||||
Surface(AetheriaRuntimeInventoryPanelSurfaceBuilder.SurfaceId, "Inventory Panel", AetheriaRuntimeVerseRecordKeys.InventoryPanelSurface.ToString(), "player", "Current inventory panel surface.", transport: "cultmesh-record"),
|
||||
Surface(AetheriaRuntimeInventoryDropdownSurfaceBuilder.SurfaceId, "Inventory Dropdown", AetheriaRuntimeVerseRecordKeys.InventoryDropdownSurface.ToString(), "player", "Inventory navigation dropdown surface.", transport: "cultmesh-record"),
|
||||
Surface(AetheriaRuntimeShipSettingsSurfaceBuilder.SurfaceId, "Current Ship Settings", "", "player", "Current ship settings surface.", status: "contextual"),
|
||||
Surface(AetheriaRuntimeCargoItemDetailsSurfaceBuilder.SurfaceId, "Cargo Item Details", "", "player", "Selected cargo item details surface.", status: "contextual"),
|
||||
Surface(AetheriaRuntimeEquippedItemDetailsSurfaceBuilder.SurfaceId, "Equipped Item Details", "", "player", "Selected equipped item details surface.", status: "contextual"),
|
||||
Surface("aetheria.trade.menu", "Trade Menu", AetheriaRuntimeVerseRecordKeys.TradeMenuSurface.ToString(), "player", "Daemon-derived station stock trade menu.", transport: "cultmesh-record"),
|
||||
Surface(AetheriaRuntimeTradeCargoSelectorSurfaceBuilder.SurfaceId, "Trade Cargo Selector", "", "player", "Trade cargo target selector surface.", status: "contextual"),
|
||||
Surface(AetheriaRuntimeTradeInteractionSurfaceBuilder.FilterSurfaceId, "Trade Filter Selector", "", "player", "Trade filter selector surface.", status: "contextual"),
|
||||
Surface(AetheriaRuntimeTradeInteractionSurfaceBuilder.RowActionSurfaceId, "Trade Row Actions", "", "player", "Trade row action selector surface.", status: "contextual"),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GameCult.Caching;
|
||||
using GameCult.Eve.Surface;
|
||||
|
||||
[assembly: CultGeneratedDocumentMetadataProvider(typeof(GameCult.Aetheria.State.Verse.AetheriaRuntimeEveSurfaceDocumentMetadataProvider))]
|
||||
|
||||
namespace GameCult.Aetheria.State.Verse
|
||||
{
|
||||
public sealed class AetheriaRuntimeEveSurfaceDocumentMetadataProvider : ICultGeneratedDocumentMetadataProvider
|
||||
{
|
||||
public IEnumerable<CultGeneratedDocumentDefinition> GetDocumentDefinitions()
|
||||
{
|
||||
yield return new CultGeneratedDocumentDefinition(
|
||||
typeof(EveSurfaceDocument),
|
||||
"gamecult.eve.surface",
|
||||
"gamecult.eve.surface.v1",
|
||||
isGlobal: false,
|
||||
nameMember: null,
|
||||
nameAccessor: null,
|
||||
serializePayload: value => AetheriaRuntimeCultCacheDocumentStore.WriteRuntimeSurfaceDocument(
|
||||
AetheriaRuntimeSurfaceDocuments.FromPortableSurface((EveSurfaceDocument)value)),
|
||||
deserializePayload: payload => AetheriaRuntimeSurfaceDocuments.ToPortableSurface(
|
||||
AetheriaRuntimeCultCacheDocumentStore.ReadRuntimeSurfaceDocument(payload)),
|
||||
indexAccessors: Array.Empty<CultGeneratedDocumentIndexAccessor>(),
|
||||
members: new[]
|
||||
{
|
||||
Member("Type", 0, "string"),
|
||||
Member("Schema", 1, "string"),
|
||||
Member("ProviderId", 2, "string"),
|
||||
Member("ProviderKind", 3, "string"),
|
||||
Member("Title", 4, "string"),
|
||||
Member("Version", 5, "int64"),
|
||||
Member("UpdatedAtUtc", 6, "string"),
|
||||
Member("Surface", 7, "object"),
|
||||
Member("Commands", 8, "array")
|
||||
});
|
||||
}
|
||||
|
||||
private static CultGeneratedDocumentMemberDefinition Member(
|
||||
string name,
|
||||
int slot,
|
||||
string typeName)
|
||||
{
|
||||
return new CultGeneratedDocumentMemberDefinition(
|
||||
name,
|
||||
slot,
|
||||
typeName,
|
||||
isReference: false,
|
||||
isMany: false,
|
||||
targetSchemaName: null,
|
||||
isName: false,
|
||||
indexAlias: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +65,21 @@ namespace GameCult.Aetheria.State.Verse
|
|||
public static CultRecordKey DaemonEditorTuiSurface { get; } =
|
||||
new CultRecordKey("eve:surface:aetheria.daemon.editor.tui");
|
||||
|
||||
public static CultRecordKey MainMenuSurface { get; } =
|
||||
new CultRecordKey("eve:surface:aetheria.main_menu.root");
|
||||
|
||||
public static CultRecordKey InventoryPanelSurface { get; } =
|
||||
new CultRecordKey("eve:surface:aetheria.inventory.panel");
|
||||
|
||||
public static CultRecordKey InventoryDropdownSurface { get; } =
|
||||
new CultRecordKey("eve:surface:aetheria.inventory.panel.dropdown");
|
||||
|
||||
public static CultRecordKey MapMenuSurface { get; } =
|
||||
new CultRecordKey("eve:surface:aetheria.map.zone_details");
|
||||
|
||||
public static CultRecordKey TradeMenuSurface { get; } =
|
||||
new CultRecordKey("eve:surface:aetheria.trade.menu");
|
||||
|
||||
public static CultRecordKey DaemonCommand(string commandId)
|
||||
{
|
||||
return new CultRecordKey($"daemon:commands:{StableToken(commandId)}:gamecult.aetheria.daemon_command.v1");
|
||||
|
|
|
|||
Loading…
Reference in a new issue