using System.Collections.Generic; using GeometryTD.Entity; using GeometryTD.Map; using UnityEngine; namespace GeometryTD.CustomComponent { internal sealed class SpawnerResolver { private readonly List _spawners = new(); private readonly Dictionary _spawnerByOrder = new(); private readonly List _pathBuffer = new(); private int _nextSpawnerIndex; private int _currentMapEntityId; public void Reset() { _spawners.Clear(); _spawnerByOrder.Clear(); _pathBuffer.Clear(); _nextSpawnerIndex = 0; _currentMapEntityId = 0; } public void RefreshCache(CombatScheduler combatScheduler, bool force) { MapEntity currentMap = combatScheduler != null ? combatScheduler.CurrentMap : null; if (currentMap == null) { Reset(); return; } if (!force && _currentMapEntityId == currentMap.Id && _spawners.Count > 0) { return; } _spawners.Clear(); _spawnerByOrder.Clear(); _nextSpawnerIndex = 0; _currentMapEntityId = currentMap.Id; Spawner[] mapSpawners = currentMap.Spawners; for (int i = 0; i < mapSpawners.Length; i++) { Spawner spawner = mapSpawners[i]; if (spawner == null) { continue; } if (!currentMap.TryGetDefaultPathCells(spawner, out _)) { continue; } _spawners.Add(spawner); if (spawner.SpawnOrder > 0 && !_spawnerByOrder.ContainsKey(spawner.SpawnOrder)) { _spawnerByOrder[spawner.SpawnOrder] = spawner; } } _spawners.Sort((left, right) => left.SpawnOrder.CompareTo(right.SpawnOrder)); } public bool TryResolveSpawnPath(CombatScheduler combatScheduler, int spawnPointId, out IReadOnlyList pathPoints) { pathPoints = null; MapEntity currentMap = combatScheduler != null ? combatScheduler.CurrentMap : null; if (currentMap == null) { return false; } Spawner spawner = ResolveSpawner(spawnPointId); if (spawner == null) { return false; } if (!currentMap.TryFindPathWorldPoints(spawner, null, _pathBuffer) || _pathBuffer.Count <= 0) { return false; } pathPoints = _pathBuffer; return true; } private Spawner ResolveSpawner(int spawnPointId) { if (spawnPointId > 0 && _spawnerByOrder.TryGetValue(spawnPointId, out Spawner mappedSpawner)) { return mappedSpawner; } if (_spawners.Count <= 0) { return null; } Spawner fallbackSpawner = _spawners[_nextSpawnerIndex % _spawners.Count]; _nextSpawnerIndex++; return fallbackSpawner; } } }