using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using Animancer; using BITKit; using BITKit.Entities; using BITKit.GameSocket; using BITKit.WorldNode; using Cinemachine; using Cysharp.Threading.Tasks; using Lightbug.CharacterControllerPro.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Net.Project.B.Health; using Net.Project.B.Interaction; using Net.Project.B.Inventory; using Net.Project.B.Weapon; using NodeCanvas.Framework; using Project.B.Animation; using Project.B.CharacterController; using Project.B.Entities; using UnityEngine; using YooAsset; using Object = UnityEngine.Object; namespace Net.Like.Xue.Tokyo { public class YangdunCreateFactory : IPlayerFactory { private readonly ILogger _logger; private readonly IServiceCollection _serviceCollection; private readonly IServiceProvider _serviceProvider; private readonly IWorldNodeService _worldNodeService; private const string PlayerPath = "Player_Base"; private readonly List<(IEntity entity,GameObject go)> _entities = new(); private readonly IHealthService _healthService; private GameObject _playerPrefab; private readonly InputActionGroup _inputActionGroup=new(); private UniTaskCompletionSource _waitPlayerStart=new(); public YangdunCreateFactory(IServiceProvider serviceProvider, IServiceCollection serviceCollection, IWorldNodeService worldNodeService, ILogger logger, IHealthService healthService) { _serviceProvider = serviceProvider; _serviceCollection = serviceCollection; _worldNodeService = worldNodeService; _logger = logger; _healthService = healthService; _worldNodeService.OnNodeRegistered += OnNodeRegistered; _healthService.OnHealthChanged+=OnHealthChanged; } private void OnNodeRegistered(IWorldNode obj) { if(obj is not WorldInfoPlayerStart infoPlayerStart)return; _waitPlayerStart.TrySetResult(infoPlayerStart); } public IReadOnlyDictionary Entities => _entities.ToDictionary(x => x.entity.Id, x => x.entity); public async UniTask CreateAsync(string addressablePath) { await UniTask.SwitchToMainThread(); if (_playerPrefab is not null) { return await Create(addressablePath); } var asyncHandle = YooAssets.LoadAssetAsync(PlayerPath); await asyncHandle; _playerPrefab = asyncHandle.AssetObject as GameObject; return await Create(addressablePath); } public event Func OnEntityCreate; public event Func OnEntityCreated; private async UniTask Create(string addressablePath = null) { var entity = new Entity(); var startNode = await _waitPlayerStart.Task; var startTransform = startNode.WorldObject.As().transform; _waitPlayerStart = new(); var go = Object.Instantiate(_playerPrefab,startTransform.position,startTransform.rotation); entity.ServiceCollection.Add(_serviceCollection); go.GetCancellationTokenOnDestroy().Register(entity.Dispose); entity.ServiceCollection.AddSingleton(entity); entity.ServiceCollection.AddSingleton(go); entity.ServiceCollection.AddSingleton(go.transform); entity.ServiceCollection.AddSingleton(go.GetComponent()); entity.ServiceCollection.AddSingleton(go.GetComponent()); entity.ServiceCollection.AddSingleton(go.GetComponentInChildren()); entity.ServiceCollection.AddSingleton(go.GetComponent()); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(x=>x.GetRequiredService().CharacterController); entity.ServiceCollection.AddSingleton(_inputActionGroup); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService()); entity.ServiceCollection.AddSingleton(); await OnEntityCreate.UniTaskFunc(addressablePath,entity); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); var characterController = entity.ServiceProvider.GetRequiredService(); characterController.TransitionState(); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); await OnEntityCreated.UniTaskFunc(addressablePath,entity); _entities.Add(new ValueTuple(entity,go)); _logger.LogInformation($"Player Created. {entity.Id}"); return entity; } public async void Dispose() { await UniTask.SwitchToMainThread(); foreach (var (entity, go) in _entities) { if (entity is IDisposable disposable) { disposable.Dispose(); } if (go) Object.Destroy(go); } _healthService.OnHealthChanged-=OnHealthChanged; } private void OnHealthChanged(int arg1, int arg2, int arg3, object arg4) { _inputActionGroup.allowInput.SetDisableElements(this,arg3<0); } } }