Integrate Aetheria reactive state worktree

This commit is contained in:
Meta Vens 2026-06-28 01:18:21 +01:00
commit 65133ac8a0
61 changed files with 3427 additions and 402 deletions

View file

@ -89,9 +89,8 @@ public class InventoryMenu : MonoBehaviour
// {
// _destroyItem = false;
// });
var hasDockingIndex = TryResolveObservedDockingIndex(out var dockingIndex);
var hasObservedCurrentEntity = hasDockingIndex && dockingIndex.TryResolveCurrentEntity(out var currentEntity);
var cargo = hasDockingIndex && dockingIndex.TryResolveCurrentDockingBay(out var dockingBay)
var hasObservedCurrentEntity = TryResolveCurrentEntityFacade(out var currentEntity);
var cargo = TryGetTypedCurrentDockingBayFacade(out var dockingBay)
? dockingBay
: currentEntity?.CargoBays.FirstOrDefault();
if (cargo!=null)
@ -727,46 +726,81 @@ public class InventoryMenu : MonoBehaviour
private bool TryResolveCurrentDockingBayRow(out AetheriaRuntimeStationDockingBayRow dockingBay)
{
dockingBay = null;
return TryResolveObservedDockingIndex(out var dockingIndex) &&
dockingIndex.TryResolveCurrentDockingBayRow(out dockingBay);
var stationRefit = ResolveStationRefit();
dockingBay = stationRefit?.IsDocked == true && stationRefit.DockingBayIndex >= 0
? (stationRefit.DockingBays ?? Array.Empty<AetheriaRuntimeStationDockingBayRow>())
.FirstOrDefault(row => row != null && row.DockingBayIndex == stationRefit.DockingBayIndex)
: null;
return dockingBay != null;
}
private bool TryResolveCurrentEntityKey(out string currentEntityKey)
{
currentEntityKey = "";
return TryResolveObservedDockingIndex(out var dockingIndex) &&
dockingIndex.TryResolveCurrentEntityKey(out currentEntityKey);
currentEntityKey = ResolveDockingState()?.CurrentEntityKey ?? "";
return !string.IsNullOrWhiteSpace(currentEntityKey);
}
private bool TryResolveCurrentEntityDocument(out AetheriaRuntimeCurrentEntityDocument currentEntity)
{
currentEntity = null;
return TryResolveObservedDockingIndex(out var dockingIndex) &&
dockingIndex.TryResolveCurrentEntityDocument(out currentEntity);
try
{
currentEntity = ResolveClient()
.Aetheria()
.DockingState
.Latest()
?.CurrentEntity;
}
catch (Exception ex)
{
Debug.LogWarning($"Failed to read Aetheria current entity for inventory ship settings: {ex.Message}");
return false;
}
return currentEntity != null;
}
private AetheriaRuntimeStationRefitDocument ResolveStationRefit()
{
return TryResolveObservedDockingIndex(out var dockingIndex)
? dockingIndex.ResolveStationRefit()
: null;
return ResolveDockingState()?.StationRefit;
}
private bool TryResolveCurrentDocking(out AetheriaRuntimeCurrentDockingDocument docking)
private bool TryResolveCurrentEntityFacade(out Entity currentEntity)
{
docking = null;
return TryResolveObservedDockingIndex(out var dockingIndex) &&
dockingIndex.TryResolveCurrentDocking(out docking);
currentEntity = null;
var currentEntityKey = ResolveDockingState()?.CurrentEntityKey;
return _observedFacadeIndex != null &&
!string.IsNullOrWhiteSpace(currentEntityKey) &&
_observedFacadeIndex.TryResolveEntityByRecordKey(currentEntityKey, out currentEntity);
}
private bool TryResolveObservedDockingIndex(out AetheriaUnityObservedDockingIndex dockingIndex)
private bool TryGetTypedCurrentDockingBayFacade(out EquippedCargoBay dockingBay)
{
dockingIndex = null;
if (_observedFacadeIndex == null)
return false;
dockingBay = null;
var docking = ResolveDockingState()?.CurrentDocking;
return _observedFacadeIndex != null &&
docking?.IsDocked == true &&
_observedFacadeIndex.TryResolveDockingBayByRecordKey(
docking.DockParentEntityKey,
docking.DockingBayIndex,
out dockingBay);
}
dockingIndex = new AetheriaUnityObservedDockingIndex(ResolveClient, _observedFacadeIndex);
return true;
private AetheriaClientDockingSnapshot ResolveDockingState()
{
try
{
return ResolveClient()
.Aetheria()
.DockingState
.Latest();
}
catch (Exception ex)
{
Debug.LogWarning($"Failed to read Aetheria docking state for inventory menu: {ex.Message}");
return null;
}
}
private bool TryResolveCargoBay(EquippedCargoBay cargoBay, out string entityKey, out int cargoIndex)

