diff --git a/ReleaseConsumerProject/Assets/Tests/PlayMode/GenericWorldCaptureTests.cs b/ReleaseConsumerProject/Assets/Tests/PlayMode/GenericWorldCaptureTests.cs index 4615ea8..e609d55 100644 --- a/ReleaseConsumerProject/Assets/Tests/PlayMode/GenericWorldCaptureTests.cs +++ b/ReleaseConsumerProject/Assets/Tests/PlayMode/GenericWorldCaptureTests.cs @@ -210,6 +210,21 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests int pickupCollectionEventCount = 0; int initialPickupEntityCount = 0; int finalPickupEntityCount = -1; + bool destructionPickupObserved = false; + int maximumTrajectoryCount = 0; + bool hitMarkerObserved = false; + var witnessProfile = Environment.GetEnvironmentVariable("EVEUNITY_WITNESS_PROFILE") ?? + "full-session-gameplay"; + Assert.That(witnessProfile, + Is.EqualTo("cold-start-lowering").Or.EqualTo("full-session-gameplay"), + "The witness profile must name an explicit proof boundary."); + var requireSessionGameplay = string.Equals( + witnessProfile, + "full-session-gameplay", + StringComparison.Ordinal); + EveUnityAimPresentationRenderer aimRenderer = null; + EveUnityBeamPresentation beamPresentation = null; + EveUnityBeamPresentationRenderer beamRenderer = null; try { @@ -280,8 +295,9 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests Assert.That(host.PresentedEntities.CurrentGeneration.Entities.Count, Is.GreaterThan(0)); initialPickupEntityCount = host.PresentedEntities.CurrentGeneration.Entities.Count(entity => string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); - Assert.That(initialPickupEntityCount, Is.GreaterThan(0), - "The daemon fixture did not publish its physical starter pickup through the entity SoA."); + if (requireSessionGameplay) + Assert.That(initialPickupEntityCount, Is.Zero, + "The witness scenario must obtain salvage from daemon-owned destruction, not a boot-seeded pickup."); runtime.FeedbackAvailable += feedback => { if (!string.Equals(feedback.Kind, "pickup.collected", StringComparison.Ordinal)) return; @@ -343,6 +359,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests AssertReconciledProviderReceipt(runtime.LastReceipt, release.CommandId, provider.Selection.ProviderId, provider.Selection.SurfaceId, releaseVersion); + if (requireSessionGameplay) + { var movementVersion = runtime.ActiveVersion; var focus = runtime.SubmitFocusIntent(playerId); var focusDeadline = Time.realtimeSinceStartup + 12f; @@ -399,10 +417,10 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests 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 aimRenderer = root.GetComponent(); + aimRenderer = root.GetComponent(); Assert.That(aimRenderer, Is.Not.Null); - var beamPresentation = EveUnityBeamPresentation.FindAll(runtime.ActiveProjection).SingleOrDefault(); + 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, @@ -429,7 +447,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests 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(); + beamRenderer = root.GetComponent(); Assert.That(beamRenderer, Is.Not.Null); beamRenderer.RefreshNow(); Assert.That(beamRenderer.ActiveBeamCount, Is.EqualTo(1)); @@ -439,28 +457,6 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests tractorBeamParticleSystemCount = beamRenderer.ActiveParticleSystemCount; Assert.That(tractorBeamParticleSystemCount, Is.GreaterThan(0), "The generic beam lowerer did not instantiate the provider-owned effect prefab."); - var pickupDeadline = Time.realtimeSinceStartup + 12f; - while (Time.realtimeSinceStartup < pickupDeadline && - (pickupCollection == null || - host.PresentedEntities.CurrentGeneration.Entities.Any(entity => - string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)))) - { - yield return new WaitForSecondsRealtime(0.1f); - runtime.Refresh(); - } - finalPickupEntityCount = host.PresentedEntities.CurrentGeneration.Entities.Count(entity => - string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); - Assert.That(pickupCollection, Is.Not.Null, - "The released client did not observe provider-owned feedback for Ymir contact collection."); - Assert.That(pickupCollectionEventCount, Is.EqualTo(1), - "One Ymir contact transaction must emit one client-visible collection event."); - Assert.That(pickupCollection.ItemKey, Is.EqualTo("scrap-metal")); - Assert.That(pickupCollection.ScalarValue, Is.EqualTo(1)); - Assert.That(pickupCollection.CargoQuantityBefore, Is.Zero); - Assert.That(pickupCollection.CargoQuantityAfter, Is.EqualTo(1)); - 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 @@ -511,22 +507,74 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests Assert.That(runtime.ActiveVersion, Is.GreaterThanOrEqualTo(runtime.LastReceipt.SourceVersion)); actionReceipt = WitnessReceipt.From("action", runtime.LastReceipt); - var shotDeadline = Time.realtimeSinceStartup + 15f; - while (Time.realtimeSinceStartup < shotDeadline && observedShot == null) - { - yield return new WaitForSecondsRealtime(0.05f); - runtime.Refresh(); - } - Assert.That(observedShot, Is.Not.Null, - "A reconciled fire request never reached daemon-owned lock acquisition and shot resolution."); - observedCombat = EveUnityCombatPresentation.Find(runtime.ActiveProjection); - Assert.That(observedShot.TargetEntityIndex, Is.EqualTo(targetEntityIndex)); - Assert.That(observedShot.LockQuality, Is.GreaterThanOrEqualTo(0.99)); var trajectories = root.GetComponent(); var combatRenderer = root.GetComponent(); Assert.That(trajectories, Is.Not.Null); - Assert.That(trajectories.ActiveTrajectoryCount, Is.GreaterThan(0)); Assert.That(combatRenderer, Is.Not.Null); + var shotDeadline = Time.realtimeSinceStartup + 20f; + while (Time.realtimeSinceStartup < shotDeadline && + (observedShot == null || + host.PresentedEntities.CurrentGeneration.Entities.Any(entity => + entity.EntityId == targetEntityId) || + (!destructionPickupObserved && pickupCollection == null))) + { + yield return new WaitForSecondsRealtime(0.05f); + runtime.Refresh(); + destructionPickupObserved |= host.PresentedEntities.CurrentGeneration.Entities.Any(entity => + string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); + maximumTrajectoryCount = Math.Max(maximumTrajectoryCount, trajectories.ActiveTrajectoryCount); + combatRenderer.RefreshNow(); + hitMarkerObserved |= combatRenderer.HitMarkerVisible; + } + Assert.That(observedShot, Is.Not.Null, + "A reconciled fire request never reached daemon-owned lock acquisition and shot resolution."); + Assert.That(host.PresentedEntities.CurrentGeneration.Entities.Any(entity => + entity.EntityId == targetEntityId), Is.False, + "The low-hull witness raider was not destroyed by daemon combat."); + Assert.That(destructionPickupObserved || pickupCollection != null, Is.True, + "Daemon destruction did not publish its guaranteed cargo as a pickup."); + var collectionDeadline = Time.realtimeSinceStartup + 15f; + var nextTractorAimAt = 0f; + while (Time.realtimeSinceStartup < collectionDeadline && pickupCollection == null) + { + yield return new WaitForSecondsRealtime(0.05f); + runtime.Refresh(); + maximumTrajectoryCount = Math.Max(maximumTrajectoryCount, trajectories.ActiveTrajectoryCount); + combatRenderer.RefreshNow(); + hitMarkerObserved |= combatRenderer.HitMarkerVisible; + var pickupFact = host.PresentedEntities.CurrentGeneration.Entities.FirstOrDefault(entity => + string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); + if (pickupFact == null || Time.realtimeSinceStartup < nextTractorAimAt) + continue; + playerFact = host.PresentedEntities.CurrentGeneration.Entities + .Single(entity => entity.EntityId == playerId); + var tractorAim = pickupFact.Position - playerFact.Position; + tractorAim.y = 0; + if (tractorAim.sqrMagnitude <= 0.0001f) + continue; + tractorAim.Normalize(); + runtime.SubmitLookDirectionIntent(playerId, tractorAim.x, 0f, tractorAim.z); + nextTractorAimAt = Time.realtimeSinceStartup + 0.25f; + } + finalPickupEntityCount = host.PresentedEntities.CurrentGeneration.Entities.Count(entity => + string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); + Assert.That(pickupCollection, Is.Not.Null, + "Destruction-created salvage never reached cargo through a Ymir contact fact."); + Assert.That(pickupCollectionEventCount, Is.EqualTo(1), + "One destruction-loot Ymir contact transaction must emit one collection event."); + Assert.That(pickupCollection.ItemKey, Is.Not.Empty, + "Destruction loot must retain its canonical typed item identity."); + Assert.That(pickupCollection.EventId, Does.StartWith("ymir-fact:"), + "Collection feedback must retain the consumed Ymir fact identity."); + Assert.That(pickupCollection.ScalarValue, Is.EqualTo(1)); + Assert.That(pickupCollection.CargoQuantityBefore, Is.Zero); + Assert.That(pickupCollection.CargoQuantityAfter, Is.EqualTo(1)); + Assert.That(finalPickupEntityCount, Is.Zero, + "Collected destruction loot remained in the provider-authored entity generation."); + observedCombat = EveUnityCombatPresentation.Find(runtime.ActiveProjection); + Assert.That(observedShot.TargetEntityIndex, Is.EqualTo(targetEntityIndex)); + Assert.That(observedShot.LockQuality, Is.GreaterThanOrEqualTo(0.99)); + Assert.That(maximumTrajectoryCount, Is.GreaterThan(0)); combatRenderer.RefreshNow(); if (observedCombat != null && !string.IsNullOrWhiteSpace(observedCombat.SelectedTargetEntityId)) { @@ -534,7 +582,16 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests Assert.That(combatRenderer.LockVisible, Is.True); } if (observedShot.Hit && (observedShot.AppliedDamage > 0 || observedShot.ShieldAbsorbedDamage > 0)) - Assert.That(combatRenderer.HitMarkerVisible, Is.True); + Assert.That(hitMarkerObserved, Is.True); + } + + aimRenderer ??= root.GetComponent(); + Assert.That(aimRenderer, Is.Not.Null); + beamPresentation ??= EveUnityBeamPresentation.FindAll(runtime.ActiveProjection).SingleOrDefault(); + Assert.That(beamPresentation, Is.Not.Null, + "The provider did not advertise its continuous beam presentation."); + beamRenderer ??= root.GetComponent(); + finalPickupEntityCount = Math.Max(0, finalPickupEntityCount); var camera = cameraObject.AddComponent(); camera.clearFlags = CameraClearFlags.SolidColor; @@ -715,6 +772,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests Assert.That(fieldViewport, Is.Not.Null); Assert.That(fieldSplats, Is.Not.Null); WriteWitnessFacts( + witnessProfile, initialVersion, runtime.ActiveVersion, movementDistance, @@ -739,7 +797,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests observedCombat?.ShieldRatio ?? shieldRatioBefore, hullRatioBefore, observedCombat?.HullRatio ?? hullRatioBefore, - (float)observedShot.LockQuality, + (float)(observedShot?.LockQuality ?? 0), aimDotDistance, playerViewportWidth, playerViewportHeight, @@ -754,6 +812,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests initialPickupEntityCount, finalPickupEntityCount, pickupCollectionEventCount, + destructionPickupObserved, pickupCollection, camera.transform.position, camera.transform.forward, @@ -783,6 +842,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests } private static void WriteWitnessFacts( + string witnessProfile, long initialVersion, long finalVersion, float movementDistance, @@ -822,6 +882,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests int initialPickupEntityCount, int finalPickupEntityCount, int pickupCollectionEventCount, + bool destructionPickupObserved, EveUnityFeedbackEvent pickupCollection, Vector3 cameraPosition, Vector3 cameraForward, @@ -838,6 +899,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests if (string.IsNullOrWhiteSpace(path)) return; var document = new WitnessFacts { + witnessProfile = witnessProfile, providerAdvertisement = true, providerAssets = true, environmentPresentation = environmentPresentation, @@ -879,9 +941,12 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests tractorBeamParticleSystemCount = tractorBeamParticleSystemCount, pickupCollection = pickupCollection != null && pickupCollectionEventCount == 1 && pickupCollection.CargoQuantityAfter - pickupCollection.CargoQuantityBefore == pickupCollection.ScalarValue, + destructionLoot = destructionPickupObserved && pickupCollection != null && + pickupCollection.EventId.StartsWith("ymir-fact:", StringComparison.Ordinal), initialPickupEntityCount = initialPickupEntityCount, finalPickupEntityCount = finalPickupEntityCount, pickupCollectionEventCount = pickupCollectionEventCount, + pickupEventId = pickupCollection?.EventId ?? "", pickupItemKey = pickupCollection?.ItemKey ?? "", pickupQuantity = (float)(pickupCollection?.ScalarValue ?? 0), cargoQuantityBeforePickup = (float)(pickupCollection?.CargoQuantityBefore ?? 0), @@ -909,6 +974,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests [Serializable] private sealed class WitnessFacts { + public string witnessProfile; public bool providerAdvertisement; public bool providerAssets; public bool environmentPresentation; @@ -949,9 +1015,11 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests public float tractorReleasedPower; public int tractorBeamParticleSystemCount; public bool pickupCollection; + public bool destructionLoot; public int initialPickupEntityCount; public int finalPickupEntityCount; public int pickupCollectionEventCount; + public string pickupEventId; public string pickupItemKey; public float pickupQuantity; public float cargoQuantityBeforePickup; diff --git a/ReleaseConsumerProject/Packages/manifest.json b/ReleaseConsumerProject/Packages/manifest.json index 01675bc..57a76fa 100644 --- a/ReleaseConsumerProject/Packages/manifest.json +++ b/ReleaseConsumerProject/Packages/manifest.json @@ -6,10 +6,10 @@ "com.unity.modules.physics": "1.0.0", "com.unity.modules.uielements": "1.0.0", "com.unity.render-pipelines.universal": "17.4.0", - "org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13", + "org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14", "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.3", "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.49", + "org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.50", "org.gamecult.eve.unity-uitoolkit": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-uitoolkit#eveunity-uitoolkit-v0.1.1" }, "testables": [ diff --git a/ReleaseConsumerProject/Packages/packages-lock.json b/ReleaseConsumerProject/Packages/packages-lock.json index cc2cc9d..af58e02 100644 --- a/ReleaseConsumerProject/Packages/packages-lock.json +++ b/ReleaseConsumerProject/Packages/packages-lock.json @@ -119,11 +119,11 @@ } }, "org.gamecult.cultlib": { - "version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.13", + "version": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-v1.0.14", "depth": 0, "source": "git", "dependencies": {}, - "hash": "feb5c71513e71d681699f462fe3682b3168c6f73" + "hash": "4b7162022a8976f7941b5a7a69acf50f1b6d532b" }, "org.gamecult.eve.plugin-fields": { "version": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.2.3", @@ -144,18 +144,18 @@ "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.49", + "version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.3.50", "depth": 0, "source": "git", "dependencies": { - "org.gamecult.cultlib": "1.0.13", + "org.gamecult.cultlib": "1.0.14", "org.gamecult.eve.plugin-fields": "0.2.3", "org.gamecult.eve.surface": "0.2.2", "com.unity.mathematics": "1.3.2", "com.unity.render-pipelines.universal": "17.4.0", "com.unity.modules.particlesystem": "1.0.0" }, - "hash": "e6ba1a36f6f0bce8df2c9834c25a8a980f03413c" + "hash": "7c8442e12264806a53a9e0e08b7b090dcddb8c90" }, "org.gamecult.eve.unity-uitoolkit": { "version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-uitoolkit#eveunity-uitoolkit-v0.1.1", diff --git a/TestProject/Assets/Tests/PlayMode/GenericWorldCaptureTests.cs b/TestProject/Assets/Tests/PlayMode/GenericWorldCaptureTests.cs index 4615ea8..e609d55 100644 --- a/TestProject/Assets/Tests/PlayMode/GenericWorldCaptureTests.cs +++ b/TestProject/Assets/Tests/PlayMode/GenericWorldCaptureTests.cs @@ -210,6 +210,21 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests int pickupCollectionEventCount = 0; int initialPickupEntityCount = 0; int finalPickupEntityCount = -1; + bool destructionPickupObserved = false; + int maximumTrajectoryCount = 0; + bool hitMarkerObserved = false; + var witnessProfile = Environment.GetEnvironmentVariable("EVEUNITY_WITNESS_PROFILE") ?? + "full-session-gameplay"; + Assert.That(witnessProfile, + Is.EqualTo("cold-start-lowering").Or.EqualTo("full-session-gameplay"), + "The witness profile must name an explicit proof boundary."); + var requireSessionGameplay = string.Equals( + witnessProfile, + "full-session-gameplay", + StringComparison.Ordinal); + EveUnityAimPresentationRenderer aimRenderer = null; + EveUnityBeamPresentation beamPresentation = null; + EveUnityBeamPresentationRenderer beamRenderer = null; try { @@ -280,8 +295,9 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests Assert.That(host.PresentedEntities.CurrentGeneration.Entities.Count, Is.GreaterThan(0)); initialPickupEntityCount = host.PresentedEntities.CurrentGeneration.Entities.Count(entity => string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); - Assert.That(initialPickupEntityCount, Is.GreaterThan(0), - "The daemon fixture did not publish its physical starter pickup through the entity SoA."); + if (requireSessionGameplay) + Assert.That(initialPickupEntityCount, Is.Zero, + "The witness scenario must obtain salvage from daemon-owned destruction, not a boot-seeded pickup."); runtime.FeedbackAvailable += feedback => { if (!string.Equals(feedback.Kind, "pickup.collected", StringComparison.Ordinal)) return; @@ -343,6 +359,8 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests AssertReconciledProviderReceipt(runtime.LastReceipt, release.CommandId, provider.Selection.ProviderId, provider.Selection.SurfaceId, releaseVersion); + if (requireSessionGameplay) + { var movementVersion = runtime.ActiveVersion; var focus = runtime.SubmitFocusIntent(playerId); var focusDeadline = Time.realtimeSinceStartup + 12f; @@ -399,10 +417,10 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests 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 aimRenderer = root.GetComponent(); + aimRenderer = root.GetComponent(); Assert.That(aimRenderer, Is.Not.Null); - var beamPresentation = EveUnityBeamPresentation.FindAll(runtime.ActiveProjection).SingleOrDefault(); + 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, @@ -429,7 +447,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests 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(); + beamRenderer = root.GetComponent(); Assert.That(beamRenderer, Is.Not.Null); beamRenderer.RefreshNow(); Assert.That(beamRenderer.ActiveBeamCount, Is.EqualTo(1)); @@ -439,28 +457,6 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests tractorBeamParticleSystemCount = beamRenderer.ActiveParticleSystemCount; Assert.That(tractorBeamParticleSystemCount, Is.GreaterThan(0), "The generic beam lowerer did not instantiate the provider-owned effect prefab."); - var pickupDeadline = Time.realtimeSinceStartup + 12f; - while (Time.realtimeSinceStartup < pickupDeadline && - (pickupCollection == null || - host.PresentedEntities.CurrentGeneration.Entities.Any(entity => - string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)))) - { - yield return new WaitForSecondsRealtime(0.1f); - runtime.Refresh(); - } - finalPickupEntityCount = host.PresentedEntities.CurrentGeneration.Entities.Count(entity => - string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); - Assert.That(pickupCollection, Is.Not.Null, - "The released client did not observe provider-owned feedback for Ymir contact collection."); - Assert.That(pickupCollectionEventCount, Is.EqualTo(1), - "One Ymir contact transaction must emit one client-visible collection event."); - Assert.That(pickupCollection.ItemKey, Is.EqualTo("scrap-metal")); - Assert.That(pickupCollection.ScalarValue, Is.EqualTo(1)); - Assert.That(pickupCollection.CargoQuantityBefore, Is.Zero); - Assert.That(pickupCollection.CargoQuantityAfter, Is.EqualTo(1)); - 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 @@ -511,22 +507,74 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests Assert.That(runtime.ActiveVersion, Is.GreaterThanOrEqualTo(runtime.LastReceipt.SourceVersion)); actionReceipt = WitnessReceipt.From("action", runtime.LastReceipt); - var shotDeadline = Time.realtimeSinceStartup + 15f; - while (Time.realtimeSinceStartup < shotDeadline && observedShot == null) - { - yield return new WaitForSecondsRealtime(0.05f); - runtime.Refresh(); - } - Assert.That(observedShot, Is.Not.Null, - "A reconciled fire request never reached daemon-owned lock acquisition and shot resolution."); - observedCombat = EveUnityCombatPresentation.Find(runtime.ActiveProjection); - Assert.That(observedShot.TargetEntityIndex, Is.EqualTo(targetEntityIndex)); - Assert.That(observedShot.LockQuality, Is.GreaterThanOrEqualTo(0.99)); var trajectories = root.GetComponent(); var combatRenderer = root.GetComponent(); Assert.That(trajectories, Is.Not.Null); - Assert.That(trajectories.ActiveTrajectoryCount, Is.GreaterThan(0)); Assert.That(combatRenderer, Is.Not.Null); + var shotDeadline = Time.realtimeSinceStartup + 20f; + while (Time.realtimeSinceStartup < shotDeadline && + (observedShot == null || + host.PresentedEntities.CurrentGeneration.Entities.Any(entity => + entity.EntityId == targetEntityId) || + (!destructionPickupObserved && pickupCollection == null))) + { + yield return new WaitForSecondsRealtime(0.05f); + runtime.Refresh(); + destructionPickupObserved |= host.PresentedEntities.CurrentGeneration.Entities.Any(entity => + string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); + maximumTrajectoryCount = Math.Max(maximumTrajectoryCount, trajectories.ActiveTrajectoryCount); + combatRenderer.RefreshNow(); + hitMarkerObserved |= combatRenderer.HitMarkerVisible; + } + Assert.That(observedShot, Is.Not.Null, + "A reconciled fire request never reached daemon-owned lock acquisition and shot resolution."); + Assert.That(host.PresentedEntities.CurrentGeneration.Entities.Any(entity => + entity.EntityId == targetEntityId), Is.False, + "The low-hull witness raider was not destroyed by daemon combat."); + Assert.That(destructionPickupObserved || pickupCollection != null, Is.True, + "Daemon destruction did not publish its guaranteed cargo as a pickup."); + var collectionDeadline = Time.realtimeSinceStartup + 15f; + var nextTractorAimAt = 0f; + while (Time.realtimeSinceStartup < collectionDeadline && pickupCollection == null) + { + yield return new WaitForSecondsRealtime(0.05f); + runtime.Refresh(); + maximumTrajectoryCount = Math.Max(maximumTrajectoryCount, trajectories.ActiveTrajectoryCount); + combatRenderer.RefreshNow(); + hitMarkerObserved |= combatRenderer.HitMarkerVisible; + var pickupFact = host.PresentedEntities.CurrentGeneration.Entities.FirstOrDefault(entity => + string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); + if (pickupFact == null || Time.realtimeSinceStartup < nextTractorAimAt) + continue; + playerFact = host.PresentedEntities.CurrentGeneration.Entities + .Single(entity => entity.EntityId == playerId); + var tractorAim = pickupFact.Position - playerFact.Position; + tractorAim.y = 0; + if (tractorAim.sqrMagnitude <= 0.0001f) + continue; + tractorAim.Normalize(); + runtime.SubmitLookDirectionIntent(playerId, tractorAim.x, 0f, tractorAim.z); + nextTractorAimAt = Time.realtimeSinceStartup + 0.25f; + } + finalPickupEntityCount = host.PresentedEntities.CurrentGeneration.Entities.Count(entity => + string.Equals(entity.EntityKind, "pickup", StringComparison.Ordinal)); + Assert.That(pickupCollection, Is.Not.Null, + "Destruction-created salvage never reached cargo through a Ymir contact fact."); + Assert.That(pickupCollectionEventCount, Is.EqualTo(1), + "One destruction-loot Ymir contact transaction must emit one collection event."); + Assert.That(pickupCollection.ItemKey, Is.Not.Empty, + "Destruction loot must retain its canonical typed item identity."); + Assert.That(pickupCollection.EventId, Does.StartWith("ymir-fact:"), + "Collection feedback must retain the consumed Ymir fact identity."); + Assert.That(pickupCollection.ScalarValue, Is.EqualTo(1)); + Assert.That(pickupCollection.CargoQuantityBefore, Is.Zero); + Assert.That(pickupCollection.CargoQuantityAfter, Is.EqualTo(1)); + Assert.That(finalPickupEntityCount, Is.Zero, + "Collected destruction loot remained in the provider-authored entity generation."); + observedCombat = EveUnityCombatPresentation.Find(runtime.ActiveProjection); + Assert.That(observedShot.TargetEntityIndex, Is.EqualTo(targetEntityIndex)); + Assert.That(observedShot.LockQuality, Is.GreaterThanOrEqualTo(0.99)); + Assert.That(maximumTrajectoryCount, Is.GreaterThan(0)); combatRenderer.RefreshNow(); if (observedCombat != null && !string.IsNullOrWhiteSpace(observedCombat.SelectedTargetEntityId)) { @@ -534,7 +582,16 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests Assert.That(combatRenderer.LockVisible, Is.True); } if (observedShot.Hit && (observedShot.AppliedDamage > 0 || observedShot.ShieldAbsorbedDamage > 0)) - Assert.That(combatRenderer.HitMarkerVisible, Is.True); + Assert.That(hitMarkerObserved, Is.True); + } + + aimRenderer ??= root.GetComponent(); + Assert.That(aimRenderer, Is.Not.Null); + beamPresentation ??= EveUnityBeamPresentation.FindAll(runtime.ActiveProjection).SingleOrDefault(); + Assert.That(beamPresentation, Is.Not.Null, + "The provider did not advertise its continuous beam presentation."); + beamRenderer ??= root.GetComponent(); + finalPickupEntityCount = Math.Max(0, finalPickupEntityCount); var camera = cameraObject.AddComponent(); camera.clearFlags = CameraClearFlags.SolidColor; @@ -715,6 +772,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests Assert.That(fieldViewport, Is.Not.Null); Assert.That(fieldSplats, Is.Not.Null); WriteWitnessFacts( + witnessProfile, initialVersion, runtime.ActiveVersion, movementDistance, @@ -739,7 +797,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests observedCombat?.ShieldRatio ?? shieldRatioBefore, hullRatioBefore, observedCombat?.HullRatio ?? hullRatioBefore, - (float)observedShot.LockQuality, + (float)(observedShot?.LockQuality ?? 0), aimDotDistance, playerViewportWidth, playerViewportHeight, @@ -754,6 +812,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests initialPickupEntityCount, finalPickupEntityCount, pickupCollectionEventCount, + destructionPickupObserved, pickupCollection, camera.transform.position, camera.transform.forward, @@ -783,6 +842,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests } private static void WriteWitnessFacts( + string witnessProfile, long initialVersion, long finalVersion, float movementDistance, @@ -822,6 +882,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests int initialPickupEntityCount, int finalPickupEntityCount, int pickupCollectionEventCount, + bool destructionPickupObserved, EveUnityFeedbackEvent pickupCollection, Vector3 cameraPosition, Vector3 cameraForward, @@ -838,6 +899,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests if (string.IsNullOrWhiteSpace(path)) return; var document = new WitnessFacts { + witnessProfile = witnessProfile, providerAdvertisement = true, providerAssets = true, environmentPresentation = environmentPresentation, @@ -879,9 +941,12 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests tractorBeamParticleSystemCount = tractorBeamParticleSystemCount, pickupCollection = pickupCollection != null && pickupCollectionEventCount == 1 && pickupCollection.CargoQuantityAfter - pickupCollection.CargoQuantityBefore == pickupCollection.ScalarValue, + destructionLoot = destructionPickupObserved && pickupCollection != null && + pickupCollection.EventId.StartsWith("ymir-fact:", StringComparison.Ordinal), initialPickupEntityCount = initialPickupEntityCount, finalPickupEntityCount = finalPickupEntityCount, pickupCollectionEventCount = pickupCollectionEventCount, + pickupEventId = pickupCollection?.EventId ?? "", pickupItemKey = pickupCollection?.ItemKey ?? "", pickupQuantity = (float)(pickupCollection?.ScalarValue ?? 0), cargoQuantityBeforePickup = (float)(pickupCollection?.CargoQuantityBefore ?? 0), @@ -909,6 +974,7 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests [Serializable] private sealed class WitnessFacts { + public string witnessProfile; public bool providerAdvertisement; public bool providerAssets; public bool environmentPresentation; @@ -949,9 +1015,11 @@ namespace GameCult.EveUnity.GenericClient.PlayModeTests public float tractorReleasedPower; public int tractorBeamParticleSystemCount; public bool pickupCollection; + public bool destructionLoot; public int initialPickupEntityCount; public int finalPickupEntityCount; public int pickupCollectionEventCount; + public string pickupEventId; public string pickupItemKey; public float pickupQuantity; public float cargoQuantityBeforePickup; diff --git a/docs/aetheria-released-package-witness.md b/docs/aetheria-released-package-witness.md index b738502..99b21ab 100644 --- a/docs/aetheria-released-package-witness.md +++ b/docs/aetheria-released-package-witness.md @@ -2,22 +2,24 @@ ## Current result -The warm-cache released-package witness passes with: +The released-package witness passes in separate cold-lowering and warm-gameplay +profiles with: -- `org.gamecult.eve.unity-scene` `0.3.44`, commit - `03ce78031f28d7bfae4dcdc477a7273c6ecae55b`; +- `org.gamecult.eve.unity-scene` `0.3.50`, commit + `7c8442e12264806a53a9e0e08b7b090dcddb8c90`; - `org.gamecult.eve.plugin-fields` `0.2.3`, commit `c5a4a75c1b727499b16c2dae1895f29e2a9f72f0`; - `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 - `feb5c71513e71d681699f462fe3682b3168c6f73`; +- `org.gamecult.cultlib` `1.0.14`, commit + `4b7162022a8976f7941b5a7a69acf50f1b6d532b`; - the generic `ReleaseConsumerProject` client connected directly to the Aetheria daemon. -Evidence is in `artifacts/aetheria-daemon-fossil-fog-producers`. The PlayMode test +Evidence is in `artifacts/aetheria-daemon-cultlib-1014-cold-final` and +`artifacts/aetheria-daemon-cultlib-1014-warm-final`. 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, @@ -50,7 +52,7 @@ Fields splat layers. Its surface contract contains logical ports such as 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 `21` pilot-camera frames from daemon frame `223`. +four layers, and composited `91` pilot-camera frames through daemon frame `643`. The provider variant advertises the fossil shader's raymarch, temporal-history, and composite passes plus their logical ports. EveUnity allocates and resets the history targets generically; a partial temporal ABI fails closed. @@ -64,19 +66,20 @@ 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: `191,353`; -- pilot average luminance: `0.0283105`; -- pilot bright pixels: `705`; -- map-channel renderers: `11`; -- map changed pixels: `4,444`; +- pilot changed pixels: `196,179`; +- pilot average luminance: `0.0993295`; +- pilot bright pixels: `1,348`; +- map-channel renderers: `10`; +- map changed pixels: `4,627`; - native cockpit progress bars: `7`; - daemon tractor power at capture: `1.0` after the held input completed its authored ramp; - daemon tractor power after the advertised release: `0`; - provider tractor particle systems: `1`; -- pickup entities before/after collection: `1` / `0`; +- pickup entities before/after destruction and collection: `0` / `0`; - provider `pickup.collected` events: exactly `1`; -- collected item and quantity: `scrap-metal`, `1`; +- collected item and quantity: one canonical `aetheria.item_definition:*` key, + quantity `1`; - authoritative cargo quantity before/after: `0` / `1`; - the pilot camera excludes the advertised map layer; - the player prefab's embedded layer-14 map icon contributes exactly `0` pilot @@ -87,7 +90,7 @@ 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.44` adds generic lowering for Eve Fields `0.2.3`'s +fog sea. Release `0.3.50` 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 @@ -119,10 +122,12 @@ build removes the fossil's embedded tractor object from player/ship prefabs, so the standalone `beam.presentation` prefab is the only tractor renderer. Its cyan/yellow dotted band is visible in the pilot capture and absent from the map capture. -The same released run begins with one provider-owned pickup in the entity SoA. -Held tractor input produces a Ymir Begin contact fact; the daemon consumes that -fact once, removes the pickup once, changes cargo from `0` to `1`, and emits one -`pickup.collected` feedback event carrying the exact delta. Aetheria's Ymir body +The warm gameplay run begins with no pickup. A daemon-authoritative shot destroys +the deterministic salvage target and creates one provider-owned pickup carrying +a canonical generated cargo item. Held tractor input produces a Ymir Begin +contact fact; the daemon consumes that fact once, removes the pickup once, +changes cargo from `0` to `1`, and emits one `pickup.collected` feedback event +whose identity begins with `ymir-fact:`. Aetheria's Ymir body mapping excludes stations and non-ship world bodies from pickup collision facts, so ambient station contact cannot become a cargo writer. Capacity rejection and its `cargo-capacity` reason are covered by the daemon smoke, not claimed as a @@ -138,19 +143,23 @@ Primary artifacts: - `aetheria-daemon-world.png`: pilot-camera capture; - `aetheria-daemon-map.png`: map-only capture. -## Cold delivery is not currently proven +## Cold delivery proof -The current `46,412,252` byte Unity bundle (SHA-256 -`bc45d84b54666e813bfccca12496ba4a3533ed08896dfc57de726749574fa796`) -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. +The `cold-start-lowering` profile starts with zero bodies and zero partials. It +receives the `46,412,384` byte Unity bundle through the managed +`cultmesh.content.v1` session, verifies SHA-256 +`f5960f240ecfd56de417e8e51fde34cfb962fc6fcf0840cc373190e7dbc6048f`, +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 +excluded map objects and the map camera included them. -A cold witness may be claimed only when an empty cache receives the bundle over -the intended body transport, atomically promotes the hash-addressed `.body`, -leaves no `.partial` file, and completes the same released-client assertions. - -`artifacts/render-channel-witness-gravity-cold-4` records a historical 0.3.18 -cold run. It remains useful regression evidence, but it does not describe the -health of the current transport path. +Cold asset acquisition and transient gameplay are deliberately separate proof +profiles. Starting Unity before the provider means download time is not a +stable lifetime for a boot-seeded enemy or pickup. The cold profile proves +delivery and lowering; `full-session-gameplay` starts a fresh warm authoritative +session and proves combat, destruction-created loot, Ymir contact collection, +and exactly-once receipts. Neither profile claims negotiated mapped/zero-copy +CDN delivery: the released path is the managed network content session and +still copies/fragments bytes in process. diff --git a/scripts/run-aetheria-daemon-world-witness.ps1 b/scripts/run-aetheria-daemon-world-witness.ps1 index 20d049a..967fe85 100644 --- a/scripts/run-aetheria-daemon-world-witness.ps1 +++ b/scripts/run-aetheria-daemon-world-witness.ps1 @@ -13,10 +13,10 @@ param( ) $ErrorActionPreference = "Stop" -$expectedEveUnityCommit = "e6ba1a36f6f0bce8df2c9834c25a8a980f03413c" +$expectedEveUnityCommit = "7c8442e12264806a53a9e0e08b7b090dcddb8c90" $expectedEveFieldsCommit = "c5a4a75c1b727499b16c2dae1895f29e2a9f72f0" $expectedEveUnityUiToolkitCommit = "4d0cbe0185bdc4fc65eb63503a7c5cb578539669" -$expectedCultLibCommit = "feb5c71513e71d681699f462fe3682b3168c6f73" +$expectedCultLibCommit = "4b7162022a8976f7941b5a7a69acf50f1b6d532b" $repoRoot = Split-Path -Parent $PSScriptRoot $projectRoot = $ClientProject $outputRoot = if ([IO.Path]::IsPathRooted($OutputDirectory)) { $OutputDirectory } else { Join-Path $repoRoot $OutputDirectory } @@ -65,6 +65,11 @@ if ($CacheState -eq "warm" -and -not $cacheWasWarm) { throw "Warm witness requested without an existing verified bundle cache at $assetCachePath" } $observedCacheState = if ($cacheWasWarm) { "warm" } else { "cold" } +$witnessProfile = if ($observedCacheState -eq "cold") { + "cold-start-lowering" +} else { + "full-session-gameplay" +} $witnessStartedAt = [DateTimeOffset]::UtcNow foreach ($ephemeralPath in @( $replicaPath, @@ -161,7 +166,7 @@ $daemonArguments = @( "--client-cultmesh-host", "127.0.0.1", "--client-cultmesh-advertise-host", "127.0.0.1", "--client-cultmesh-port", $Port, - "--tick-interval-ms", 250, + "--tick-interval-ms", 20, "--fixed-delta-ms", 20, "--no-odin-announcements" ) @@ -177,6 +182,7 @@ $env:EVEUNITY_DISABLE_AUTO_LAUNCHER = "1" $env:EVEUNITY_ASSET_CACHE_PATH = $assetCachePath $env:EVEUNITY_WITNESS_FACTS_PATH = $factsPath $env:EVEUNITY_PROVIDER_READY_PATH = $providerReadyPath +$env:EVEUNITY_WITNESS_PROFILE = $witnessProfile $arguments = @( "-batchmode", "-projectPath", $projectRoot, "-runTests", "-testPlatform", "PlayMode", @@ -231,9 +237,20 @@ try { } } $facts = Get-Content -LiteralPath $factsPath -Raw | ConvertFrom-Json - if (-not $facts.combatPresentation -or [string]::IsNullOrWhiteSpace($facts.shotId) -or - [double]$facts.lockProgress -le 0.99) { - throw "Live witness did not observe daemon-owned selection, completed lock, and a resolved shot." + if ($facts.witnessProfile -ne $witnessProfile) { + throw "Live witness ran the wrong proof profile. expected=$witnessProfile actual=$($facts.witnessProfile)" + } + if (-not $facts.providerAssets -or -not $facts.environmentPresentation -or + -not $facts.movement -or -not $facts.pilotCameraExcludesMapChannel -or + -not $facts.mapCameraIncludesMapChannel -or [int]$facts.fieldVolumeLayerCount -le 0 -or + [long]$facts.fieldVolumeCompositeCount -le 0) { + throw "Live witness did not prove provider assets, movement, Fields lowering, and camera-channel separation." + } + 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 + -not $facts.destructionLoot -or [int]$facts.pickupCollectionEventCount -ne 1)) { + throw "Full-session witness did not prove combat and exactly-once destruction-loot Ymir contact collection." } $releaseLock = Get-Content -LiteralPath (Join-Path $repoRoot "ReleaseConsumerProject\Packages\packages-lock.json") -Raw | ConvertFrom-Json $releasedPackageClient = $projectRoot -eq "ReleaseConsumerProject" @@ -297,6 +314,7 @@ try { generatedAtUtc = [DateTimeOffset]::UtcNow.ToString("O") execution = [ordered]@{ cacheState = $observedCacheState + profile = $witnessProfile durationMs = $durationMs testDurationMs = $testDurationMs } @@ -335,7 +353,11 @@ try { sizeBytes = $resultsArtifact.Length } ) - authority = "released-generic-runtime-observes-provider-assets-authoritative-combat-receipts-and-camera-channel-separation" + authority = if ($witnessProfile -eq "full-session-gameplay") { + "released-generic-runtime-observes-provider-assets-authoritative-gameplay-receipts-ymir-contact-collection-and-camera-channel-separation" + } else { + "released-generic-runtime-cold-loads-provider-assets-lowers-playable-world-and-preserves-camera-channel-separation" + } } $witness | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $witnessPath -Encoding UTF8 $stateWitnessPath = Join-Path $outputRoot "runtime-witness.$observedCacheState.json" @@ -349,6 +371,6 @@ try { finally { if ($null -ne $unity -and -not $unity.HasExited) { Stop-Process -Id $unity.Id -Force -ErrorAction SilentlyContinue } if ($null -ne $daemon -and -not $daemon.HasExited) { Stop-Process -Id $daemon.Id -Force } - Remove-Item Env:EVEUNITY_RENDEZVOUS_ENDPOINT, Env:EVEUNITY_PROVIDER_ENDPOINT, Env:EVEUNITY_PROVIDER_ID, Env:EVEUNITY_SURFACE_ID, Env:EVEUNITY_REPLICA_PATH, Env:EVEUNITY_AETHERIA_CAPTURE_PATH, Env:EVEUNITY_AETHERIA_MAP_CAPTURE_PATH, Env:EVEUNITY_DISABLE_AUTO_LAUNCHER, Env:EVEUNITY_ASSET_CACHE_PATH, Env:EVEUNITY_WITNESS_FACTS_PATH, Env:EVEUNITY_PROVIDER_READY_PATH -ErrorAction SilentlyContinue + Remove-Item Env:EVEUNITY_RENDEZVOUS_ENDPOINT, Env:EVEUNITY_PROVIDER_ENDPOINT, Env:EVEUNITY_PROVIDER_ID, Env:EVEUNITY_SURFACE_ID, Env:EVEUNITY_REPLICA_PATH, Env:EVEUNITY_AETHERIA_CAPTURE_PATH, Env:EVEUNITY_AETHERIA_MAP_CAPTURE_PATH, Env:EVEUNITY_DISABLE_AUTO_LAUNCHER, Env:EVEUNITY_ASSET_CACHE_PATH, Env:EVEUNITY_WITNESS_FACTS_PATH, Env:EVEUNITY_PROVIDER_READY_PATH, Env:EVEUNITY_WITNESS_PROFILE -ErrorAction SilentlyContinue Remove-Item Env:AETHERIA_TRACE_EVE_SNAPSHOTS -ErrorAction SilentlyContinue } diff --git a/scripts/run-interactive-aetheria.ps1 b/scripts/run-interactive-aetheria.ps1 index 3dae7e9..c02e208 100644 --- a/scripts/run-interactive-aetheria.ps1 +++ b/scripts/run-interactive-aetheria.ps1 @@ -85,7 +85,7 @@ $daemon = Start-Process dotnet -ArgumentList @( "--client-cultmesh-host", "127.0.0.1", "--client-cultmesh-advertise-host", "127.0.0.1", "--client-cultmesh-port", $Port, - "--tick-interval-ms", 250, + "--tick-interval-ms", 20, "--fixed-delta-ms", 20, "--no-odin-announcements" ) -PassThru -WindowStyle Hidden -RedirectStandardOutput $daemonLog -RedirectStandardError "$daemonLog.error"