/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ using System; using System.Linq; using GameCult.Aetheria.State.Verse; public sealed class AetheriaUnityObservedTargetQuery { private readonly Func _resolveClient; private readonly AetheriaUnityObservedFacadeIndex _facadeIndex; public AetheriaUnityObservedTargetQuery( Func resolveClient, AetheriaUnityObservedFacadeIndex facadeIndex) { _resolveClient = resolveClient ?? (() => null); _facadeIndex = facadeIndex ?? throw new ArgumentNullException(nameof(facadeIndex)); } public Entity GetObservedTarget(Entity observer) { if (TryQueryEntityTarget(observer, out var targetEntityIndex) && _facadeIndex.TryResolveEntityByDaemonIndex(targetEntityIndex, out var targetEntity)) { return targetEntity; } return null; } public float GetObservedInfoGathered(Entity observer, Entity target) { return TryQueryEntityContact(observer, target, out var contact) ? (float)contact.InfoGathered : 0f; } public bool IsObservedHostileContact(Entity observer, Entity target) { return TryQueryEntityContact(observer, target, out var contact) && contact.Hostile; } public AetheriaRuntimeZoneContactRow[] GetObservedVisibleContacts( Entity observer, double minimumInfoGathered, bool visibleOnly) { var contacts = ReadZoneContacts(); if (observer == null || contacts == null) return Array.Empty(); return (contacts.Contacts ?? Array.Empty()) .Where(contact => contact.ObserverEntityIndex == observer.DaemonEntityIndex && contact.InfoGathered > minimumInfoGathered && (!visibleOnly || contact.Visible)) .ToArray(); } private bool TryQueryEntityContact( Entity observer, Entity target, out AetheriaRuntimeZoneContactRow contact) { contact = default; if (observer == null || target == null) return false; contact = (ReadZoneContacts()?.Contacts ?? Array.Empty()) .FirstOrDefault(row => row.ObserverEntityIndex == observer.DaemonEntityIndex && row.TargetEntityIndex == target.DaemonEntityIndex); return contact != null; } private bool TryQueryEntityTarget( Entity observer, out int targetEntityIndex) { targetEntityIndex = -1; if (observer == null) return false; targetEntityIndex = (ReadZoneContacts()?.Targets ?? Array.Empty()) .FirstOrDefault(row => row.EntityIndex == observer.DaemonEntityIndex) ?.TargetEntityIndex ?? -1; return targetEntityIndex >= 0; } private AetheriaRuntimeZoneContactsDocument ReadZoneContacts() { try { return _resolveClient() ?.Aetheria() .ZoneContacts .LatestAsync() .GetAwaiter() .GetResult(); } catch { return null; } } }