Query compass markers from daemon contacts
This commit is contained in:
parent
e05e310553
commit
9af4f4f2da
4 changed files with 239 additions and 9 deletions
|
|
@ -1827,7 +1827,11 @@ static void RequireDaemonRenderQueryAuthority(string root)
|
|||
"public static AetheriaRuntimeDaemonAsteroidInstancePose[] QueryAsteroidInstancePoses(",
|
||||
"public static int QueryAsteroidInstancePoses(",
|
||||
"TryResolveAsteroidBeltCenter(body, orbitPositions, orbits, out var center)",
|
||||
"ResolveAsteroidBeltRadius(body)"
|
||||
"ResolveAsteroidBeltRadius(body)",
|
||||
"AetheriaRuntimeDaemonCompassMarker",
|
||||
"public static AetheriaRuntimeDaemonCompassMarker[] QueryCompassMarkers(",
|
||||
"public static int QueryCompassMarkers(",
|
||||
"BuildEntityMap(zone)"
|
||||
};
|
||||
|
||||
var missingQuerySymbols = requiredQuerySymbols
|
||||
|
|
@ -1934,6 +1938,12 @@ static void RequireDaemonRenderQueryAuthority(string root)
|
|||
"ZoneRenderer must reconcile rendered entities from daemon frame snapshots instead of subscribing to mirrored Unity entity collection mutations.");
|
||||
}
|
||||
|
||||
if (zoneRenderer.Contains("PerspectiveEntity.EntityInfoGathered", StringComparison.Ordinal))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"ZoneRenderer must query daemon compass markers instead of reading mirrored Unity entity visibility state.");
|
||||
}
|
||||
|
||||
var requiredZoneRendererSymbols = new[]
|
||||
{
|
||||
"private AetheriaRuntimeZoneSnapshotCommit _daemonZoneSnapshot;",
|
||||
|
|
@ -1941,6 +1951,8 @@ static void RequireDaemonRenderQueryAuthority(string root)
|
|||
"private readonly Dictionary<string, AetheriaRuntimeDaemonBodyPose> _daemonBodyPosesByBodyKey",
|
||||
"private readonly List<AetheriaRuntimeDaemonAsteroidBeltPose> _daemonAsteroidBeltPoses",
|
||||
"private readonly Dictionary<string, AetheriaRuntimeDaemonAsteroidBeltPose> _daemonAsteroidBeltPosesByBodyKey",
|
||||
"private readonly List<AetheriaRuntimeDaemonCompassMarker> _daemonCompassMarkers",
|
||||
"private readonly Dictionary<int, AetheriaRuntimeDaemonCompassMarker> _daemonCompassMarkersByEntityIndex",
|
||||
"public void LoadZone(Zone zone, AetheriaRuntimeZoneSnapshotCommit daemonZone = null)",
|
||||
"_daemonZoneSnapshot = daemonZone;",
|
||||
"AetheriaRuntimeDaemonRenderQueries.EvaluateGravityTerrainHeight(",
|
||||
|
|
@ -1955,6 +1967,8 @@ static void RequireDaemonRenderQueryAuthority(string root)
|
|||
"AetheriaRuntimeDaemonRenderQueries.QueryBodyPoses(_daemonZoneSnapshot, _daemonBodyPoses);",
|
||||
"AetheriaRuntimeDaemonRenderQueries.QueryAsteroidBeltPoses(_daemonZoneSnapshot, _daemonAsteroidBeltPoses);",
|
||||
"AetheriaRuntimeDaemonRenderQueries.QueryAsteroidInstancePoses(",
|
||||
"AetheriaRuntimeDaemonRenderQueries.QueryCompassMarkers(",
|
||||
"_daemonCompassMarkersByEntityIndex.TryGetValue(entityInstance.Entity.DaemonEntityIndex, out var marker)",
|
||||
"_daemonBodyPosesByBodyKey.TryGetValue(planet.Key, out var pose)",
|
||||
"_daemonAsteroidBeltPosesByBodyKey.TryGetValue(key, out var beltPose)",
|
||||
"pose.GravityWaveSpeed"
|
||||
|
|
|
|||
|
|
@ -933,6 +933,100 @@ public class DaemonRuntimeDocumentTests
|
|||
Assert.AreEqual(0, poses[2].Size, 0.0001);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DaemonRenderQueriesPublishCompassMarkersFromVisibleContacts()
|
||||
{
|
||||
var zone = new AetheriaRuntimeZoneSnapshotCommit
|
||||
{
|
||||
Entities = new[]
|
||||
{
|
||||
new AetheriaRuntimeEntitySnapshotCommit
|
||||
{
|
||||
EntityIndex = 0,
|
||||
PositionX = 10,
|
||||
PositionZ = 20,
|
||||
Contacts = new[]
|
||||
{
|
||||
new AetheriaRuntimeEntityContactCommit
|
||||
{
|
||||
TargetEntityIndex = 1,
|
||||
InfoGathered = 0.8,
|
||||
Visible = true,
|
||||
Hostile = true
|
||||
},
|
||||
new AetheriaRuntimeEntityContactCommit
|
||||
{
|
||||
TargetEntityIndex = 2,
|
||||
InfoGathered = 0.2,
|
||||
Visible = true
|
||||
},
|
||||
new AetheriaRuntimeEntityContactCommit
|
||||
{
|
||||
TargetEntityIndex = 3,
|
||||
InfoGathered = 0.9,
|
||||
Visible = false
|
||||
},
|
||||
new AetheriaRuntimeEntityContactCommit
|
||||
{
|
||||
TargetEntityIndex = 4,
|
||||
InfoGathered = 0.9,
|
||||
Visible = true
|
||||
},
|
||||
new AetheriaRuntimeEntityContactCommit
|
||||
{
|
||||
TargetEntityIndex = 99,
|
||||
InfoGathered = 0.9,
|
||||
Visible = true
|
||||
}
|
||||
}
|
||||
},
|
||||
new AetheriaRuntimeEntitySnapshotCommit
|
||||
{
|
||||
EntityIndex = 1,
|
||||
PositionX = 13,
|
||||
PositionZ = 24
|
||||
},
|
||||
new AetheriaRuntimeEntitySnapshotCommit
|
||||
{
|
||||
EntityIndex = 2,
|
||||
PositionX = 100,
|
||||
PositionZ = 20
|
||||
},
|
||||
new AetheriaRuntimeEntitySnapshotCommit
|
||||
{
|
||||
EntityIndex = 3,
|
||||
PositionX = 10,
|
||||
PositionZ = 200
|
||||
},
|
||||
new AetheriaRuntimeEntitySnapshotCommit
|
||||
{
|
||||
EntityIndex = 4,
|
||||
PositionX = 11,
|
||||
PositionZ = 20
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var markers = new List<AetheriaRuntimeDaemonCompassMarker>();
|
||||
var count = AetheriaRuntimeDaemonRenderQueries.QueryCompassMarkers(
|
||||
zone,
|
||||
0,
|
||||
0.5,
|
||||
2,
|
||||
markers);
|
||||
|
||||
Assert.AreEqual(1, count);
|
||||
Assert.AreEqual(1, markers.Count);
|
||||
Assert.AreEqual(1, markers[0].TargetEntityIndex);
|
||||
Assert.AreEqual(13, markers[0].PositionX, 0.0001);
|
||||
Assert.AreEqual(24, markers[0].PositionZ, 0.0001);
|
||||
Assert.AreEqual(3, markers[0].DeltaX, 0.0001);
|
||||
Assert.AreEqual(4, markers[0].DeltaZ, 0.0001);
|
||||
Assert.AreEqual(5, markers[0].Distance, 0.0001);
|
||||
Assert.AreEqual(0.8, markers[0].InfoGathered, 0.0001);
|
||||
Assert.IsTrue(markers[0].Hostile);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SoaViewIndexRejectsInvalidRenderGroups()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -94,6 +94,10 @@ public class ZoneRenderer : MonoBehaviour
|
|||
new Dictionary<string, AetheriaRuntimeDaemonAsteroidBeltPose>(StringComparer.Ordinal);
|
||||
private readonly List<AetheriaRuntimeDaemonAsteroidInstancePose> _visibleAsteroidInstancePoses =
|
||||
new List<AetheriaRuntimeDaemonAsteroidInstancePose>();
|
||||
private readonly List<AetheriaRuntimeDaemonCompassMarker> _daemonCompassMarkers =
|
||||
new List<AetheriaRuntimeDaemonCompassMarker>();
|
||||
private readonly Dictionary<int, AetheriaRuntimeDaemonCompassMarker> _daemonCompassMarkersByEntityIndex =
|
||||
new Dictionary<int, AetheriaRuntimeDaemonCompassMarker>();
|
||||
|
||||
public Dictionary<Wormhole, (GameObject gravity, CompassIcon icon)> WormholeInstances = new Dictionary<Wormhole, (GameObject, CompassIcon)>();
|
||||
private List<ItemPickup> _loot = new List<ItemPickup>();
|
||||
|
|
@ -471,6 +475,7 @@ public class ZoneRenderer : MonoBehaviour
|
|||
Shader.SetGlobalFloat("_AsteroidVerticalOffset", ActionGameManager.Instance.Settings.PlanetSettings.AsteroidVerticalOffset);
|
||||
RefreshDaemonBodyPoses();
|
||||
RefreshDaemonAsteroidBeltPoses();
|
||||
RefreshDaemonCompassMarkers();
|
||||
|
||||
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(MainCamera);
|
||||
bool isVisible(Bounds bounds) => GeometryUtility.TestPlanesAABB(planes, bounds);
|
||||
|
|
@ -556,14 +561,16 @@ public class ZoneRenderer : MonoBehaviour
|
|||
{
|
||||
if(entityInstance.CompassIcon)
|
||||
{
|
||||
var difference = entityInstance.Entity.CultPositionXZ - PerspectiveEntity.CultPositionXZ;
|
||||
var distance = CultMath.math.length(difference);
|
||||
|
||||
entityInstance.CompassIcon.gameObject.SetActive(
|
||||
PerspectiveEntity.EntityInfoGathered.ContainsKey(entityInstance.Entity) &&
|
||||
PerspectiveEntity.EntityInfoGathered[entityInstance.Entity] > Settings.GameplaySettings.TargetDetectionInfoThreshold &&
|
||||
distance > _minimapDistance);
|
||||
entityInstance.CompassIcon.transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg - 90);
|
||||
var active = entityInstance.Entity != null &&
|
||||
_daemonCompassMarkersByEntityIndex.TryGetValue(entityInstance.Entity.DaemonEntityIndex, out var marker);
|
||||
entityInstance.CompassIcon.gameObject.SetActive(active);
|
||||
if (active)
|
||||
{
|
||||
entityInstance.CompassIcon.transform.rotation = Quaternion.Euler(
|
||||
0,
|
||||
0,
|
||||
Mathf.Atan2((float)marker.DeltaZ, (float)marker.DeltaX) * Mathf.Rad2Deg - 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -616,6 +623,19 @@ public class ZoneRenderer : MonoBehaviour
|
|||
}
|
||||
}
|
||||
|
||||
private void RefreshDaemonCompassMarkers()
|
||||
{
|
||||
AetheriaRuntimeDaemonRenderQueries.QueryCompassMarkers(
|
||||
_daemonZoneSnapshot,
|
||||
PerspectiveEntity?.DaemonEntityIndex ?? -1,
|
||||
Settings.GameplaySettings.TargetDetectionInfoThreshold,
|
||||
_minimapDistance,
|
||||
_daemonCompassMarkers);
|
||||
_daemonCompassMarkersByEntityIndex.Clear();
|
||||
foreach (var marker in _daemonCompassMarkers)
|
||||
_daemonCompassMarkersByEntityIndex[marker.TargetEntityIndex] = marker;
|
||||
}
|
||||
|
||||
private float GetTerrainHeight(float2 position)
|
||||
{
|
||||
return (float)AetheriaRuntimeDaemonRenderQueries.EvaluateGravityTerrainHeight(
|
||||
|
|
|
|||
|
|
@ -156,6 +156,38 @@ namespace GameCult.Aetheria.State.Verse
|
|||
public double Size { get; }
|
||||
}
|
||||
|
||||
public readonly struct AetheriaRuntimeDaemonCompassMarker
|
||||
{
|
||||
public AetheriaRuntimeDaemonCompassMarker(
|
||||
int targetEntityIndex,
|
||||
double positionX,
|
||||
double positionZ,
|
||||
double deltaX,
|
||||
double deltaZ,
|
||||
double distance,
|
||||
double infoGathered,
|
||||
bool hostile)
|
||||
{
|
||||
TargetEntityIndex = targetEntityIndex;
|
||||
PositionX = positionX;
|
||||
PositionZ = positionZ;
|
||||
DeltaX = deltaX;
|
||||
DeltaZ = deltaZ;
|
||||
Distance = Math.Max(0, distance);
|
||||
InfoGathered = infoGathered;
|
||||
Hostile = hostile;
|
||||
}
|
||||
|
||||
public int TargetEntityIndex { get; }
|
||||
public double PositionX { get; }
|
||||
public double PositionZ { get; }
|
||||
public double DeltaX { get; }
|
||||
public double DeltaZ { get; }
|
||||
public double Distance { get; }
|
||||
public double InfoGathered { get; }
|
||||
public bool Hostile { get; }
|
||||
}
|
||||
|
||||
public readonly struct AetheriaRuntimeGravityTerrainBand
|
||||
{
|
||||
public AetheriaRuntimeGravityTerrainBand(double startDepth, double depthRange)
|
||||
|
|
@ -358,6 +390,64 @@ namespace GameCult.Aetheria.State.Verse
|
|||
return poses.Count;
|
||||
}
|
||||
|
||||
public static AetheriaRuntimeDaemonCompassMarker[] QueryCompassMarkers(
|
||||
AetheriaRuntimeZoneSnapshotCommit? zone,
|
||||
int observerEntityIndex,
|
||||
double minimumInfoGathered,
|
||||
double minimumDistance)
|
||||
{
|
||||
var markers = new List<AetheriaRuntimeDaemonCompassMarker>();
|
||||
QueryCompassMarkers(zone, observerEntityIndex, minimumInfoGathered, minimumDistance, markers);
|
||||
return markers.Count == 0 ? Array.Empty<AetheriaRuntimeDaemonCompassMarker>() : markers.ToArray();
|
||||
}
|
||||
|
||||
public static int QueryCompassMarkers(
|
||||
AetheriaRuntimeZoneSnapshotCommit? zone,
|
||||
int observerEntityIndex,
|
||||
double minimumInfoGathered,
|
||||
double minimumDistance,
|
||||
List<AetheriaRuntimeDaemonCompassMarker> markers)
|
||||
{
|
||||
if (markers == null) throw new ArgumentNullException(nameof(markers));
|
||||
markers.Clear();
|
||||
if (zone == null || observerEntityIndex < 0)
|
||||
return 0;
|
||||
|
||||
var entities = BuildEntityMap(zone);
|
||||
if (!entities.TryGetValue(observerEntityIndex, out var observer))
|
||||
return 0;
|
||||
|
||||
var requiredDistance = Math.Max(0, minimumDistance);
|
||||
foreach (var contact in observer.Contacts ?? Array.Empty<AetheriaRuntimeEntityContactCommit>())
|
||||
{
|
||||
if (contact == null ||
|
||||
!contact.Visible ||
|
||||
contact.InfoGathered <= minimumInfoGathered ||
|
||||
!entities.TryGetValue(contact.TargetEntityIndex, out var target))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var deltaX = target.PositionX - observer.PositionX;
|
||||
var deltaZ = target.PositionZ - observer.PositionZ;
|
||||
var distance = Math.Sqrt(deltaX * deltaX + deltaZ * deltaZ);
|
||||
if (distance <= requiredDistance)
|
||||
continue;
|
||||
|
||||
markers.Add(new AetheriaRuntimeDaemonCompassMarker(
|
||||
target.EntityIndex,
|
||||
target.PositionX,
|
||||
target.PositionZ,
|
||||
deltaX,
|
||||
deltaZ,
|
||||
distance,
|
||||
contact.InfoGathered,
|
||||
contact.Hostile));
|
||||
}
|
||||
|
||||
return markers.Count;
|
||||
}
|
||||
|
||||
public static AetheriaRuntimeDaemonRenderGroupDocument[] QueryRenderGroups(
|
||||
AetheriaRuntimeDaemonSoaViewIndex? index,
|
||||
double minX,
|
||||
|
|
@ -464,6 +554,18 @@ namespace GameCult.Aetheria.State.Verse
|
|||
zone.GravityTerrainDepth - startDepth + maxDepth);
|
||||
}
|
||||
|
||||
private static Dictionary<int, AetheriaRuntimeEntitySnapshotCommit> BuildEntityMap(AetheriaRuntimeZoneSnapshotCommit zone)
|
||||
{
|
||||
var entities = new Dictionary<int, AetheriaRuntimeEntitySnapshotCommit>();
|
||||
foreach (var entity in zone.Entities ?? Array.Empty<AetheriaRuntimeEntitySnapshotCommit>())
|
||||
{
|
||||
if (entity != null && entity.EntityIndex >= 0)
|
||||
entities[entity.EntityIndex] = entity;
|
||||
}
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
private static Dictionary<string, AetheriaRuntimeXzPoint> BuildOrbitPositions(AetheriaRuntimeZoneSnapshotCommit zone)
|
||||
{
|
||||
var source = BuildOrbitMap(zone);
|
||||
|
|
|
|||
Loading…
Reference in a new issue