209 lines
6.3 KiB
C#
209 lines
6.3 KiB
C#
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<Player>(), stack);
|
|
if (count > 1000)
|
|
{
|
|
LogExtensions.Audit("Bag", "LargeResourceAdd", $"{{\"playerId\":{self.GetParent<Player>()?.Id ?? 0},\"itemId\":{itemId},\"count\":{count}}}");
|
|
}
|
|
return stack;
|
|
}
|
|
}
|
|
|
|
long itemIndex = self.NextItemIndex++;
|
|
ItemUnit unit = self.AddChildWithId<ItemUnit, long, int, long, long>(itemIndex, itemIndex, itemId, count, 0);
|
|
self.ItemMap[itemIndex] = unit;
|
|
BagNoticeHelper.NotifyItemChange(self.GetParent<Player>(), unit);
|
|
if (count > 1000)
|
|
{
|
|
LogExtensions.Audit("Bag", "LargeResourceAdd", $"{{\"playerId\":{self.GetParent<Player>()?.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<ItemUnit> 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<Player>(), unit);
|
|
}
|
|
}
|
|
|
|
return remain == 0;
|
|
}
|
|
|
|
public static bool RemoveItemByIndex(this BagComponent self, long itemIndex)
|
|
{
|
|
if (!self.ItemMap.TryGetValue(itemIndex, out EntityRef<ItemUnit> unitRef))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ItemUnit unit = unitRef;
|
|
self.ItemMap.Remove(itemIndex);
|
|
BagNoticeHelper.NotifyItemRemove(self.GetParent<Player>(), itemIndex);
|
|
unit.Dispose();
|
|
return true;
|
|
}
|
|
|
|
public static bool SetHeroIdOnEquip(this BagComponent self, long itemIndex, long heroId)
|
|
{
|
|
if (!self.ItemMap.TryGetValue(itemIndex, out EntityRef<ItemUnit> unitRef))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ItemUnit unit = unitRef;
|
|
unit.HeroId = heroId;
|
|
BagNoticeHelper.NotifyItemChange(self.GetParent<Player>(), unit);
|
|
return true;
|
|
}
|
|
|
|
public static void AddItems(this BagComponent self, List<RewardEntry> rewards)
|
|
{
|
|
if (rewards == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach (RewardEntry reward in rewards)
|
|
{
|
|
self.AddItem(reward.ItemId, reward.Count);
|
|
}
|
|
|
|
self.GetParent<Player>()?.SetDirty();
|
|
}
|
|
|
|
public static bool RemoveItems(this BagComponent self, List<CostEntry> costs)
|
|
{
|
|
if (!self.HasItems(costs))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
foreach (CostEntry cost in costs)
|
|
{
|
|
if (!self.RemoveItem(cost.ItemId, cost.Count))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
self.GetParent<Player>()?.SetDirty();
|
|
return true;
|
|
}
|
|
|
|
public static long GetItemCount(this BagComponent self, int itemId)
|
|
{
|
|
long total = 0;
|
|
foreach (EntityRef<ItemUnit> 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<CostEntry> 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<ItemUnit> 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<long> removed = new();
|
|
foreach (EntityRef<ItemUnit> 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<Player>()?.SetDirty();
|
|
}
|
|
}
|
|
}
|