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 { /// /// 数据字典 /// protected readonly Dictionary dictionary = new(); /// /// 隐式接口实现 /// public int Id => (int)UnityEntity.Id; public bool DropOrSpawn(IBasicItem item) { Drop(item); return true; } /// /// 工厂方法 /// public event Func AddFactory; public event Func RemoveFactory; public event Func DropFactory; // 回调 public event Action OnAdd; public event Action OnUsedItem; public event Action OnRemove; public event Func TryUseItemFactory; public event Func AllowUseItemFactory; public event Action OnSet; public event Action OnDrop; public event Action OnRebuild; public bool Clear(int id) { throw new NotImplementedException(); } public bool TryUseItem(IBasicItem item) { if (dictionary.ContainsKey(item.Id) is false) { return false; } var isUsed=false; if (item.GetAssetable().TryGetProperty(out var customItemBehavior)) { Entity.Inject(customItemBehavior); isUsed = customItemBehavior.TryUse(item); } return isUsed ||TryUseItemFactory is not null && TryUseItemFactory.CastAsFunc().Any(x => x.Invoke(item)); } public bool AllowUseItem(IBasicItem item) { return AllowUseItemFactory.CastAsFunc().Any(func => func.Invoke(item)); } public void UseItem(IBasicItem item) { if(item.GetAssetable().TryGetProperty(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 _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; } foreach (var func in AddFactory.CastAsFunc()) { if (func.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>().Any(x => x.Invoke(item) is false)) { return false; } dictionary.Remove(id); OnRemove?.Invoke(item); return true; } public virtual bool Remove(Func 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 func, out IBasicItem item) { return dictionary.Values.OrderBy(x=>x.TryGetProperty(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>() .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); } } }