Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / package / Package.cs
  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. /// <summary>
  5. /// 物体背包类
  6. /// </summary>
  7. public class Package<T> : IDestroy where T : ActivityObject, IPackageItem
  8. {
  9. /// <summary>
  10. /// 当前使用对象改变时回调
  11. /// </summary>
  12. public event Action<T> ChangeActiveItemEvent;
  13. public bool IsDestroyed { get; private set; }
  14. /// <summary>
  15. /// 归属者
  16. /// </summary>
  17. public Role Master { get; private set; }
  18.  
  19. /// <summary>
  20. /// 当前使用的物体对象
  21. /// </summary>
  22. public T ActiveItem
  23. {
  24. get => _activeItem;
  25. set
  26. {
  27. if (value != _activeItem)
  28. {
  29. _activeItem = value;
  30. if (ChangeActiveItemEvent != null)
  31. {
  32. ChangeActiveItemEvent(value);
  33. }
  34. }
  35. }
  36. }
  37.  
  38. private T _activeItem;
  39.  
  40. /// <summary>
  41. /// 当前使用的物体的索引
  42. /// </summary>
  43. public int ActiveIndex { get; private set; } = 0;
  44.  
  45. /// <summary>
  46. /// 物体背包容量
  47. /// </summary>
  48. public int Capacity { get; private set; } = 0;
  49.  
  50. /// <summary>
  51. /// 物体插槽
  52. /// </summary>
  53. public T[] ItemSlot { get; private set; }
  54.  
  55. public Package(Role master, int capacity)
  56. {
  57. Master = master;
  58. SetCapacity(capacity);
  59. }
  60.  
  61. /// <summary>
  62. /// 修改物体背包容量
  63. /// </summary>
  64. public void SetCapacity(int capacity)
  65. {
  66. if (capacity < 0)
  67. {
  68. capacity = 0;
  69. }
  70.  
  71. if (capacity == Capacity)
  72. {
  73. return;
  74. }
  75.  
  76. if (ItemSlot == null)
  77. {
  78. ItemSlot = new T[capacity];
  79. }
  80. else if (ItemSlot.Length > capacity) //删减格子
  81. {
  82. var newArray = new T[capacity];
  83. for (var i = 0; i < ItemSlot.Length; i++)
  84. {
  85. var packageItem = ItemSlot[i];
  86. if (i < capacity)
  87. {
  88. newArray[i] = packageItem;
  89. }
  90. else
  91. {
  92. //溢出的item
  93. packageItem.OnOverflowItem();
  94. packageItem.Master = null;
  95. packageItem.PackageIndex = -1;
  96. }
  97. }
  98.  
  99. ItemSlot = newArray;
  100. }
  101. else //添加格子
  102. {
  103. var newArray = new T[capacity];
  104. for (var i = 0; i < ItemSlot.Length; i++)
  105. {
  106. newArray[i] = ItemSlot[i];
  107. }
  108. ItemSlot = newArray;
  109. }
  110. Capacity = capacity;
  111. }
  112.  
  113. /// <summary>
  114. /// 返回当前物体背包是否是空的
  115. /// </summary>
  116. public bool IsEmpty()
  117. {
  118. for (var i = 0; i < ItemSlot.Length; i++)
  119. {
  120. if (ItemSlot[i] != null)
  121. {
  122. return false;
  123. }
  124. }
  125.  
  126. return true;
  127. }
  128. /// <summary>
  129. /// 返回当前物体背包是否还有空位
  130. /// </summary>
  131. public bool HasVacancy()
  132. {
  133. for (var i = 0; i < ItemSlot.Length; i++)
  134. {
  135. if (ItemSlot[i] == null)
  136. {
  137. return true;
  138. }
  139. }
  140.  
  141. return false;
  142. }
  143.  
  144. /// <summary>
  145. /// 根据索引获取物体
  146. /// </summary>
  147. public T GetItem(int index)
  148. {
  149. if (index < 0 || index >= ItemSlot.Length)
  150. {
  151. return null;
  152. }
  153. return ItemSlot[index];
  154. }
  155.  
  156. /// <summary>
  157. /// 根据物体id查找物体背包中该物体所在的位置, 如果没有, 则返回 -1
  158. /// </summary>
  159. /// <param name="id">物体id</param>
  160. public int FindIndex(string id)
  161. {
  162. for (var i = 0; i < ItemSlot.Length; i++)
  163. {
  164. var item = ItemSlot[i];
  165. if (item != null && item.ItemConfig.Id == id)
  166. {
  167. return i;
  168. }
  169. }
  170. return -1;
  171. }
  172.  
  173. /// <summary>
  174. /// 通过回调函数查询物体在物体背包中的位置, 如果没有, 则返回 -1
  175. /// </summary>
  176. public int FindIndex(Func<T, int, bool> handler)
  177. {
  178. for (var i = 0; i < ItemSlot.Length; i++)
  179. {
  180. var item = ItemSlot[i];
  181. if (item != null && handler(item, i))
  182. {
  183. return i;
  184. }
  185. }
  186. return -1;
  187. }
  188.  
  189. /// <summary>
  190. /// 遍历所有物体
  191. /// </summary>
  192. public void ForEach(Action<T, int> handler)
  193. {
  194. for (var i = 0; i < ItemSlot.Length; i++)
  195. {
  196. var item = ItemSlot[i];
  197. if (item != null)
  198. {
  199. handler(item, i);
  200. }
  201. }
  202. }
  203.  
  204. /// <summary>
  205. /// 从物体背包中移除所有物体, 并返回
  206. /// </summary>
  207. public T[] GetAndClearItem()
  208. {
  209. var items = new List<T>();
  210. for (var i = 0; i < ItemSlot.Length; i++)
  211. {
  212. var item = ItemSlot[i];
  213. if (item != null)
  214. {
  215. //触发移除物体
  216. item.OnRemoveItem();
  217. item.Master = null;
  218. item.PackageIndex = -1;
  219.  
  220. items.Add(item);
  221. ItemSlot[i] = null;
  222. }
  223. }
  224.  
  225. return items.ToArray();
  226. }
  227.  
  228. /// <summary>
  229. /// 拾起物体, 存入物体背包中, 返回存放在物体背包的位置, 如果容不下这个物体, 则会返回 -1
  230. /// </summary>
  231. /// <param name="item">物体对象</param>
  232. /// <param name="exchange">是否立即切换到该物体, 默认 true </param>
  233. public int PickupItem(T item, bool exchange = true)
  234. {
  235. //已经被拾起了
  236. if (item.Master != null)
  237. {
  238. return -1;
  239. }
  240. for (var i = 0; i < ItemSlot.Length; i++)
  241. {
  242. var tempItem = ItemSlot[i];
  243. if (tempItem == null)
  244. {
  245. ItemSlot[i] = item;
  246. item.Master = Master;
  247. item.PackageIndex = i;
  248. item.OnPickUpItem();
  249. if (exchange)
  250. {
  251. ExchangeByIndex(i);
  252. }
  253.  
  254. return i;
  255. }
  256. }
  257. return -1;
  258. }
  259.  
  260. /// <summary>
  261. /// 移除指定位置的物体, 并返回这个物体对象, 如果移除正在使用的这个物体, 则会自动切换到上一个物体
  262. /// </summary>
  263. /// <param name="index">所在物体背包的位置索引</param>
  264. public T RemoveItem(int index)
  265. {
  266. if (index < 0 || index >= ItemSlot.Length)
  267. {
  268. return null;
  269. }
  270. var item = ItemSlot[index];
  271. if (item == null)
  272. {
  273. return null;
  274. }
  275. ItemSlot[index] = null;
  276.  
  277. //如果是当前手持的物体, 就需要调用切换物体操作
  278. if (index == ActiveIndex)
  279. {
  280. //没有其他物体了
  281. if (ExchangePrev(true) == index)
  282. {
  283. ActiveIndex = 0;
  284. ActiveItem = null;
  285. }
  286. }
  287. //移除物体
  288. item.OnRemoveItem();
  289. item.Master = null;
  290. item.PackageIndex = -1;
  291. // item.GetParent().RemoveChild(item);
  292. // item.Remove();
  293. return item;
  294. }
  295.  
  296. /// <summary>
  297. /// 移除指定位置的物体, 并返回这个物体对象, 如果移除正在使用的这个物体, 则会自动切换到上一个物体
  298. /// </summary>
  299. public T RemoveItem(T item)
  300. {
  301. return RemoveItem(IndexOf(item));
  302. }
  303.  
  304. /// <summary>
  305. /// 切换到上一个物体
  306. /// </summary>
  307. public int ExchangePrev()
  308. {
  309. return ExchangePrev(false);
  310. }
  311. private int ExchangePrev(bool removeFlag)
  312. {
  313. var index = ActiveIndex - 1;
  314. do
  315. {
  316. if (index < 0)
  317. {
  318. index = ItemSlot.Length - 1;
  319. }
  320. if (ExchangeByIndex(index, removeFlag))
  321. {
  322. return index;
  323. }
  324. } while (index-- != ActiveIndex);
  325. return -1;
  326. }
  327.  
  328. /// <summary>
  329. /// 切换到下一个物体,
  330. /// </summary>
  331. public int ExchangeNext()
  332. {
  333. var index = ActiveIndex + 1;
  334. do
  335. {
  336. if (index >= ItemSlot.Length)
  337. {
  338. index = 0;
  339. }
  340. if (ExchangeByIndex(index))
  341. {
  342. return index;
  343. }
  344. } while (index++ != ActiveIndex);
  345. return -1;
  346. }
  347.  
  348. /// <summary>
  349. /// 切换到指定索引的物体
  350. /// </summary>
  351. public bool ExchangeByIndex(int index)
  352. {
  353. return ExchangeByIndex(index, false);
  354. }
  355.  
  356. private bool ExchangeByIndex(int index, bool removeFlag)
  357. {
  358. if (index == ActiveIndex && ActiveItem != null) return true;
  359. if (index < 0 || index > ItemSlot.Length) return false;
  360. var item = ItemSlot[index];
  361. if (item == null) return false;
  362.  
  363. //将上一个物体放到背后
  364. if (!removeFlag && ActiveItem != null)
  365. {
  366. //收起物体
  367. ActiveItem.OnConcealItem();
  368. }
  369.  
  370. //切换物体
  371. ActiveItem = item;
  372. ActiveIndex = index;
  373. ActiveItem.OnActiveItem();
  374. return true;
  375. }
  376.  
  377. /// <summary>
  378. /// 返回背包中是否有指定物体
  379. /// </summary>
  380. public bool Contains(T item)
  381. {
  382. if (ItemSlot == null)
  383. {
  384. return false;
  385. }
  386.  
  387. foreach (var packageItem in ItemSlot)
  388. {
  389. if (packageItem == item)
  390. {
  391. return true;
  392. }
  393. }
  394.  
  395. return false;
  396. }
  397.  
  398. /// <summary>
  399. /// 返回指定物体在当前背包中的索引, 如果不在背包中, 则返回 -1
  400. /// </summary>
  401. public int IndexOf(T item)
  402. {
  403. if (ItemSlot == null)
  404. {
  405. return -1;
  406. }
  407.  
  408. for (var i = 0; i < ItemSlot.Length; i++)
  409. {
  410. var packageItem = ItemSlot[i];
  411. if (packageItem == item)
  412. {
  413. return i;
  414. }
  415. }
  416.  
  417. return -1;
  418. }
  419.  
  420. /// <summary>
  421. /// 返回指定 id 的物体在背包中的索引, 如果不在背包中, 则返回 -1
  422. /// </summary>
  423. public int IndexOfByItemId(string itemId)
  424. {
  425. if (ItemSlot == null)
  426. {
  427. return -1;
  428. }
  429.  
  430. for (var i = 0; i < ItemSlot.Length; i++)
  431. {
  432. var packageItem = ItemSlot[i];
  433. if (packageItem != null && packageItem.ItemConfig.Id == itemId)
  434. {
  435. return i;
  436. }
  437. }
  438.  
  439. return -1;
  440. }
  441.  
  442. /// <summary>
  443. /// 获取背包中指定 id 的物体, 如果有多个相同 id 的物体, 则返回第一个匹配的物体
  444. /// </summary>
  445. public T GetItemById(string itemId)
  446. {
  447. if (ItemSlot == null)
  448. {
  449. return null;
  450. }
  451.  
  452. for (var i = 0; i < ItemSlot.Length; i++)
  453. {
  454. var packageItem = ItemSlot[i];
  455. if (packageItem != null && packageItem.ItemConfig.Id == itemId)
  456. {
  457. return packageItem;
  458. }
  459. }
  460.  
  461. return null;
  462. }
  463. public void Destroy()
  464. {
  465. if (IsDestroyed)
  466. {
  467. return;
  468. }
  469.  
  470. IsDestroyed = true;
  471. for (var i = 0; i < ItemSlot.Length; i++)
  472. {
  473. var activityObject = ItemSlot[i];
  474. if (activityObject != null)
  475. {
  476. activityObject.Destroy();
  477. ItemSlot[i] = null;
  478. }
  479. }
  480. }
  481. }