using System; using System.Collections; using System.Collections.Generic; using System.Linq; using BITFALL.Entities.Equipment; using BITFALL.Entities.Inventory; using BITFALL.Player.Inventory; using UnityEngine; using BITKit; using BITKit.Entities; using Cysharp.Threading.Tasks; namespace BITFALL { /// /// 玩家装备容器 /// 支持,护甲,头盔和背包等 /// [CustomType(typeof(IEntityEquipmentContainer))] public class EntityEquipmentContainer : EntityBehavior, IEntityEquipmentContainer { public IDictionary Equipment { get; } = new Dictionary(); [Inject] private IEntityInventory _inventory; public override void OnAwake() { var health = UnityEntity.Get(); health.OnSetAlive += OnSetAlive; _inventory.OnAdd += OnAdd; _inventory.AllowUseItemFactory += OnAllowUse; } private async void OnAdd(IBasicItem obj) { if (obj is null) return; var asset = obj.GetAssetable(); if (asset.TryGetProperty(out var equipmentAsSlot) is false) return; if (Equipment.TryGetValue(equipmentAsSlot.slot, out _)) return; await UniTask.NextFrame(); await UniTask.NextFrame(); await UniTask.NextFrame(); if(destroyCancellationToken.IsCancellationRequested) return; TryExecute(obj); } private bool OnAllowUse(IBasicItem arg) { return Equipment.Values.Any(x => x.Id == arg?.Id) ; } private void OnSetAlive(bool obj) { if (Data.Get(BITConstant.Environment.sp_keepInventory)) return; if (obj) return; foreach (var x in Equipment.ToArray()) { OnDeEquip?.Invoke(x.Key, x.Value); _inventory.Add(x.Value); } Equipment.Clear(); } public override void OnStart() { base.OnStart(); _inventory.TryUseItemFactory += TryExecute; } public Action OnEquip { get; set; } public Action OnDeEquip { get; set; } public bool TryDeEquip(T slot) where T : IEquipmentSlot { if (!Equipment.TryGetAny(x => x.Key.GetType().IsInstanceOfType(slot), out var pair)) return false; if (_inventory.Add(pair.Value)) { DeEquip(slot, pair.Value); } return false; } public bool TryUseEquip(T slot) where T : IEquipmentSlot { return TryUseEquip(System.Activator.CreateInstance(typeof(T)) as IEquipmentSlot); } public bool TryUseEquip(IEquipmentSlot slot) { if (!Equipment.TryGetAny(x => x.Key.GetType().IsInstanceOfType(slot), out var pair)) return false; if (!Equipment.TryRemove(pair.Key)) return false; OnDeEquip?.Invoke(pair.Key, pair.Value); _inventory.UseItem(pair.Value); //自动补齐 if (_inventory.TryGetItem(x => x.AddressablePath == pair.Value.AddressablePath, out var item)) { Equip(pair.Key, item); _inventory.Remove(item); } return true; } private bool Equip(IEquipmentSlot slot, IBasicItem item) { if (Equipment.TryAdd(slot, item) is false) return false; OnEquip?.Invoke(slot, item); return true; } private bool DeEquip(IEquipmentSlot slot, IBasicItem item) { if (Equipment.TryRemove(slot) is false) return false; OnDeEquip?.Invoke(slot, item); return true; } public int Priority => 0; public bool TryExecute(IBasicItem value) { var asset = value.GetAssetable(); //尝试获取可装备信息 if (!asset.TryGetProperty(out var equipmentAsSlot)) return false; //已装备物品 if (Equipment.TryGetValue(equipmentAsSlot.slot, out var current)) { if (_inventory.Add(current) is false) return false; Equipment.Remove(equipmentAsSlot.slot); OnDeEquip?.Invoke(equipmentAsSlot.slot, current); } //装配物品 Equip(equipmentAsSlot.slot, value); _inventory.Remove(value); return true; } } }