Net.Like.Xue.Tokyo/Packages-Local/Com.Project.B.Unity/GameServices/GameMapPlayerService.cs

118 lines
3.7 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using BITKit;
using BITKit.Entities;
using BITKit.WorldNode;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Project.B.CharacterController;
using Project.B.Entities;
using Project.B.Map;
using UnityEngine;
using UnityEngine.AI;
namespace Project.B.Player
{
public class GameMapPlayerService:IDisposable
{
private readonly IEntitiesService _entitiesService;
private readonly IGameMapService _gameMapService;
private readonly IPlayerFactory _playerFactory;
private readonly INpcFactory _npcFactory;
private UniTaskCompletionSource<IEntity> _player=new();
private readonly ILogger<GameMapPlayerService> _logger;
private bool _isDisposed;
public GameMapPlayerService(IPlayerFactory playerFactory, IGameMapService gameMapService, INpcFactory npcFactory, IEntitiesService entitiesService, ILogger<GameMapPlayerService> logger)
{
_playerFactory = playerFactory;
_gameMapService = gameMapService;
_npcFactory = npcFactory;
_entitiesService = entitiesService;
_logger = logger;
_entitiesService.OnAdd += OnAdd;
_gameMapService.OnTaskStatusChanged += OnTaskStatusChanged;
_gameMapService.OnMapChanging += OnMapChanging;
}
private async UniTask OnMapChanging(string arg)
{
await _player.Task;
}
private async void OnAdd(IEntity entity)
{
if (entity.ServiceProvider.QueryComponents(out WorldInfoNpcStartNode _) is false) return;
entity.ServiceProvider.QueryComponents(out GameObject gameObject);
if(!gameObject)return;
var gameObjectName = gameObject.name;
await UniTask.NextFrame();
if(_isDisposed)return;
try
{
var npc = await _npcFactory.CreateAsync(null,
entity.ServiceProvider.QueryComponents(out Animator _) ? gameObject : null);
if (npc.ServiceProvider.QueryComponents(out ICharacterController characterController))
{
characterController.Position = gameObject.transform.position;
characterController.Rotation = gameObject.transform.rotation;
}
else if (npc.ServiceProvider.QueryComponents(out NavMeshAgent agent))
{
agent.transform.rotation = gameObject.transform.rotation;
}
else if (npc.ServiceProvider.QueryComponents(out Transform transform))
{
transform.SetPositionAndRotation(gameObject.transform.position, gameObject.transform.rotation);
}
}
catch (Exception)
{
_logger.LogError($"{gameObjectName}创建失败",gameObject);
throw;
}
}
private async void OnTaskStatusChanged(TaskStatus arg1, TaskStatus arg2)
{
switch (arg2)
{
case TaskStatus.Created:
_playerFactory.Dispose();
break;
case TaskStatus.RanToCompletion:
_player.TrySetResult(await _playerFactory.CreateAsync(null,null));
_player = new();
break;
}
}
public void Dispose()
{
_gameMapService.OnTaskStatusChanged -= OnTaskStatusChanged;
_entitiesService.OnAdd -= OnAdd;
_isDisposed = true;
}
}
}