From b4e2f1fcc7bf3ef11872f78f45ea6e52d3b42713 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 12 Jul 2026 07:25:09 +0100 Subject: [PATCH] Make canonical Unity client buildable and typed-state seeded --- Aetheria.Unity/Assets/AetheriaUnityClient.cs | 5 +-- .../Assets/Editor/AetheriaUnityBuild.cs | 39 +++++++++++++++++++ Aetheria.Unity/Assets/Settings.meta | 8 ++++ .../AetheriaUniversalRenderPipeline.asset | 3 ++ ...AetheriaUniversalRenderPipeline.asset.meta | 8 ++++ .../Settings/AetheriaUniversalRenderer.asset | 3 ++ .../AetheriaUniversalRenderer.asset.meta | 8 ++++ Aetheria.Unity/Packages/manifest.json | 2 +- Aetheria.Unity/Packages/packages-lock.json | 4 +- .../ProjectSettings/GraphicsSettings.asset | 4 +- .../ProjectSettings/QualitySettings.asset | 4 +- Aetheria.Unity/README.md | 4 +- scripts/run-aetheria-unity.ps1 | 8 ++++ 13 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 Aetheria.Unity/Assets/Settings.meta create mode 100644 Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderPipeline.asset create mode 100644 Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderPipeline.asset.meta create mode 100644 Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderer.asset create mode 100644 Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderer.asset.meta diff --git a/Aetheria.Unity/Assets/AetheriaUnityClient.cs b/Aetheria.Unity/Assets/AetheriaUnityClient.cs index 6a5373dd0..cfc5753a1 100644 --- a/Aetheria.Unity/Assets/AetheriaUnityClient.cs +++ b/Aetheria.Unity/Assets/AetheriaUnityClient.cs @@ -44,9 +44,8 @@ public sealed class AetheriaUnityClient : MonoBehaviour private static void CreateView() { - var pipeline = UniversalRenderPipelineAsset.Create(); - GraphicsSettings.defaultRenderPipeline = pipeline; - QualitySettings.renderPipeline = pipeline; + if (GraphicsSettings.currentRenderPipeline is not UniversalRenderPipelineAsset) + throw new InvalidOperationException("Aetheria Unity requires the project-configured Universal Render Pipeline asset."); var cameraObject = new GameObject("Main Camera") { tag = "MainCamera" }; var camera = cameraObject.AddComponent(); cameraObject.AddComponent().renderPostProcessing = true; diff --git a/Aetheria.Unity/Assets/Editor/AetheriaUnityBuild.cs b/Aetheria.Unity/Assets/Editor/AetheriaUnityBuild.cs index db571c926..c44046784 100644 --- a/Aetheria.Unity/Assets/Editor/AetheriaUnityBuild.cs +++ b/Aetheria.Unity/Assets/Editor/AetheriaUnityBuild.cs @@ -2,12 +2,15 @@ using System.IO; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; using UnityEngine.SceneManagement; public static class AetheriaUnityBuild { public static void BuildWindows() { + EnsureRenderPipeline(); const string scenePath = "Assets/Aetheria.unity"; var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single); new GameObject("Aetheria Unity Client").AddComponent(); @@ -21,4 +24,40 @@ public static class AetheriaUnityBuild if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded) throw new System.InvalidOperationException("Aetheria Unity build failed: " + report.summary.result); } + + private static void EnsureRenderPipeline() + { + const string settingsDirectory = "Assets/Settings"; + const string rendererPath = settingsDirectory + "/AetheriaUniversalRenderer.asset"; + const string pipelinePath = settingsDirectory + "/AetheriaUniversalRenderPipeline.asset"; + if (!AssetDatabase.IsValidFolder(settingsDirectory)) + AssetDatabase.CreateFolder("Assets", "Settings"); + + var renderer = AssetDatabase.LoadAssetAtPath(rendererPath); + if (renderer == null) + { + renderer = ScriptableObject.CreateInstance(); + renderer.name = "Aetheria Universal Renderer"; + AssetDatabase.CreateAsset(renderer, rendererPath); + } + + var pipeline = AssetDatabase.LoadAssetAtPath(pipelinePath); + if (pipeline == null) + { + pipeline = ScriptableObject.CreateInstance(); + pipeline.name = "Aetheria Universal Render Pipeline"; + AssetDatabase.CreateAsset(pipeline, pipelinePath); + } + + var serialized = new SerializedObject(pipeline); + var rendererList = serialized.FindProperty("m_RendererDataList"); + rendererList.arraySize = 1; + rendererList.GetArrayElementAtIndex(0).objectReferenceValue = renderer; + serialized.FindProperty("m_DefaultRendererIndex").intValue = 0; + serialized.ApplyModifiedPropertiesWithoutUndo(); + EditorUtility.SetDirty(pipeline); + GraphicsSettings.defaultRenderPipeline = pipeline; + QualitySettings.renderPipeline = pipeline; + AssetDatabase.SaveAssets(); + } } diff --git a/Aetheria.Unity/Assets/Settings.meta b/Aetheria.Unity/Assets/Settings.meta new file mode 100644 index 000000000..f8d623a21 --- /dev/null +++ b/Aetheria.Unity/Assets/Settings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6d8cacdee90ec28468309ce67d880eca +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderPipeline.asset b/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderPipeline.asset new file mode 100644 index 000000000..3ec15383a --- /dev/null +++ b/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderPipeline.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db8118ae05674be155ce2518d2d8e65de1ba0329ec3bc4b7015d201fa26678ea +size 4600 diff --git a/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderPipeline.asset.meta b/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderPipeline.asset.meta new file mode 100644 index 000000000..92ed0501d --- /dev/null +++ b/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderPipeline.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0f71fbcaedd8dfd41901262f38b2970a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderer.asset b/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderer.asset new file mode 100644 index 000000000..c34e35992 --- /dev/null +++ b/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderer.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b3955cedef3ce645efdd49f5746127f5575f7499bec82284643eea5eb293473 +size 1874 diff --git a/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderer.asset.meta b/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderer.asset.meta new file mode 100644 index 000000000..4ae781ead --- /dev/null +++ b/Aetheria.Unity/Assets/Settings/AetheriaUniversalRenderer.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cddf5d6d804ca7449a09c71a7eb69794 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Aetheria.Unity/Packages/manifest.json b/Aetheria.Unity/Packages/manifest.json index ea2d65247..2a96d72ee 100644 --- a/Aetheria.Unity/Packages/manifest.json +++ b/Aetheria.Unity/Packages/manifest.json @@ -9,6 +9,6 @@ "org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-source-v1.0.3-r2", "org.gamecult.eve.plugin-fields": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.1.1", "org.gamecult.eve.surface": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.1.0", - "org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#b112acb34d1e2561f1e770a9088bd0123e6614ab" + "org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#2ed4e263ee266617f827bc606304ad221ea6c00b" } } diff --git a/Aetheria.Unity/Packages/packages-lock.json b/Aetheria.Unity/Packages/packages-lock.json index 3593c6e13..110d453b9 100644 --- a/Aetheria.Unity/Packages/packages-lock.json +++ b/Aetheria.Unity/Packages/packages-lock.json @@ -142,7 +142,7 @@ "hash": "e10821f1cc81f619479c6507438f6a097d1f0ce2" }, "org.gamecult.eve.unity-scene": { - "version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#b112acb34d1e2561f1e770a9088bd0123e6614ab", + "version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#2ed4e263ee266617f827bc606304ad221ea6c00b", "depth": 0, "source": "git", "dependencies": { @@ -151,7 +151,7 @@ "org.gamecult.eve.surface": "0.1.0", "com.unity.mathematics": "1.3.2" }, - "hash": "b112acb34d1e2561f1e770a9088bd0123e6614ab" + "hash": "2ed4e263ee266617f827bc606304ad221ea6c00b" }, "com.unity.modules.assetbundle": { "version": "1.0.0", diff --git a/Aetheria.Unity/ProjectSettings/GraphicsSettings.asset b/Aetheria.Unity/ProjectSettings/GraphicsSettings.asset index 377875120..3889b1bf7 100644 --- a/Aetheria.Unity/ProjectSettings/GraphicsSettings.asset +++ b/Aetheria.Unity/ProjectSettings/GraphicsSettings.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:40de98f4d46d02fb08e268ad3a722a00eed7289f4ef6d2e759984b1b4a85d2af -size 2433 +oid sha256:6d131c76b47b3db7c5968cbe782b9d303c488ba4eb1a7153fc9cf79efc23b817 +size 2615 diff --git a/Aetheria.Unity/ProjectSettings/QualitySettings.asset b/Aetheria.Unity/ProjectSettings/QualitySettings.asset index 35b1eeb41..2bad22066 100644 --- a/Aetheria.Unity/ProjectSettings/QualitySettings.asset +++ b/Aetheria.Unity/ProjectSettings/QualitySettings.asset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1f893b1be47ad2442f58338dd7c860dc1986bb317e2f5bb31084454ffabbf4c -size 9802 +oid sha256:165a2e860e0bc25834c5e9641b6cb7a0e8090141434d68b36929a6794a28284e +size 9858 diff --git a/Aetheria.Unity/README.md b/Aetheria.Unity/README.md index ba90df14c..5251bba0b 100644 --- a/Aetheria.Unity/README.md +++ b/Aetheria.Unity/README.md @@ -13,7 +13,9 @@ powershell -ExecutionPolicy Bypass -File .\scripts\run-aetheria-unity.ps1 The launcher builds the provider's Unity AssetBundle, starts the Aetheria daemon, builds this project, and opens the standalone client. Close the client window to -stop the daemon. +stop the daemon. A new writable client run is materialized by +`Aetheria.State.Import` from the provider-owned legacy catalog inputs into the +current typed CultCache schema; source catalog data is not mutated by play. Configuration is supplied through `EVEUNITY_RENDEZVOUS_ENDPOINT` and `EVEUNITY_SURFACE_ID`. The defaults are `rudp://127.0.0.1:3076` and diff --git a/scripts/run-aetheria-unity.ps1 b/scripts/run-aetheria-unity.ps1 index ca85a45cd..dcefb9734 100644 --- a/scripts/run-aetheria-unity.ps1 +++ b/scripts/run-aetheria-unity.ps1 @@ -10,7 +10,9 @@ $project = Join-Path $root "Aetheria.Unity" $artifacts = Join-Path $project "Build\Logs" $clientExe = Join-Path $project "Build\Windows\Aetheria.exe" $daemonProject = Join-Path $root "Aetheria.State.Daemon\Aetheria.State.Daemon.csproj" +$importProject = Join-Path $root "Aetheria.State.Import\Aetheria.State.Import.csproj" $state = Join-Path $project "Build\aetheria-unity.cc" +$stateRecords = "$state.records" New-Item -ItemType Directory -Force $artifacts | Out-Null if (-not $SkipBuild) { @@ -38,6 +40,12 @@ if (-not $SkipBuild) { } if (-not (Test-Path $clientExe)) { throw "Client executable not found. Run without -SkipBuild first." } +if (-not (Test-Path $stateRecords)) { + dotnet run --project $importProject -- $root $state + if ($LASTEXITCODE -ne 0 -or -not (Test-Path $stateRecords)) { + throw "Aetheria typed state import failed with exit code $LASTEXITCODE" + } +} $daemonLog = Join-Path $artifacts "daemon.log" $daemon = Start-Process dotnet -ArgumentList @( "run", "--project", $daemonProject, "--",