View file

@ -260,9 +260,7 @@ public class InventoryPanel : MonoBehaviour, IPointerClickHandler
}
return;
case AetheriaRuntimeInventoryDropdownSelectionKind.DockingBay:
if (TryResolveObservedDockingIndex(out var dockingIndex) &&
dockingIndex.TryResolveCurrentDockingBayRow(out _) &&
dockingIndex.TryResolveCurrentDockingBay(out var dockingBay))
if (TryResolveCurrentDockingBayFacade(out var dockingBay))
{
Display(dockingBay);
}
@ -1133,29 +1131,53 @@ private void Update()
private bool TryResolveCurrentEntityKey(out string currentEntityKey)
{
currentEntityKey = "";
return TryResolveObservedDockingIndex(out var dockingIndex) &&
dockingIndex.TryResolveCurrentEntityKey(out currentEntityKey);
var snapshot = ResolveDockingState();
currentEntityKey = snapshot?.CurrentEntityKey ?? "";
return !string.IsNullOrWhiteSpace(currentEntityKey);
}
private bool TryResolveCurrentDockingBayRow(out AetheriaRuntimeStationDockingBayRow dockingBay)
{
dockingBay = null;
return TryResolveObservedDockingIndex(out var dockingIndex) &&
dockingIndex.TryResolveCurrentDockingBayRow(out dockingBay);
var stationRefit = ResolveStationRefit();
dockingBay = stationRefit?.IsDocked == true && stationRefit.DockingBayIndex >= 0
? (stationRefit.DockingBays ?? Array.Empty<AetheriaRuntimeStationDockingBayRow>())
.FirstOrDefault(row => row != null && row.DockingBayIndex == stationRefit.DockingBayIndex)
: null;
return dockingBay != null;
}
private bool TryResolveCurrentDocking(out AetheriaRuntimeCurrentDockingDocument docking)
private bool TryResolveCurrentDockingBayFacade(out EquippedCargoBay dockingBay)
{
docking = null;
return TryResolveObservedDockingIndex(out var dockingIndex) &&
dockingIndex.TryResolveCurrentDocking(out docking);
dockingBay = null;
var docking = ResolveDockingState()?.CurrentDocking;
return _observedFacadeIndex != null &&
docking?.IsDocked == true &&
_observedFacadeIndex.TryResolveDockingBayByRecordKey(
docking.DockParentEntityKey,
docking.DockingBayIndex,
out dockingBay);
}
private AetheriaRuntimeStationRefitDocument ResolveStationRefit()
{
return TryResolveObservedDockingIndex(out var dockingIndex)
? dockingIndex.ResolveStationRefit()
: null;
return ResolveDockingState()?.StationRefit;
}
private AetheriaClientDockingSnapshot ResolveDockingState()
{
try
{
return ResolveClient()
.Aetheria()
.DockingState
.Latest();
}
catch (Exception ex)
{
Debug.LogWarning($"Failed to read Aetheria docking state for inventory panel: {ex.Message}");
return null;
}
}
private bool TryResolveObservedDockingIndex(out AetheriaUnityObservedDockingIndex dockingIndex)

View file

