Move RTS body icon authority to daemon
This commit is contained in:
parent
1e3c066155
commit
91b79265b9
13 changed files with 125 additions and 35 deletions
BIN
Aetheria RTS.lnk
Normal file
BIN
Aetheria RTS.lnk
Normal file
Binary file not shown.
|
|
@ -339,6 +339,7 @@ export type BodyView = {
|
|||
radius: number;
|
||||
isAsteroidBelt: boolean;
|
||||
iconAsset: AssetRef;
|
||||
iconSize: number;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,19 @@ type AetheriaPublicationDocumentSpec = CultMeshPublicationDocumentBinding & {
|
|||
readonly remoteRecordKey?: string;
|
||||
};
|
||||
|
||||
type AetheriaRuntimeRtsQueryExecutors = {
|
||||
mapViewport: (request: ViewportRequest) => Promise<ViewportResponse>;
|
||||
objectsViewport: (request: ViewportRequest) => Promise<ObjectsViewportResponse>;
|
||||
gravityViewport: (request: ViewportRequest) => Promise<GravityViewportResponse>;
|
||||
renderSplatsViewport: (request: ViewportRequest) => Promise<RenderSplatsViewportResponse>;
|
||||
selectedObject: (request: SelectedObjectRequest) => Promise<SelectedObjectDocument>;
|
||||
inventory: (request: SelectedObjectRequest) => Promise<InventoryDocument>;
|
||||
daemonHealth: () => Promise<DaemonHealthDocument>;
|
||||
authorityStatus: () => Promise<AuthorityStatusDocument>;
|
||||
starbridgeSession: () => Promise<StarbridgeSessionDocument>;
|
||||
assetManifest: () => Promise<AssetManifestDocument>;
|
||||
};
|
||||
|
||||
export type AetheriaCultMeshClientOptions = {
|
||||
publicationMode?: "local" | "remote";
|
||||
snapshotTimeoutMs?: number;
|
||||
|
|
@ -211,6 +224,7 @@ export class AetheriaCultMeshClient {
|
|||
starbridgeSession: async () => readStarbridgeSessionSummaryDocument(await this.fetchStarbridgeSessionSummaryDocument()),
|
||||
assetManifest: async () => readAssetManifestDocument(await this.fetchAssetManifestDocument()),
|
||||
};
|
||||
this.queryExecutors = executors;
|
||||
this.queries = createAetheriaRuntimeRtsQueryHandles(
|
||||
executors,
|
||||
this.queryVerse.context.routeHint,
|
||||
|
|
@ -251,6 +265,7 @@ export class AetheriaCultMeshClient {
|
|||
|
||||
private readonly publicationDescription: string;
|
||||
private readonly publications: CultMeshDocumentCatalog;
|
||||
private readonly queryExecutors: AetheriaRuntimeRtsQueryExecutors;
|
||||
private readonly queries: ReturnType<typeof createAetheriaRuntimeRtsQueryHandles>;
|
||||
private readonly documents: AetheriaRuntimeRtsDocuments;
|
||||
private readonly operations: AetheriaRuntimeRtsOperationHandles;
|
||||
|
|
@ -278,27 +293,27 @@ export class AetheriaCultMeshClient {
|
|||
}
|
||||
|
||||
public async mapViewport(request: ViewportRequest): Promise<ViewportResponse> {
|
||||
return this.aetheria.zone().viewport.within(request);
|
||||
return this.queryExecutors.mapViewport(request);
|
||||
}
|
||||
|
||||
public async objectsViewport(request: ViewportRequest): Promise<ObjectsViewportResponse> {
|
||||
return this.aetheria.zone().objects.visibleWithin(request);
|
||||
return this.queryExecutors.objectsViewport(request);
|
||||
}
|
||||
|
||||
public async gravityViewport(request: ViewportRequest): Promise<GravityViewportResponse> {
|
||||
return this.aetheria.zone().gravity.within(request);
|
||||
return this.queryExecutors.gravityViewport(request);
|
||||
}
|
||||
|
||||
public async renderSplatsViewport(request: ViewportRequest): Promise<RenderSplatsViewportResponse> {
|
||||
return this.aetheria.zone().renderSplats.within(request);
|
||||
return this.queryExecutors.renderSplatsViewport(request);
|
||||
}
|
||||
|
||||
public async selectedObject(request: SelectedObjectRequest): Promise<SelectedObjectDocument> {
|
||||
return this.aetheria.selectedObject(request.entityIndex);
|
||||
return this.queryExecutors.selectedObject(request);
|
||||
}
|
||||
|
||||
public async inventory(request: SelectedObjectRequest): Promise<InventoryDocument> {
|
||||
return this.aetheria.inventory(request.entityIndex);
|
||||
return this.queryExecutors.inventory(request);
|
||||
}
|
||||
|
||||
public async daemonHealth(): Promise<DaemonHealthDocument> {
|
||||
|
|
@ -533,16 +548,16 @@ export class AetheriaCultMeshClient {
|
|||
selectedObject,
|
||||
inventory,
|
||||
] = await Promise.all([
|
||||
this.aetheria.zone().gravity.within(request.viewport),
|
||||
this.aetheria.daemon.health(),
|
||||
this.aetheria.daemon.authorityStatus(),
|
||||
this.aetheria.daemon.starbridgeSession(),
|
||||
this.aetheria.daemon.assetManifest(),
|
||||
this.queryExecutors.gravityViewport(request.viewport),
|
||||
this.queryExecutors.daemonHealth(),
|
||||
this.queryExecutors.authorityStatus(),
|
||||
this.queryExecutors.starbridgeSession(),
|
||||
this.queryExecutors.assetManifest(),
|
||||
selectedEntityIndex >= 0
|
||||
? this.aetheria.selectedObject(selectedEntityIndex)
|
||||
? this.queryExecutors.selectedObject({ entityIndex: selectedEntityIndex })
|
||||
: Promise.resolve(null),
|
||||
selectedEntityIndex >= 0
|
||||
? this.aetheria.inventory(selectedEntityIndex)
|
||||
? this.queryExecutors.inventory({ entityIndex: selectedEntityIndex })
|
||||
: Promise.resolve(null),
|
||||
]);
|
||||
|
||||
|
|
@ -658,14 +673,14 @@ function normalizeDaemonTarget(target: string | AetheriaCultMeshDaemonTarget): R
|
|||
|
||||
async function retryTransientPublicationRead<T>(read: () => Promise<T>): Promise<T> {
|
||||
let lastError: unknown;
|
||||
for (let attempt = 0; attempt < 8; attempt += 1) {
|
||||
for (let attempt = 0; attempt < 40; attempt += 1) {
|
||||
try {
|
||||
return await read();
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
if (!isTransientPublicationReadError(error))
|
||||
throw error;
|
||||
await delay(20 + attempt * 15);
|
||||
await delay(25 + attempt * 8);
|
||||
}
|
||||
}
|
||||
throw lastError;
|
||||
|
|
@ -673,7 +688,10 @@ async function retryTransientPublicationRead<T>(read: () => Promise<T>): Promise
|
|||
|
||||
function isTransientPublicationReadError(error: unknown): boolean {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
return message.includes("EBUSY") || message.includes("EPERM") || message.includes("ENOENT");
|
||||
return message.includes("EBUSY") ||
|
||||
message.includes("EPERM") ||
|
||||
message.includes("ENOENT") ||
|
||||
message.includes("did not contain schema");
|
||||
}
|
||||
|
||||
function buildMainMenuSurface(
|
||||
|
|
|
|||
|
|
@ -254,7 +254,8 @@ export type AetheriaRuntimeDaemonFrameDocumentSlot =
|
|||
| "rejectedImportedFactIds"
|
||||
| "duplicateImportedFactIds"
|
||||
| "cumulativeImportedFactIds"
|
||||
| "cumulativeRejectedImportedFactIds";
|
||||
| "cumulativeRejectedImportedFactIds"
|
||||
| "renderSettings";
|
||||
|
||||
export const aetheriaRuntimeDaemonFrameDocumentSlots: Record<AetheriaRuntimeDaemonFrameDocumentSlot, number> = {
|
||||
schema: 0,
|
||||
|
|
@ -278,6 +279,7 @@ export const aetheriaRuntimeDaemonFrameDocumentSlots: Record<AetheriaRuntimeDaem
|
|||
duplicateImportedFactIds: 18,
|
||||
cumulativeImportedFactIds: 19,
|
||||
cumulativeRejectedImportedFactIds: 20,
|
||||
renderSettings: 21,
|
||||
};
|
||||
|
||||
export type AetheriaRuntimeDaemonHealthDocumentSlot =
|
||||
|
|
@ -1099,7 +1101,8 @@ export type AetheriaRuntimeBodySnapshotCommitSlot =
|
|||
| "gravityWellDepth"
|
||||
| "gravityWaveRadius"
|
||||
| "gravityWaveDepth"
|
||||
| "gravityWaveSpeed";
|
||||
| "gravityWaveSpeed"
|
||||
| "iconSize";
|
||||
|
||||
export const aetheriaRuntimeBodySnapshotCommitSlots: Record<AetheriaRuntimeBodySnapshotCommitSlot, number> = {
|
||||
kind: 1,
|
||||
|
|
@ -1122,6 +1125,7 @@ export const aetheriaRuntimeBodySnapshotCommitSlots: Record<AetheriaRuntimeBodyS
|
|||
gravityWaveRadius: 19,
|
||||
gravityWaveDepth: 20,
|
||||
gravityWaveSpeed: 21,
|
||||
iconSize: 22,
|
||||
};
|
||||
|
||||
export type AetheriaRuntimeSunVisualCommitSlot =
|
||||
|
|
@ -1322,7 +1326,8 @@ export type AetheriaRuntimeRtsBodyViewSlot =
|
|||
| "radius"
|
||||
| "isAsteroidBelt"
|
||||
| "body"
|
||||
| "iconAsset";
|
||||
| "iconAsset"
|
||||
| "iconSize";
|
||||
|
||||
export const aetheriaRuntimeRtsBodyViewSlots: Record<AetheriaRuntimeRtsBodyViewSlot, number> = {
|
||||
bodyKey: 0,
|
||||
|
|
@ -1335,6 +1340,7 @@ export const aetheriaRuntimeRtsBodyViewSlots: Record<AetheriaRuntimeRtsBodyViewS
|
|||
isAsteroidBelt: 7,
|
||||
body: 8,
|
||||
iconAsset: 9,
|
||||
iconSize: 10,
|
||||
};
|
||||
|
||||
export type AetheriaRuntimeStarbridgeScenarioDocumentSlot =
|
||||
|
|
@ -1863,6 +1869,7 @@ export type BodyView = {
|
|||
radius: number;
|
||||
isAsteroidBelt: boolean;
|
||||
iconAsset: AssetRef;
|
||||
iconSize: number;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -565,6 +565,7 @@ function toBodyView(body: unknown[]): BodyView {
|
|||
radius: Math.max(32, num(body[bodySlots.bodyRadiusMultiplier]) * 70),
|
||||
isAsteroidBelt: kind.toLowerCase().includes("asteroid"),
|
||||
iconAsset: bodyIconAsset(kind),
|
||||
iconSize: num(body[bodySlots.iconSize]),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ const sources = [
|
|||
resolve(repoRoot, "Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonDocuments.cs"),
|
||||
resolve(repoRoot, "Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeEveCommandDocument.cs"),
|
||||
resolve(repoRoot, "Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeAssetDocuments.cs"),
|
||||
resolve(repoRoot, "Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonRenderQueries.cs"),
|
||||
resolve(repoRoot, "Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeDaemonTradeItemQueries.cs"),
|
||||
resolve(repoRoot, "Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeSnapshotDocuments.cs"),
|
||||
resolve(repoRoot, "Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeRtsViewportDocuments.cs"),
|
||||
resolve(repoRoot, "Packages/org.gamecult.aetheria.state/Runtime/AetheriaRuntimeRenderSplatDocuments.cs"),
|
||||
|
|
@ -1528,6 +1530,7 @@ export type BodyView = {
|
|||
radius: number;
|
||||
isAsteroidBelt: boolean;
|
||||
iconAsset: AssetRef;
|
||||
iconSize: number;
|
||||
};
|
||||
`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ using var discoveryHost = new AetheriaVerseDiscoveryHost(node);
|
|||
await EnsureWorldDocumentAsync(node).ConfigureAwait(false);
|
||||
await EnsureTradeValuePolicyAsync(node, startedAtUtc).ConfigureAwait(false);
|
||||
await node.FlushAsync().ConfigureAwait(false);
|
||||
await EnsurePlayableRunDocumentsAsync(node, startedAtUtc).ConfigureAwait(false);
|
||||
await EnsurePlayableRunDocumentsAsync(node, options, startedAtUtc).ConfigureAwait(false);
|
||||
await EnsureStarbridgeSessionDocumentsAsync(node, options).ConfigureAwait(false);
|
||||
var verseHost = await EnsureVerseHostSettingsAsync(node, options, startedAtUtc).ConfigureAwait(false);
|
||||
await EnsureVerseAuthorityPolicyAsync(node, options).ConfigureAwait(false);
|
||||
|
|
@ -129,7 +129,8 @@ static async Task<AetheriaRuntimeDaemonTickResult> TickAsync(
|
|||
: currentFrame.SessionId;
|
||||
var run = HasPlayableRun(currentFrame?.Run) && HasRtsScenario(currentFrame?.Run)
|
||||
? currentFrame!.Run
|
||||
: await ReadRuntimeRunCheckpointAsync(node).ConfigureAwait(false) ?? new AetheriaRuntimeRunCheckpointCommit();
|
||||
: await ReadRuntimeRunCheckpointAsync(node, options.RenderSettings).ConfigureAwait(false) ?? new AetheriaRuntimeRunCheckpointCommit();
|
||||
ApplyDaemonRenderSettings(run, options.RenderSettings);
|
||||
|
||||
var loadoutTemplates = node.Cache
|
||||
.GetAll<AetheriaLoadoutTemplate>()
|
||||
|
|
@ -175,6 +176,7 @@ static async Task<AetheriaRuntimeDaemonTickResult> TickAsync(
|
|||
CumulativeAppliedCommandIds = currentFrame?.CumulativeAppliedCommandIds ?? currentFrame?.AppliedCommandIds ?? Array.Empty<string>(),
|
||||
CumulativeRejectedCommandIds = currentFrame?.CumulativeRejectedCommandIds ?? currentFrame?.RejectedCommandIds ?? Array.Empty<string>(),
|
||||
Catalog = node.RuntimeCatalog().Latest(),
|
||||
RenderSettings = options.RenderSettings,
|
||||
StarbridgeScenario = starbridgeScenario,
|
||||
StarbridgeSession = starbridgeSession,
|
||||
BuildPublications = buildPublications,
|
||||
|
|
@ -1684,12 +1686,15 @@ static async Task EnsureTradeValuePolicyAsync(AetheriaStateNode node, string now
|
|||
now)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
static async Task EnsurePlayableRunDocumentsAsync(AetheriaStateNode node, string now)
|
||||
static async Task EnsurePlayableRunDocumentsAsync(
|
||||
AetheriaStateNode node,
|
||||
AetheriaDaemonHostOptions options,
|
||||
string now)
|
||||
{
|
||||
var settings = await node.MutableDocument<AetheriaPlayerSettings>(AetheriaStateNode.PlayerSettingsKey).ReadAsync().ConfigureAwait(false);
|
||||
if (!string.IsNullOrWhiteSpace(settings?.ActiveRunKey))
|
||||
{
|
||||
var existingRun = await ReadRuntimeRunCheckpointAsync(node).ConfigureAwait(false);
|
||||
var existingRun = await ReadRuntimeRunCheckpointAsync(node, options.RenderSettings).ConfigureAwait(false);
|
||||
if (HasPlayableRun(existingRun) && HasRtsScenario(existingRun))
|
||||
return;
|
||||
}
|
||||
|
|
@ -1846,7 +1851,9 @@ static async Task EnsureVerseAuthorityPolicyAsync(
|
|||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
static async Task<AetheriaRuntimeRunCheckpointCommit?> ReadRuntimeRunCheckpointAsync(AetheriaStateNode node)
|
||||
static async Task<AetheriaRuntimeRunCheckpointCommit?> ReadRuntimeRunCheckpointAsync(
|
||||
AetheriaStateNode node,
|
||||
AetheriaRuntimeDaemonRenderSettings renderSettings)
|
||||
{
|
||||
var settings = await node.MutableDocument<AetheriaPlayerSettings>(AetheriaStateNode.PlayerSettingsKey).ReadAsync().ConfigureAwait(false);
|
||||
if (string.IsNullOrWhiteSpace(settings?.ActiveRunKey))
|
||||
|
|
@ -1864,7 +1871,7 @@ static async Task<AetheriaRuntimeRunCheckpointCommit?> ReadRuntimeRunCheckpointA
|
|||
if (zone == null)
|
||||
continue;
|
||||
|
||||
zones.Add(await ToRuntimeZoneAsync(node, zone, zoneIndex).ConfigureAwait(false));
|
||||
zones.Add(await ToRuntimeZoneAsync(node, zone, zoneIndex, renderSettings).ConfigureAwait(false));
|
||||
}
|
||||
|
||||
return new AetheriaRuntimeRunCheckpointCommit
|
||||
|
|
@ -1893,7 +1900,8 @@ static async Task<AetheriaRuntimeRunCheckpointCommit?> ReadRuntimeRunCheckpointA
|
|||
static async Task<AetheriaRuntimeZoneSnapshotCommit> ToRuntimeZoneAsync(
|
||||
AetheriaStateNode node,
|
||||
AetheriaZoneState zone,
|
||||
int zoneIndex)
|
||||
int zoneIndex,
|
||||
AetheriaRuntimeDaemonRenderSettings renderSettings)
|
||||
{
|
||||
var entityKeys = zone.EntityKeys ?? Array.Empty<string>();
|
||||
var entityIndices = entityKeys
|
||||
|
|
@ -1919,7 +1927,7 @@ static async Task<AetheriaRuntimeZoneSnapshotCommit> ToRuntimeZoneAsync(
|
|||
OwnerFactionIndex = zone.OwnerFactionIndex,
|
||||
Entities = entities,
|
||||
Orbits = (zone.Orbits ?? Array.Empty<AetheriaOrbitSnapshot>()).Select(ToRuntimeOrbit).ToArray(),
|
||||
Bodies = (zone.Bodies ?? Array.Empty<AetheriaBodySnapshot>()).Select(body => ToRuntimeBody(body, entityIndices)).ToArray(),
|
||||
Bodies = (zone.Bodies ?? Array.Empty<AetheriaBodySnapshot>()).Select(body => ToRuntimeBody(body, entityIndices, renderSettings)).ToArray(),
|
||||
DroppedPickups = (zone.DroppedPickups ?? Array.Empty<AetheriaDroppedPickupSnapshot>()).Select(ToRuntimePickup).ToArray(),
|
||||
GravityTerrainRadius = zone.GravityTerrainRadius,
|
||||
GravityTerrainDepth = zone.GravityTerrainDepth,
|
||||
|
|
@ -2036,7 +2044,8 @@ static AetheriaRuntimeOrbitSnapshotCommit ToRuntimeOrbit(AetheriaOrbitSnapshot o
|
|||
|
||||
static AetheriaRuntimeBodySnapshotCommit ToRuntimeBody(
|
||||
AetheriaBodySnapshot body,
|
||||
IReadOnlyDictionary<string, int> entityIndices)
|
||||
IReadOnlyDictionary<string, int> entityIndices,
|
||||
AetheriaRuntimeDaemonRenderSettings renderSettings)
|
||||
{
|
||||
return new AetheriaRuntimeBodySnapshotCommit
|
||||
{
|
||||
|
|
@ -2106,10 +2115,22 @@ static AetheriaRuntimeBodySnapshotCommit ToRuntimeBody(
|
|||
GravityWellDepth = body.GravityWellDepth,
|
||||
GravityWaveRadius = body.GravityWaveRadius,
|
||||
GravityWaveDepth = body.GravityWaveDepth,
|
||||
GravityWaveSpeed = body.GravityWaveSpeed
|
||||
GravityWaveSpeed = body.GravityWaveSpeed,
|
||||
IconSize = renderSettings.ResolveBodyIconSize(body.Mass)
|
||||
};
|
||||
}
|
||||
|
||||
static void ApplyDaemonRenderSettings(
|
||||
AetheriaRuntimeRunCheckpointCommit run,
|
||||
AetheriaRuntimeDaemonRenderSettings renderSettings)
|
||||
{
|
||||
foreach (var zone in run.Zones ?? Array.Empty<AetheriaRuntimeZoneSnapshotCommit>())
|
||||
{
|
||||
foreach (var body in zone.Bodies ?? Array.Empty<AetheriaRuntimeBodySnapshotCommit>())
|
||||
body.IconSize = renderSettings.ResolveBodyIconSize(body.Mass);
|
||||
}
|
||||
}
|
||||
|
||||
static AetheriaRuntimeDroppedPickupCommit ToRuntimePickup(AetheriaDroppedPickupSnapshot pickup)
|
||||
{
|
||||
return new AetheriaRuntimeDroppedPickupCommit
|
||||
|
|
@ -2283,6 +2304,8 @@ internal sealed class AetheriaDaemonHostOptions
|
|||
public TimeSpan TickInterval { get; init; } = TimeSpan.FromMilliseconds(20);
|
||||
public TimeSpan ApiPublicationInterval { get; init; } = TimeSpan.FromSeconds(1);
|
||||
public double FixedDeltaSeconds { get; init; } = 0.02;
|
||||
public AetheriaRuntimeDaemonRenderSettings RenderSettings { get; init; } =
|
||||
AetheriaRuntimeDaemonRenderSettings.AetheriaDefault;
|
||||
public bool Once { get; init; }
|
||||
|
||||
public static AetheriaDaemonHostOptions Parse(IReadOnlyList<string> args)
|
||||
|
|
|
|||
|
|
@ -532,6 +532,10 @@ namespace GameCult.Aetheria.State.Verse
|
|||
[Key(20)]
|
||||
public IReadOnlyList<string> CumulativeRejectedImportedFactIds { get; set; } = Array.Empty<string>();
|
||||
|
||||
[Key(21)]
|
||||
public AetheriaRuntimeDaemonRenderSettings RenderSettings { get; set; } =
|
||||
AetheriaRuntimeDaemonRenderSettings.AetheriaDefault;
|
||||
|
||||
public static AetheriaRuntimeDaemonFrameDocument Create(
|
||||
AetheriaRuntimeRunCheckpointCommit run,
|
||||
string daemonId,
|
||||
|
|
@ -540,7 +544,8 @@ namespace GameCult.Aetheria.State.Verse
|
|||
double simulationTimeSeconds,
|
||||
double fixedDeltaSeconds,
|
||||
bool isAuthoritative = true,
|
||||
string stateSource = "daemon")
|
||||
string stateSource = "daemon",
|
||||
AetheriaRuntimeDaemonRenderSettings? renderSettings = null)
|
||||
{
|
||||
return new AetheriaRuntimeDaemonFrameDocument
|
||||
{
|
||||
|
|
@ -552,7 +557,8 @@ namespace GameCult.Aetheria.State.Verse
|
|||
FixedDeltaSeconds = fixedDeltaSeconds,
|
||||
IsAuthoritative = isAuthoritative,
|
||||
StateSource = string.IsNullOrWhiteSpace(stateSource) ? "daemon" : stateSource,
|
||||
Run = run ?? new AetheriaRuntimeRunCheckpointCommit()
|
||||
Run = run ?? new AetheriaRuntimeRunCheckpointCommit(),
|
||||
RenderSettings = renderSettings ?? AetheriaRuntimeDaemonRenderSettings.AetheriaDefault
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CultMath;
|
||||
using MessagePack;
|
||||
|
||||
#nullable enable
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
}
|
||||
}
|
||||
|
||||
[MessagePackObject(true)]
|
||||
public readonly struct AetheriaRuntimeExponentialCurve
|
||||
{
|
||||
public AetheriaRuntimeExponentialCurve(double exponent, double multiplier, double constant)
|
||||
|
|
@ -61,8 +63,25 @@ namespace GameCult.Aetheria.State.Verse
|
|||
}
|
||||
}
|
||||
|
||||
[MessagePackObject(true)]
|
||||
public readonly struct AetheriaRuntimeDaemonRenderSettings
|
||||
{
|
||||
public static AetheriaRuntimeDaemonRenderSettings AetheriaDefault { get; } =
|
||||
new AetheriaRuntimeDaemonRenderSettings(
|
||||
default,
|
||||
default,
|
||||
default,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
bodyIconSizeCurve: new AetheriaRuntimeExponentialCurve(0.15, 10.0, 25.0),
|
||||
bodyRadiusCurve: default,
|
||||
lightRadiusCurve: default,
|
||||
gravityWaveFrequencyCurve: default);
|
||||
|
||||
public AetheriaRuntimeDaemonRenderSettings(
|
||||
AetheriaRuntimeExponentialCurve temperatureEmissionCurve,
|
||||
AetheriaRuntimeExponentialLerp lockIndicatorFrequency,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ namespace GameCult.Aetheria.State.Verse
|
|||
public AetheriaRuntimeStarbridgeScenarioDocument? StarbridgeScenario { get; set; }
|
||||
public AetheriaRuntimeStarbridgeSessionDocument? StarbridgeSession { get; set; }
|
||||
public AetheriaRuntimeCatalogSnapshot? Catalog { get; set; }
|
||||
public AetheriaRuntimeDaemonRenderSettings RenderSettings { get; set; } =
|
||||
AetheriaRuntimeDaemonRenderSettings.AetheriaDefault;
|
||||
public bool BuildPublications { get; set; } = true;
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +138,8 @@ namespace GameCult.Aetheria.State.Verse
|
|||
options.SessionId,
|
||||
options.FrameId,
|
||||
options.SimulationTimeSeconds,
|
||||
options.FixedDeltaSeconds);
|
||||
options.FixedDeltaSeconds,
|
||||
renderSettings: options.RenderSettings);
|
||||
frame.AppliedCommandIds = operationResult.AppliedCommandIds;
|
||||
frame.RejectedCommandIds = operationResult.RejectedCommandIds;
|
||||
frame.AccountedCommandIds = accountedBeforeTick
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ namespace GameCult.Aetheria.State.Verse
|
|||
ZoneName = string.IsNullOrWhiteSpace(zone.Name) ? $"Zone {zone.ZoneIndex}" : zone.Name,
|
||||
Viewport = normalizedViewport,
|
||||
GravityInfluences = visibleBodies.Select(ToGravityInfluence).ToArray(),
|
||||
Bodies = visibleBodies.Select(ToBodyView).ToArray(),
|
||||
Bodies = visibleBodies.Select(body => ToBodyView(body, frame.RenderSettings)).ToArray(),
|
||||
TerrainRadius = zone.GravityTerrainRadius,
|
||||
TerrainDepth = zone.GravityTerrainDepth,
|
||||
TerrainDepthExponent = zone.GravityTerrainDepthExponent,
|
||||
|
|
@ -850,7 +850,9 @@ namespace GameCult.Aetheria.State.Verse
|
|||
return obj;
|
||||
}
|
||||
|
||||
private static AetheriaRuntimeRtsBodyView ToBodyView(AetheriaRuntimeBodySnapshotCommit body)
|
||||
private static AetheriaRuntimeRtsBodyView ToBodyView(
|
||||
AetheriaRuntimeBodySnapshotCommit body,
|
||||
AetheriaRuntimeDaemonRenderSettings renderSettings)
|
||||
{
|
||||
var view = new AetheriaRuntimeRtsBodyView
|
||||
{
|
||||
|
|
@ -862,7 +864,8 @@ namespace GameCult.Aetheria.State.Verse
|
|||
Y = body.GravityInfluenceCenterZ,
|
||||
Radius = Math.Max(32, body.BodyRadiusMultiplier * 70),
|
||||
IsAsteroidBelt = (body.Kind ?? "").IndexOf("asteroid", StringComparison.OrdinalIgnoreCase) >= 0,
|
||||
Body = body
|
||||
Body = body,
|
||||
IconSize = body.IconSize > 0 ? body.IconSize : renderSettings.ResolveBodyIconSize(body.Mass)
|
||||
};
|
||||
view.IconAsset = AetheriaRuntimeAssets.ResolveBodyIcon(view);
|
||||
return view;
|
||||
|
|
|
|||
|
|
@ -1498,5 +1498,8 @@ namespace GameCult.Aetheria.State.Verse
|
|||
[Key(9)]
|
||||
public AetheriaRuntimeAssetRef IconAsset { get; set; } =
|
||||
AetheriaRuntimeAssetRef.Empty(AetheriaRuntimeAssetKinds.Sprite);
|
||||
|
||||
[Key(10)]
|
||||
public double IconSize { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -599,6 +599,9 @@ namespace GameCult.Aetheria.State.Verse
|
|||
|
||||
[Key(21)]
|
||||
public double GravityWaveSpeed { get; set; }
|
||||
|
||||
[Key(22)]
|
||||
public double IconSize { get; set; }
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
|
|
|
|||
Loading…
Reference in a new issue