Prove released provider volume lowering

This commit is contained in:
Meta Vens 2026-07-15 20:07:35 +01:00
commit 4a513f4264
8 changed files with 299 additions and 35 deletions

View file

@ -461,6 +461,31 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
Assert.That(finalPickupEntityCount, Is.EqualTo(initialPickupEntityCount - 1),
"Collected pickup remained in the provider-authored entity generation.");
targetFact = host.PresentedEntities.CurrentGeneration.Entities
.Single(entity => entity.EntityId == targetEntityId);
playerFact = host.PresentedEntities.CurrentGeneration.Entities
.Single(entity => entity.EntityId == playerId);
aim = targetFact.Position - playerFact.Position;
aim.y = 0;
Assert.That(aim.sqrMagnitude, Is.GreaterThan(0.0001f));
aim.Normalize();
lookVersion = runtime.ActiveVersion;
look = runtime.SubmitLookDirectionIntent(playerId, aim.x, 0f, aim.z);
lookDeadline = Time.realtimeSinceStartup + 12f;
while (Time.realtimeSinceStartup < lookDeadline &&
(runtime.LastReceipt == null || runtime.LastReceipt.CommandId != look.CommandId ||
!string.Equals(runtime.LastReceipt.State, "reconciled", StringComparison.OrdinalIgnoreCase) ||
runtime.ActiveVersion < runtime.LastReceipt.SourceVersion ||
Vector3.Dot(FindMarker(root, playerId).transform.forward, aim) < 0.99f))
{
yield return new WaitForSecondsRealtime(0.1f);
runtime.Refresh();
}
AssertReconciledProviderReceipt(runtime.LastReceipt, look.CommandId,
provider.Selection.ProviderId, provider.Selection.SurfaceId, lookVersion);
Assert.That(Vector3.Dot(FindMarker(root, playerId).transform.forward, aim), Is.GreaterThan(0.99f));
lookReceipt = WitnessReceipt.From("look", runtime.LastReceipt);
var focusVersion = runtime.ActiveVersion;
var inputDriver = root.GetComponent<EveUnityPlayableWorldInputDriver>() ??
root.AddComponent<EveUnityPlayableWorldInputDriver>();
@ -605,6 +630,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(capturePath)));
File.WriteAllBytes(capturePath, pixels.EncodeToPNG());
Assert.That(new FileInfo(capturePath).Length, Is.GreaterThan(1024));
WriteFieldLayerCaptures(root, host.Runtime.ActiveWorld, capturePath);
WriteFieldCloudCapture(root, capturePath);
MeasureRendererOutputs(
camera,
target,
@ -1098,6 +1125,11 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
renderer.enabled = false;
camera.clearFlags = CameraClearFlags.SolidColor;
camera.backgroundColor = Color.black;
camera.Render();
RenderTexture.active = target;
pixels.ReadPixels(new Rect(0, 0, target.width, target.height), 0, 0);
pixels.Apply();
var baseline = pixels.GetPixels();
for (var index = 0; index < measuredRenderers.Count; index++)
{
var fact = facts[index];
@ -1106,9 +1138,10 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
RenderTexture.active = target;
pixels.ReadPixels(new Rect(0, 0, target.width, target.height), 0, 0);
pixels.Apply();
fact.renderedPixelCount = CountChangedPixels(pixels, Color.black);
MeasureLuminance(
pixels,
MeasureDifference(
pixels.GetPixels(),
baseline,
out fact.renderedPixelCount,
out fact.renderedAverageLuminance,
out fact.renderedBrightPixelCount);
measuredRenderers[index].enabled = false;
@ -1123,6 +1156,32 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
}
}
private static void MeasureDifference(
IReadOnlyList<Color> actual,
IReadOnlyList<Color> baseline,
out int changedPixelCount,
out float averageLuminance,
out int brightPixelCount)
{
changedPixelCount = 0;
brightPixelCount = 0;
double total = 0;
var count = Math.Min(actual.Count, baseline.Count);
for (var index = 0; index < count; index++)
{
var delta = new Color(
Mathf.Abs(actual[index].r - baseline[index].r),
Mathf.Abs(actual[index].g - baseline[index].g),
Mathf.Abs(actual[index].b - baseline[index].b));
var magnitude = delta.r + delta.g + delta.b;
if (magnitude > 0.08f) changedPixelCount++;
var luminance = delta.r * 0.2126f + delta.g * 0.7152f + delta.b * 0.0722f;
total += luminance;
if (luminance >= 0.2f) brightPixelCount++;
}
averageLuminance = count == 0 ? 0f : (float)(total / count);
}
private static int CountChangedPixels(Texture2D texture, Color background)
{
var changed = 0;
@ -1136,6 +1195,59 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
return changed;
}
private static void WriteFieldLayerCaptures(GameObject root, EveUnityPlayableWorldProjection world, string capturePath)
{
var renderer = root.GetComponent<EveFieldsSplatLayerRenderer>();
if (renderer == null || world == null || string.IsNullOrWhiteSpace(capturePath)) return;
var directory = Path.GetDirectoryName(Path.GetFullPath(capturePath));
foreach (var field in world.FieldVolumes)
{
if (!field.Props.TryGetValue("layerBindings", out var bindings)) continue;
foreach (var pair in (bindings ?? "").Split(';'))
{
var separator = pair.IndexOf('=');
if (separator <= 0) continue;
var layerKey = pair.Substring(0, separator).Trim();
if (!renderer.TryGetTexture(layerKey, out var texture) || texture == null) continue;
var previous = RenderTexture.active;
RenderTexture.active = texture;
var copy = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false, true);
copy.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
copy.Apply();
RenderTexture.active = previous;
File.WriteAllBytes(Path.Combine(directory, $"field-{layerKey}.png"), copy.EncodeToPNG());
UnityEngine.Object.DestroyImmediate(copy);
RenderTexture.active = texture;
var floatCopy = new Texture2D(texture.width, texture.height, TextureFormat.RGBAFloat, false, true);
floatCopy.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
floatCopy.Apply();
RenderTexture.active = previous;
File.WriteAllBytes(Path.Combine(directory, $"field-{layerKey}.exr"), floatCopy.EncodeToEXR());
UnityEngine.Object.DestroyImmediate(floatCopy);
}
}
}
private static void WriteFieldCloudCapture(GameObject root, string capturePath)
{
var renderer = root.GetComponent<EveUnityFieldsVolumeRenderer>();
var field = typeof(EveUnityFieldsVolumeRenderer).GetField(
"_cloudTexture",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
var texture = field?.GetValue(renderer) as RenderTexture;
if (texture == null || string.IsNullOrWhiteSpace(capturePath)) return;
var previous = RenderTexture.active;
RenderTexture.active = texture;
var copy = new Texture2D(texture.width, texture.height, TextureFormat.RGBAFloat, false, true);
copy.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
copy.Apply();
RenderTexture.active = previous;
var directory = Path.GetDirectoryName(Path.GetFullPath(capturePath));
File.WriteAllBytes(Path.Combine(directory, "field-volume-cloud.exr"), copy.EncodeToEXR());
UnityEngine.Object.DestroyImmediate(copy);
}
private static EveUnitySceneProviderSurfaceDocument WorldDocument()
{
var entities = new[]

View file

@ -9,7 +9,7 @@
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13",
"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.2.0",
"org.gamecult.eve.surface": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.2",
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.33",
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.37",
"org.gamecult.eve.unity-uitoolkit": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-uitoolkit#eveunity-uitoolkit-v0.1.1"
},
"testables": [

View file

@ -144,7 +144,7 @@
"hash": "140e1bd963a0033e66777a3b2c5fe6e9c97dfe32"
},
"org.gamecult.eve.unity-scene": {
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.33",
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.37",
"depth": 0,
"source": "git",
"dependencies": {
@ -154,7 +154,7 @@
"com.unity.mathematics": "1.3.2",
"com.unity.modules.particlesystem": "1.0.0"
},
"hash": "852458dade1ae535d2ff3cfc9f8fe430e341ce2a"
"hash": "5ce654800760203154132d4b0fd1475294283ba6"
},
"org.gamecult.eve.unity-uitoolkit": {
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-uitoolkit#eveunity-uitoolkit-v0.1.1",

View file

@ -461,6 +461,31 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
Assert.That(finalPickupEntityCount, Is.EqualTo(initialPickupEntityCount - 1),
"Collected pickup remained in the provider-authored entity generation.");
targetFact = host.PresentedEntities.CurrentGeneration.Entities
.Single(entity => entity.EntityId == targetEntityId);
playerFact = host.PresentedEntities.CurrentGeneration.Entities
.Single(entity => entity.EntityId == playerId);
aim = targetFact.Position - playerFact.Position;
aim.y = 0;
Assert.That(aim.sqrMagnitude, Is.GreaterThan(0.0001f));
aim.Normalize();
lookVersion = runtime.ActiveVersion;
look = runtime.SubmitLookDirectionIntent(playerId, aim.x, 0f, aim.z);
lookDeadline = Time.realtimeSinceStartup + 12f;
while (Time.realtimeSinceStartup < lookDeadline &&
(runtime.LastReceipt == null || runtime.LastReceipt.CommandId != look.CommandId ||
!string.Equals(runtime.LastReceipt.State, "reconciled", StringComparison.OrdinalIgnoreCase) ||
runtime.ActiveVersion < runtime.LastReceipt.SourceVersion ||
Vector3.Dot(FindMarker(root, playerId).transform.forward, aim) < 0.99f))
{
yield return new WaitForSecondsRealtime(0.1f);
runtime.Refresh();
}
AssertReconciledProviderReceipt(runtime.LastReceipt, look.CommandId,
provider.Selection.ProviderId, provider.Selection.SurfaceId, lookVersion);
Assert.That(Vector3.Dot(FindMarker(root, playerId).transform.forward, aim), Is.GreaterThan(0.99f));
lookReceipt = WitnessReceipt.From("look", runtime.LastReceipt);
var focusVersion = runtime.ActiveVersion;
var inputDriver = root.GetComponent<EveUnityPlayableWorldInputDriver>() ??
root.AddComponent<EveUnityPlayableWorldInputDriver>();
@ -605,6 +630,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(capturePath)));
File.WriteAllBytes(capturePath, pixels.EncodeToPNG());
Assert.That(new FileInfo(capturePath).Length, Is.GreaterThan(1024));
WriteFieldLayerCaptures(root, host.Runtime.ActiveWorld, capturePath);
WriteFieldCloudCapture(root, capturePath);
MeasureRendererOutputs(
camera,
target,
@ -1098,6 +1125,11 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
renderer.enabled = false;
camera.clearFlags = CameraClearFlags.SolidColor;
camera.backgroundColor = Color.black;
camera.Render();
RenderTexture.active = target;
pixels.ReadPixels(new Rect(0, 0, target.width, target.height), 0, 0);
pixels.Apply();
var baseline = pixels.GetPixels();
for (var index = 0; index < measuredRenderers.Count; index++)
{
var fact = facts[index];
@ -1106,9 +1138,10 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
RenderTexture.active = target;
pixels.ReadPixels(new Rect(0, 0, target.width, target.height), 0, 0);
pixels.Apply();
fact.renderedPixelCount = CountChangedPixels(pixels, Color.black);
MeasureLuminance(
pixels,
MeasureDifference(
pixels.GetPixels(),
baseline,
out fact.renderedPixelCount,
out fact.renderedAverageLuminance,
out fact.renderedBrightPixelCount);
measuredRenderers[index].enabled = false;
@ -1123,6 +1156,32 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
}
}
private static void MeasureDifference(
IReadOnlyList<Color> actual,
IReadOnlyList<Color> baseline,
out int changedPixelCount,
out float averageLuminance,
out int brightPixelCount)
{
changedPixelCount = 0;
brightPixelCount = 0;
double total = 0;
var count = Math.Min(actual.Count, baseline.Count);
for (var index = 0; index < count; index++)
{
var delta = new Color(
Mathf.Abs(actual[index].r - baseline[index].r),
Mathf.Abs(actual[index].g - baseline[index].g),
Mathf.Abs(actual[index].b - baseline[index].b));
var magnitude = delta.r + delta.g + delta.b;
if (magnitude > 0.08f) changedPixelCount++;
var luminance = delta.r * 0.2126f + delta.g * 0.7152f + delta.b * 0.0722f;
total += luminance;
if (luminance >= 0.2f) brightPixelCount++;
}
averageLuminance = count == 0 ? 0f : (float)(total / count);
}
private static int CountChangedPixels(Texture2D texture, Color background)
{
var changed = 0;
@ -1136,6 +1195,59 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
return changed;
}
private static void WriteFieldLayerCaptures(GameObject root, EveUnityPlayableWorldProjection world, string capturePath)
{
var renderer = root.GetComponent<EveFieldsSplatLayerRenderer>();
if (renderer == null || world == null || string.IsNullOrWhiteSpace(capturePath)) return;
var directory = Path.GetDirectoryName(Path.GetFullPath(capturePath));
foreach (var field in world.FieldVolumes)
{
if (!field.Props.TryGetValue("layerBindings", out var bindings)) continue;
foreach (var pair in (bindings ?? "").Split(';'))
{
var separator = pair.IndexOf('=');
if (separator <= 0) continue;
var layerKey = pair.Substring(0, separator).Trim();
if (!renderer.TryGetTexture(layerKey, out var texture) || texture == null) continue;
var previous = RenderTexture.active;
RenderTexture.active = texture;
var copy = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false, true);
copy.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
copy.Apply();
RenderTexture.active = previous;
File.WriteAllBytes(Path.Combine(directory, $"field-{layerKey}.png"), copy.EncodeToPNG());
UnityEngine.Object.DestroyImmediate(copy);
RenderTexture.active = texture;
var floatCopy = new Texture2D(texture.width, texture.height, TextureFormat.RGBAFloat, false, true);
floatCopy.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
floatCopy.Apply();
RenderTexture.active = previous;
File.WriteAllBytes(Path.Combine(directory, $"field-{layerKey}.exr"), floatCopy.EncodeToEXR());
UnityEngine.Object.DestroyImmediate(floatCopy);
}
}
}
private static void WriteFieldCloudCapture(GameObject root, string capturePath)
{
var renderer = root.GetComponent<EveUnityFieldsVolumeRenderer>();
var field = typeof(EveUnityFieldsVolumeRenderer).GetField(
"_cloudTexture",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
var texture = field?.GetValue(renderer) as RenderTexture;
if (texture == null || string.IsNullOrWhiteSpace(capturePath)) return;
var previous = RenderTexture.active;
RenderTexture.active = texture;
var copy = new Texture2D(texture.width, texture.height, TextureFormat.RGBAFloat, false, true);
copy.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
copy.Apply();
RenderTexture.active = previous;
var directory = Path.GetDirectoryName(Path.GetFullPath(capturePath));
File.WriteAllBytes(Path.Combine(directory, "field-volume-cloud.exr"), copy.EncodeToEXR());
UnityEngine.Object.DestroyImmediate(copy);
}
private static EveUnitySceneProviderSurfaceDocument WorldDocument()
{
var entities = new[]

View file

@ -33,7 +33,9 @@
"version": "file:../../../EvePlugins/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields",
"depth": 0,
"source": "local",
"dependencies": {}
"dependencies": {
"org.gamecult.cultlib": "1.0.13"
}
},
"org.gamecult.eve.surface": {
"version": "file:../../packages/org.gamecult.eve.surface",
@ -49,7 +51,7 @@
"source": "local",
"dependencies": {
"org.gamecult.cultlib": "1.0.13",
"org.gamecult.eve.plugin-fields": "0.1.1",
"org.gamecult.eve.plugin-fields": "0.2.0",
"org.gamecult.eve.surface": "0.2.2",
"com.unity.mathematics": "1.3.2",
"com.unity.modules.particlesystem": "1.0.0"

View file

@ -4,9 +4,12 @@
The warm-cache released-package witness passes with:
- `org.gamecult.eve.unity-scene` `0.3.32`, commit
`817912a041ac1911e1e27a4b88617754d90ad4b7`;
- `org.gamecult.eve.surface` `0.2.2`, from the same commit;
- `org.gamecult.eve.unity-scene` `0.3.37`, commit
`5ce654800760203154132d4b0fd1475294283ba6`;
- `org.gamecult.eve.plugin-fields` `0.2.0`, commit
`382a23d8f8a07e4b5eef5f81f84655861a858367`;
- `org.gamecult.eve.surface` `0.2.2`, commit
`140e1bd963a0033e66777a3b2c5fe6e9c97dfe32`;
- `org.gamecult.eve.unity-uitoolkit` `0.1.1`, commit
`4d0cbe0185bdc4fc65eb63503a7c5cb578539669`;
- `org.gamecult.cultlib` `1.0.13`, commit
@ -14,7 +17,7 @@ The warm-cache released-package witness passes with:
- the generic `ReleaseConsumerProject` client connected directly to the
Aetheria daemon.
Evidence is in `artifacts/aetheria-daemon-native-0326-warm`. The PlayMode test
Evidence is in `artifacts/aetheria-daemon-gravity-fog-warm`. The PlayMode test
passed and recorded provider-owned reconciled movement, look, targeting,
tractor press, tractor release, contact-gated cargo collection, and action
receipts. The daemon-owned look direction reached the SoA body rotation,
@ -37,6 +40,14 @@ with `display: none` in the pilot presentation. The runnable generic-client
launcher mounts the same advertised document and forwards its typed commands;
it contains no Aetheria gameplay or client-authored world light.
The same surface publishes a `field.volume3d` node over four canonical Eve
Fields splat layers. Its surface contract contains logical ports such as
`surfaceHeight`, `patch`, and `tint`; it contains no Unity `_Nebula*` property
names or pass indices. The selected `unity-scene` provider asset variant owns
that concrete shader ABI through `unity.volume.*` metadata. The released
generic lowerer resolved the provider shader and dither texture, rasterized all
four layers, and composited `22` pilot-camera frames from daemon frame `220`.
The two PNGs below are deliberate camera-channel captures, not a composited
screen capture, so they prove world/map isolation rather than HUD pixels. The
native cockpit proof is the asserted UI Toolkit visual tree recorded as
@ -46,11 +57,11 @@ daemon lock progress `1.0`; Unity does not manufacture or smooth that value.
Camera-channel facts:
- provider-authored player renderers: `13`, including the lowered tractor effect;
- pilot changed pixels: `230,302`;
- pilot average luminance: `0.002843`;
- pilot bright pixels: `1,040`;
- pilot changed pixels: `230,323`;
- pilot average luminance: `0.0532403`;
- pilot bright pixels: `954`;
- map-channel renderers: `11`;
- map changed pixels: `3,921`;
- map changed pixels: `4,115`;
- native cockpit progress bars: `7`;
- daemon tractor power at capture: `1.0` after the held input completed its
authored ramp;
@ -66,12 +77,12 @@ Camera-channel facts:
- the map camera renders exactly the advertised map layer.
Visual inspection confirms that map glyphs are absent from the pilot frame and
present in the map-only frame. Restoring the authored ARPG camera in place of
the copied TestScene tuning increased hull-renderer pixel coverage by roughly
four times and bright pilot pixels from `502` to `1,319`. The pilot presentation
remains dark. Renderer-isolation facts prove that the hull draws under the
provider-owned light, so the next native-art work is available pre-generated
provider textures, not a client-side lighting fallback.
present in the map-only frame. The pilot frame also shows the provider-owned
gravity-shaped fog basin rather than a client-authored background effect. Its
current dark, broad shape is transport/lowering proof, not visual-parity proof;
restoring the fossil's cloud structure, scale, tint range, and scene readability
remains provider art work. EveUnity must not compensate with Aetheria-specific
lighting or fog rules.
Substance is not part of this path; later texture baking belongs in Blender.
Aetheria currently bundles ambientCG's 1K `Metal012` color, normal, and
metalness maps under CC0. The same pre-generated maps now replace dead
@ -112,8 +123,8 @@ Primary artifacts:
## Cold delivery is not currently proven
The current `46,131,569` byte Unity bundle (SHA-256
`a4b26fb234ae7d82eda26fb342d7f77a236e3bc1107420175eb1c626785db212`)
The current `46,413,003` byte Unity bundle (SHA-256
`229a7833120d9b4fe7e4270f13adc8ce8e553246a99efcbf20bb50d3ca18494d`)
times out from an empty cache. Its bytes are
still transported through batched snapshot records rather than the intended
mapped/network body transport. Increasing the Unity timeout would hide the

View file

@ -17,6 +17,7 @@ drivers, asset-provider hooks, package release, runtime tests, and captures.
- `gamecult.eve.provider_advertisement.v1`
- `gamecult.eve.surface.v1`
- provider asset-manifest documents
- runtime-selected asset-variant metadata, including native rendering-program bindings
- provider command receipts
- semantic render-channel inclusion and exclusion policy
- Unity input and local presentation assets
@ -31,15 +32,18 @@ drivers, asset-provider hooks, package release, runtime tests, and captures.
## Derived State
`ActiveWorld`, scene objects, transforms, markers, camera pose, native
render-channel layer mappings, asset caches, presentation counters, and receipt
display state are projections. They are not world truth.
render-channel layer mappings, resolved native shader ports/passes, asset caches,
presentation counters, and receipt display state are projections. They are not
world truth.
## Forbidden Writers
Unity transforms, input drivers, camera rigs, scene sinks, asset caches, and
pending receipts may not mutate or simulate provider world state. Plugin
projection shells may not implement Sai, Norn, or TeX semantics. Portable
surfaces may not carry Unity layer numbers or camera culling masks.
surfaces may not carry Unity layer numbers, camera culling masks, shader property
names, shader keywords, or native pass indices. Those bindings belong to the
selected runtime asset variant.
## Shared Paths

View file

@ -13,7 +13,8 @@ param(
)
$ErrorActionPreference = "Stop"
$expectedEveUnityCommit = "817912a041ac1911e1e27a4b88617754d90ad4b7"
$expectedEveUnityCommit = "5ce654800760203154132d4b0fd1475294283ba6"
$expectedEveFieldsCommit = "382a23d8f8a07e4b5eef5f81f84655861a858367"
$expectedEveUnityUiToolkitCommit = "4d0cbe0185bdc4fc65eb63503a7c5cb578539669"
$expectedCultLibCommit = "feb5c71513e71d681699f462fe3682b3168c6f73"
$repoRoot = Split-Path -Parent $PSScriptRoot
@ -118,8 +119,27 @@ if (-not $SkipAssetBundleBuild) {
}
}
$daemonBuildLogPath = Join-Path $outputRoot "aetheria-daemon-build.log"
$daemonBuildErrorLogPath = Join-Path $outputRoot "aetheria-daemon-build.error.log"
$daemonBuildArguments = @(
"build", $daemonProject,
"-p:CultLibRoot=$CultLibRoot", "-p:EveUnityRoot=$EveUnityRoot", "-p:YmirRoot=$YmirRoot"
)
$previousErrorActionPreference = $ErrorActionPreference
try {
$ErrorActionPreference = "Continue"
& dotnet @daemonBuildArguments 1> $daemonBuildLogPath 2> $daemonBuildErrorLogPath
$daemonBuildExitCode = $LASTEXITCODE
}
finally {
$ErrorActionPreference = $previousErrorActionPreference
}
if ($daemonBuildExitCode -ne 0) {
throw "Aetheria daemon prebuild failed with exit code $daemonBuildExitCode. See $daemonBuildErrorLogPath"
}
$daemonArguments = @(
"run", "--project", $daemonProject,
"run", "--project", $daemonProject, "--no-build",
"-p:CultLibRoot=$CultLibRoot", "-p:EveUnityRoot=$EveUnityRoot", "-p:YmirRoot=$YmirRoot",
"--",
"--root", $AetheriaRoot,
@ -204,17 +224,19 @@ try {
$releaseLock = Get-Content -LiteralPath (Join-Path $repoRoot "ReleaseConsumerProject\Packages\packages-lock.json") -Raw | ConvertFrom-Json
$releasedPackageClient = $projectRoot -eq "ReleaseConsumerProject"
$sceneLock = $releaseLock.dependencies.'org.gamecult.eve.unity-scene'
$fieldsLock = $releaseLock.dependencies.'org.gamecult.eve.plugin-fields'
$uiToolkitLock = $releaseLock.dependencies.'org.gamecult.eve.unity-uitoolkit'
$cultLibLock = $releaseLock.dependencies.'org.gamecult.cultlib'
if (-not $releasedPackageClient) { throw "Released witness must run ReleaseConsumerProject, got '$projectRoot'." }
if ($sceneLock.source -ne "git" -or $uiToolkitLock.source -ne "git" -or $cultLibLock.source -ne "git" -or
$sceneLock.version -like "file:*" -or $uiToolkitLock.version -like "file:*" -or $cultLibLock.version -like "file:*") {
if ($sceneLock.source -ne "git" -or $fieldsLock.source -ne "git" -or $uiToolkitLock.source -ne "git" -or $cultLibLock.source -ne "git" -or
$sceneLock.version -like "file:*" -or $fieldsLock.version -like "file:*" -or $uiToolkitLock.version -like "file:*" -or $cultLibLock.version -like "file:*") {
throw "Released witness resolved a non-git/local package dependency."
}
if ($sceneLock.hash -ne $expectedEveUnityCommit -or
$fieldsLock.hash -ne $expectedEveFieldsCommit -or
$uiToolkitLock.hash -ne $expectedEveUnityUiToolkitCommit -or
$cultLibLock.hash -ne $expectedCultLibCommit) {
throw "Released package commits do not match the witnessed releases. scene=$($sceneLock.hash) uitoolkit=$($uiToolkitLock.hash) cultlib=$($cultLibLock.hash)"
throw "Released package commits do not match the witnessed releases. scene=$($sceneLock.hash) fields=$($fieldsLock.hash) uitoolkit=$($uiToolkitLock.hash) cultlib=$($cultLibLock.hash)"
}
$finalBodies = @(Get-ChildItem -LiteralPath $assetCachePath -Filter *.body -File -Recurse -ErrorAction SilentlyContinue)
$finalPartials = @(Get-ChildItem -LiteralPath $assetCachePath -Filter *.partial -File -Recurse -ErrorAction SilentlyContinue)
@ -234,6 +256,7 @@ try {
$facts | Add-Member -NotePropertyName releasedPackageClient -NotePropertyValue $releasedPackageClient
$facts | Add-Member -NotePropertyName clientProject -NotePropertyValue $projectRoot
$facts | Add-Member -NotePropertyName eveUnityPackageCommit -NotePropertyValue $sceneLock.hash
$facts | Add-Member -NotePropertyName eveFieldsPackageCommit -NotePropertyValue $fieldsLock.hash
$facts | Add-Member -NotePropertyName eveUnityUiToolkitPackageCommit -NotePropertyValue $uiToolkitLock.hash
$facts | Add-Member -NotePropertyName cultLibPackageCommit -NotePropertyValue $cultLibLock.hash
$facts | Add-Member -NotePropertyName contentDelivery -NotePropertyValue ([ordered]@{