Files
Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/Entities/PlayerFactory.cs

360 lines
15 KiB
C#
Raw Normal View History

2025-06-24 23:49:13 +08:00
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<PlayerFactory> _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<Transform> _waitPlayerStart=new();
public PlayerFactory(IServiceProvider serviceProvider, IServiceCollection serviceCollection, ILogger<PlayerFactory> 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<WorldInfoPlayerStart>() is not {}infoPlayerStart)return;
_waitPlayerStart.TrySetResult(entity.ServiceProvider.GetService<Transform>());
}
public IReadOnlyDictionary<int, IEntity> Entities => _entities.ToDictionary(x => x.entity.Id, x => x.entity);
public async UniTask<IEntity> CreateAsync(string addressablePath,object model)
{
await UniTask.SwitchToMainThread();
if (_playerPrefab is not null)
{
return await Create(addressablePath);
}
_playerPrefab =await ModService.LoadAsset<GameObject>(PlayerPath);
return await Create(addressablePath);
}
public event Func<string, IEntity,UniTask> OnEntityCreate;
public event Func<string, IEntity,UniTask> OnEntityCreated;
private async UniTask<IEntity> 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<LocalPlayerComponent>();
entity.ServiceCollection.AddSingleton(new IdComponent()
{
Id = entity.Id = go.GetInstanceID() ,
Name = Environment.UserName,
});
var blackboard = go.GetComponent<IBlackboard>();
var animancer = go.GetComponent<AnimancerComponent>();
var entityCancellationToken = go.GetCancellationTokenOnDestroy();
entityCancellationToken.Register(entity.Dispose);
if (go.TryGetComponent<MotionWarping>(out var motionWarping) is false)
{
motionWarping = go.AddComponent<MotionWarping>();
}
entity.ServiceCollection.AddSingleton(motionWarping);
entity.ServiceCollection.AddSingleton<Net.Project.B.Faction.Player>();
entity.ServiceCollection.AddSingleton<IFactionType,Net.Project.B.Faction.Player>();
entity.ServiceCollection.AddSingleton<Human>();
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IEntitiesService>());
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IPoolService>());
entity.ServiceCollection.AddSingleton(typeof(IMicroStateMachine<IPlayerControlMode>),_serviceProvider.GetRequiredService(typeof(IMicroStateMachine<IPlayerControlMode>)));
entity.ServiceCollection.AddSingleton(typeof(IWrapper<PlayerSettings>), _serviceProvider.GetRequiredService<IWrapper<PlayerSettings>>());
entity.ServiceCollection.AddSingleton<IEntity>(entity);
entity.ServiceCollection.AddSingleton(go);
entity.ServiceCollection.AddSingleton(go.transform);
if (go.TryGetComponent<ITag>(out var tag))
{
entity.ServiceCollection.AddSingleton(tag);
}
entity.ServiceCollection.AddSingleton(blackboard);
entity.ServiceCollection.AddSingleton(go.GetComponent<CharacterActor>());
entity.ServiceCollection.AddSingleton(go.GetComponentInChildren<CinemachineVirtualCameraBase>());
entity.ServiceCollection.AddSingleton(go.GetComponent<Animator>());
entity.ServiceCollection.AddSingleton(animancer);
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IWrapper<CosmeticsCustomizeComponent>>());
entity.ServiceCollection.AddSingleton<IPlayerCharacterController, PlayerCharacterController>();
entity.ServiceCollection.AddSingleton<ICharacterController>(x =>
x.GetRequiredService<IPlayerCharacterController>().CharacterController);
entity.ServiceCollection.AddSingleton(inputActionGroup);
entity.ServiceCollection.AddSingleton(_healthService);
entity.ServiceCollection.AddSingleton<IHealthComponent, HealthComponent>();
entity.ServiceCollection.AddSingleton<IKnockedComponent, KnockedComponent>();
entity.ServiceCollection.AddSingleton(
_serviceProvider.GetRequiredService<IKnockedService>());
entity.ServiceCollection.AddSingleton<ICharacterInitialize, CharacterInitialize>();
entity.ServiceCollection.AddSingleton<ICharacterStateWalk, CharacterWalkState>();
entity.ServiceCollection.AddSingleton<ICharacterStateIdle, CharacterIdleState>();
entity.ServiceCollection.AddSingleton<ICharacterStateCrouched, CharacterCrouchedState>();
entity.ServiceCollection.AddSingleton<ICharacterStateRun, CharacterRunState>();
entity.ServiceCollection.AddSingleton<ICharacterSprint, CharacterSprintState>();
entity.ServiceCollection.AddSingleton<ICharacterStateStepUp, CharacterStepUpState>();
entity.ServiceCollection.AddSingleton<ICharacterKnocked, CharacterKnockedState>();
entity.ServiceCollection.AddSingleton<ICharacterSliding, CharacterSlidingState>();
entity.ServiceCollection.AddSingleton<ICharacterStateClimb, CharacterClimbState>();
entity.ServiceCollection.AddSingleton<ICharacterSeating, CharacterSeating>();
entity.ServiceCollection.AddSingleton<ICharacterStateAnimation, CharacterAnimationState>();
entity.ServiceCollection.AddSingleton<ICharacterLadder, CharacterLadderState>();
entity.ServiceCollection.AddSingleton<ICharacterParachute, CharacterParachute>();
entity.ServiceCollection.AddSingleton<ICharacterFreeFall, CharacterFreeFall>();
entity.ServiceCollection.AddSingleton<ICharacterSwimming, CharacterSwimming>();
entity.ServiceCollection.AddSingleton<ICharacterStateVault, CharacterVaultState>();
entity.ServiceCollection.AddSingleton<PlayerCameraController>();
entity.ServiceCollection.AddSingleton<PlayerModelController>();
entity.ServiceCollection.AddKeyedSingleton<PlayerAnimancerController>(0);
entity.ServiceCollection.AddKeyedSingleton<PlayerAnimancerController>(2);
entity.ServiceCollection.AddKeyedScoped<PlayerAnimancerController>(nameof(PlayerHandAnimancer));
entity.ServiceCollection.AddSingleton<PlayerAnimancerEmoji>();
entity.ServiceCollection.AddSingleton<PlayerHandAnimancer>();
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IWorldInteractionService>());
entity.ServiceCollection.AddSingleton<IHotkeyCollection,PlayerInteractionController>();
entity.ServiceCollection.AddSingleton<IPlayerInventory, PlayerInventory>();
entity.ServiceCollection.AddSingleton<IPlayerWeaponInventory, PlayerWeaponInventory>();
entity.ServiceCollection.AddSingleton<IPlayerEquipmentInventory, PlayerEquipmentInventory>();
entity.ServiceCollection.AddSingleton<PlayerClothInventory>();
entity.ServiceCollection.AddTransient<IPlayerWeaponController, PlayerWeaponController>();
entity.ServiceCollection.AddTransient<IPlayerWeaponController<PlayerGunControllerClass>, PlayerGunController>();
entity.ServiceCollection.AddTransient<IPlayerWeaponController<PlayerMeleeControllerClass>, PlayerMeleeController>();
entity.ServiceCollection.AddTransient<IPlayerWeaponController<PlayerSpotterScopeControllerClass>, PlayerSpotterScopeController>();
entity.ServiceCollection.AddTransient<IPlayerWeaponController<PlayerHandheldControllerClass>, PlayerHandheldController>();
entity.ServiceCollection.AddTransient<IPlayerWeaponController<AppControllerClass>,PlayerHandheldController>();
entity.ServiceCollection.AddSingleton<IEmojiService<AnimationClip>, UnityEmojiService>();
entity.ServiceCollection.AddSingleton<PlayerCosmeticsService>();
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IBulletService>());
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IDamageService>());
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IMeleeService>());
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IMarkService>());
entity.ServiceCollection.AddSingleton<PlayerFootstepController>();
entity.ServiceCollection.AddSingleton<IBuffComponent,BuffComponent>();
entity.ServiceCollection.AddSingleton<LevelComponent>();
await OnEntityCreate.UniTaskFunc(addressablePath, entity);
await entity.ServiceProvider.GetRequiredService<PlayerCosmeticsService>();
entity.ServiceProvider.GetRequiredService<ICharacterStateWalk>();
entity.ServiceProvider.GetRequiredService<IHotkeyCollection>();
entity.ServiceProvider.GetRequiredService<PlayerClothInventory>();
var characterController = entity.ServiceProvider.GetRequiredService<ICharacterController>();
{
var layer0 = entity.ServiceProvider.GetRequiredKeyedService<PlayerAnimancerController>(0);
animancer.Layers[1].SetMask(blackboard.GetVariable<AvatarMask>("avatar_mask_upper").value);
animancer.Layers[2].SetMask(blackboard.GetVariable<AvatarMask>("avatar_mask_lower").value);
animancer.Layers[3].IsAdditive = true;
var layer2 = entity.ServiceProvider.GetRequiredKeyedService<PlayerAnimancerController>(2);
layer0.Layer = 0;
layer2.Layer = 2;
}
characterController.TransitionState<ICharacterInitialize>();
entity.ServiceProvider.QueryComponents(out IBuffComponent buffComponent);
buffComponent.AddBuff(new Hunger()
{
Value = 32
});
buffComponent.AddBuff(new Thirsty()
{
Value = 64
});
entity.ServiceProvider.GetRequiredService<PlayerCameraController>();
entity.ServiceProvider.GetRequiredService<PlayerModelController>();
entity.ServiceProvider.GetRequiredService<PlayerAnimancerEmoji>();
entity.ServiceProvider.GetRequiredService<IPlayerInventory>();
entity.ServiceProvider.GetRequiredService<IPlayerWeaponInventory>();
entity.ServiceProvider.GetRequiredService<LevelComponent>();
var footstep = entity.ServiceProvider.GetRequiredService<PlayerFootstepController>();
var handController = entity.ServiceProvider.GetRequiredService<PlayerHandAnimancer>();
await OnEntityCreated.UniTaskFunc(addressablePath, entity);
_entities.Add(new ValueTuple<IEntity, GameObject>(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);
}
}
}
}