// Assets/_Project/Scripts/UI/Minimap/MinimapEntityRegistry.cs
using System;
using System.Collections.Generic;
using UnityEngine;
namespace TD.UI.Minimap
{
///
/// Visual category for a minimap entity. Determines the shape and size of the icon drawn
/// by . Color is supplied separately by the entity itself so the
/// view does not need to know about ownership / faction mapping.
///
public enum MinimapIconKind : byte
{
Enemy,
Tower,
Builder,
}
///
/// Anything that wants to appear on the minimap as a dynamic icon implements this. The view
/// reads every getter on each refresh tick, so values may change between reads (movement is
/// fine — no caching needed).
///
public interface IMinimapEntity
{
Vector3 WorldPosition { get; }
Color MinimapColor { get; }
MinimapIconKind IconKind { get; }
///
/// The entity's diameter (or footprint extent) in world units. The view converts this
/// to pixels using the current minimap zoom, so a 2×2 tower will appear as a 2-tile
/// square on the minimap and adjacent towers will visually touch — matching their
/// world-space relationship. For point-like entities (builders, enemies) the view
/// also enforces a minimum pixel size so they stay visible when fully zoomed out.
///
float MinimapWorldSize { get; }
}
///
/// Static registry of every entity currently visible on the minimap. Entities register
/// themselves on spawn and deregister on despawn; the iterates the
/// set on each refresh.
///
///
/// Backing store is a so duplicate Register calls are no-ops and
/// Deregister is O(1). Iteration uses the struct enumerator via to
/// avoid the boxing that would happen if we exposed an .
///
/// Static lifetime is intentional: the registry survives scene transitions only if entities
/// remember to deregister. NGO's OnNetworkDespawn covers that for towers / builders /
/// enemies. Manual is provided for tests and for explicit reset on match
/// teardown if needed.
///
public static class MinimapEntityRegistry
{
private static readonly HashSet s_entities = new HashSet();
/// Number of currently-registered entities. Cheap, no allocation.
public static int Count => s_entities.Count;
///
/// Registers for minimap rendering. No-op if already registered.
/// Safe to call from any thread that Unity allows (i.e., the main thread).
///
public static void Register(IMinimapEntity entity)
{
if (entity == null) return;
s_entities.Add(entity);
}
/// Removes from the registry. No-op if not present.
public static void Deregister(IMinimapEntity entity)
{
if (entity == null) return;
s_entities.Remove(entity);
}
///
/// Invokes once per registered entity. Uses HashSet's struct
/// enumerator so iteration is allocation-free (the only allocation is the closure that
/// may carry, which is the caller's choice).
///
public static void ForEach(Action action)
{
if (action == null) return;
foreach (var e in s_entities) action(e);
}
/// Drops every registered entity. Tests and explicit match-teardown use only.
public static void Clear() => s_entities.Clear();
}
}