173 lines
5.3 KiB
C#
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);
|
|
}
|
|
}
|
|
} |