Build typed Aetheria client surfaces
This commit is contained in:
parent
74b3b3d72a
commit
2e96660d48
246 changed files with 37893 additions and 6728 deletions
117
Assets/Scripts/Gameplay/AetheriaUnityGameplayBootShell.cs
Normal file
117
Assets/Scripts/Gameplay/AetheriaUnityGameplayBootShell.cs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
using System;
|
||||
using GameCult.Aetheria.State.Verse;
|
||||
|
||||
public sealed class AetheriaUnityGameplayBootShell
|
||||
{
|
||||
public GameSettings Settings { get; set; }
|
||||
public ZoneRenderer ZoneRenderer { get; set; }
|
||||
public AetheriaUnityCockpitHudShell CockpitHudShell { get; set; }
|
||||
public float TargetSpottedBlinkFrequency { get; set; }
|
||||
public float TargetSpottedBlinkOffset { get; set; }
|
||||
public Action<string> Log { get; set; }
|
||||
|
||||
public AetheriaUnityGameplayBootResult Boot()
|
||||
{
|
||||
var stateBoot = AetheriaRuntimeStateBoot.Inspect(AetheriaUnityRuntimePaths.GameDataDirectory);
|
||||
Log?.Invoke($"Aetheria runtime target: {stateBoot.TargetLabel} via {stateBoot.TargetKind} ({stateBoot.TargetSource})");
|
||||
Log?.Invoke($"Aetheria runtime id: {stateBoot.RuntimeId}");
|
||||
Log?.Invoke($"Aetheria runtime state file: {stateBoot.StateFilePath}");
|
||||
stateBoot = SyncRemoteReplicaBeforeBoot(stateBoot);
|
||||
|
||||
if (!stateBoot.SupportsLocalStateFileRead)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Aetheria runtime target cannot read the daemon mirror state required for gameplay boot: {stateBoot.FailureMessage}");
|
||||
}
|
||||
|
||||
if (!stateBoot.StateFileExists)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Aetheria runtime state file is missing at {stateBoot.StateFilePath}; gameplay requires an authoritative daemon mirror.");
|
||||
}
|
||||
|
||||
var runtimeCatalog = AetheriaUnityRuntimeClientProvider.ResolveClient(stateBoot.StateFilePath, stateBoot.RuntimeId)
|
||||
.OpenRuntimeCatalog();
|
||||
if (runtimeCatalog == null)
|
||||
throw new InvalidOperationException("Aetheria typed runtime catalog is required before gameplay boot.");
|
||||
|
||||
Log?.Invoke($"Aetheria runtime catalog: {runtimeCatalog.Items.Count} items, {runtimeCatalog.Corporations.Count} corporations, {runtimeCatalog.NameFiles.Count} name files");
|
||||
|
||||
var itemManager = new ItemManager(
|
||||
runtimeCatalog,
|
||||
Settings.GameplaySettings,
|
||||
message => Log?.Invoke(message));
|
||||
var loadoutItemProjector = new AetheriaUnityLoadoutItemProjector(itemManager, runtimeCatalog);
|
||||
ZoneRenderer.SetDroppedPickupItemProjector(loadoutItemProjector.CreateLoadoutItem);
|
||||
ZoneRenderer.BodySettingsCollections = Settings.BodySettingsCollections;
|
||||
ZoneRenderer.RenderSettings = AetheriaUnityRenderSettingsBridge.Build(
|
||||
Settings,
|
||||
TargetSpottedBlinkFrequency,
|
||||
TargetSpottedBlinkOffset);
|
||||
CockpitHudShell.SetRenderSettings(ZoneRenderer.RenderSettings);
|
||||
|
||||
if (!AetheriaUnityRuntimeClientProvider.PlayerSettings.GraphicsSettings.ShowAsteroidsInMinimap)
|
||||
ZoneRenderer.ShowAsteroidUI = false;
|
||||
|
||||
return new AetheriaUnityGameplayBootResult(
|
||||
runtimeCatalog,
|
||||
itemManager,
|
||||
loadoutItemProjector);
|
||||
}
|
||||
|
||||
private AetheriaRuntimeStateBootReport SyncRemoteReplicaBeforeBoot(AetheriaRuntimeStateBootReport stateBoot)
|
||||
{
|
||||
if (!ShouldSyncRemoteReplicaBeforeBoot(stateBoot))
|
||||
return stateBoot;
|
||||
|
||||
Log?.Invoke($"Aetheria remote Verse replica missing; syncing {stateBoot.TargetLabel} from {stateBoot.CultMeshAddress}");
|
||||
try
|
||||
{
|
||||
var target = AetheriaState.At(AetheriaUnityRuntimePaths.GameDataDirectory)
|
||||
.ClientTarget
|
||||
.SyncReplica();
|
||||
AetheriaUnityRuntimePaths.ClearRuntimeStateFilePathCache();
|
||||
|
||||
var refreshed = AetheriaRuntimeStateBoot.Inspect(AetheriaUnityRuntimePaths.GameDataDirectory);
|
||||
Log?.Invoke($"Aetheria remote Verse replica synced: {refreshed.StateFilePath}");
|
||||
if (!string.IsNullOrWhiteSpace(target.LastReplicaSyncAtUtc))
|
||||
Log?.Invoke($"Aetheria remote Verse replica sync time: {target.LastReplicaSyncAtUtc}");
|
||||
return refreshed;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AetheriaUnityRuntimePaths.ClearRuntimeStateFilePathCache();
|
||||
throw new InvalidOperationException(
|
||||
$"Aetheria remote Verse replica sync failed before gameplay boot: {ex.Message}",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ShouldSyncRemoteReplicaBeforeBoot(AetheriaRuntimeStateBootReport stateBoot)
|
||||
{
|
||||
return string.Equals(stateBoot.TargetSource, "client-target", StringComparison.Ordinal)
|
||||
&& string.Equals(stateBoot.TargetKind, AetheriaRuntimeClientTargetKinds.CultMeshVerse, StringComparison.Ordinal)
|
||||
&& (!stateBoot.SupportsLocalStateFileRead || !stateBoot.StateFileExists);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct AetheriaUnityGameplayBootResult
|
||||
{
|
||||
public AetheriaUnityGameplayBootResult(
|
||||
AetheriaRuntimeCatalogSnapshot runtimeCatalog,
|
||||
ItemManager itemManager,
|
||||
AetheriaUnityLoadoutItemProjector loadoutItemProjector)
|
||||
{
|
||||
RuntimeCatalog = runtimeCatalog;
|
||||
ItemManager = itemManager;
|
||||
LoadoutItemProjector = loadoutItemProjector;
|
||||
}
|
||||
|
||||
public AetheriaRuntimeCatalogSnapshot RuntimeCatalog { get; }
|
||||
public ItemManager ItemManager { get; }
|
||||
public AetheriaUnityLoadoutItemProjector LoadoutItemProjector { get; }
|
||||
}
|
||||
Loading…
Reference in a new issue