2026-06-25 18:09:33 +01:00
|
|
|
/* 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;
|
2026-06-28 02:39:41 +01:00
|
|
|
using System.Collections.Generic;
|
2026-06-25 18:09:33 +01:00
|
|
|
using System.IO;
|
|
|
|
|
using GameCult.Aetheria.State.Verse;
|
2026-06-28 22:39:32 +01:00
|
|
|
using GameCult.Mesh;
|
2026-06-25 18:09:33 +01:00
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
public static class AetheriaUnityRuntimeClientProvider
|
|
|
|
|
{
|
2026-06-28 02:39:41 +01:00
|
|
|
private static readonly Dictionary<string, AetheriaClient> RuntimeClients =
|
|
|
|
|
new Dictionary<string, AetheriaClient>(StringComparer.Ordinal);
|
2026-06-25 18:09:33 +01:00
|
|
|
private static RuntimePlayerSettings _runtimePlayerSettings;
|
2026-06-28 09:55:28 +01:00
|
|
|
private static bool _playerSettingsLoaded;
|
2026-06-25 18:09:33 +01:00
|
|
|
|
2026-06-28 09:55:28 +01:00
|
|
|
public static RuntimePlayerSettings PlayerSettings
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
_runtimePlayerSettings ??= CreateDefaultPlayerSettings();
|
|
|
|
|
RefreshPlayerSettings(_runtimePlayerSettings);
|
|
|
|
|
return _runtimePlayerSettings;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-06-25 18:09:33 +01:00
|
|
|
|
2026-06-29 07:04:08 +01:00
|
|
|
private static AetheriaClient ResolveClient(string stateFilePath, string runtimeId = "")
|
2026-06-25 18:09:33 +01:00
|
|
|
{
|
|
|
|
|
var effectiveRuntimeId = string.IsNullOrWhiteSpace(runtimeId) ? "raven-unity" : runtimeId;
|
2026-06-28 02:39:41 +01:00
|
|
|
var cacheKey = CacheKey(stateFilePath, effectiveRuntimeId);
|
|
|
|
|
if (RuntimeClients.TryGetValue(cacheKey, out var runtimeClient))
|
|
|
|
|
return runtimeClient;
|
2026-06-25 18:09:33 +01:00
|
|
|
|
2026-06-28 02:39:41 +01:00
|
|
|
runtimeClient = AetheriaClient
|
2026-06-25 18:09:33 +01:00
|
|
|
.OpenAsync(
|
|
|
|
|
stateFilePath,
|
|
|
|
|
effectiveRuntimeId,
|
|
|
|
|
"local",
|
|
|
|
|
startServer: false,
|
|
|
|
|
pullOnOpen: true)
|
|
|
|
|
.GetAwaiter()
|
|
|
|
|
.GetResult();
|
2026-06-28 02:39:41 +01:00
|
|
|
RuntimeClients[cacheKey] = runtimeClient;
|
|
|
|
|
return runtimeClient;
|
2026-06-25 18:09:33 +01:00
|
|
|
}
|
|
|
|
|
|
2026-06-29 07:04:08 +01:00
|
|
|
private static AetheriaClient ResolveClient(AetheriaRuntimeStateBootReport stateBoot, string runtimeId = "")
|
2026-06-28 02:32:13 +01:00
|
|
|
{
|
|
|
|
|
return ResolveClient(
|
|
|
|
|
stateBoot.StateFilePath,
|
|
|
|
|
string.IsNullOrWhiteSpace(runtimeId) ? stateBoot.RuntimeId : runtimeId);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 07:04:08 +01:00
|
|
|
private static AetheriaClient RuntimeClient(string runtimeId = "")
|
2026-06-29 06:10:30 +01:00
|
|
|
{
|
|
|
|
|
return ResolveClient(AetheriaUnityRuntimePaths.RuntimeStateFilePath, runtimeId);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 07:04:08 +01:00
|
|
|
private static AetheriaClient RuntimeClient(
|
2026-06-29 06:25:07 +01:00
|
|
|
AetheriaRuntimeStateBootReport stateBoot,
|
|
|
|
|
string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return ResolveClient(stateBoot, runtimeId);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 06:10:30 +01:00
|
|
|
public static AetheriaClientState RuntimeState(string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return RuntimeClient(runtimeId).State;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 06:25:07 +01:00
|
|
|
public static AetheriaClientState RuntimeState(
|
|
|
|
|
AetheriaRuntimeStateBootReport stateBoot,
|
|
|
|
|
string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return RuntimeClient(stateBoot, runtimeId).State;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 12:54:07 +01:00
|
|
|
public static AetheriaUnityRtsViewportDocuments MapViewportDocuments(
|
|
|
|
|
AetheriaRuntimeRtsViewportBounds viewport,
|
|
|
|
|
string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return AetheriaUnityRtsViewportDocuments.OpenMap(RuntimeState(runtimeId), viewport);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static AetheriaUnityRtsViewportDocuments ZonePresentationDocuments(
|
|
|
|
|
AetheriaRuntimeRtsViewportBounds viewport,
|
|
|
|
|
string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return AetheriaUnityRtsViewportDocuments.OpenZonePresentation(RuntimeState(runtimeId), viewport);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static AetheriaUnityRtsViewportDocuments RenderSplatViewportDocuments(
|
|
|
|
|
AetheriaRuntimeRtsViewportBounds viewport,
|
|
|
|
|
string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return AetheriaUnityRtsViewportDocuments.OpenRenderSplats(RuntimeState(runtimeId), viewport);
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 12:45:03 +01:00
|
|
|
public static AetheriaUnityDaemonRenderDocuments DaemonRenderDocuments(
|
|
|
|
|
AetheriaRuntimeStateBootReport stateBoot,
|
|
|
|
|
string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return AetheriaUnityDaemonRenderDocuments.Open(RuntimeState(stateBoot, runtimeId));
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 06:10:30 +01:00
|
|
|
public static AetheriaControl Control(string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return RuntimeClient(runtimeId).Control;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 06:25:07 +01:00
|
|
|
public static AetheriaControl Control(
|
|
|
|
|
AetheriaRuntimeStateBootReport stateBoot,
|
|
|
|
|
string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return RuntimeClient(stateBoot, runtimeId).Control;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 06:46:38 +01:00
|
|
|
public static AetheriaUi Ui(string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return RuntimeClient(runtimeId).Ui;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static AetheriaUi Ui(
|
|
|
|
|
AetheriaRuntimeStateBootReport stateBoot,
|
|
|
|
|
string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return RuntimeClient(stateBoot, runtimeId).Ui;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 07:01:38 +01:00
|
|
|
public static CultMeshStateRefResolver EveSurfaceStateRefResolver(string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return RuntimeState(runtimeId).CreateEveSurfaceCultMeshStateRefResolver();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static CultMeshStateRefResolver EveSurfaceStateRefResolver(
|
|
|
|
|
AetheriaRuntimeStateBootReport stateBoot,
|
|
|
|
|
string runtimeId = "")
|
|
|
|
|
{
|
|
|
|
|
return RuntimeState(stateBoot, runtimeId).CreateEveSurfaceCultMeshStateRefResolver();
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-25 18:09:33 +01:00
|
|
|
public static void Dispose()
|
|
|
|
|
{
|
2026-06-28 09:55:28 +01:00
|
|
|
_runtimePlayerSettings = null;
|
|
|
|
|
_playerSettingsLoaded = false;
|
|
|
|
|
|
2026-06-28 02:39:41 +01:00
|
|
|
foreach (var client in RuntimeClients.Values)
|
|
|
|
|
client.Dispose();
|
|
|
|
|
RuntimeClients.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string CacheKey(string stateFilePath, string runtimeId)
|
|
|
|
|
{
|
2026-06-29 06:51:33 +01:00
|
|
|
return (stateFilePath ?? "") + "\n" + runtimeId;
|
2026-06-25 18:09:33 +01:00
|
|
|
}
|
|
|
|
|
|
2026-06-28 09:55:28 +01:00
|
|
|
private static void RefreshPlayerSettings(RuntimePlayerSettings settings)
|
2026-06-25 18:09:33 +01:00
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2026-06-30 19:14:49 +01:00
|
|
|
var stored = RuntimeState().PlayerSettings.Latest();
|
2026-06-25 18:09:33 +01:00
|
|
|
if (stored == null)
|
2026-06-28 09:55:28 +01:00
|
|
|
return;
|
2026-06-25 18:09:33 +01:00
|
|
|
|
|
|
|
|
ApplyPlayerSettings(settings, stored);
|
2026-06-28 09:55:28 +01:00
|
|
|
if (!_playerSettingsLoaded)
|
|
|
|
|
{
|
2026-06-29 09:46:15 +01:00
|
|
|
Debug.Log("Loaded Aetheria Verse player settings from typed state.");
|
2026-06-28 09:55:28 +01:00
|
|
|
_playerSettingsLoaded = true;
|
|
|
|
|
}
|
2026-06-25 18:09:33 +01:00
|
|
|
}
|
|
|
|
|
catch (FileNotFoundException)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogWarning($"Failed to load Aetheria Verse player settings from typed state; using defaults: {ex}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static RuntimePlayerSettings CreateDefaultPlayerSettings()
|
|
|
|
|
{
|
|
|
|
|
var settings = new RuntimePlayerSettings();
|
|
|
|
|
settings.Name = Environment.UserName;
|
|
|
|
|
settings.InputSettings.SetActionBarInputEnabled("<Keyboard>/leftShift", true);
|
|
|
|
|
settings.InputSettings.SetActionBarInputEnabled("<Mouse>/leftButton", true);
|
|
|
|
|
settings.InputSettings.SetActionBarInputEnabled("<Mouse>/rightButton", true);
|
|
|
|
|
settings.InputSettings.SetActionBarInputEnabled("<Mouse>/middleButton", true);
|
|
|
|
|
for (var i = 1; i < 6; i++)
|
|
|
|
|
settings.InputSettings.SetActionBarInputEnabled($"<Keyboard>/{i}", true);
|
|
|
|
|
return settings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void ApplyPlayerSettings(
|
|
|
|
|
RuntimePlayerSettings settings,
|
2026-06-28 01:52:11 +01:00
|
|
|
AetheriaRuntimePlayerSettingsDocument stored)
|
2026-06-25 18:09:33 +01:00
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(stored.PlayerName))
|
|
|
|
|
settings.Name = stored.PlayerName;
|
|
|
|
|
|
|
|
|
|
settings.TutorialPassed = stored.TutorialPassed;
|
|
|
|
|
|
|
|
|
|
settings.HashedStoryFiles.Clear();
|
|
|
|
|
foreach (var storyFileHash in stored.StoryFileHashes)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(storyFileHash.StoryPath))
|
|
|
|
|
settings.HashedStoryFiles[storyFileHash.StoryPath] = storyFileHash.Hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Enum.TryParse(stored.TemperatureUnit, out TemperatureUnit temperatureUnit))
|
|
|
|
|
settings.GameplaySettings.TemperatureUnit = temperatureUnit;
|
|
|
|
|
settings.GameplaySettings.SignificantDigits = Math.Max(0, stored.SignificantDigits);
|
|
|
|
|
|
|
|
|
|
if (Enum.TryParse(stored.NebulaQuality, out Quality nebulaQuality))
|
|
|
|
|
settings.GraphicsSettings.NebulaQuality = nebulaQuality;
|
|
|
|
|
settings.GraphicsSettings.ShowAsteroidsInMinimap = stored.ShowAsteroidsInMinimap;
|
|
|
|
|
|
|
|
|
|
settings.InputSettings.InputActionMap.Clear();
|
|
|
|
|
foreach (var binding in stored.BindingOverrides)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrWhiteSpace(binding.ActionName) ||
|
|
|
|
|
string.IsNullOrWhiteSpace(binding.BindingPath) ||
|
|
|
|
|
binding.BindingIndex < 0)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
settings.InputSettings.SetBindingOverride(binding.ActionName, binding.BindingIndex, binding.BindingPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
settings.InputSettings.ActionBarInputs.Clear();
|
|
|
|
|
foreach (var input in stored.ActionBarInputs)
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(input))
|
|
|
|
|
settings.InputSettings.SetActionBarInputEnabled(input, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|