using System.Collections.Generic; using System.Linq; namespace ET.Server { [FriendOf(typeof(ItemUnit))] [FriendOf(typeof(BagComponent))] public static class BagComponentSystem { // 约定:>=10000 的道具按装备类处理(独立实例,不堆叠) private static bool IsEquipItem(int itemId) { return itemId >= 10000; } public static ItemUnit AddItem(this BagComponent self, int itemId, long count) { if (count <= 0) { return null; } if (!IsEquipItem(itemId)) { ItemUnit stack = self.ItemMap.Values.Select(x => (ItemUnit)x).FirstOrDefault(x => x.ItemId == itemId && x.HeroId == 0); if (stack != null) { stack.Count += count; BagNoticeHelper.NotifyItemChange(self.GetParent(), stack); if (count > 1000) { LogExtensions.Audit("Bag", "LargeResourceAdd", $"{{\"playerId\":{self.GetParent()?.Id ?? 0},\"itemId\":{itemId},\"count\":{count}}}"); } return stack; } } long itemIndex = self.NextItemIndex++; ItemUnit unit = self.AddChildWithId(itemIndex, itemIndex, itemId, count, 0); self.ItemMap[itemIndex] = unit; BagNoticeHelper.NotifyItemChange(self.GetParent(), unit); if (count > 1000) { LogExtensions.Audit("Bag", "LargeResourceAdd", $"{{\"playerId\":{self.GetParent()?.Id ?? 0},\"itemId\":{itemId},\"count\":{count}}}"); } return unit; } public static bool RemoveItem(this BagComponent self, int itemId, long count) { if (count <= 0) { return true; } if (self.GetItemCount(itemId) < count) { return false; } long remain = count; List units = self.ItemMap.Values .Select(x => (ItemUnit)x) .Where(x => x.ItemId == itemId && x.HeroId == 0) .OrderBy(x => x.ItemIndex) .ToList(); foreach (ItemUnit unit in units) { if (remain <= 0) { break; } long cost = remain > unit.Count ? unit.Count : remain; unit.Count -= cost; remain -= cost; if (unit.Count <= 0) { self.RemoveItemByIndex(unit.ItemIndex); } else { BagNoticeHelper.NotifyItemChange(self.GetParent(), unit); } } return remain == 0; } public static bool RemoveItemByIndex(this BagComponent self, long itemIndex) { if (!self.ItemMap.TryGetValue(itemIndex, out EntityRef unitRef)) { return false; } ItemUnit unit = unitRef; self.ItemMap.Remove(itemIndex); BagNoticeHelper.NotifyItemRemove(self.GetParent(), itemIndex); unit.Dispose(); return true; } public static bool SetHeroIdOnEquip(this BagComponent self, long itemIndex, long heroId) { if (!self.ItemMap.TryGetValue(itemIndex, out EntityRef unitRef)) { return false; } ItemUnit unit = unitRef; unit.HeroId = heroId; BagNoticeHelper.NotifyItemChange(self.GetParent(), unit); return true; } public static void AddItems(this BagComponent self, List rewards) { if (rewards == null) { return; } foreach (RewardEntry reward in rewards) { self.AddItem(reward.ItemId, reward.Count); } self.GetParent()?.SetDirty(); } public static bool RemoveItems(this BagComponent self, List costs) { if (!self.HasItems(costs)) { return false; } foreach (CostEntry cost in costs) { if (!self.RemoveItem(cost.ItemId, cost.Count)) { return false; } } self.GetParent()?.SetDirty(); return true; } public static long GetItemCount(this BagComponent self, int itemId) { long total = 0; foreach (EntityRef unitRef in self.ItemMap.Values) { ItemUnit unit = unitRef; if (unit.ItemId == itemId && unit.HeroId == 0) { total += unit.Count; } } return total; } public static bool HasItems(this BagComponent self, List costs) { if (costs == null) { return true; } foreach (CostEntry cost in costs) { if (self.GetItemCount(cost.ItemId) < cost.Count) { return false; } } return true; } public static List GetAllItems(this BagComponent self) { return self.ItemMap.Values.Select(x => (ItemUnit)x).OrderBy(x => x.ItemIndex).ToList(); } public static void ClearBagKeepEquipped(this BagComponent self) { List removed = new(); foreach (EntityRef unitRef in self.ItemMap.Values) { ItemUnit item = unitRef; if (item.HeroId == 0) { removed.Add(item.ItemIndex); } } foreach (long itemIndex in removed) { self.RemoveItemByIndex(itemIndex); } self.GetParent()?.SetDirty(); } } }