using System.Collections.Generic; using UnityEngine; namespace IdleSpectator; public static class InterestCollector { private static readonly object Gate = new object(); private static readonly List Pending = new List(); public static void OnWorldLogMessage(WorldLogMessage message) { if (message == null) { return; } if (!WorldLogInterestTable.TryGetTier(message.asset_id, out InterestTier tier)) { return; } Vector3 position = message.getLocation(); Actor unit = null; if (message.hasFollowLocation()) { unit = message.unit; } if (unit == null && position == Vector3.zero) { return; } EnqueueDirect(new InterestEvent { Tier = tier, Score = (float)tier * 100f + Time.unscaledTime * 0.001f, Position = position, FollowUnit = unit, Label = WorldLogInterestTable.MakeLabel(message), CreatedAt = Time.unscaledTime, AssetId = message.asset_id }); } public static void EnqueueDirect(InterestEvent interest) { if (interest == null || !interest.HasValidPosition) { return; } lock (Gate) { Pending.Add(interest); if (Pending.Count > 64) { Pending.RemoveRange(0, Pending.Count - 64); } } } public static bool TryGetBest(out InterestEvent best) { lock (Gate) { best = null; if (Pending.Count == 0) { return false; } int bestIndex = 0; for (int i = 1; i < Pending.Count; i++) { InterestEvent candidate = Pending[i]; InterestEvent current = Pending[bestIndex]; if (candidate.Tier > current.Tier || (candidate.Tier == current.Tier && candidate.CreatedAt > current.CreatedAt)) { bestIndex = i; } } best = Pending[bestIndex]; return true; } } public static void Remove(InterestEvent interest) { if (interest == null) { return; } lock (Gate) { Pending.Remove(interest); } } public static void Clear() { lock (Gate) { Pending.Clear(); } } public static int PendingCount { get { lock (Gate) { return Pending.Count; } } } public static bool HasPendingAtLeast(InterestTier minTier) { lock (Gate) { for (int i = 0; i < Pending.Count; i++) { if (Pending[i] != null && Pending[i].Tier >= minTier) { return true; } } return false; } } }