using System; using Cysharp.Threading.Tasks; using UnityEngine.Pool; namespace DanieleMarotta.RiversongCodeShowcase { public class EntityIdMapUpdateSystem : GameSystem, IInitializable, IDisposable, IOnWorldGenerationCompletedCallback { [InjectService] private IEntityCollection _entityCollection; [InjectService] private ISignalBus _signalBus; [InjectService] private World _world; [InjectService] private GameConfig _config; public EntityIdMapUpdateSystem(IServiceLocator serviceLocator) : base(serviceLocator) { } public UniTask InitializeAsync() { _entityCollection.On().Added += OnConstructionSiteAdded; _entityCollection.On().Removed += OnConstructionSiteRemoved; _entityCollection.On().Added += OnBuildingAdded; _entityCollection.On().Removed += OnBuildingRemoved; _signalBus.Subscribe(OnWorldGenerationCompleted); _signalBus.Subscribe(OnRawResourcesRemoved); return UniTask.CompletedTask; } public void Dispose() { _entityCollection.On().Added -= OnConstructionSiteAdded; _entityCollection.On().Removed -= OnConstructionSiteRemoved; _entityCollection.On().Added -= OnBuildingAdded; _entityCollection.On().Removed -= OnBuildingRemoved; _signalBus.Unsubscribe(OnWorldGenerationCompleted); _signalBus.Unsubscribe(OnRawResourcesRemoved); } private void OnConstructionSiteAdded(ConstructionSite constructionSite) { _world.EntityIdMap.SetBuildingId(constructionSite.Rect, constructionSite.Id); } private void OnConstructionSiteRemoved(ConstructionSite constructionSite) { _world.EntityIdMap.SetBuildingId(constructionSite.Rect, Entity.InvalidId); } private void OnBuildingAdded(Building building) { _world.EntityIdMap.SetBuildingId(building.Rect, building.Id); } private void OnBuildingRemoved(Building building) { _world.EntityIdMap.SetBuildingId(building.Rect, Entity.InvalidId); } private void OnWorldGenerationCompleted(WorldGenerationCompletedSignal signal) { signal.Callbacks.Add(this); } public UniTask OnWorldGenerationCompletedAsync(World world) { foreach (var resourceNode in _world.RawResources) _world.EntityIdMap.SetResourceNodeId(resourceNode.Tile, resourceNode.DefinitionId); return UniTask.CompletedTask; } private void OnRawResourcesRemoved(RawResourcesRemovedSignal signal) { using var resourceNodesScope = ListPool<(int, bool)>.Get(out var resourceNodes); foreach (var removedResourceNode in signal.ResourceNodes) { resourceNodes.Clear(); _world.RawResources.GetResourceNodes(TileRect.OneTile(removedResourceNode.Tile), _config.GeneralSettings.BaseElevation, resourceNodes); var definitionId = Entity.InvalidId; if (resourceNodes.Count > 0) { var (resourceId, _) = resourceNodes[0]; _world.RawResources.TryGetResourceNode(resourceId, out var resourceNode); definitionId = resourceNode.DefinitionId; } _world.EntityIdMap.SetResourceNodeId(removedResourceNode.Tile, definitionId); } } } }