260 lines
9.4 KiB
C#
260 lines
9.4 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using BITKit;
|
|
using BITKit.Entities;
|
|
using Cysharp.Threading.Tasks;
|
|
using Microsoft.CodeAnalysis.Diagnostics;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Net.Project.B.Inventory;
|
|
using Net.Project.B.Item;
|
|
using NodeCanvas.Framework;
|
|
using Project.B.CharacterController;
|
|
using Project.B.Item;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace Net.Project.B.Cosmetics
|
|
{
|
|
public class PlayerCosmeticsService:IDisposable
|
|
{
|
|
private readonly IPlayerInventory _playerInventory;
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly Animator _animator;
|
|
private readonly IWrapper<CosmeticsCustomizeComponent> _cosmeticsCustomize;
|
|
private readonly IManagedItemService _managedItemService;
|
|
private readonly IEntitiesService _entitiesService;
|
|
private readonly IBlackboard _blackboard;
|
|
|
|
private readonly ConcurrentDictionary<int, GameObject> _instanced = new();
|
|
private readonly ConcurrentDictionary<int, GameObject> _cosmeticsInstances = new();
|
|
|
|
private readonly ConcurrentDictionary<int, ScriptableItem> _scriptableItems = new();
|
|
private Transform _weapon;
|
|
private readonly UniTaskCompletionSource _waitUntilInitialized = new();
|
|
public UniTask.Awaiter GetAwaiter() => _waitUntilInitialized.Task.GetAwaiter();
|
|
public PlayerCosmeticsService(IEntitiesService entitiesService, IBlackboard blackboard, IWrapper<CosmeticsCustomizeComponent> cosmeticsCustomize, Animator animator, IManagedItemService managedItemService, IServiceProvider serviceProvider, IPlayerInventory playerInventory)
|
|
{
|
|
_entitiesService = entitiesService;
|
|
_blackboard = blackboard;
|
|
_cosmeticsCustomize = cosmeticsCustomize;
|
|
_animator = animator;
|
|
_managedItemService = managedItemService;
|
|
_serviceProvider = serviceProvider;
|
|
_playerInventory = playerInventory;
|
|
|
|
_cosmeticsCustomize.OnValueChanged += OnCosmeticsChanged;
|
|
|
|
|
|
|
|
foreach (var x in _entitiesService.QueryComponents<ScriptableItem>())
|
|
{
|
|
_scriptableItems.TryAdd(x.Id, x);
|
|
}
|
|
|
|
Init();
|
|
}
|
|
|
|
private async void Init()
|
|
{
|
|
var arg2 = _cosmeticsCustomize.Value;
|
|
|
|
var cosmetics = _entitiesService
|
|
.QueryComponents<ScriptableCosmetics>()
|
|
.ToArray().Where(x => arg2.ComponentIds.Contains(x.ScriptableId))
|
|
.ToArray();
|
|
|
|
foreach (var x in _cosmeticsInstances.Values)
|
|
{
|
|
SetupModel(x, false);
|
|
Object.Destroy(x);
|
|
}
|
|
|
|
_cosmeticsInstances.Clear();
|
|
|
|
foreach (var cosmetic in cosmetics)
|
|
{
|
|
switch (cosmetic.CosmeticsClass)
|
|
{
|
|
case CosmeticsModel:
|
|
{
|
|
var model = _blackboard.GetVariable<GameObject>("player_model").value;
|
|
model.DestoryChilds();
|
|
|
|
var newModel = Object.Instantiate(cosmetic.Model, model.transform);
|
|
newModel.localPosition = default;
|
|
newModel.localRotation = default;
|
|
|
|
if (newModel.TryGetComponent<IBlackboard>(out var newBlackboard))
|
|
{
|
|
foreach (var (name, variable) in newBlackboard.variables)
|
|
{
|
|
_blackboard.SetVariableValue(name, variable.value);
|
|
}
|
|
}
|
|
|
|
_animator.Rebind();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
await UniTask.NextFrame();
|
|
_animator.Rebind();
|
|
|
|
OnCosmeticsChanged(null,_cosmeticsCustomize.Value);
|
|
|
|
_waitUntilInitialized.TrySetResult();
|
|
|
|
var equipmentInventory = _serviceProvider.GetRequiredService<IPlayerEquipmentInventory>();
|
|
|
|
equipmentInventory.OnItemAdded += OnAdded;
|
|
equipmentInventory.OnItemRemoved += OnRemoved;
|
|
equipmentInventory.OnItemConsumed += OnRemoved;
|
|
|
|
_serviceProvider.GetRequiredService<IPlayerWeaponInventory>().StateMachine.OnStateChanged += OnStateChanged;
|
|
}
|
|
|
|
private void OnStateChanged(IPlayerWeaponController arg1, IPlayerWeaponController arg2)
|
|
{
|
|
if (_weapon)
|
|
{
|
|
SetupModel(_weapon.gameObject,false);
|
|
Object.Destroy(_weapon.gameObject);
|
|
}
|
|
|
|
if (arg2 is null)
|
|
{
|
|
_weapon = null;
|
|
return;
|
|
}
|
|
|
|
|
|
if(_managedItemService.Items.TryGetValue(arg2.Identifier,out var item) is false && _playerInventory.Container.ItemDictionary.TryGetValue(arg2.Identifier,out item) is false)return;
|
|
if(_scriptableItems.TryGetValue(item.ScriptableId,out var scriptableItem) is false)return;
|
|
if(!scriptableItem.Model)return;
|
|
if( _blackboard.GetVariable<Transform>("player_weapon").value is not {} playerWeapon || !playerWeapon)return;
|
|
|
|
_weapon = Object.Instantiate(scriptableItem.Model, playerWeapon);
|
|
|
|
_weapon.localPosition = _weapon.localEulerAngles = default;
|
|
|
|
SetupModel(_weapon.gameObject,true);
|
|
_serviceProvider.GetRequiredService<IPlayerCharacterController>().AllowTpsCamera.Invoke();
|
|
}
|
|
|
|
private void OnRemoved(int arg1, IRuntimeItem arg2)
|
|
{
|
|
if(_instanced.TryRemove(arg2.ScriptableId,out var model) is false)return;
|
|
if(!model)return;
|
|
SetupModel(model, false);
|
|
|
|
Object.Destroy(model);
|
|
}
|
|
|
|
private void OnAdded(int arg1, IRuntimeItem arg2)
|
|
{
|
|
if(_entitiesService.QueryComponents<ScriptableItem>().ToArray().FirstOrDefault(x=>x.Id == arg2.ScriptableId) is not ScriptableCloth scriptableCloth)return;
|
|
|
|
if(!scriptableCloth.ClothModel)return;
|
|
|
|
var bone = _animator.GetBoneTransform(scriptableCloth.Bone);
|
|
|
|
var newModel = Object.Instantiate(scriptableCloth.ClothModel,bone);
|
|
|
|
foreach (var x in newModel.GetComponentsInChildren<Collider>())
|
|
{
|
|
Object.Destroy(x);
|
|
}
|
|
|
|
SetupModel(newModel.gameObject, true);
|
|
|
|
_instanced.TryAdd(arg2.ScriptableId, newModel.gameObject);
|
|
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_cosmeticsCustomize.OnValueChanged -= OnCosmeticsChanged;
|
|
}
|
|
|
|
private void OnCosmeticsChanged(CosmeticsCustomizeComponent arg1, CosmeticsCustomizeComponent arg2)
|
|
{
|
|
var cosmetics = _entitiesService
|
|
.QueryComponents<ScriptableCosmetics>()
|
|
.ToArray().Where(x=>arg2.ComponentIds.Contains(x.ScriptableId))
|
|
.ToArray();
|
|
|
|
foreach (var x in _cosmeticsInstances.Values)
|
|
{
|
|
SetupModel(x, false);
|
|
Object.Destroy(x);
|
|
}
|
|
_cosmeticsInstances.Clear();
|
|
|
|
|
|
foreach (var cosmetic in cosmetics)
|
|
{
|
|
switch (cosmetic.CosmeticsClass)
|
|
{
|
|
|
|
case CosmeticsHat:
|
|
{
|
|
var bone = _animator.GetBoneTransform(cosmetic.Bone);
|
|
if (!bone)
|
|
{
|
|
Debug.LogWarning(_animator.name + "没有找到" + cosmetic.Bone + "骨骼");
|
|
continue;
|
|
}
|
|
var newModel = Object.Instantiate(cosmetic.Model,bone);
|
|
|
|
foreach (var x in newModel.GetComponentsInChildren<Collider>())
|
|
{
|
|
Object.Destroy(x);
|
|
}
|
|
|
|
newModel.localPosition = default;
|
|
newModel.localRotation = default;
|
|
|
|
_cosmeticsInstances.TryAdd(cosmetic.ScriptableId, newModel.gameObject);
|
|
|
|
SetupModel(newModel.gameObject, true);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetupModel(GameObject model,bool isRegister)
|
|
{
|
|
foreach (var collider in model.GetComponentsInChildren<Collider>())
|
|
{
|
|
Object.Destroy(collider);
|
|
}
|
|
|
|
foreach (var rigidbody in model.GetComponentsInChildren<Rigidbody>())
|
|
{
|
|
Object.Destroy(rigidbody);
|
|
}
|
|
|
|
var list = _blackboard.GetVariable<List<Renderer>>("tps_model").GetValue();
|
|
|
|
foreach (var renderer in model.GetComponentsInChildren<Renderer>())
|
|
{
|
|
if (isRegister)
|
|
{
|
|
list.Add(renderer);
|
|
}
|
|
else
|
|
{
|
|
list.Remove(renderer);
|
|
}
|
|
}
|
|
_blackboard.GetVariable<List<Renderer>>("tps_model").SetValue(list);
|
|
}
|
|
}
|
|
|
|
}
|