using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using BITKit; using BITKit.Entities; using Cysharp.Threading.Tasks; using Microsoft.Extensions.Logging; using Net.Project.B.Interaction; using Project.B.Map; using UnityEngine; using Object = UnityEngine.Object; namespace Net.Project.B.WorldNode { public class UnityEvacuateService:IDisposable { private readonly ILogger _logger; private readonly IGameMapService _gameMapService; private readonly IEntitiesService _entitiesService; private readonly IWorldInteractionService _interactionService; private readonly ConcurrentDictionary _scriptableEvacuates = new(); private CancellationTokenSource _cancellationTokenSource=new(); public UnityEvacuateService(IWorldInteractionService interactionService, IEntitiesService entitiesService, IGameMapService gameMapService, ILogger logger) { _interactionService = interactionService; _entitiesService = entitiesService; _gameMapService = gameMapService; _logger = logger; _interactionService.OnInteraction += OnInteraction; foreach (var x in entitiesService.QueryComponents()) { _scriptableEvacuates[x.EvacuateType.GetType()] = x; } _gameMapService.OnMapChanging += OnMapChanging; _entitiesService.OnAdd += OnAdd; } private void OnAdd(IEntity entity) { if(entity.ServiceProvider.QueryComponents(out UnityEvacuateNode evacuateNode) is false)return; if(_scriptableEvacuates.TryGetValue(evacuateNode.EvacuateType.GetType(),out var scriptableEvacuate) is false)return; scriptableEvacuate.Initialize(entity); } private UniTask OnMapChanging(string arg) { if (string.IsNullOrEmpty(arg)) { _cancellationTokenSource.Cancel(); _cancellationTokenSource = new(); } return UniTask.CompletedTask; } private void OnInteraction(object arg1, IWorldInteractable arg2, WorldInteractionProcess arg3, object arg4) { if(arg3 is not (WorldInteractionProcess.Performed or WorldInteractionProcess.System))return; if(_entitiesService.TryGetEntity(arg2.Id,out var entity) is false)return; if(entity.ServiceProvider.QueryComponents(out UnityEvacuateNode evacuateNode) is false)return; if(entity.ServiceProvider.QueryComponents(out GameObject gameObject) is false)return; Object.Destroy(gameObject); if (_scriptableEvacuates.TryGetValue(evacuateNode.EvacuateType.GetType(), out var scriptableEvacuate)) { var instance = Object.Instantiate(scriptableEvacuate); instance.Invoke(entity,_cancellationTokenSource.Token).Forget(); _logger.LogInformation($"已执行{evacuateNode.EvacuateType.GetType().Name}"); } else { _logger.LogWarning($"未找到{evacuateNode.EvacuateType.GetType().Name}"); } } public void Dispose() { _cancellationTokenSource?.Dispose(); } } }