@ -205,38 +205,36 @@ public class LocalMenu : MonoBehaviour
return "Local";
}
private bool TryResolveCurrentDocking(out AetheriaRuntimeCurrentDockingDocument docking)
private bool TryResolveDockingState(out AetheriaClientDockingSnapshot dockingState)
{
docking = null;
dockingState = null;
try
{
docking = ResolveClient()
dockingState = ResolveClient()
.Aetheria()
.Current
.Docking
.LatestAsync()
.GetAwaiter()
.GetResult();
.DockingState
.Latest();
}
catch (Exception ex)
{
Debug.LogWarning($"Failed to read Aetheria current docking for local story surface: {ex.Message}");
Debug.LogWarning($"Failed to read Aetheria docking state for local story surface: {ex.Message}");
return false;
}
return docking != null;
return dockingState != null;
}
private bool TryResolveDockedLocalStory(out LocationStory story)
{
story = null;
if (_observedFacadeIndex == null ||
!TryResolveCurrentDocking(out var docking) ||
!docking.IsDocked ||
!TryResolveDockingState(out var dockingState) ||
dockingState?.IsDocked != true ||
dockingState.CurrentDocking == null ||
!_observedFacadeIndex.TryResolveDockingBayByRecordKey(
docking.DockParentEntityKey,
docking.DockingBayIndex,
dockingState.CurrentDocking.DockParentEntityKey,
dockingState.CurrentDocking.DockingBayIndex,
out var dockingBay) ||
dockingBay?.Entity is not OrbitalEntity { Story: { } dockedStory })
{

View file

@ -25,24 +25,27 @@ public class MapRenderer : MonoBehaviour
public Camera InfluenceCamera;
public Image OverlayDisplay;
public Image GravityDisplay;
public Material GravityBackdropMaterial;
public Image TintDisplay;
public Image InfluenceDisplay;
public AetheriaRenderSplatLayerRenderer SplatLayerRenderer;
public AetheriaDaemonRenderAssetCatalog AssetCatalog;
public RectTransform RtsIconRoot;
public RawImage RtsIconPrototype;
public float Scale;
public float2 Position;
public float IconSize = 1f/128;
private RectTransform _rect;
private RenderTexture _mapTexture;
private RenderTexture _gravityTexture;
private RenderTexture _tintTexture;
private RenderTexture _influenceTexture;
private int2 _size;
private bool _init;
private AetheriaClient _client;
private string _clientStatePath = "";
private AetheriaRuntimeObjectsViewportDocument _objectsViewport;
private AetheriaRuntimeGravityViewportDocument _gravityViewport;
private AetheriaRuntimeRenderSplatsViewportDocument _renderSplatsViewport;
private float _nextViewportRefreshTime;
private readonly List<RawImage> _rtsIconPool = new List<RawImage>();
void Start()
{
@ -52,10 +55,16 @@ public class MapRenderer : MonoBehaviour
private void OnEnable()
{
_init = true;
MapOverlayCamera.gameObject.SetActive(true);
GravityCamera.gameObject.SetActive(true);
TintCamera.gameObject.SetActive(true);
InfluenceCamera.gameObject.SetActive(true);
SetCameraActive(MapOverlayCamera, false);
SetCameraActive(GravityCamera, false);
SetCameraActive(TintCamera, false);
SetCameraActive(InfluenceCamera, false);
if (OverlayDisplay != null)
OverlayDisplay.gameObject.SetActive(false);
if (GravityBackdropMaterial != null && GravityDisplay != null)
GravityDisplay.material = GravityBackdropMaterial;
EnsureRtsIconRoot();
SetRtsIconsActive(true);
RefreshViewportDocuments(force: true);
// If hiding minimap asteroids, turn them back on for the map screen
@ -69,10 +78,13 @@ public class MapRenderer : MonoBehaviour
{
ReleaseTextures();
}
MapOverlayCamera.gameObject.SetActive(false);
GravityCamera.gameObject.SetActive(false);
TintCamera.gameObject.SetActive(false);
InfluenceCamera.gameObject.SetActive(false);
SetCameraActive(MapOverlayCamera, false);
SetCameraActive(GravityCamera, false);
SetCameraActive(TintCamera, false);
SetCameraActive(InfluenceCamera, false);
if (OverlayDisplay != null)
OverlayDisplay.gameObject.SetActive(false);
SetRtsIconsActive(false);
// If hiding minimap asteroids, turn them back off when leaving the map screen
if (!ResolveShowAsteroidsInMinimap())
@ -88,12 +100,6 @@ public class MapRenderer : MonoBehaviour
{
_mapTexture.Release();
_mapTexture = null;
_gravityTexture.Release();
_gravityTexture = null;
_tintTexture.Release();
_tintTexture = null;
_influenceTexture.Release();
_influenceTexture = null;
}
void LateUpdate()
@ -108,40 +114,12 @@ public class MapRenderer : MonoBehaviour
ReleaseTextures();
}
_mapTexture = new RenderTexture(_size.x, _size.y, 0, RenderTextureFormat.Default);
MapOverlayCamera.targetTexture = _mapTexture;
OverlayDisplay.material.SetTexture("_DetailTex", _mapTexture);
_gravityTexture = new RenderTexture(_size.x, _size.y, 0, RenderTextureFormat.RFloat);
GravityCamera.targetTexture = _gravityTexture;
GravityDisplay.material.SetTexture("_DetailTex", _gravityTexture);
_tintTexture = new RenderTexture(_size.x / 2, _size.y / 2, 0, RenderTextureFormat.RGB111110Float);
TintCamera.targetTexture = _tintTexture;
TintDisplay.material.SetTexture("_DetailTex", _tintTexture);
_influenceTexture = new RenderTexture(_size.x, _size.y, 0, RenderTextureFormat.RFloat);
InfluenceCamera.targetTexture = _influenceTexture;
InfluenceDisplay.material.SetTexture("_DetailTex", _influenceTexture);
}
var pos = ((Vector2) Position).Flatland(1);
MapOverlayCamera.transform.position = pos;
MapOverlayCamera.orthographicSize = _size.y * Scale * .5f;
GravityCamera.transform.position = pos;
GravityCamera.orthographicSize = _size.y * Scale * .5f;
GravityDisplay.material.SetFloat("_Scale", Scale / 2);
TintCamera.transform.position = pos;
TintCamera.orthographicSize = _size.y * Scale * .5f;
InfluenceCamera.transform.position = pos;
InfluenceCamera.orthographicSize = _size.y * Scale * .5f;
ZoneRenderer.SetIconSize(IconSize * Scale);
RefreshViewportDocuments(force: false);
RenderSplatLayers();
RenderRtsIcons();
}
private void RefreshViewportDocuments(bool force)
@ -158,8 +136,8 @@ public class MapRenderer : MonoBehaviour
.ObjectsViewportAsync(viewport)
.GetAwaiter()
.GetResult();
_gravityViewport = client
.GravityViewportAsync(viewport)
_renderSplatsViewport = client
.RenderSplatsViewportAsync(viewport)
.GetAwaiter()
.GetResult();
@ -175,6 +153,153 @@ public class MapRenderer : MonoBehaviour
}
}
private void RenderSplatLayers()
{
if (_renderSplatsViewport == null)
return;
if (SplatLayerRenderer == null)
SplatLayerRenderer = GetComponent<AetheriaRenderSplatLayerRenderer>() ??
gameObject.AddComponent<AetheriaRenderSplatLayerRenderer>();
SplatLayerRenderer.Render(_renderSplatsViewport, _size.x, _size.y);
ApplyLayerTexture(AetheriaRuntimeRenderSplatLayerKeys.GravityHeight, GravityDisplay);
ApplyLayerTexture(AetheriaRuntimeRenderSplatLayerKeys.FogTint, TintDisplay);
ApplyLayerTexture(AetheriaRuntimeRenderSplatLayerKeys.Influence, InfluenceDisplay);
}
private void ApplyLayerTexture(string layerKey, Image display)
{
if (display == null ||
SplatLayerRenderer == null ||
!SplatLayerRenderer.TryGetTexture(layerKey, out var texture) ||
texture == null)
{
return;
}
display.material.SetTexture("_DetailTex", texture);
}
private static void SetCameraActive(Camera camera, bool active)
{
if (camera != null)
camera.gameObject.SetActive(active);
}
private void RenderRtsIcons()
{
EnsureRtsIconRoot();
if (RtsIconRoot == null)
return;
var objects = _objectsViewport?.Objects ?? Array.Empty<AetheriaRuntimeRtsViewportObject>();
for (var i = 0; i < objects.Count; i++)
{
var icon = ResolveRtsIcon(i);
ApplyRtsIcon(icon, objects[i]);
}
for (var i = objects.Count; i < _rtsIconPool.Count; i++)
if (_rtsIconPool[i] != null)
_rtsIconPool[i].gameObject.SetActive(false);
}
private RawImage ResolveRtsIcon(int index)
{
while (_rtsIconPool.Count <= index)
{
RawImage icon;
if (RtsIconPrototype != null)
{
icon = Instantiate(RtsIconPrototype, RtsIconRoot);
}
else
{
var go = new GameObject("RTS Map Icon", typeof(RectTransform), typeof(CanvasRenderer), typeof(RawImage));
go.transform.SetParent(RtsIconRoot, false);
icon = go.GetComponent<RawImage>();
icon.texture = Texture2D.whiteTexture;
icon.raycastTarget = false;
}
_rtsIconPool.Add(icon);
}
return _rtsIconPool[index];
}
private void ApplyRtsIcon(RawImage icon, AetheriaRuntimeRtsViewportObject obj)
{
if (icon == null || obj == null)
return;
icon.gameObject.SetActive(true);
if (AssetCatalog != null && AssetCatalog.TryResolveTexture(obj.IconAsset, out var texture))
icon.texture = texture;
icon.color = ResolveIconColor(obj);
var rectTransform = icon.rectTransform;
var pixelSize = Mathf.Max(4f, IconSize * (obj.Controlled ? 1.25f : 1f));
rectTransform.anchorMin = rectTransform.anchorMax = new Vector2(0.5f, 0.5f);
rectTransform.pivot = new Vector2(0.5f, 0.5f);
rectTransform.sizeDelta = new Vector2(pixelSize, pixelSize);
rectTransform.anchoredPosition = WorldToMapPosition(obj.X, obj.Y);
rectTransform.localRotation = Quaternion.Euler(
0,
0,
Mathf.Atan2((float)obj.DirectionY, (float)obj.DirectionX) * Mathf.Rad2Deg - 90f);
}
private Vector2 WorldToMapPosition(double worldX, double worldY)
{
var viewport = _objectsViewport?.Viewport ?? ResolveViewportBounds();
var minX = Math.Min(viewport.MinX, viewport.MaxX);
var maxX = Math.Max(viewport.MinX, viewport.MaxX);
var minY = Math.Min(viewport.MinY, viewport.MaxY);
var maxY = Math.Max(viewport.MinY, viewport.MaxY);
var width = Math.Max(0.0001, maxX - minX);
var height = Math.Max(0.0001, maxY - minY);
var rootRect = RtsIconRoot != null ? RtsIconRoot.rect : new Rect(0, 0, _size.x, _size.y);
var u = (float)((worldX - minX) / width);
var v = (float)((worldY - minY) / height);
return new Vector2(
(u - 0.5f) * rootRect.width,
(v - 0.5f) * rootRect.height);
}
private static Color ResolveIconColor(AetheriaRuntimeRtsViewportObject obj)
{
var color = obj.Controlled
? new Color(0.3f, 0.9f, 1.0f, 1.0f)
: Color.HSVToRGB(frac((obj.FactionKey ?? obj.Kind ?? "").GetHashCode() * 0.0137f), 0.55f, 0.95f);
color.a = Mathf.Clamp01(Mathf.Max(0.25f, (float)obj.Visibility));
return color;
}
private void EnsureRtsIconRoot()
{
if (RtsIconRoot != null)
return;
var parent = GravityDisplay != null
? GravityDisplay.transform.parent
: transform;
var go = new GameObject("RTS Command Icons", typeof(RectTransform));
go.transform.SetParent(parent, false);
RtsIconRoot = go.GetComponent<RectTransform>();
RtsIconRoot.anchorMin = Vector2.zero;
RtsIconRoot.anchorMax = Vector2.one;
RtsIconRoot.offsetMin = Vector2.zero;
RtsIconRoot.offsetMax = Vector2.zero;
RtsIconRoot.SetAsLastSibling();
}
private void SetRtsIconsActive(bool active)
{
if (RtsIconRoot != null)
RtsIconRoot.gameObject.SetActive(active);
}
private AetheriaRuntimeRtsViewportBounds ResolveViewportBounds()
{
var screenHeight = _size.y <= 0 ? Math.Max(1, Screen.height) : _size.y;

View file

@ -169,17 +169,14 @@ public class MenuPanel : MonoBehaviour
.ToArray();
}
private AetheriaRuntimeCurrentDockingDocument ResolveCurrentDocking()
private AetheriaClientDockingSnapshot ResolveCurrentDocking()
{
try
{
return ResolveClient()
.Aetheria()
.Current
.Docking
.LatestAsync()
.GetAwaiter()
.GetResult();
.DockingState
.Latest();
}
catch (Exception ex)
{

View file

@ -15,6 +15,7 @@ using float2 = Unity.Mathematics.float2;
public class SectorMap : MonoBehaviour
{
public Camera InfluenceCamera;
public AetheriaRenderSplatRasterizer InfluenceSplatRasterizer;
public Prototype InfluenceRendererPrototype;
public MeshRenderer SectorRenderer;
public Prototype ZonePrototype;
@ -216,6 +217,7 @@ public class SectorMap : MonoBehaviour
public void Start()
{
EnsureSectorMapLoaded();
DisableLegacyInfluenceCamera();
}
private void EnsureSectorMapLoaded()
@ -341,33 +343,162 @@ public class SectorMap : MonoBehaviour
private void RenderInfluence()
{
DisableLegacyInfluenceCamera();
foreach (var pair in _factionMaterials)
{
foreach (var zone in _sectorMap?.Zones ?? Array.Empty<AetheriaRuntimeSectorMapZone>())
{
if (!_zoneInstances.TryGetValue(zone.ZoneIndex, out var instance))
continue;
var influence = 0f;
if (zone.FactionIndices?.Count > 0)
{
if (zone.FactionIndices.Contains(pair.Key))
{
influence = 10;
if (zone.OwnerFactionIndex != pair.Key)
influence *= .5f;
}
else influence = -10;
}
instance.Influence.material.SetFloat("_Depth", influence);
}
InfluenceCamera.targetTexture = pair.Value.influence;
InfluenceCamera.Render();
var document = BuildInfluenceSplatDocument(pair.Key);
ResolveInfluenceSplatRasterizer().RenderLayerToTarget(
document,
pair.Value.influence,
0,
0,
Color.clear);
}
}
private AetheriaRenderSplatRasterizer ResolveInfluenceSplatRasterizer()
{
if (InfluenceSplatRasterizer != null)
return InfluenceSplatRasterizer;
InfluenceSplatRasterizer = GetComponent<AetheriaRenderSplatRasterizer>();
if (InfluenceSplatRasterizer == null)
InfluenceSplatRasterizer = gameObject.AddComponent<AetheriaRenderSplatRasterizer>();
return InfluenceSplatRasterizer;
}
private AetheriaRuntimeRenderSplatsViewportDocument BuildInfluenceSplatDocument(int factionIndex)
{
var zones = (_sectorMap?.Zones ?? Array.Empty<AetheriaRuntimeSectorMapZone>()).ToArray();
var minX = zones.Length > 0 ? zones.Min(zone => zone.X) : -1;
var maxX = zones.Length > 0 ? zones.Max(zone => zone.X) : 1;
var minY = zones.Length > 0 ? zones.Min(zone => zone.Y) : -1;
var maxY = zones.Length > 0 ? zones.Max(zone => zone.Y) : 1;
var padding = Math.Max(IconBackgroundSize * 2, 4);
var centerX = new List<double>();
var centerY = new List<double>();
var halfExtentX = new List<double>();
var halfExtentY = new List<double>();
var rotationCos = new List<double>();
var rotationSin = new List<double>();
var channel = new List<int>();
var falloff = new List<int>();
var valueR = new List<double>();
var valueG = new List<double>();
var valueB = new List<double>();
var valueA = new List<double>();
var sourceKey = new List<string>();
var layerIndex = new List<int>();
var sourceKind = new List<int>();
var frequencyX = new List<double>();
var frequencyY = new List<double>();
var phaseX = new List<double>();
var phaseY = new List<double>();
var animationSpeed = new List<double>();
var sourceFlags = new List<double>();
foreach (var zone in zones)
{
if (!_zoneInstances.ContainsKey(zone.ZoneIndex))
continue;
var influence = ResolveZoneInfluence(zone, factionIndex);
if (Math.Abs(influence) <= 0.0001f)
continue;
centerX.Add(zone.X);
centerY.Add(zone.Y);
halfExtentX.Add(Math.Max(IconBackgroundSize, 1));
halfExtentY.Add(Math.Max(IconBackgroundSize, 1));
rotationCos.Add(1);
rotationSin.Add(0);
channel.Add(AetheriaRuntimeRenderSplatChannels.Influence);
falloff.Add(AetheriaRuntimeRenderSplatFalloffs.Smooth);
valueR.Add(influence);
valueG.Add(influence);
valueB.Add(influence);
valueA.Add(1);
sourceKey.Add($"sector-zone:{zone.ZoneIndex}:faction:{factionIndex}");
layerIndex.Add(0);
sourceKind.Add(AetheriaRuntimeRenderSplatSourceKinds.Constant);
frequencyX.Add(0);
frequencyY.Add(0);
phaseX.Add(0);
phaseY.Add(0);
animationSpeed.Add(0);
sourceFlags.Add(0);
}
return new AetheriaRuntimeRenderSplatsViewportDocument
{
Schema = AetheriaRuntimeDaemonSchemas.RenderSplatsViewport,
Viewport = new AetheriaRuntimeRtsViewportBounds
{
MinX = minX - padding,
MinY = minY - padding,
MaxX = maxX + padding,
MaxY = maxY + padding
},
Layers = new[]
{
new AetheriaRuntimeRenderSplatLayerDefinition
{
LayerKey = AetheriaRuntimeRenderSplatLayerKeys.Influence,
DisplayName = "Sector Influence",
Channel = AetheriaRuntimeRenderSplatChannels.Influence,
BlendMode = AetheriaRuntimeRenderSplatBlendModes.Add,
GraphicsFormat = "R16_SFloat"
}
},
Splats = new AetheriaRuntimeRenderSplatSoa
{
Count = centerX.Count,
CenterX = centerX,
CenterY = centerY,
HalfExtentX = halfExtentX,
HalfExtentY = halfExtentY,
RotationCos = rotationCos,
RotationSin = rotationSin,
Channel = channel,
Falloff = falloff,
ValueR = valueR,
ValueG = valueG,
ValueB = valueB,
ValueA = valueA,
SourceKey = sourceKey,
LayerIndex = layerIndex,
SourceKind = sourceKind,
FrequencyX = frequencyX,
FrequencyY = frequencyY,
PhaseX = phaseX,
PhaseY = phaseY,
AnimationSpeed = animationSpeed,
SourceFlags = sourceFlags
}
};
}
private static float ResolveZoneInfluence(AetheriaRuntimeSectorMapZone zone, int factionIndex)
{
if (zone.FactionIndices?.Count <= 0)
return 0f;
if (!zone.FactionIndices.Contains(factionIndex))
return -10f;
return zone.OwnerFactionIndex == factionIndex ? 10f : 5f;
}
private void DisableLegacyInfluenceCamera()
{
if (InfluenceCamera == null)
return;
InfluenceCamera.targetTexture = null;
InfluenceCamera.gameObject.SetActive(false);
}
private AetheriaClient ResolveClient()
{
var gameDataDirectory = new DirectoryInfo(Path.Combine(Application.dataPath, "..", "GameData"));

View file

@ -47,6 +47,7 @@ public class TradeMenu : MonoBehaviour
private AetheriaRuntimeTradeCargoSelectorSurfaceProjection _cargoSelectorSurfaceProjection;
private AetheriaRuntimeStationCargoTargetRow[] _cargoSelectorStationRefitTargets =
Array.Empty<AetheriaRuntimeStationCargoTargetRow>();
private AetheriaClientDockingSnapshot _dockingState;
private AetheriaRuntimeStationRefitDocument _stationRefit;
private AetheriaRuntimeTradeFilterSurfaceProjection _filterSurfaceProjection;
private Action[] _rowActionCallbacks = Array.Empty<Action>();
@ -56,8 +57,10 @@ public class TradeMenu : MonoBehaviour
private void OnEnable()
{
if (!TryResolveCurrentDocking(out var docking) ||
!docking.IsDocked ||
var dockingState = ResolveDockingState();
var docking = dockingState?.CurrentDocking;
if (dockingState?.IsDocked != true ||
docking == null ||
string.IsNullOrWhiteSpace(docking.DockParentEntityKey) ||
docking.DockingBayIndex < 0)
{
@ -514,7 +517,8 @@ public class TradeMenu : MonoBehaviour
private bool TryResolveCurrentDockingTargetEntityKey(out string targetEntityKey)
{
targetEntityKey = "";
if (!TryResolveCurrentDocking(out var docking) ||
var docking = ResolveDockingState()?.CurrentDocking;
if (docking == null ||
!docking.IsDocked ||
string.IsNullOrWhiteSpace(docking.DockParentEntityKey))
{
@ -525,54 +529,40 @@ public class TradeMenu : MonoBehaviour
return true;
}
private bool TryResolveCurrentDocking(out AetheriaRuntimeCurrentDockingDocument docking)
{
docking = null;
try
{
docking = ResolveClient()
.Aetheria()
.Current
.Docking
.LatestAsync()
.GetAwaiter()
.GetResult();
}
catch (Exception ex)
{
Debug.LogWarning($"Failed to read Aetheria current docking for trade menu: {ex.Message}");
return false;
}
return docking != null;
}
private AetheriaRuntimeStationRefitDocument ResolveStationRefit()
{
if (_stationRefit != null)
return _stationRefit;
_stationRefit = ResolveDockingState()?.StationRefit;
return _stationRefit;
}
private AetheriaClientDockingSnapshot ResolveDockingState()
{
if (_dockingState != null)
return _dockingState;
try
{
_stationRefit = ResolveClient()
_dockingState = ResolveClient()
.Aetheria()
.StationRefit
.LatestAsync()
.GetAwaiter()
.GetResult();
.DockingState
.Latest();
_stationRefit = _dockingState?.StationRefit;
}
catch (Exception ex)
{
Debug.LogWarning($"Failed to read Aetheria station refit projection for trade menu: {ex.Message}");
Debug.LogWarning($"Failed to read Aetheria docking state for trade menu: {ex.Message}");
return null;
}
return _stationRefit;
return _dockingState;
}
private void InvalidateStationRefit()
{
_dockingState = null;
_stationRefit = null;
}
@ -649,6 +639,7 @@ public class TradeMenu : MonoBehaviour
_clientStatePath = "";
_catalog = null;
_playerSettings = null;
_dockingState = null;
_stationRefit = null;
}