Record released tractor beam witness

This commit is contained in:
Meta Vens 2026-07-15 11:04:11 +01:00
commit f6fb8a5b17
6 changed files with 144 additions and 19 deletions

View file

@ -191,6 +191,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
WitnessReceipt movementReceipt = null;
WitnessReceipt lookReceipt = null;
WitnessReceipt focusReceipt = null;
WitnessReceipt tractorReceipt = null;
WitnessReceipt actionReceipt = null;
EveUnityShotReceipt observedShot = null;
EveUnityCombatPresentation observedCombat = null;
@ -200,6 +201,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
float movementDistance = 0f;
float aimDotDistance = 0f;
int cockpitProgressCount = 0;
float tractorBeamPower = 0f;
int tractorBeamParticleSystemCount = 0;
try
{
@ -245,7 +248,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
var cockpit = loweredSurface.Q<VisualElement>("aetheria.daemon.game.cockpit");
Assert.That(cockpit, Is.Not.Null, "The provider did not publish a generic cockpit overlay.");
cockpitProgressCount = cockpit.Query<ProgressBar>().ToList().Count;
Assert.That(cockpitProgressCount, Is.GreaterThanOrEqualTo(6));
Assert.That(cockpitProgressCount, Is.GreaterThanOrEqualTo(7));
Assert.That(loweredSurface.Q<VisualElement>("aetheria.daemon.game.frame").style.display.value,
Is.EqualTo(DisplayStyle.None), "Daemon diagnostics leaked into the pilot UI.");
host.ShotAvailable += shot => observedShot = shot;
@ -376,6 +379,44 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
var aimRenderer = root.GetComponent<EveUnityAimPresentationRenderer>();
Assert.That(aimRenderer, Is.Not.Null);
var beamPresentation = EveUnityBeamPresentation.FindAll(runtime.ActiveProjection).SingleOrDefault();
Assert.That(beamPresentation, Is.Not.Null,
"The provider did not advertise its continuous beam presentation.");
Assert.That(beamPresentation.ActivationActionId, Is.Not.Empty,
"The beam presentation does not name an advertised generic action.");
var tractorVersion = runtime.ActiveVersion;
var tractor = host.SubmitAdvertisedActionIntent(playerId, beamPresentation.ActivationActionId);
var tractorDeadline = Time.realtimeSinceStartup + 12f;
while (Time.realtimeSinceStartup < tractorDeadline &&
(runtime.LastReceipt == null || runtime.LastReceipt.CommandId != tractor.CommandId ||
!string.Equals(runtime.LastReceipt.State, "reconciled", StringComparison.OrdinalIgnoreCase) ||
runtime.ActiveVersion < runtime.LastReceipt.SourceVersion ||
EveUnityBeamPresentation.FindAll(runtime.ActiveProjection).Single().Power <=
beamPresentation.ActivationThreshold))
{
yield return new WaitForSecondsRealtime(0.1f);
runtime.Refresh();
}
AssertReconciledProviderReceipt(runtime.LastReceipt, tractor.CommandId,
provider.Selection.ProviderId, provider.Selection.SurfaceId, tractorVersion);
tractorReceipt = WitnessReceipt.From("beam", runtime.LastReceipt);
Assert.That(beamPresentation.SourceEntityId, Is.EqualTo(playerId),
"The daemon beam source does not identify the presented player entity.");
Assert.That(host.PresentedEntities.TryGetByEntityId(beamPresentation.SourceEntityId, out _), Is.True,
"The generic beam lowerer cannot resolve the advertised source entity.");
Assert.That(provider.ResolvePrefab(new EveUnityPlayableWorldAssetBinding(
beamPresentation.AssetRole, beamPresentation.AssetRole, "provider-asset-ref")), Is.Not.Null,
$"The provider asset catalog did not resolve beam role '{beamPresentation.AssetRole}'.");
var beamRenderer = root.GetComponent<EveUnityBeamPresentationRenderer>();
Assert.That(beamRenderer, Is.Not.Null);
beamRenderer.RefreshNow();
Assert.That(beamRenderer.ActiveBeamCount, Is.EqualTo(1));
Assert.That(beamRenderer.TryGetPower(beamPresentation.Id, out tractorBeamPower), Is.True);
Assert.That(tractorBeamPower, Is.GreaterThan(beamPresentation.ActivationThreshold));
tractorBeamParticleSystemCount = beamRenderer.ActiveParticleSystemCount;
Assert.That(tractorBeamParticleSystemCount, Is.GreaterThan(0),
"The generic beam lowerer did not instantiate the provider-owned effect prefab.");
var focusVersion = runtime.ActiveVersion;
var inputDriver = root.GetComponent<EveUnityPlayableWorldInputDriver>() ??
root.AddComponent<EveUnityPlayableWorldInputDriver>();
@ -573,6 +614,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
movementReceipt,
lookReceipt,
focusReceipt,
tractorReceipt,
actionReceipt,
observedShot,
shieldRatioBefore,
@ -588,6 +630,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
pilotAverageLuminance,
pilotBrightPixelCount,
cockpitProgressCount,
tractorBeamPower,
tractorBeamParticleSystemCount,
playerRendererFacts);
}
finally
@ -620,6 +664,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
WitnessReceipt movement,
WitnessReceipt look,
WitnessReceipt targeting,
WitnessReceipt tractor,
WitnessReceipt action,
EveUnityShotReceipt shot,
float shieldRatioBefore,
@ -635,6 +680,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
float pilotAverageLuminance,
int pilotBrightPixelCount,
int cockpitProgressCount,
float tractorBeamPower,
int tractorBeamParticleSystemCount,
RendererFact[] playerRendererFacts)
{
var path = Environment.GetEnvironmentVariable("EVEUNITY_WITNESS_FACTS_PATH");
@ -647,6 +694,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
movement = movement != null,
aimPresentation = look != null && aimDotDistance >= 49.9f,
targeting = targeting != null,
beamPresentation = tractor != null && tractorBeamPower > 0.01f && tractorBeamParticleSystemCount > 0,
action = action != null,
combatPresentation = shot != null,
shotId = shot?.ShotId ?? "",
@ -672,12 +720,14 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
pilotAverageLuminance = pilotAverageLuminance,
pilotBrightPixelCount = pilotBrightPixelCount,
cockpitProgressCount = cockpitProgressCount,
tractorBeamPower = tractorBeamPower,
tractorBeamParticleSystemCount = tractorBeamParticleSystemCount,
playerRenderers = playerRendererFacts,
mapChannelRendererCount = mapChannelRendererCount,
mapChangedPixels = mapChangedPixels,
pilotCameraExcludesMapChannel = pilotCameraExcludesMapChannel,
mapCameraIncludesMapChannel = mapCameraIncludesMapChannel,
receipts = new[] { movement, look, targeting, action }
receipts = new[] { movement, look, targeting, tractor, action }
};
Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path)));
File.WriteAllText(path, JsonUtility.ToJson(document, true));
@ -692,6 +742,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
public bool movement;
public bool aimPresentation;
public bool targeting;
public bool beamPresentation;
public bool action;
public bool combatPresentation;
public string shotId;
@ -717,6 +768,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
public float pilotAverageLuminance;
public int pilotBrightPixelCount;
public int cockpitProgressCount;
public float tractorBeamPower;
public int tractorBeamParticleSystemCount;
public RendererFact[] playerRenderers;
public int mapChannelRendererCount;
public int mapChangedPixels;

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.1.1",
"org.gamecult.eve.surface": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.2.1",
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.27",
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.30",
"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

