215 lines
7.0 KiB
C#
215 lines
7.0 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;
|
|
|
|
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;
|
|
}
|
|
// if (item.GetAssetable().TryGetProperty<ICustomItemBehavior>(out var customItemBehavior))
|
|
// {
|
|
// // customItemBehavior.Inject(UnityEntity);
|
|
// // if (customItemBehavior.TryUse(item))
|
|
// // {
|
|
// // customItemBehavior.OnUse(item);
|
|
// // Remove(item);
|
|
// // return true;
|
|
// // }
|
|
// customItemBehavior.Inject(UnityEntity);
|
|
// if (customItemBehavior.TryUse(item))
|
|
// {
|
|
// customItemBehavior.OnUse(item);
|
|
// }
|
|
// if (customItemBehavior.IsAdditive is false) return true;
|
|
// }
|
|
var isUsed=false;
|
|
if (item.GetAssetable().TryGetProperty<ICustomItemBehavior>(out var customItemBehavior))
|
|
{
|
|
Entity.Inject(customItemBehavior);
|
|
isUsed = customItemBehavior.TryUse(item);
|
|
}
|
|
return isUsed ||TryUseItemFactory is not null && TryUseItemFactory.CastAsFunc().Any(x => x.Invoke(item));
|
|
}
|
|
|
|
public void UseItem(IBasicItem item)
|
|
{
|
|
if(item.GetAssetable().TryGetProperty<ICustomItemBehavior>(out var customItemBehavior))
|
|
{
|
|
customItemBehavior.OnUse(item);
|
|
}
|
|
dictionary.TryRemove(item.Id);
|
|
OnUsedItem?.Invoke(item);
|
|
}
|
|
|
|
public bool TrySetItem(IBasicItem item)
|
|
{
|
|
if (dictionary.TryGetValue(item.Id, out var currentItem) is false) return false;
|
|
dictionary[item.Id] = item;
|
|
OnSet?.Invoke(item);
|
|
return true;
|
|
}
|
|
|
|
[Inject]
|
|
protected IHealth _health;
|
|
[Inject]
|
|
protected IEntitySlot<Transform> _modelSlots;
|
|
public override void OnAwake()
|
|
{
|
|
_health.OnSetAlive += OnSetAlive;
|
|
}
|
|
protected virtual 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.OrderBy(x=>x.TryGetProperty<ICount>(out var count)?count.Count:0).Reverse().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 virtual void Drop(IBasicItem item)
|
|
{
|
|
OnDrop?.Invoke(item);
|
|
var prefab = item.GetAssetable();
|
|
var position = Transform.position + Vector3.up;
|
|
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);
|
|
instance.WaitForInitializationComplete();
|
|
}
|
|
protected virtual void InvokeOnDrop(IBasicItem item)
|
|
{
|
|
OnDrop?.Invoke(item);
|
|
}
|
|
|
|
protected void RebuildInternal()
|
|
{
|
|
OnRebuild?.Invoke(this);
|
|
}
|
|
}
|
|
} |