178 lines
7.1 KiB
C#
178 lines
7.1 KiB
C#
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<PlayerFactory> _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<WorldInfoPlayerStart> _waitPlayerStart=new();
|
|
|
|
public YangdunCreateFactory(IServiceProvider serviceProvider, IServiceCollection serviceCollection, IWorldNodeService worldNodeService, ILogger<PlayerFactory> 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<int, IEntity> Entities => _entities.ToDictionary(x => x.entity.Id, x => x.entity);
|
|
|
|
public async UniTask<IEntity> CreateAsync(string addressablePath)
|
|
{
|
|
await UniTask.SwitchToMainThread();
|
|
if (_playerPrefab is not null)
|
|
{
|
|
return await Create(addressablePath);
|
|
}
|
|
var asyncHandle = YooAssets.LoadAssetAsync<GameObject>(PlayerPath);
|
|
await asyncHandle;
|
|
_playerPrefab = asyncHandle.AssetObject as GameObject;
|
|
|
|
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 startNode = await _waitPlayerStart.Task;
|
|
var startTransform = startNode.WorldObject.As<GameObject>().transform;
|
|
|
|
_waitPlayerStart = new();
|
|
|
|
var go = Object.Instantiate(_playerPrefab,startTransform.position,startTransform.rotation);
|
|
|
|
entity.ServiceCollection.Add(_serviceCollection);
|
|
|
|
go.GetCancellationTokenOnDestroy().Register(entity.Dispose);
|
|
|
|
entity.ServiceCollection.AddSingleton<IEntity>(entity);
|
|
|
|
entity.ServiceCollection.AddSingleton(go);
|
|
entity.ServiceCollection.AddSingleton(go.transform);
|
|
|
|
entity.ServiceCollection.AddSingleton(go.GetComponent<IBlackboard>());
|
|
|
|
entity.ServiceCollection.AddSingleton(go.GetComponent<CharacterActor>());
|
|
entity.ServiceCollection.AddSingleton(go.GetComponentInChildren<CinemachineVirtualCameraBase>());
|
|
entity.ServiceCollection.AddSingleton<IAnimancerComponent>(go.GetComponent<AnimancerComponent>());
|
|
|
|
entity.ServiceCollection.AddSingleton<IPlayerCharacterController, PlayerCharacterController>();
|
|
entity.ServiceCollection.AddSingleton<ICharacterController>(x=>x.GetRequiredService<IPlayerCharacterController>().CharacterController);
|
|
|
|
entity.ServiceCollection.AddSingleton(_inputActionGroup);
|
|
|
|
|
|
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<PlayerCameraController>();
|
|
entity.ServiceCollection.AddSingleton<PlayerModelController>();
|
|
|
|
entity.ServiceCollection.AddSingleton<PlayerAnimancerController>();
|
|
|
|
entity.ServiceCollection.AddSingleton(_serviceProvider.GetRequiredService<IWorldInteractionService>());
|
|
entity.ServiceCollection.AddSingleton<PlayerInteractionController>();
|
|
|
|
|
|
await OnEntityCreate.UniTaskFunc(addressablePath,entity);
|
|
|
|
entity.ServiceProvider.GetRequiredService<ICharacterStateWalk>();
|
|
|
|
entity.ServiceProvider.GetRequiredService<PlayerInteractionController>();
|
|
|
|
var characterController = entity.ServiceProvider.GetRequiredService<ICharacterController>();
|
|
|
|
characterController.TransitionState<ICharacterStateWalk>();
|
|
|
|
entity.ServiceProvider.GetRequiredService<PlayerAnimancerController>();
|
|
|
|
entity.ServiceProvider.GetRequiredService<PlayerCameraController>();
|
|
|
|
entity.ServiceProvider.GetRequiredService<PlayerModelController>();
|
|
|
|
|
|
await OnEntityCreated.UniTaskFunc(addressablePath,entity);
|
|
|
|
_entities.Add(new ValueTuple<IEntity, GameObject>(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);
|
|
}
|
|
}
|
|
|
|
}
|