@ -142,16 +142,17 @@
"hash": "d0aa50d31f3b6da96bffc194fdc3aa358f37e332"
},
"org.gamecult.eve.unity-scene": {
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.27",
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.30",
"depth": 0,
"source": "git",
"dependencies": {
"org.gamecult.cultlib": "1.0.13",
"org.gamecult.eve.plugin-fields": "0.1.1",
"org.gamecult.eve.surface": "0.2.1",
"com.unity.mathematics": "1.3.2"
"com.unity.mathematics": "1.3.2",
"com.unity.modules.particlesystem": "1.0.0"
},
"hash": "63a41712c5a68ce835bc1820980fc4786c34eb7b"
"hash": "f979cd425a9f8f951736c56051e8368b6d6ac2f3"
},
"org.gamecult.eve.unity-uitoolkit": {
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-uitoolkit#eveunity-uitoolkit-v0.1.1",
@ -192,6 +193,12 @@
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.particlesystem": {
"version": "1.0.0",
"depth": 1,
"source": "builtin",
"dependencies": {}
},
"com.unity.modules.physics": {
"version": "1.0.0",
"depth": 0,

View file

@ -191,6 +191,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
WitnessReceipt movementReceipt = null;
WitnessReceipt lookReceipt = null;
WitnessReceipt focusReceipt = null;
WitnessReceipt tractorReceipt = null;
WitnessReceipt actionReceipt = null;
EveUnityShotReceipt observedShot = null;
EveUnityCombatPresentation observedCombat = null;
@ -200,6 +201,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
float movementDistance = 0f;
float aimDotDistance = 0f;
int cockpitProgressCount = 0;
float tractorBeamPower = 0f;
int tractorBeamParticleSystemCount = 0;
try
{
@ -245,7 +248,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
var cockpit = loweredSurface.Q<VisualElement>("aetheria.daemon.game.cockpit");
Assert.That(cockpit, Is.Not.Null, "The provider did not publish a generic cockpit overlay.");
cockpitProgressCount = cockpit.Query<ProgressBar>().ToList().Count;
Assert.That(cockpitProgressCount, Is.GreaterThanOrEqualTo(6));
Assert.That(cockpitProgressCount, Is.GreaterThanOrEqualTo(7));
Assert.That(loweredSurface.Q<VisualElement>("aetheria.daemon.game.frame").style.display.value,
Is.EqualTo(DisplayStyle.None), "Daemon diagnostics leaked into the pilot UI.");
host.ShotAvailable += shot => observedShot = shot;
@ -376,6 +379,44 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
var aimRenderer = root.GetComponent<EveUnityAimPresentationRenderer>();
Assert.That(aimRenderer, Is.Not.Null);
var beamPresentation = EveUnityBeamPresentation.FindAll(runtime.ActiveProjection).SingleOrDefault();
Assert.That(beamPresentation, Is.Not.Null,
"The provider did not advertise its continuous beam presentation.");
Assert.That(beamPresentation.ActivationActionId, Is.Not.Empty,
"The beam presentation does not name an advertised generic action.");
var tractorVersion = runtime.ActiveVersion;
var tractor = host.SubmitAdvertisedActionIntent(playerId, beamPresentation.ActivationActionId);
var tractorDeadline = Time.realtimeSinceStartup + 12f;
while (Time.realtimeSinceStartup < tractorDeadline &&
(runtime.LastReceipt == null || runtime.LastReceipt.CommandId != tractor.CommandId ||
!string.Equals(runtime.LastReceipt.State, "reconciled", StringComparison.OrdinalIgnoreCase) ||
runtime.ActiveVersion < runtime.LastReceipt.SourceVersion ||
EveUnityBeamPresentation.FindAll(runtime.ActiveProjection).Single().Power <=
beamPresentation.ActivationThreshold))
{
yield return new WaitForSecondsRealtime(0.1f);
runtime.Refresh();
}
AssertReconciledProviderReceipt(runtime.LastReceipt, tractor.CommandId,
provider.Selection.ProviderId, provider.Selection.SurfaceId, tractorVersion);
tractorReceipt = WitnessReceipt.From("beam", runtime.LastReceipt);
Assert.That(beamPresentation.SourceEntityId, Is.EqualTo(playerId),
"The daemon beam source does not identify the presented player entity.");
Assert.That(host.PresentedEntities.TryGetByEntityId(beamPresentation.SourceEntityId, out _), Is.True,
"The generic beam lowerer cannot resolve the advertised source entity.");
Assert.That(provider.ResolvePrefab(new EveUnityPlayableWorldAssetBinding(
beamPresentation.AssetRole, beamPresentation.AssetRole, "provider-asset-ref")), Is.Not.Null,
$"The provider asset catalog did not resolve beam role '{beamPresentation.AssetRole}'.");
var beamRenderer = root.GetComponent<EveUnityBeamPresentationRenderer>();
Assert.That(beamRenderer, Is.Not.Null);
beamRenderer.RefreshNow();
Assert.That(beamRenderer.ActiveBeamCount, Is.EqualTo(1));
Assert.That(beamRenderer.TryGetPower(beamPresentation.Id, out tractorBeamPower), Is.True);
Assert.That(tractorBeamPower, Is.GreaterThan(beamPresentation.ActivationThreshold));
tractorBeamParticleSystemCount = beamRenderer.ActiveParticleSystemCount;
Assert.That(tractorBeamParticleSystemCount, Is.GreaterThan(0),
"The generic beam lowerer did not instantiate the provider-owned effect prefab.");
var focusVersion = runtime.ActiveVersion;
var inputDriver = root.GetComponent<EveUnityPlayableWorldInputDriver>() ??
root.AddComponent<EveUnityPlayableWorldInputDriver>();
@ -573,6 +614,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
movementReceipt,
lookReceipt,
focusReceipt,
tractorReceipt,
actionReceipt,
observedShot,
shieldRatioBefore,
@ -588,6 +630,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
pilotAverageLuminance,
pilotBrightPixelCount,
cockpitProgressCount,
tractorBeamPower,
tractorBeamParticleSystemCount,
playerRendererFacts);
}
finally
@ -620,6 +664,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
WitnessReceipt movement,
WitnessReceipt look,
WitnessReceipt targeting,
WitnessReceipt tractor,
WitnessReceipt action,
EveUnityShotReceipt shot,
float shieldRatioBefore,
@ -635,6 +680,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
float pilotAverageLuminance,
int pilotBrightPixelCount,
int cockpitProgressCount,
float tractorBeamPower,
int tractorBeamParticleSystemCount,
RendererFact[] playerRendererFacts)
{
var path = Environment.GetEnvironmentVariable("EVEUNITY_WITNESS_FACTS_PATH");
@ -647,6 +694,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
movement = movement != null,
aimPresentation = look != null && aimDotDistance >= 49.9f,
targeting = targeting != null,
beamPresentation = tractor != null && tractorBeamPower > 0.01f && tractorBeamParticleSystemCount > 0,
action = action != null,
combatPresentation = shot != null,
shotId = shot?.ShotId ?? "",
@ -672,12 +720,14 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
pilotAverageLuminance = pilotAverageLuminance,
pilotBrightPixelCount = pilotBrightPixelCount,
cockpitProgressCount = cockpitProgressCount,
tractorBeamPower = tractorBeamPower,
tractorBeamParticleSystemCount = tractorBeamParticleSystemCount,
playerRenderers = playerRendererFacts,
mapChannelRendererCount = mapChannelRendererCount,
mapChangedPixels = mapChangedPixels,
pilotCameraExcludesMapChannel = pilotCameraExcludesMapChannel,
mapCameraIncludesMapChannel = mapCameraIncludesMapChannel,
receipts = new[] { movement, look, targeting, action }
receipts = new[] { movement, look, targeting, tractor, action }
};
Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path)));
File.WriteAllText(path, JsonUtility.ToJson(document, true));
@ -692,6 +742,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
public bool movement;
public bool aimPresentation;
public bool targeting;
public bool beamPresentation;
public bool action;
public bool combatPresentation;
public string shotId;
@ -717,6 +768,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
public float pilotAverageLuminance;
public int pilotBrightPixelCount;
public int cockpitProgressCount;
public float tractorBeamPower;
public int tractorBeamParticleSystemCount;
public RendererFact[] playerRenderers;
public int mapChannelRendererCount;
public int mapChangedPixels;

