BITFALL/Assets/Artists/Scripts/Entities/Inventory/EntityInventory.cs

173 lines
5.3 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BITKit;
using BITKit.Entities;
using System;
using System.Linq;
using System.Threading;
using AYellowpaper.SerializedCollections;
using BITFALL.Entities.Inventory;
using BITKit.Entities.Slot;
using Cysharp.Threading.Tasks;
using UnityEngine.AddressableAssets;
namespace BITFALL
{
[CustomType(typeof(IEntityInventory))]
[CustomType(typeof(IBasicItemContainer))]
public class EntityInventory : EntityBehavior, IEntityInventory
{
/// <summary>
/// 数据字典
/// </summary>
protected readonly Dictionary<int, IBasicItem> dictionary = new();
/// <summary>
/// 隐式接口实现
/// </summary>
public int Id => (int)UnityEntity.Id;
public bool DropOrSpawn(IBasicItem item)
{
Drop(item);
return true;
}
/// <summary>
/// 工厂方法
/// </summary>
public event Func<IBasicItem, bool> AddFactory;
public event Func<IBasicItem, bool> RemoveFactory;
public event Func<IBasicItem, bool> DropFactory;
// 回调
public event Action<IBasicItem> OnAdd;
public event Action<IBasicItem> OnUsedItem;
public event Action<IBasicItem> OnRemove;
public event Func<IBasicItem, bool> TryUseItemFactory;
public event Action<IBasicItem> OnSet;
public event Action<IBasicItem> OnDrop;
public event Action<IBasicItemContainer> OnRebuild;
public bool Clear(int id)
{
throw new NotImplementedException();
}
public bool TryUseItem(IBasicItem item)
{
if (dictionary.ContainsKey(item.Id) is false)
{
return false;
}
return TryUseItemFactory is not null && TryUseItemFactory.CastAsFunc().Any(x => x.Invoke(item));
}
public void UseItem(IBasicItem item)
{
OnUsedItem?.Invoke(item);
dictionary.TryRemove(item.Id);
}
[Inject]
protected IHealth _health;
[Inject]
protected IEntitySlot<Transform> _modelSlots;
public override void OnAwake()
{
_health.OnSetAlive += OnSetAlive;
}
private void OnSetAlive(bool alive)
{
if (alive) return;
foreach (var x in dictionary.Values.ToArray())
{
OnRemove?.Invoke(x);
Drop(x);
}
dictionary.Clear();
}
public virtual bool Add(IBasicItem item)
{
if (_health.IsAlive is false)
{
Drop(item);
return true;
}
if (AddFactory?.GetInvocationList().Cast<Func<IBasicItem, bool>>().Any(x => x.Invoke(item)) is false)
{
return false;
}
if (!dictionary.TryAdd(item.Id, item)) return false;
{
OnAdd?.Invoke(item);
return true;
}
}
public virtual IBasicItem[] GetItems() => dictionary.Values.ToArray();
public virtual bool Remove(IBasicItem item)
{
return Remove(item.Id);
}
public virtual bool Remove(int id)
{
if (!dictionary.TryGetValue(id, out var item)) return false;
if (RemoveFactory is not null)
if (RemoveFactory.GetInvocationList().Cast<Func<IBasicItem,bool>>().Any(x => x.Invoke(item) is false))
{
return false;
}
dictionary.Remove(id);
OnRemove?.Invoke(item);
return true;
}
public virtual bool Remove(Func<IBasicItem, bool> removeFactory)
{
bool isRemoved = false;
foreach (var x in dictionary.Values.ToArray())
{
if (removeFactory.Invoke(x))
{
Remove(x.Id);
isRemoved = true;
}
}
return isRemoved;
}
public bool TryGetItem(Func<IBasicItem, bool> func, out IBasicItem item)
{
return dictionary.Values.TryGetAny(func, out item);
}
public bool Drop(int _Id)
{
if (!dictionary.TryGetValue(_Id, out var item)) return false;
if (!Remove(item)) return false;
if (DropFactory != null && DropFactory.GetInvocationList().Cast<Func<IBasicItem, bool>>()
.Any(x => x.Invoke(item) is false))
{
return false;
}
Drop(item);
return true;
}
protected void Drop(IBasicItem item)
{
OnDrop?.Invoke(item);
var prefab = Addressables.LoadAssetAsync<AssetableItem>(item.AddressablePath).WaitForCompletion();
var _transform = transform;
var position = _transform.position;
var rotation = _transform.rotation;
if (_modelSlots.Slots.TryGetValue(prefab.AddressablePath, out var anchor))
{
position = anchor.position;
rotation = anchor.rotation;
}
var instance = Instantiate(prefab.GetPrefab(), position, rotation);
instance.CopyItemsFrom(item);
}
}
}