diff --git a/Aetheria.State.Verify/Program.cs b/Aetheria.State.Verify/Program.cs index fceec3042..75bfb3764 100644 --- a/Aetheria.State.Verify/Program.cs +++ b/Aetheria.State.Verify/Program.cs @@ -8176,6 +8176,10 @@ static void RequireUnityObserverDoesNotTickLocalSimulation(string root) var sectorRenderer = File.Exists(sectorRendererPath) ? File.ReadAllText(sectorRendererPath) : throw new InvalidOperationException("Cannot verify daemon current-zone UI projection; SectorRenderer.cs is missing."); + var sectorMapPath = Path.Combine(root, "Assets", "Scripts", "UI", "Menu", "SectorMap.cs"); + var sectorMap = File.Exists(sectorMapPath) + ? File.ReadAllText(sectorMapPath) + : throw new InvalidOperationException("Cannot verify daemon current-zone UI projection; SectorMap.cs is missing."); if (mapRenderer.Contains("GameManager.Zone.GalaxyZone", StringComparison.Ordinal) || sectorRenderer.Contains("GameManager.Zone.GalaxyZone", StringComparison.Ordinal) || @@ -8185,6 +8189,21 @@ static void RequireUnityObserverDoesNotTickLocalSimulation(string root) "Map and sector UI must read current-zone identity from the daemon-observed run, not Unity's mirrored Zone hierarchy."); } + if (!actionGameManager.Contains("public static bool TryGetObservedGalaxy(out Galaxy galaxy)", StringComparison.Ordinal) || + !sectorMap.Contains("ActionGameManager.TryGetObservedGalaxy(out var observedGalaxy)", StringComparison.Ordinal) || + !sectorRenderer.Contains("ActionGameManager.TryGetObservedGalaxy(out var observedGalaxy)", StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "Map and sector UI must request projected galaxy data through an explicit observed-galaxy boundary."); + } + + if (sectorMap.Contains("ActionGameManager.ObservedGalaxy", StringComparison.Ordinal) || + sectorRenderer.Contains("ActionGameManager.ObservedGalaxy", StringComparison.Ordinal)) + { + throw new InvalidOperationException( + "Map and sector UI must not read the raw ObservedGalaxy projection directly."); + } + var requiredDaemonControlValidationSymbols = new[] { "case AetheriaRuntimeDaemonCommandKinds.SetTractorPower:", diff --git a/Assets/Scripts/Gameplay/ActionGameManager.cs b/Assets/Scripts/Gameplay/ActionGameManager.cs index 406b5884c..a02fad172 100644 --- a/Assets/Scripts/Gameplay/ActionGameManager.cs +++ b/Assets/Scripts/Gameplay/ActionGameManager.cs @@ -494,6 +494,12 @@ public class ActionGameManager : MonoBehaviour set => _currentEntity = value; } + public static bool TryGetObservedGalaxy(out Galaxy galaxy) + { + galaxy = ObservedGalaxy; + return galaxy != null; + } + public bool IsObservedDocked => TryGetObservedDockingBay(out _); public bool TryGetObservedCurrentEntity(out Entity entity) diff --git a/Assets/Scripts/UI/Menu/SectorMap.cs b/Assets/Scripts/UI/Menu/SectorMap.cs index ca92be71f..cbe878124 100644 --- a/Assets/Scripts/UI/Menu/SectorMap.cs +++ b/Assets/Scripts/UI/Menu/SectorMap.cs @@ -91,6 +91,9 @@ public class SectorMap : MonoBehaviour public IEnumerator RevealZone(IEnumerable zones, float linkDuration, float iconDuration) { + if (!ActionGameManager.TryGetObservedGalaxy(out var observedGalaxy)) + yield break; + var linksToReveal = new List<(float2 start, float2 end, Transform linkInstance, bool critical)>(); var zoneTransforms = new List(); var zoneInstanceScale = ZonePrototype.transform.localScale; @@ -111,7 +114,7 @@ public class SectorMap : MonoBehaviour { zoneInstance.Primary.sharedMaterial = _factionMaterials[zone.Owner].primaryMaterial; zoneInstance.Secondary.sharedMaterial = _factionMaterials[zone.Owner].secondaryMaterial; - if(zone == ActionGameManager.ObservedGalaxy.HomeZones[zone.Owner]) + if(zone == observedGalaxy.HomeZones[zone.Owner]) zoneInstance.Secondary.transform.localScale = Vector3.one * 4; } else @@ -119,7 +122,7 @@ public class SectorMap : MonoBehaviour zoneInstance.Secondary.gameObject.SetActive(false); } - var isOnCriticalPath = ActionGameManager.ObservedGalaxy.ExitPath?.Contains(zone) ?? false; + var isOnCriticalPath = observedGalaxy.ExitPath?.Contains(zone) ?? false; foreach (var adjacentZone in zone.AdjacentZones) { // If the adjacent zone is in the set already revealed, then show the link @@ -128,7 +131,7 @@ public class SectorMap : MonoBehaviour _revealedLinks.Contains((adjacentZone, zone)))) { var link = LinkPrototype.Instantiate(); - var critical = isOnCriticalPath && (ActionGameManager.ObservedGalaxy.ExitPath?.Contains(adjacentZone) ?? false); + var critical = isOnCriticalPath && (observedGalaxy.ExitPath?.Contains(adjacentZone) ?? false); linksToReveal.Add((zone.Position, adjacentZone.Position, link, critical)); if (zone.Owner != null && zone.Owner.HasSameKey(adjacentZone.Owner)) link.GetComponent().sharedMaterial = _factionMaterials[zone.Owner].linkMaterial; @@ -151,7 +154,7 @@ public class SectorMap : MonoBehaviour zoneTextTransform.pivot = new Vector2(sign(linkDirection.x)/2+.5f,sign(linkDirection.y)/2+.5f); zoneTextTransform.localPosition = new Vector3(-linkDirection.x * LabelDistance, -linkDirection.y * LabelDistance, -1); - if (zone == ActionGameManager.ObservedGalaxy.Entrance) + if (zone == observedGalaxy.Entrance) { var iconInstance = IconPrototype.Instantiate(); iconInstance.material.mainTexture = EntranceIcon; @@ -161,7 +164,7 @@ public class SectorMap : MonoBehaviour iconTransform.localPosition = new Vector3(-linkDirection.x * IconDistance, -linkDirection.y * IconDistance); } - if (zone == ActionGameManager.ObservedGalaxy.Exit) + if (zone == observedGalaxy.Exit) { var iconInstance = IconPrototype.Instantiate(); iconInstance.material.mainTexture = ExitIcon; @@ -171,8 +174,8 @@ public class SectorMap : MonoBehaviour iconTransform.localPosition = new Vector3(-linkDirection.x * IconDistance, -linkDirection.y * IconDistance); } - var homeMega = ActionGameManager.ObservedGalaxy.HomeZones.Keys - .FirstOrDefault(m => ActionGameManager.ObservedGalaxy.HomeZones[m] == zone); + var homeMega = observedGalaxy.HomeZones.Keys + .FirstOrDefault(m => observedGalaxy.HomeZones[m] == zone); if (homeMega != null) { var backgroundInstance = IconBackgroundPrototype.Instantiate(); @@ -195,8 +198,8 @@ public class SectorMap : MonoBehaviour iconTransform.localPosition = new Vector3(-linkDirection.x * IconDistance, -linkDirection.y * IconDistance); } - var bossMega = ActionGameManager.ObservedGalaxy.BossZones.Keys - .FirstOrDefault(m => ActionGameManager.ObservedGalaxy.BossZones[m] == zone); + var bossMega = observedGalaxy.BossZones.Keys + .FirstOrDefault(m => observedGalaxy.BossZones[m] == zone); if (bossMega != null) { var backgroundInstance = IconBackgroundPrototype.Instantiate(); @@ -268,12 +271,12 @@ public class SectorMap : MonoBehaviour public void Start() { - if (ActionGameManager.ObservedGalaxy == null) + if (!ActionGameManager.TryGetObservedGalaxy(out var observedGalaxy)) { gameObject.SetActive(false); return; } - foreach (var mega in ActionGameManager.ObservedGalaxy.Factions) + foreach (var mega in observedGalaxy.Factions) { var influenceTexture = new RenderTexture(1024, 1024, 0, RenderTextureFormat.RHalf); var influenceRenderer = InfluenceRendererPrototype.Instantiate(); @@ -300,22 +303,25 @@ public class SectorMap : MonoBehaviour legendElement.Label.text = mega.ShortName; } - SectorRenderer.material.SetFloat("CloudAmplitude", ActionGameManager.ObservedGalaxy.Background.CloudAmplitude); - SectorRenderer.material.SetFloat("CloudExponent", ActionGameManager.ObservedGalaxy.Background.CloudExponent); - SectorRenderer.material.SetFloat("NoisePosition", ActionGameManager.ObservedGalaxy.Background.NoisePosition); - SectorRenderer.material.SetFloat("NoiseAmplitude", ActionGameManager.ObservedGalaxy.Background.NoiseAmplitude); - SectorRenderer.material.SetFloat("NoiseOffset", ActionGameManager.ObservedGalaxy.Background.NoiseOffset); - SectorRenderer.material.SetFloat("NoiseGain", ActionGameManager.ObservedGalaxy.Background.NoiseGain); - SectorRenderer.material.SetFloat("NoiseLacunarity", ActionGameManager.ObservedGalaxy.Background.NoiseLacunarity); - SectorRenderer.material.SetFloat("NoiseFrequency", ActionGameManager.ObservedGalaxy.Background.NoiseFrequency); + SectorRenderer.material.SetFloat("CloudAmplitude", observedGalaxy.Background.CloudAmplitude); + SectorRenderer.material.SetFloat("CloudExponent", observedGalaxy.Background.CloudExponent); + SectorRenderer.material.SetFloat("NoisePosition", observedGalaxy.Background.NoisePosition); + SectorRenderer.material.SetFloat("NoiseAmplitude", observedGalaxy.Background.NoiseAmplitude); + SectorRenderer.material.SetFloat("NoiseOffset", observedGalaxy.Background.NoiseOffset); + SectorRenderer.material.SetFloat("NoiseGain", observedGalaxy.Background.NoiseGain); + SectorRenderer.material.SetFloat("NoiseLacunarity", observedGalaxy.Background.NoiseLacunarity); + SectorRenderer.material.SetFloat("NoiseFrequency", observedGalaxy.Background.NoiseFrequency); } private void RenderInfluence() { + if (!ActionGameManager.TryGetObservedGalaxy(out var observedGalaxy)) + return; + // Render Influence Textures - foreach (var mega in ActionGameManager.ObservedGalaxy.Factions) + foreach (var mega in observedGalaxy.Factions) { - foreach (var zone in ActionGameManager.ObservedGalaxy.Zones) + foreach (var zone in observedGalaxy.Zones) { if(_zoneInstances.ContainsKey(zone)) { diff --git a/Assets/Scripts/UI/Menu/SectorRenderer.cs b/Assets/Scripts/UI/Menu/SectorRenderer.cs index ac653f3cb..3b8e16869 100644 --- a/Assets/Scripts/UI/Menu/SectorRenderer.cs +++ b/Assets/Scripts/UI/Menu/SectorRenderer.cs @@ -142,7 +142,9 @@ public class SectorRenderer : MonoBehaviour, IBeginDragHandler, IDragHandler, IS private AetheriaRuntimeZoneDetailsSurfaceState ProjectZoneDetailsSurfaceState(GalaxyZone zone) { - var density = saturate(ActionGameManager.ObservedGalaxy.Background.CloudDensity(zone.Position) / 2); + var density = ActionGameManager.TryGetObservedGalaxy(out var observedGalaxy) + ? saturate(observedGalaxy.Background.CloudDensity(zone.Position) / 2) + : 0f; var radius = GameManager.Settings.ZoneSettings.ZoneRadius.Evaluate(density); var mass = GameManager.Settings.ZoneSettings.ZoneMass.Evaluate(density); var otherFactions = zone.Factions