View file

@ -4,8 +4,8 @@
The warm-cache released-package witness passes with:
- `org.gamecult.eve.unity-scene` `0.3.27`, commit
`63a41712c5a68ce835bc1820980fc4786c34eb7b`;
- `org.gamecult.eve.unity-scene` `0.3.30`, commit
`f979cd425a9f8f951736c56051e8368b6d6ac2f3`;
- `org.gamecult.eve.unity-uitoolkit` `0.1.1`, commit
`4d0cbe0185bdc4fc65eb63503a7c5cb578539669`;
- `org.gamecult.cultlib` `1.0.13`, commit
@ -14,8 +14,8 @@ The warm-cache released-package witness passes with:
Aetheria daemon.
Evidence is in `artifacts/aetheria-daemon-native-0326-warm`. The PlayMode test
passed and recorded provider-owned reconciled movement, look, targeting, and
action receipts. The daemon-owned look direction reached the SoA body rotation,
passed and recorded provider-owned reconciled movement, look, targeting,
tractor, and action receipts. The daemon-owned look direction reached the SoA body rotation,
and the generic aim presentation rendered at the advertised 50-unit minimum
convergence distance. The advertised skybox material and reflection cubemap
resolved from the provider bundle as their required native types and became the
@ -43,13 +43,15 @@ daemon lock progress `1.0`; Unity does not manufacture or smooth that value.
Camera-channel facts:
- provider-authored player renderers: `12`;
- pilot changed pixels: `230,189`;
- pilot average luminance: `0.003343`;
- pilot bright pixels: `1,227`;
- provider-authored player renderers: `14`, including the lowered tractor effect;
- pilot changed pixels: `230,255`;
- pilot average luminance: `0.004634`;
- pilot bright pixels: `1,542`;
- map-channel renderers: `11`;
- map changed pixels: `6,246`;
- map changed pixels: `8,510`;
- native cockpit progress bars: `7`;
- daemon tractor power at capture: `0.24`;
- provider tractor particle systems: `1`;
- the pilot camera excludes the advertised map layer;
- the player prefab's embedded layer-14 map icon contributes exactly `0` pilot
pixels;
@ -71,6 +73,14 @@ resolves textured native URP materials in `9` distinct player-material slots,
up from `3`, without adding another texture payload. This is temporary provider
art with recorded provenance, not a replacement texture pipeline.
The tractor proof is structural, not yet a native-look victory lap. The daemon
publishes `beam.presentation`, the generic client routes `pilot.scoop` through
the advertised `SetTractorPower` operation and payload, and the provider-owned
prefab is attached to the SoA-presented ship with nonzero daemon power. Its
particle renderer contributes only one measured pilot pixel in this capture.
Effect tuning remains provider art work; the runtime must not compensate with
an Aetheria-specific beam.
Primary artifacts:
- `results.xml`: one passing PlayMode witness;
@ -81,7 +91,9 @@ Primary artifacts:
## Cold delivery is not currently proven
The current 46.1 MB Unity bundle times out from an empty cache. Its bytes are
The current `46,133,487` byte Unity bundle (SHA-256
`ff07aa7f71aa2da0e8e6fe2f4ed68900931d6e67c153b586777467316d4fb80f`)
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
transport fault and is not an accepted fix.

View file

@ -13,7 +13,7 @@ param(
)
$ErrorActionPreference = "Stop"
$expectedEveUnityCommit = "63a41712c5a68ce835bc1820980fc4786c34eb7b"
$expectedEveUnityCommit = "f979cd425a9f8f951736c56051e8368b6d6ac2f3"
$expectedEveUnityUiToolkitCommit = "4d0cbe0185bdc4fc65eb63503a7c5cb578539669"
$expectedCultLibCommit = "feb5c71513e71d681699f462fe3682b3168c6f73"
$repoRoot = Split-Path -Parent $PSScriptRoot