using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Threading; using Animancer; using BITFALL.Bullet; using BITKit; using BITKit.Entities; using BITKit.Mod; using BITKit.Pool; using BITKit.StateMachine; using BITKit.UX.Hotkey; using BITKit.WorldNode; using Cinemachine; using Cysharp.Threading.Tasks; using Kinemation.MotionWarping.Runtime.Core; using Lightbug.CharacterControllerPro.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Net.Project.B.AI; using Net.Project.B.Buff; using Net.Project.B.Cosmetics; using Net.Project.B.Damage; using Net.Project.B.Emoji; using Net.Project.B.Faction; using Net.Project.B.Health; using Net.Project.B.Interaction; using Net.Project.B.Inventory; using Net.Project.B.Level; using Net.Project.B.Mark; using Net.Project.B.Melee; using Net.Project.B.PDA; using Net.Project.B.Weapon; using NodeCanvas.Framework; using Project.B.Animation; using Project.B.CharacterController; using Project.B.Player; using UnityEngine; using YooAsset; using Object = UnityEngine.Object; namespace Project.B.Entities { public class PlayerFactory:IPlayerFactory { private readonly ILogger _logger; private readonly IServiceCollection _serviceCollection; private readonly IServiceProvider _serviceProvider; private const string PlayerPath = "Player_Base"; private readonly List<(IEntity entity,GameObject go)> _entities = new(); private readonly IHealthService _healthService; private readonly IEntitiesService _entitiesService; private GameObject _playerPrefab; private UniTaskCompletionSource _waitPlayerStart=new(); public PlayerFactory(IServiceProvider serviceProvider, IServiceCollection serviceCollection, ILogger logger, IHealthService healthService, IEntitiesService entitiesService) { _serviceProvider = serviceProvider; _serviceCollection = serviceCollection; _logger = logger; _healthService = healthService; _entitiesService = entitiesService; _entitiesService.OnAdd+= OnNodeRegistered; } private void OnNodeRegistered(IEntity entity) { if(entity.ServiceProvider.GetService() is not {}infoPlayerStart)return; _waitPlayerStart.TrySetResult(entity.ServiceProvider.GetService()); } public IReadOnlyDictionary Entities => _entities.ToDictionary(x => x.entity.Id, x => x.entity); public async UniTask CreateAsync(string addressablePath,object model) { await UniTask.SwitchToMainThread(); if (_playerPrefab is not null) { return await Create(addressablePath); } _playerPrefab =await ModService.LoadAsset(PlayerPath); return await Create(addressablePath); } public event Func OnEntityCreate; public event Func OnEntityCreated; private async UniTask Create(string addressablePath = null) { var entity = new Entity(); var cts = new CancellationTokenSource(); cts.CancelAfter(1000); Vector3 position = default; Quaternion rotation = default; try { var startNode = await _waitPlayerStart.Task.AttachExternalCancellation(cts.Token); position = startNode.position; rotation = startNode.rotation; _logger.LogInformation($"找到出生点:{position}"); } catch (OperationCanceledException) { _logger.LogInformation("没有找到出生点,在默认位置开始"); await UniTask.SwitchToMainThread(); } _waitPlayerStart = new(); InputActionGroup inputActionGroup = new(); var go = Object.Instantiate(_playerPrefab, position, rotation); entity.ServiceCollection.Add(_serviceCollection); entity.CancellationToken = go.GetCancellationTokenOnDestroy(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(new IdComponent() { Id = entity.Id = go.GetInstanceID() , Name = Environment.UserName, }); var blackboard = go.GetComponent(); var animancer = go.GetComponent(); var entityCancellationToken = go.GetCancellationTokenOnDestroy(); entityCancellationToken.Register(entity.Dispose); if (go.TryGetComponent(out var motionWarping) is false) { motionWarping = go.AddComponent(); } entity.ServiceCollection.AddSingleton(motionWarping); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService()); entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService()); entity.ServiceCollection.AddSingleton(typeof(IMicroStateMachine),_serviceProvider.GetRequiredService(typeof(IMicroStateMachine))); entity.ServiceCollection.AddSingleton(typeof(IWrapper), _serviceProvider.GetRequiredService>()); entity.ServiceCollection.AddSingleton(entity); entity.ServiceCollection.AddSingleton(go); entity.ServiceCollection.AddSingleton(go.transform); if (go.TryGetComponent(out var tag)) { entity.ServiceCollection.AddSingleton(tag); } entity.ServiceCollection.AddSingleton(blackboard); entity.ServiceCollection.AddSingleton(go.GetComponent()); entity.ServiceCollection.AddSingleton(go.GetComponentInChildren()); entity.ServiceCollection.AddSingleton(go.GetComponent()); entity.ServiceCollection.AddSingleton(animancer); entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService>()); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(x => x.GetRequiredService().CharacterController); entity.ServiceCollection.AddSingleton(inputActionGroup); entity.ServiceCollection.AddSingleton(_healthService); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton( _serviceProvider.GetRequiredService()); 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(); 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.AddKeyedSingleton(0); entity.ServiceCollection.AddKeyedSingleton(2); entity.ServiceCollection.AddKeyedScoped(nameof(PlayerHandAnimancer)); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService()); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddTransient(); entity.ServiceCollection.AddTransient, PlayerGunController>(); entity.ServiceCollection.AddTransient, PlayerMeleeController>(); entity.ServiceCollection.AddTransient, PlayerSpotterScopeController>(); entity.ServiceCollection.AddTransient, PlayerHandheldController>(); entity.ServiceCollection.AddTransient,PlayerHandheldController>(); entity.ServiceCollection.AddSingleton, UnityEmojiService>(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService()); entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService()); entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService()); entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService()); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); entity.ServiceCollection.AddSingleton(); await OnEntityCreate.UniTaskFunc(addressablePath, entity); await entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); var characterController = entity.ServiceProvider.GetRequiredService(); { var layer0 = entity.ServiceProvider.GetRequiredKeyedService(0); animancer.Layers[1].SetMask(blackboard.GetVariable("avatar_mask_upper").value); animancer.Layers[2].SetMask(blackboard.GetVariable("avatar_mask_lower").value); animancer.Layers[3].IsAdditive = true; var layer2 = entity.ServiceProvider.GetRequiredKeyedService(2); layer0.Layer = 0; layer2.Layer = 2; } characterController.TransitionState(); entity.ServiceProvider.QueryComponents(out IBuffComponent buffComponent); buffComponent.AddBuff(new Hunger() { Value = 32 }); buffComponent.AddBuff(new Thirsty() { Value = 64 }); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); entity.ServiceProvider.GetRequiredService(); var footstep = entity.ServiceProvider.GetRequiredService(); var handController = entity.ServiceProvider.GetRequiredService(); await OnEntityCreated.UniTaskFunc(addressablePath, entity); _entities.Add(new ValueTuple(entity, go)); _logger.LogInformation($"Player Created. {entity.Id}"); _healthService.OnHealthChanged+=OnHealthChanged; entityCancellationToken.Register(DisposeEntity); _entitiesService.Register(entity); return entity; void OnHealthChanged(int arg1, int arg2, int arg3, object arg4) { if(entity.Id!=arg1)return; inputActionGroup.allowInput.SetDisableElements(this, arg3 < 0); } void DisposeEntity() { inputActionGroup.Dispose(); handController.Dispose(); footstep.Dispose(); _entitiesService.UnRegister(entity); _healthService.OnHealthChanged-=OnHealthChanged; } } 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); } } } }