Prove generic celestial world lowering
This commit is contained in:
parent
c5e73df1ff
commit
93a95b23df
4 changed files with 156 additions and 28 deletions
|
|
@ -225,6 +225,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
EveUnityAimPresentationRenderer aimRenderer = null;
|
||||
EveUnityBeamPresentation beamPresentation = null;
|
||||
EveUnityBeamPresentationRenderer beamRenderer = null;
|
||||
EveUnityShotTrajectoryRenderer trajectories = null;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -279,7 +280,13 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
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;
|
||||
trajectories = root.GetComponent<EveUnityShotTrajectoryRenderer>();
|
||||
Assert.That(trajectories, Is.Not.Null);
|
||||
host.ShotAvailable += shot =>
|
||||
{
|
||||
observedShot = shot;
|
||||
maximumTrajectoryCount = Math.Max(maximumTrajectoryCount, trajectories.ActiveTrajectoryCount);
|
||||
};
|
||||
runtime = host.Runtime;
|
||||
Assert.That(runtime, Is.Not.Null);
|
||||
Assert.That(runtime.ActiveWorld.PlayerEntityId, Is.Not.Empty);
|
||||
|
|
@ -507,9 +514,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
Assert.That(runtime.ActiveVersion, Is.GreaterThanOrEqualTo(runtime.LastReceipt.SourceVersion));
|
||||
actionReceipt = WitnessReceipt.From("action", runtime.LastReceipt);
|
||||
|
||||
var trajectories = root.GetComponent<EveUnityShotTrajectoryRenderer>();
|
||||
var combatRenderer = root.GetComponent<EveUnityCombatPresentationRenderer>();
|
||||
Assert.That(trajectories, Is.Not.Null);
|
||||
Assert.That(combatRenderer, Is.Not.Null);
|
||||
var shotDeadline = Time.realtimeSinceStartup + 20f;
|
||||
while (Time.realtimeSinceStartup < shotDeadline &&
|
||||
|
|
@ -823,7 +828,10 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
Convert.ToSingle(fieldViewport.GetType().GetProperty("MaxX")?.GetValue(fieldViewport)),
|
||||
Convert.ToSingle(fieldViewport.GetType().GetProperty("MaxY")?.GetValue(fieldViewport)),
|
||||
Convert.ToInt32(fieldSplats.GetType().GetProperty("Count")?.GetValue(fieldSplats)),
|
||||
playerRendererFacts);
|
||||
playerRendererFacts,
|
||||
root.GetComponentsInChildren<EveUnityPlayableWorldEntityMarker>(includeInactive: true)
|
||||
.Select(marker => PresentedEntityFact.From(camera, marker))
|
||||
.ToArray());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -893,7 +901,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
float fieldViewportMaxX,
|
||||
float fieldViewportMaxY,
|
||||
int fieldSplatCount,
|
||||
RendererFact[] playerRendererFacts)
|
||||
RendererFact[] playerRendererFacts,
|
||||
PresentedEntityFact[] presentedEntityFacts)
|
||||
{
|
||||
var path = Environment.GetEnvironmentVariable("EVEUNITY_WITNESS_FACTS_PATH");
|
||||
if (string.IsNullOrWhiteSpace(path)) return;
|
||||
|
|
@ -961,6 +970,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
fieldViewportMaxY = fieldViewportMaxY,
|
||||
fieldSplatCount = fieldSplatCount,
|
||||
playerRenderers = playerRendererFacts,
|
||||
presentedEntities = presentedEntityFacts,
|
||||
mapChannelRendererCount = mapChannelRendererCount,
|
||||
mapChangedPixels = mapChangedPixels,
|
||||
pilotCameraExcludesMapChannel = pilotCameraExcludesMapChannel,
|
||||
|
|
@ -1034,6 +1044,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
public float fieldViewportMaxY;
|
||||
public int fieldSplatCount;
|
||||
public RendererFact[] playerRenderers;
|
||||
public PresentedEntityFact[] presentedEntities;
|
||||
public int mapChannelRendererCount;
|
||||
public int mapChangedPixels;
|
||||
public bool pilotCameraExcludesMapChannel;
|
||||
|
|
@ -1110,6 +1121,45 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private sealed class PresentedEntityFact
|
||||
{
|
||||
public string entityId;
|
||||
public string entityKind;
|
||||
public string label;
|
||||
public string assetRef;
|
||||
public string worldPosition;
|
||||
public string worldScale;
|
||||
public int rendererCount;
|
||||
public int enabledRendererCount;
|
||||
public bool intersectsPilotFrustum;
|
||||
public float viewportWidth;
|
||||
public float viewportHeight;
|
||||
|
||||
public static PresentedEntityFact From(Camera camera, EveUnityPlayableWorldEntityMarker marker)
|
||||
{
|
||||
var renderers = marker.GetComponentsInChildren<Renderer>(includeInactive: true);
|
||||
MeasureViewportCoverage(camera, renderers, out var width, out var height);
|
||||
var planes = GeometryUtility.CalculateFrustumPlanes(camera);
|
||||
return new PresentedEntityFact
|
||||
{
|
||||
entityId = marker.EntityId,
|
||||
entityKind = marker.EntityKind,
|
||||
label = marker.Label,
|
||||
assetRef = marker.AssetRef,
|
||||
worldPosition = FormatVector(marker.transform.position),
|
||||
worldScale = FormatVector(marker.transform.lossyScale),
|
||||
rendererCount = renderers.Length,
|
||||
enabledRendererCount = renderers.Count(renderer => renderer.enabled && renderer.gameObject.activeInHierarchy),
|
||||
intersectsPilotFrustum = renderers.Any(renderer =>
|
||||
renderer.enabled && renderer.gameObject.activeInHierarchy &&
|
||||
GeometryUtility.TestPlanesAABB(planes, renderer.bounds)),
|
||||
viewportWidth = width,
|
||||
viewportHeight = height
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private sealed class MaterialFact
|
||||
{
|
||||
|
|
|
|||
|
|
@ -225,6 +225,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
EveUnityAimPresentationRenderer aimRenderer = null;
|
||||
EveUnityBeamPresentation beamPresentation = null;
|
||||
EveUnityBeamPresentationRenderer beamRenderer = null;
|
||||
EveUnityShotTrajectoryRenderer trajectories = null;
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -279,7 +280,13 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
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;
|
||||
trajectories = root.GetComponent<EveUnityShotTrajectoryRenderer>();
|
||||
Assert.That(trajectories, Is.Not.Null);
|
||||
host.ShotAvailable += shot =>
|
||||
{
|
||||
observedShot = shot;
|
||||
maximumTrajectoryCount = Math.Max(maximumTrajectoryCount, trajectories.ActiveTrajectoryCount);
|
||||
};
|
||||
runtime = host.Runtime;
|
||||
Assert.That(runtime, Is.Not.Null);
|
||||
Assert.That(runtime.ActiveWorld.PlayerEntityId, Is.Not.Empty);
|
||||
|
|
@ -507,9 +514,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
Assert.That(runtime.ActiveVersion, Is.GreaterThanOrEqualTo(runtime.LastReceipt.SourceVersion));
|
||||
actionReceipt = WitnessReceipt.From("action", runtime.LastReceipt);
|
||||
|
||||
var trajectories = root.GetComponent<EveUnityShotTrajectoryRenderer>();
|
||||
var combatRenderer = root.GetComponent<EveUnityCombatPresentationRenderer>();
|
||||
Assert.That(trajectories, Is.Not.Null);
|
||||
Assert.That(combatRenderer, Is.Not.Null);
|
||||
var shotDeadline = Time.realtimeSinceStartup + 20f;
|
||||
while (Time.realtimeSinceStartup < shotDeadline &&
|
||||
|
|
@ -823,7 +828,10 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
Convert.ToSingle(fieldViewport.GetType().GetProperty("MaxX")?.GetValue(fieldViewport)),
|
||||
Convert.ToSingle(fieldViewport.GetType().GetProperty("MaxY")?.GetValue(fieldViewport)),
|
||||
Convert.ToInt32(fieldSplats.GetType().GetProperty("Count")?.GetValue(fieldSplats)),
|
||||
playerRendererFacts);
|
||||
playerRendererFacts,
|
||||
root.GetComponentsInChildren<EveUnityPlayableWorldEntityMarker>(includeInactive: true)
|
||||
.Select(marker => PresentedEntityFact.From(camera, marker))
|
||||
.ToArray());
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -893,7 +901,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
float fieldViewportMaxX,
|
||||
float fieldViewportMaxY,
|
||||
int fieldSplatCount,
|
||||
RendererFact[] playerRendererFacts)
|
||||
RendererFact[] playerRendererFacts,
|
||||
PresentedEntityFact[] presentedEntityFacts)
|
||||
{
|
||||
var path = Environment.GetEnvironmentVariable("EVEUNITY_WITNESS_FACTS_PATH");
|
||||
if (string.IsNullOrWhiteSpace(path)) return;
|
||||
|
|
@ -961,6 +970,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
fieldViewportMaxY = fieldViewportMaxY,
|
||||
fieldSplatCount = fieldSplatCount,
|
||||
playerRenderers = playerRendererFacts,
|
||||
presentedEntities = presentedEntityFacts,
|
||||
mapChannelRendererCount = mapChannelRendererCount,
|
||||
mapChangedPixels = mapChangedPixels,
|
||||
pilotCameraExcludesMapChannel = pilotCameraExcludesMapChannel,
|
||||
|
|
@ -1034,6 +1044,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
public float fieldViewportMaxY;
|
||||
public int fieldSplatCount;
|
||||
public RendererFact[] playerRenderers;
|
||||
public PresentedEntityFact[] presentedEntities;
|
||||
public int mapChannelRendererCount;
|
||||
public int mapChangedPixels;
|
||||
public bool pilotCameraExcludesMapChannel;
|
||||
|
|
@ -1110,6 +1121,45 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests
|
|||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private sealed class PresentedEntityFact
|
||||
{
|
||||
public string entityId;
|
||||
public string entityKind;
|
||||
public string label;
|
||||
public string assetRef;
|
||||
public string worldPosition;
|
||||
public string worldScale;
|
||||
public int rendererCount;
|
||||
public int enabledRendererCount;
|
||||
public bool intersectsPilotFrustum;
|
||||
public float viewportWidth;
|
||||
public float viewportHeight;
|
||||
|
||||
public static PresentedEntityFact From(Camera camera, EveUnityPlayableWorldEntityMarker marker)
|
||||
{
|
||||
var renderers = marker.GetComponentsInChildren<Renderer>(includeInactive: true);
|
||||
MeasureViewportCoverage(camera, renderers, out var width, out var height);
|
||||
var planes = GeometryUtility.CalculateFrustumPlanes(camera);
|
||||
return new PresentedEntityFact
|
||||
{
|
||||
entityId = marker.EntityId,
|
||||
entityKind = marker.EntityKind,
|
||||
label = marker.Label,
|
||||
assetRef = marker.AssetRef,
|
||||
worldPosition = FormatVector(marker.transform.position),
|
||||
worldScale = FormatVector(marker.transform.lossyScale),
|
||||
rendererCount = renderers.Length,
|
||||
enabledRendererCount = renderers.Count(renderer => renderer.enabled && renderer.gameObject.activeInHierarchy),
|
||||
intersectsPilotFrustum = renderers.Any(renderer =>
|
||||
renderer.enabled && renderer.gameObject.activeInHierarchy &&
|
||||
GeometryUtility.TestPlanesAABB(planes, renderer.bounds)),
|
||||
viewportWidth = width,
|
||||
viewportHeight = height
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
private sealed class MaterialFact
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
The released-package witness passes in separate cold-lowering and warm-gameplay
|
||||
profiles with:
|
||||
|
||||
- `org.gamecult.eve.unity-scene` `0.3.50`, commit
|
||||
`7c8442e12264806a53a9e0e08b7b090dcddb8c90`;
|
||||
- `org.gamecult.eve.unity-scene` `0.3.51`, commit
|
||||
`21ac39e7bdfca9d81a0b7d89834f7e9da60aaad6`;
|
||||
- `org.gamecult.eve.plugin-fields` `0.2.3`, commit
|
||||
`c5a4a75c1b727499b16c2dae1895f29e2a9f72f0`;
|
||||
- `org.gamecult.eve.surface` `0.2.2`, commit
|
||||
|
|
@ -18,8 +18,9 @@ profiles with:
|
|||
- the generic `ReleaseConsumerProject` client connected directly to the
|
||||
Aetheria daemon.
|
||||
|
||||
Evidence is in `artifacts/aetheria-daemon-cultlib-1014-cold-final` and
|
||||
`artifacts/aetheria-daemon-cultlib-1014-warm-final`. The warm PlayMode test
|
||||
Current celestial-package evidence is in
|
||||
`artifacts/aetheria-daemon-celestial-cold`; the retained cold and warm witness
|
||||
documents distinguish transfer from gameplay. The warm 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,
|
||||
|
|
@ -32,7 +33,7 @@ direction, color, and intensity; the generic camera rig lowers that contract to
|
|||
the only live directional light (`0.75` intensity).
|
||||
Aetheria also advertises the original undocked `ARPG.unity` Third Person Rig:
|
||||
entity-forward perspective follow, `30` unit distance, `60` degree vertical
|
||||
field of view, target screen position `0.64,0.81`, zero position damping, and
|
||||
field of view, canonical bottom-origin target screen position `0.64,0.19`, zero position damping, and
|
||||
`1`-`4096` clip planes. Its generic `aim.convergence-point.v1` relation makes
|
||||
the optical axis reach the daemon-published aim point while preserving that
|
||||
entity framing. The generic camera rig lowers both constraints without
|
||||
|
|
@ -66,11 +67,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: `196,179`;
|
||||
- pilot average luminance: `0.0993295`;
|
||||
- pilot bright pixels: `1,348`;
|
||||
- pilot changed pixels: `225,548`;
|
||||
- pilot average luminance: `0.119513`;
|
||||
- pilot bright pixels: `97,617`;
|
||||
- map-channel renderers: `10`;
|
||||
- map changed pixels: `4,627`;
|
||||
- map changed pixels: `4,723`;
|
||||
- native cockpit progress bars: `7`;
|
||||
- daemon tractor power at capture: `1.0` after the held input completed its
|
||||
authored ramp;
|
||||
|
|
@ -86,11 +87,22 @@ Camera-channel facts:
|
|||
pixels;
|
||||
- the map camera renders exactly the advertised map layer.
|
||||
|
||||
The daemon also publishes the current zone's celestial presentation through the
|
||||
same generic entity SoA generation as ordinary world entities. The current warm
|
||||
witness records eleven sun/planet/gas-giant rows and eighteen asteroid rows.
|
||||
Every row resolved a provider asset with enabled native renderers, and seven
|
||||
celestial instances intersected the pilot frustum. These identities are
|
||||
presentation-only and cannot receive gameplay commands. EveUnity contains no
|
||||
Aetheria or celestial branch; release `0.3.51` fixes the generic prefab wrapper
|
||||
so semantic instance scale composes with, rather than overwrites, provider-local
|
||||
scale.
|
||||
|
||||
Visual inspection confirms that map glyphs are absent from the pilot frame and
|
||||
present in the map-only frame. This is transport, authority, field-production,
|
||||
and lowering proof, not visual parity: the current pilot capture is nearly black
|
||||
with sparse clipped geometry instead of the fossil's bright blue gravity-shaped
|
||||
fog sea. Release `0.3.50` includes generic lowering for Eve Fields `0.2.3`'s
|
||||
and lowering proof, not visual parity: the current pilot capture contains the
|
||||
blue fog field and provider geometry, but nearby ships remain too dark and the
|
||||
celestial composition lacks the fossil capture's readable close body. Release
|
||||
`0.3.51` includes generic lowering for Eve Fields `0.2.3`'s
|
||||
`AnimatedRadialCosine` source alongside `PowerPulse`, dither-scale,
|
||||
temporal-history, and finite-look-at semantics. Aetheria publishes the fossil
|
||||
global animated simplex/cellular/ambient producer stack, body-owned radial wave
|
||||
|
|
@ -146,13 +158,14 @@ Primary artifacts:
|
|||
## Cold delivery proof
|
||||
|
||||
The `cold-start-lowering` profile starts with zero bodies and zero partials. It
|
||||
receives the `46,412,384` byte Unity bundle through the managed
|
||||
receives the `55,529,775` byte Unity bundle through the managed
|
||||
`cultmesh.content.v1` session, verifies SHA-256
|
||||
`f5960f240ecfd56de417e8e51fde34cfb962fc6fcf0840cc373190e7dbc6048f`,
|
||||
`5cb34be9b29f533ddfea89a439f43170c3691538b2dba9578d1f96ff91cc0b34`,
|
||||
atomically promotes one `.body`, and leaves zero partials under the unchanged
|
||||
300-second deadline. The full witness took `84.991` seconds; the Unity test took
|
||||
`43.212` seconds. It then lowered provider assets, movement, environment, four
|
||||
field layers across `127` composites, and both camera channels. The pilot camera
|
||||
300-second deadline. Including a clean provider-bundle build, the full witness
|
||||
took `263.477` seconds; the Unity test took `48.083` seconds. It then lowered
|
||||
provider assets, movement, environment, four field layers across `125`
|
||||
composites, and both camera channels. The pilot camera
|
||||
excluded map objects and the map camera included them.
|
||||
|
||||
Cold asset acquisition and transient gameplay are deliberately separate proof
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ param(
|
|||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$expectedEveUnityCommit = "7c8442e12264806a53a9e0e08b7b090dcddb8c90"
|
||||
$expectedEveUnityCommit = "21ac39e7bdfca9d81a0b7d89834f7e9da60aaad6"
|
||||
$expectedEveFieldsCommit = "c5a4a75c1b727499b16c2dae1895f29e2a9f72f0"
|
||||
$expectedEveUnityUiToolkitCommit = "4d0cbe0185bdc4fc65eb63503a7c5cb578539669"
|
||||
$expectedCultLibCommit = "4b7162022a8976f7941b5a7a69acf50f1b6d532b"
|
||||
|
|
@ -246,6 +246,21 @@ try {
|
|||
[long]$facts.fieldVolumeCompositeCount -le 0) {
|
||||
throw "Live witness did not prove provider assets, movement, Fields lowering, and camera-channel separation."
|
||||
}
|
||||
$presentedCelestials = @($facts.presentedEntities | Where-Object { $_.entityKind -like "celestial.*" })
|
||||
$presentedBodies = @($presentedCelestials | Where-Object {
|
||||
$_.entityKind -in @("celestial.sun", "celestial.planet", "celestial.gas-giant")
|
||||
})
|
||||
$presentedAsteroids = @($presentedCelestials | Where-Object { $_.entityKind -eq "celestial.asteroid" })
|
||||
$invalidCelestials = @($presentedCelestials | Where-Object {
|
||||
[string]::IsNullOrWhiteSpace($_.assetRef) -or
|
||||
[int]$_.rendererCount -le 0 -or
|
||||
[int]$_.enabledRendererCount -le 0
|
||||
})
|
||||
if ($presentedBodies.Count -le 0 -or $presentedAsteroids.Count -le 0 -or
|
||||
$invalidCelestials.Count -ne 0 -or
|
||||
@($presentedCelestials | Where-Object { $_.intersectsPilotFrustum }).Count -le 0) {
|
||||
throw "Live witness did not prove provider-owned celestial bodies and asteroids reached the generic scene and intersected the pilot frustum. bodies=$($presentedBodies.Count) asteroids=$($presentedAsteroids.Count) invalid=$($invalidCelestials.Count)"
|
||||
}
|
||||
if ($witnessProfile -eq "full-session-gameplay" -and
|
||||
(-not $facts.combatPresentation -or [string]::IsNullOrWhiteSpace($facts.shotId) -or
|
||||
[double]$facts.lockProgress -le 0.99 -or -not $facts.pickupCollection -or
|
||||
|
|
|
|||
Reference in a new issue