using System; using System.Collections.Generic; /// <summary> /// 物体背包类 /// </summary> public class Package<T> : IDestroy where T : ActivityObject, IPackageItem { public bool IsDestroyed { get; private set; } /// <summary> /// 归属者 /// </summary> public Role Master { get; private set; } /// <summary> /// 当前使用的物体对象 /// </summary> public T ActiveItem { get; private set; } /// <summary> /// 当前使用的物体的索引 /// </summary> public int ActiveIndex { get; private set; } = 0; /// <summary> /// 物体背包容量 /// </summary> public int Capacity { get; private set; } = 0; /// <summary> /// 物体插槽 /// </summary> public T[] ItemSlot { get; private set; } public Package(Role master, int capacity) { Master = master; SetCapacity(capacity); } /// <summary> /// 修改物体背包容量 /// </summary> public void SetCapacity(int capacity) { if (capacity < 0) { capacity = 0; } if (capacity == Capacity) { return; } if (ItemSlot == null) { ItemSlot = new T[capacity]; } else if (ItemSlot.Length > capacity) //删减格子 { var newArray = new T[capacity]; for (var i = 0; i < ItemSlot.Length; i++) { var packageItem = ItemSlot[i]; if (i < capacity) { newArray[i] = packageItem; } else { //溢出的item packageItem.OnOverflowItem(); packageItem.Master = null; packageItem.PackageIndex = -1; } } ItemSlot = newArray; } else //添加格子 { var newArray = new T[capacity]; for (var i = 0; i < ItemSlot.Length; i++) { newArray[i] = ItemSlot[i]; } ItemSlot = newArray; } Capacity = capacity; } /// <summary> /// 返回当前物体背包是否是空的 /// </summary> public bool IsEmpty() { for (var i = 0; i < ItemSlot.Length; i++) { if (ItemSlot[i] != null) { return false; } } return true; } /// <summary> /// 返回当前物体背包是否还有空位 /// </summary> public bool HasVacancy() { for (var i = 0; i < ItemSlot.Length; i++) { if (ItemSlot[i] == null) { return true; } } return false; } /// <summary> /// 根据索引获取物体 /// </summary> public T GetItem(int index) { if (index < 0 || index >= ItemSlot.Length) { return null; } return ItemSlot[index]; } /// <summary> /// 根据物体id查找物体背包中该物体所在的位置, 如果没有, 则返回 -1 /// </summary> /// <param name="id">物体id</param> public int FindIndex(string id) { for (var i = 0; i < ItemSlot.Length; i++) { var item = ItemSlot[i]; if (item != null && item.ItemConfig.Id == id) { return i; } } return -1; } /// <summary> /// 通过回调函数查询物体在物体背包中的位置, 如果没有, 则返回 -1 /// </summary> public int FindIndex(Func<T, int, bool> handler) { for (var i = 0; i < ItemSlot.Length; i++) { var item = ItemSlot[i]; if (item != null && handler(item, i)) { return i; } } return -1; } /// <summary> /// 遍历所有物体 /// </summary> public void ForEach(Action<T, int> handler) { for (var i = 0; i < ItemSlot.Length; i++) { var item = ItemSlot[i]; if (item != null) { handler(item, i); } } } /// <summary> /// 从物体背包中移除所有物体, 并返回 /// </summary> public T[] GetAndClearItem() { var items = new List<T>(); for (var i = 0; i < ItemSlot.Length; i++) { var item = ItemSlot[i]; if (item != null) { //触发移除物体 item.OnRemoveItem(); item.Master = null; item.PackageIndex = -1; items.Add(item); ItemSlot[i] = null; } } return items.ToArray(); } /// <summary> /// 拾起物体, 存入物体背包中, 返回存放在物体背包的位置, 如果容不下这个物体, 则会返回 -1 /// </summary> /// <param name="item">物体对象</param> /// <param name="exchange">是否立即切换到该物体, 默认 true </param> public int PickupItem(T item, bool exchange = true) { //已经被拾起了 if (item.Master != null) { return -1; } for (var i = 0; i < ItemSlot.Length; i++) { var tempItem = ItemSlot[i]; if (tempItem == null) { ItemSlot[i] = item; item.Master = Master; item.PackageIndex = i; item.OnPickUpItem(); if (exchange) { ExchangeByIndex(i); } return i; } } return -1; } /// <summary> /// 移除指定位置的物体, 并返回这个物体对象, 如果移除正在使用的这个物体, 则会自动切换到上一个物体 /// </summary> /// <param name="index">所在物体背包的位置索引</param> public T RemoveItem(int index) { if (index < 0 || index >= ItemSlot.Length) { return null; } var item = ItemSlot[index]; if (item == null) { return null; } ItemSlot[index] = null; //如果是当前手持的物体, 就需要调用切换物体操作 if (index == ActiveIndex) { //没有其他物体了 if (ExchangePrev(true) == index) { ActiveIndex = 0; ActiveItem = null; } } //移除物体 item.OnRemoveItem(); item.Master = null; item.PackageIndex = -1; // item.GetParent().RemoveChild(item); // item.Remove(); return item; } /// <summary> /// 移除指定位置的物体, 并返回这个物体对象, 如果移除正在使用的这个物体, 则会自动切换到上一个物体 /// </summary> public T RemoveItem(T item) { return RemoveItem(IndexOf(item)); } /// <summary> /// 切换到上一个物体 /// </summary> public int ExchangePrev() { return ExchangePrev(false); } private int ExchangePrev(bool removeFlag) { var index = ActiveIndex - 1; do { if (index < 0) { index = ItemSlot.Length - 1; } if (ExchangeByIndex(index, removeFlag)) { return index; } } while (index-- != ActiveIndex); return -1; } /// <summary> /// 切换到下一个物体, /// </summary> public int ExchangeNext() { var index = ActiveIndex + 1; do { if (index >= ItemSlot.Length) { index = 0; } if (ExchangeByIndex(index)) { return index; } } while (index++ != ActiveIndex); return -1; } /// <summary> /// 切换到指定索引的物体 /// </summary> public bool ExchangeByIndex(int index) { return ExchangeByIndex(index, false); } private bool ExchangeByIndex(int index, bool removeFlag) { if (index == ActiveIndex && ActiveItem != null) return true; if (index < 0 || index > ItemSlot.Length) return false; var item = ItemSlot[index]; if (item == null) return false; //将上一个物体放到背后 if (!removeFlag && ActiveItem != null) { //收起物体 ActiveItem.OnConcealItem(); } //切换物体 ActiveItem = item; ActiveIndex = index; ActiveItem.OnActiveItem(); return true; } /// <summary> /// 返回背包中是否有指定物体 /// </summary> public bool Contains(T item) { if (ItemSlot == null) { return false; } foreach (var packageItem in ItemSlot) { if (packageItem == item) { return true; } } return false; } /// <summary> /// 返回指定物体在当前背包中的索引, 如果不在背包中, 则返回 -1 /// </summary> public int IndexOf(T item) { if (ItemSlot == null) { return -1; } for (var i = 0; i < ItemSlot.Length; i++) { var packageItem = ItemSlot[i]; if (packageItem == item) { return i; } } return -1; } /// <summary> /// 返回指定 id 的物体在背包中的索引, 如果不在背包中, 则返回 -1 /// </summary> public int IndexOfByItemId(string itemId) { if (ItemSlot == null) { return -1; } for (var i = 0; i < ItemSlot.Length; i++) { var packageItem = ItemSlot[i]; if (packageItem != null && packageItem.ItemConfig.Id == itemId) { return i; } } return -1; } /// <summary> /// 获取背包中指定 id 的物体, 如果有多个相同 id 的物体, 则返回第一个匹配的物体 /// </summary> public T GetItemById(string itemId) { if (ItemSlot == null) { return null; } for (var i = 0; i < ItemSlot.Length; i++) { var packageItem = ItemSlot[i]; if (packageItem != null && packageItem.ItemConfig.Id == itemId) { return packageItem; } } return null; } public void Destroy() { if (IsDestroyed) { return; } IsDestroyed = true; for (var i = 0; i < ItemSlot.Length; i++) { var activityObject = ItemSlot[i]; if (activityObject != null) { activityObject.Destroy(); ItemSlot[i] = null; } } } }