提交示例代码
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
using Fantasy.Entitas.Interface;
|
||||
// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public sealed class ContainerComponentDestroySystem : DestroySystem<ContainerComponent>
|
||||
{
|
||||
protected override void Destroy(ContainerComponent self)
|
||||
{
|
||||
foreach (var (_, container) in self.Containers)
|
||||
{
|
||||
container.Dispose();
|
||||
}
|
||||
|
||||
self.Containers.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ContainerComponentDeserializeSystem : DeserializeSystem<ContainerComponent>
|
||||
{
|
||||
protected override void Deserialize(ContainerComponent self)
|
||||
{
|
||||
var account = self.GetParent<Account>();
|
||||
foreach (var (key, container) in self.Containers)
|
||||
{
|
||||
container.Deserialize(self.Scene);
|
||||
container.Account = account;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ContainerComponentAwakeSystem : AwakeSystem<ContainerComponent>
|
||||
{
|
||||
protected override void Awake(ContainerComponent self)
|
||||
{
|
||||
var account = self.GetParent<Account>();
|
||||
var unitConfig = account.UnitConfig;
|
||||
// 根据角色的配置文件创建容器。
|
||||
foreach (var containerConfigId in unitConfig.MountContainer)
|
||||
{
|
||||
if (!ContainerConfigData.Instance.TryGet(containerConfigId, out var containerConfig))
|
||||
{
|
||||
Log.Error($"containerConfigId : {containerConfigId} not found");
|
||||
return;
|
||||
}
|
||||
|
||||
ContainerHelper.Create(account, (ContainerType)containerConfig.Type);
|
||||
}
|
||||
// 创建初始化物品到容器中。
|
||||
var unitConfigItems = unitConfig.Items;
|
||||
for (var itemArgs = 0; itemArgs < unitConfigItems.Length; itemArgs += 3)
|
||||
{
|
||||
try
|
||||
{
|
||||
var containerType = unitConfigItems[itemArgs];
|
||||
var itemConfigId = unitConfigItems[itemArgs + 1];
|
||||
var itemCount = (int)unitConfigItems[itemArgs + 2];
|
||||
var item = ItemFactory.Create(self.Scene, itemConfigId, itemCount, true);
|
||||
if (item == null)
|
||||
{
|
||||
// 这里创建物品失败,可以选择跳过这个物品,继续下一个创建。
|
||||
// 也可以直接停止全部的物品创建。
|
||||
continue;
|
||||
}
|
||||
// 添加物品到容器中。
|
||||
var addItemErrorCode = ContainerHelper.AddItem(account, (ContainerType)containerType, item, ItemReason.ContainerAdd, false);
|
||||
if (addItemErrorCode != 0)
|
||||
{
|
||||
Log.Error($"cant add item to container errorCode:{addItemErrorCode}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Error($"unitConfig :{unitConfig.Id} items参数不正确,要求是3个一组。");
|
||||
// 你可以选择如果有一个出错了,跳过、继续下一个创建。
|
||||
// 你还可以选择如果出错了,直接终止跳出。
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
291
物品和背包的完整代码/Server/Hotfix/Gate/Container/ContainerHelper.cs
Normal file
291
物品和背包的完整代码/Server/Hotfix/Gate/Container/ContainerHelper.cs
Normal file
@@ -0,0 +1,291 @@
|
||||
// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Network;
|
||||
|
||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
namespace Fantasy;
|
||||
|
||||
public static class ContainerHelper
|
||||
{
|
||||
#region Container
|
||||
|
||||
public static Container Create(Account account, ContainerType containerType)
|
||||
{
|
||||
if (!ContainerConfigData.Instance.TryGetConfig(containerType, out var containerConfig))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var containerComponent = account.GetComponent<ContainerComponent>();
|
||||
|
||||
if (containerComponent == null)
|
||||
{
|
||||
Log.Error($"account {account.Id} not found ContainerComponent!");
|
||||
return null;
|
||||
}
|
||||
|
||||
var containerTypeInt = (int)containerType;
|
||||
|
||||
if (containerComponent.Containers.ContainsKey(containerTypeInt))
|
||||
{
|
||||
Log.Error($"account {account.Id} containerType {containerType} already exists!");
|
||||
return null;
|
||||
}
|
||||
|
||||
var container = Entity.Create<Container>(account.Scene, true, true);
|
||||
container.ConfigId = containerConfig.Id;
|
||||
container.Account = account;
|
||||
container.CurrentCellCount = 0;
|
||||
containerComponent.Containers.Add(containerTypeInt, container);
|
||||
return container;
|
||||
}
|
||||
|
||||
public static uint TryGetContainer(Account account, ContainerType containerType, out Container container)
|
||||
{
|
||||
container = null;
|
||||
var containerComponent = account.GetComponent<ContainerComponent>();
|
||||
|
||||
if (containerComponent == null)
|
||||
{
|
||||
// 没有找到容器组件的错误码。
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!containerComponent.Containers.TryGetValue((int)containerType, out container))
|
||||
{
|
||||
// 在容器组件中没有找到该容器的错误码。
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetItem
|
||||
|
||||
public static bool GetItemById(Account account, ContainerType containerType, long id, out Item item)
|
||||
{
|
||||
if (TryGetContainer(account, containerType, out var container) != 0)
|
||||
{
|
||||
item = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return container.GetItemById(id, out item);
|
||||
}
|
||||
|
||||
public static bool GetItemByCell(Account account, ContainerType containerType, long cell, out Item item)
|
||||
{
|
||||
if (TryGetContainer(account, containerType, out var container) != 0)
|
||||
{
|
||||
item = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return container.GetItemByCell(cell, out item);
|
||||
}
|
||||
|
||||
public static void GetItemsByConfigId(Account account, ContainerType containerType, uint configId, List<Item> items)
|
||||
{
|
||||
if (TryGetContainer(account, containerType, out var container) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
container.GetItemsByConfigId(configId, items);
|
||||
}
|
||||
|
||||
public static void GetItemsByType(Account account, ContainerType containerType, ItemType itemType, List<Item> items)
|
||||
{
|
||||
if (TryGetContainer(account, containerType, out var container) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
container.GetItemsByType(itemType, items);
|
||||
}
|
||||
|
||||
public static bool IsFull(Account account, ContainerType containerType)
|
||||
{
|
||||
if (TryGetContainer(account, containerType, out var container) != 0)
|
||||
{
|
||||
// 这里的可以返回False,因为容器组件中可能这个容器。
|
||||
// 但是也可以返回true,是因为这个函数的语义是判断容器已满,如果找不到容器,也可以认为是满的。
|
||||
return true;
|
||||
}
|
||||
|
||||
return container.IsFull();
|
||||
}
|
||||
|
||||
public static int GetItemCount(Account account, ContainerType containerType, uint configId)
|
||||
{
|
||||
if (TryGetContainer(account, containerType, out var container) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return container.GetItemCount(configId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AddItem
|
||||
|
||||
public static uint AddItem(Account account, ContainerType containerType, Item item, ItemReason itemReason, bool isSendClient)
|
||||
{
|
||||
var tryGetContainer = TryGetContainer(account, containerType, out var container);
|
||||
|
||||
if (tryGetContainer != 0)
|
||||
{
|
||||
return tryGetContainer;
|
||||
}
|
||||
|
||||
return container.AddItem(item, itemReason, isSendClient);
|
||||
}
|
||||
|
||||
public static uint AddItem(Account account, ContainerType containerType, Item item, long cellId, ItemReason itemReason, bool isSendClient)
|
||||
{
|
||||
var tryGetContainer = TryGetContainer(account, containerType, out var container);
|
||||
|
||||
if (tryGetContainer != 0)
|
||||
{
|
||||
return tryGetContainer;
|
||||
}
|
||||
|
||||
return container.AddItem(item, cellId, itemReason, isSendClient);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SplitItem
|
||||
|
||||
public static uint SplitItem(Account account, ContainerType containerType, long itemId, int count, out Item splitItem)
|
||||
{
|
||||
var tryGetContainer = TryGetContainer(account, containerType, out var container);
|
||||
|
||||
if (tryGetContainer != 0)
|
||||
{
|
||||
splitItem = null;
|
||||
return tryGetContainer;
|
||||
}
|
||||
|
||||
return container.SplitItem(itemId, count, out splitItem);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RemoveItem
|
||||
|
||||
public static uint RemoveItem(Account account, ContainerType containerType, long itemId, ItemReason itemReason, bool isSendClient, bool isDispose = true)
|
||||
{
|
||||
var tryGetContainer = TryGetContainer(account, containerType, out var container);
|
||||
|
||||
if (tryGetContainer != 0)
|
||||
{
|
||||
return tryGetContainer;
|
||||
}
|
||||
|
||||
return container.RemoveItem(itemId, itemReason, isSendClient, isDispose);
|
||||
}
|
||||
|
||||
public static uint RemoveItem(Account account, ContainerType containerType, long itemId, int count, ItemReason itemReason, bool isSendClient, bool isDispose = true)
|
||||
{
|
||||
var tryGetContainer = TryGetContainer(account, containerType, out var container);
|
||||
|
||||
if (tryGetContainer != 0)
|
||||
{
|
||||
return tryGetContainer;
|
||||
}
|
||||
|
||||
return container.RemoveItem(itemId, count, itemReason, isSendClient, isDispose);
|
||||
}
|
||||
|
||||
public static uint RemoveItemByCell(Account account, ContainerType containerType, long cellId, ItemReason itemReason, bool isSendClient, bool isDispose = true)
|
||||
{
|
||||
var tryGetContainer = TryGetContainer(account, containerType, out var container);
|
||||
|
||||
if (tryGetContainer != 0)
|
||||
{
|
||||
return tryGetContainer;
|
||||
}
|
||||
|
||||
return container.RemoveItemByCell(cellId, itemReason, isSendClient, isDispose);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sort
|
||||
|
||||
public static void Sort(Account account, ContainerType containerType)
|
||||
{
|
||||
if (TryGetContainer(account, containerType, out var container) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
container.Sort();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToProto
|
||||
|
||||
public static bool TryGetContainerInfo(Account account, ContainerType containerType, out ContainerInfo containerInfo)
|
||||
{
|
||||
var tryGetContainer = TryGetContainer(account, containerType, out var container);
|
||||
|
||||
if (tryGetContainer != 0)
|
||||
{
|
||||
containerInfo = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
containerInfo = container.ToContainerInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void SendAllContainerInfo(Account account)
|
||||
{
|
||||
var containerComponent = account.GetComponent<ContainerComponent>();
|
||||
|
||||
if (containerComponent == null)
|
||||
{
|
||||
Log.Error($"account {account.Id} not found ContainerComponent!");
|
||||
return;
|
||||
}
|
||||
|
||||
var g2CPushAllContainerInfo = new G2C_PushAllContainerInfo();
|
||||
foreach (var (_, container) in containerComponent.Containers)
|
||||
{
|
||||
g2CPushAllContainerInfo.Containers.Add(container.ToContainerInfo());
|
||||
}
|
||||
// 推送容器数据给客户端
|
||||
account.Session.Send(g2CPushAllContainerInfo);
|
||||
}
|
||||
|
||||
// public static void SendAllContainerInfo(Account account)
|
||||
// {
|
||||
// var containerComponent = account.GetComponent<ContainerComponent>();
|
||||
//
|
||||
// if (containerComponent == null)
|
||||
// {
|
||||
// Log.Error($"account {account.Id} not found ContainerComponent!");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// foreach (var (_, container) in containerComponent.Containers)
|
||||
// {
|
||||
// account.Session.Send(new G2C_PushContainerInfo()
|
||||
// {
|
||||
// Container = container.ToContainerInfo()
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
#endregion
|
||||
}
|
||||
470
物品和背包的完整代码/Server/Hotfix/Gate/Container/ContainerSystem.cs
Normal file
470
物品和背包的完整代码/Server/Hotfix/Gate/Container/ContainerSystem.cs
Normal file
@@ -0,0 +1,470 @@
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
using Fantasy.Network;
|
||||
using Fantasy.Network.Interface;
|
||||
|
||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public sealed class ContainerDestroySystem : DestroySystem<Container>
|
||||
{
|
||||
protected override void Destroy(Container self)
|
||||
{
|
||||
self.Account = null;
|
||||
self.ConfigId = 0;
|
||||
self.CurrentCellCount = 0;
|
||||
|
||||
foreach (var (_, item) in self.Items)
|
||||
{
|
||||
item.Dispose();
|
||||
}
|
||||
|
||||
self.Items.Clear();
|
||||
self.ItemsByCell.Clear();
|
||||
self.ItemsByConfigId.Clear();
|
||||
self.ItemsByType.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ContainerDeserializeSystem : DeserializeSystem<Container>
|
||||
{
|
||||
protected override void Deserialize(Container self)
|
||||
{
|
||||
foreach (var (_, item) in self.Items)
|
||||
{
|
||||
item.Deserialize(self.Scene);
|
||||
item.Container = self;
|
||||
|
||||
if (item.CellId > 0)
|
||||
{
|
||||
self.ItemsByCell.Add(item.CellId, item);
|
||||
}
|
||||
|
||||
self.ItemsByConfigId.Add(item.ConfigId, item);
|
||||
self.ItemsByType.Add(item.Config.Type, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ContainerSystem
|
||||
{
|
||||
#region Get
|
||||
|
||||
public static bool GetItemById(this Container self, long id, out Item item)
|
||||
{
|
||||
return self.Items.TryGetValue(id, out item);
|
||||
}
|
||||
|
||||
public static bool GetItemByCell(this Container self, long cell, out Item item)
|
||||
{
|
||||
return self.ItemsByCell.TryGetValue(cell, out item);
|
||||
}
|
||||
|
||||
public static void GetItemsByConfigId(this Container self, uint configId, List<Item> items)
|
||||
{
|
||||
if (!self.ItemsByConfigId.TryGetValue(configId, out var itemList))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
items.AddRange(itemList);
|
||||
}
|
||||
|
||||
public static void GetItemsByType(this Container self, ItemType itemType, List<Item> items)
|
||||
{
|
||||
if (!self.ItemsByType.TryGetValue((uint)itemType, out var itemList))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
items.AddRange(itemList);
|
||||
}
|
||||
|
||||
public static bool IsFull(this Container self)
|
||||
{
|
||||
return self.CurrentCellCount >= self.Config.CellCount;
|
||||
}
|
||||
|
||||
public static int GetItemCount(this Container self, uint configId)
|
||||
{
|
||||
if (!self.ItemsByConfigId.TryGetValue(configId, out var itemList))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach (var item in itemList)
|
||||
{
|
||||
count += item.Count;
|
||||
}
|
||||
// return itemList.Sum(x => x.Count);
|
||||
return count;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Add
|
||||
|
||||
public static uint AddItem(this Container self, Item item, ItemReason itemReason, bool isSendClient)
|
||||
{
|
||||
var containerConfig = self.Config;
|
||||
if (!ContainerType.Normal.HasFlag((ContainerType)containerConfig.Type))
|
||||
{
|
||||
Log.Error($"{self.GetType().Name} is not normal container");
|
||||
return 1;
|
||||
}
|
||||
|
||||
var count = item.Count;
|
||||
var itemConfig = item.Config;
|
||||
var g2CUpdateItems = new G2C_UpdateItems();
|
||||
g2CUpdateItems.ItemReason = (int)itemReason;
|
||||
if (itemConfig.Superposed)
|
||||
{
|
||||
var superposedMax = (int)itemConfig.SuperposedMax;
|
||||
if (self.ItemsByConfigId.TryGetValue(itemConfig.Id, out var itemList))
|
||||
{
|
||||
var availableCount = superposedMax * itemList.Count;
|
||||
// 计算当前物品可以叠加的数量
|
||||
foreach (var haveItem in itemList)
|
||||
{
|
||||
availableCount -= haveItem.Count;
|
||||
}
|
||||
// 检查当前容器中是否还有空位。
|
||||
if (item.Count > availableCount && self.IsFull())
|
||||
{
|
||||
// 当前背包已满,无法添加该物品的错误码。
|
||||
// 无法叠加的数量大于物品的数量,那就表示当前物品不可以叠加到其他物品中了。
|
||||
return 2;
|
||||
}
|
||||
foreach (var haveItem in itemList)
|
||||
{
|
||||
var haveItemCount = superposedMax - haveItem.Count;
|
||||
// 如果当前物品叠加数量已经满了,那就直接找下一个同配置Id的物品。
|
||||
if (haveItemCount <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.Count > haveItemCount)
|
||||
{
|
||||
// 如果添加的物品数量大于当前物品的可叠加数量,那就把可叠加的数量减去。
|
||||
item.Count -= haveItemCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果添加的物品数量小于当前物品的可叠加数量,那就表示当前物品可以把添加物品的全部叠加到当前物品中了。
|
||||
// 这样的话,只需要记录下添加物品的数量就可以了
|
||||
haveItemCount = item.Count;
|
||||
item.Count = 0;
|
||||
}
|
||||
|
||||
haveItem.Count += haveItemCount;
|
||||
g2CUpdateItems.Items.Add(haveItem.ToItemInfo());
|
||||
if (item.Count <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (self.IsFull())
|
||||
{
|
||||
// 当前背包已满,无法添加该物品的错误码。
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.Count <= 0)
|
||||
{
|
||||
item.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Container = self;
|
||||
self.CurrentCellCount++;
|
||||
self.Items.Add(item.Id, item);
|
||||
self.ItemsByType.Add(itemConfig.Type, item);
|
||||
self.ItemsByConfigId.Add(itemConfig.Id, item);
|
||||
g2CUpdateItems.Items.Add(item.ToItemInfo());
|
||||
}
|
||||
|
||||
if (isSendClient)
|
||||
{
|
||||
self.SendClient(g2CUpdateItems);
|
||||
}
|
||||
|
||||
Log.Debug($"AddItem itemReason:{itemReason} itemConfigId:{itemConfig.Id} Count:{count}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static uint AddItem(this Container self, Item item, long cellId, ItemReason itemReason, bool isSendClient)
|
||||
{
|
||||
var containerConfig = self.Config;
|
||||
if (!ContainerType.Cell.HasFlag((ContainerType)containerConfig.Type))
|
||||
{
|
||||
Log.Error($"{self.GetType().Name} is not cell container");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (self.IsFull())
|
||||
{
|
||||
// 当前背包已满,无法添加该物品的错误码。
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (self.ItemsByCell.ContainsKey(cellId))
|
||||
{
|
||||
// 该Cell已经存在物品了。
|
||||
return 3;
|
||||
}
|
||||
|
||||
var g2CUpdateItems = new G2C_UpdateItems();
|
||||
g2CUpdateItems.ItemReason = (int)itemReason;
|
||||
|
||||
var itemConfig = item.Config;
|
||||
var count = item.Count;
|
||||
item.CellId = cellId;
|
||||
item.Container = self;
|
||||
self.CurrentCellCount++;
|
||||
|
||||
self.Items.Add(item.Id, item);
|
||||
self.ItemsByCell.Add(cellId, item);
|
||||
self.ItemsByType.Add(itemConfig.Type, item);
|
||||
self.ItemsByConfigId.Add(item.ConfigId, item);
|
||||
|
||||
g2CUpdateItems.Items.Add(item.ToItemInfo());
|
||||
|
||||
if (isSendClient)
|
||||
{
|
||||
self.SendClient(g2CUpdateItems);
|
||||
}
|
||||
Log.Debug($"AddItem itemReason:{itemReason} itemConfigId:{itemConfig.Id} Count:{count}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Split
|
||||
|
||||
public static uint SplitItem(this Container self, long itemId, int count, out Item splitItem)
|
||||
{
|
||||
splitItem = null;
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
// 要拆分的道具数量不可以小于等于0的错误码。
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (self.Items.TryGetValue(itemId, out var item))
|
||||
{
|
||||
// 没有找到物品的错误码。
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (item.Count == count)
|
||||
{
|
||||
// 要拆分的物品数量不可以和物品的数量相同的错误码。
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (item.Count < count)
|
||||
{
|
||||
// 要拆分的物品数量不可以大于物品的数量的错误码。
|
||||
return 4;
|
||||
}
|
||||
|
||||
item.Count -= count;
|
||||
splitItem = ItemFactory.Create(self.Scene, item.ConfigId, count, item.IsBind);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Remove
|
||||
|
||||
public static uint RemoveItem(this Container self, Item item, ItemReason itemReason, bool isSendClient, bool isDispose = true)
|
||||
{
|
||||
var count = item.Count;
|
||||
var itemConfig = item.Config;
|
||||
self.Items.Remove(item.Id);
|
||||
self.ItemsByConfigId.RemoveValue(item.ConfigId,item);
|
||||
self.ItemsByType.RemoveValue(itemConfig.Type, item);
|
||||
var containerConfig = self.Config;
|
||||
if (ContainerType.Cell.HasFlag((ContainerType)containerConfig.Type))
|
||||
{
|
||||
self.ItemsByCell.Remove(item.CellId);
|
||||
}
|
||||
|
||||
var g2CUpdateItems = new G2C_UpdateItems();
|
||||
g2CUpdateItems.ItemReason = (int)itemReason;
|
||||
g2CUpdateItems.Items.Add(item.ToItemInfo());
|
||||
|
||||
if (isDispose)
|
||||
{
|
||||
item.Dispose();
|
||||
}
|
||||
|
||||
self.CurrentCellCount--;
|
||||
|
||||
if (isSendClient)
|
||||
{
|
||||
self.SendClient(g2CUpdateItems);
|
||||
}
|
||||
Log.Debug($"RemoveItem itemReason:{itemReason} itemConfigId:{itemConfig.Id} Count:{count}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static uint RemoveItem(this Container self, long itemId, ItemReason itemReason, bool isSendClient, bool isDispose = true)
|
||||
{
|
||||
if (!self.Items.TryGetValue(itemId, out var item))
|
||||
{
|
||||
// 移除的时候,容器里找不到该物品的错误码。
|
||||
return 1;
|
||||
}
|
||||
|
||||
return self.RemoveItem(item, itemReason, isSendClient, isDispose);
|
||||
}
|
||||
|
||||
public static uint RemoveItem(this Container self, long itemId, int count, ItemReason itemReason, bool isSendClient, bool isDispose = true)
|
||||
{
|
||||
if (!self.Items.TryGetValue(itemId, out var item))
|
||||
{
|
||||
// 移除的时候,容器里找不到该物品的错误码。
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (item.Count < count)
|
||||
{
|
||||
// 要移除的物品数量不足的错误码。
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (count < 1)
|
||||
{
|
||||
// 要移除物品的数量不能小于1的错误码。
|
||||
return 3;
|
||||
}
|
||||
|
||||
item.Count -= count;
|
||||
|
||||
if (item.Count <= 0)
|
||||
{
|
||||
return self.RemoveItem(item, itemReason, isSendClient, isDispose);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isSendClient)
|
||||
{
|
||||
var g2CUpdateItems = new G2C_UpdateItems();
|
||||
g2CUpdateItems.ItemReason = (int)itemReason;
|
||||
g2CUpdateItems.Items.Add(item.ToItemInfo());
|
||||
self.SendClient(g2CUpdateItems);
|
||||
}
|
||||
Log.Debug($"RemoveItem itemReason:{itemReason} itemConfigId:{item.ConfigId} Count:{count}");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static uint RemoveItemByCell(this Container self, long cellId, ItemReason itemReason, bool isSendClient, bool isDispose = true)
|
||||
{
|
||||
if (!self.ItemsByCell.TryGetValue(cellId, out var item))
|
||||
{
|
||||
// 移除的时候,容器里找不到该物品的错误码。
|
||||
return 1;
|
||||
}
|
||||
|
||||
return self.RemoveItem(item, itemReason, isSendClient, isDispose);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sort
|
||||
|
||||
public static void Sort(this Container self)
|
||||
{
|
||||
// 这里排序一般服务器不会排序,也可以说是很少用排序.
|
||||
// 一般都是让客户端做好这个排序。
|
||||
// 如果用服务器排序会出现如下几种情况:
|
||||
// 1、排序好了后,要下发给客户端,很有可能会把当前容器里的所有物品全部下发给客户端。
|
||||
// 2、如果频繁排序的话,服务器的压力就会很大。
|
||||
// 3、因为移动端很少有那种格子空一个然后再有物品的情况,所以可以不用考虑空格子的情况。
|
||||
// 如果是PC端,需要格子有空位的,这时候服务器可以考虑排序了。
|
||||
using (var list = ListPool<Item>.Create())
|
||||
{
|
||||
list.AddRange(self.Items.Values);
|
||||
list.Sort(SortCompare);
|
||||
self.Items.Clear();
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
{
|
||||
var item = list[i];
|
||||
self.Items.Add(item.Id,item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int SortCompare(Item a, Item b)
|
||||
{
|
||||
// 升序排列(从小到大)
|
||||
// 3 1 2 排序后就是1 2 3
|
||||
// < 0 那就是a 在 b 的前面
|
||||
// = 0 那就是a 和 b 相等,顺序不变
|
||||
// > 0 那就 a 在 b 的后面
|
||||
var aConfig = a.Config;
|
||||
var bConfig = b.Config;
|
||||
var aWeight = aConfig.Weight;
|
||||
var bWeight = bConfig.Weight;
|
||||
// 这里还可以增加一些自定义的逻辑
|
||||
// 比如:按照物品创建时间、是否绑定、出售价格等等。
|
||||
// 这里的话就按照需求自己扩展把。
|
||||
if (a.IsBind != b.IsBind)
|
||||
{
|
||||
// 比如这里要做一个需求是绑定的排在前面.
|
||||
return a.IsBind ? -1 : 1;
|
||||
}
|
||||
if (aWeight == bWeight)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (aWeight > bWeight)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToProto
|
||||
|
||||
public static ContainerInfo ToContainerInfo(this Container self)
|
||||
{
|
||||
var containerInfo = new ContainerInfo()
|
||||
{
|
||||
ConfigId = (int)self.ConfigId,
|
||||
CurrentCellCount = self.CurrentCellCount
|
||||
};
|
||||
|
||||
foreach (var (_, item) in self.Items)
|
||||
{
|
||||
containerInfo.Items.Add(item.ToItemInfo());
|
||||
}
|
||||
|
||||
return containerInfo;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static void SendClient(this Container self, IMessage message)
|
||||
{
|
||||
self.Account.GetParent<Session>().Send(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
|
||||
namespace Fantasy.Equip;
|
||||
|
||||
public class EquipComponentAwakeSystem : AwakeSystem<EquipComponent>
|
||||
{
|
||||
protected override void Awake(EquipComponent self)
|
||||
{
|
||||
self.Awake();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EquipComponentDestroySystem : DestroySystem<EquipComponent>
|
||||
{
|
||||
protected override void Destroy(EquipComponent self)
|
||||
{
|
||||
foreach (var (_, value) in self.MainAttrs)
|
||||
{
|
||||
value.Dispose();
|
||||
}
|
||||
foreach (var (_, value) in self.EntryAttrs)
|
||||
{
|
||||
value.Dispose();
|
||||
}
|
||||
self.Affixs.Clear();
|
||||
self.MainAttrs.Clear();
|
||||
self.EntryAttrs.Clear();
|
||||
self.Durable = 0;
|
||||
self.DurableMax = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EquipAttrDestroySystem : DestroySystem<EquipAttr>
|
||||
{
|
||||
protected override void Destroy(EquipAttr self)
|
||||
{
|
||||
self.Key = 0;
|
||||
self.Value = 0;
|
||||
self.SValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EquipComponentSystem
|
||||
{
|
||||
public static void Awake(this EquipComponent self)
|
||||
{
|
||||
var item = self.GetParent<Item>();
|
||||
var itemConfig = item.Config;
|
||||
// 设置装备的耐久
|
||||
self.Durable = itemConfig.Durable;
|
||||
self.DurableMax = self.Durable;
|
||||
// 获取装备品质主属性方案
|
||||
if (!EquipValueConfigData.Instance.TryGetValue(itemConfig.Id, itemConfig.Quality, out var equipValueConfig))
|
||||
{
|
||||
// 没有找到主属性方案,需要检查代码或配置表是否正确。
|
||||
// 到这里的话就不需要继续执行了。
|
||||
return;
|
||||
}
|
||||
// 设置主属性
|
||||
self.InitMainAttrs(itemConfig, equipValueConfig);
|
||||
// 设置附加(副)属性
|
||||
self.InitEntryAttrs(itemConfig, equipValueConfig);
|
||||
// 设置词缀
|
||||
self.InitAffix(itemConfig, equipValueConfig);
|
||||
}
|
||||
|
||||
private static void InitMainAttrs(this EquipComponent self, ItemConfig itemConfig, EquipValueConfig equipValueConfig)
|
||||
{
|
||||
self.MainAttrs.Clear();
|
||||
// 循环遍历主属性。
|
||||
foreach (var (key, value) in equipValueConfig.MainAttrs.Dic)
|
||||
{
|
||||
var equipAttr = Entity.Create<EquipAttr>(self.Scene, true, true);
|
||||
equipAttr.Key = key;
|
||||
equipAttr.Value = value;
|
||||
self.MainAttrs.Add(key, equipAttr);
|
||||
}
|
||||
// 这里还可以加一些其他的需求。
|
||||
}
|
||||
|
||||
private static void InitEntryAttrs(this EquipComponent self, ItemConfig itemConfig, EquipValueConfig equipValueConfig)
|
||||
{
|
||||
var equipEntryConfigId = equipValueConfig.EquipEntryConfigId;
|
||||
// 很有可能当前的装备没有附加(副)属性,所以如果为默认值的情况下就不进行下面的逻辑。
|
||||
if (equipEntryConfigId == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// 还有一种可能是设置的副(附加)属性不存在,一般这样的情况下都是策划配置的错误,这里的话也不进行下面的逻辑了。
|
||||
if (!EquipEntryConfigData.Instance.TryGet(equipEntryConfigId, out var equipEntryConfig))
|
||||
{
|
||||
// 也可以在这里打印出一个错误,方便排查,找到这个错误告诉策划,让策划修改下。
|
||||
// (推荐做法)也可以一个单独的Scene,在这里Scene里把这些所有配置加载出来,按个的排查,如果有错误就打印出来。
|
||||
return;
|
||||
}
|
||||
self.EntryAttrs.Clear();
|
||||
// 这里可以用权重来控制随机的数量和属性,但是这里就不演示的。
|
||||
// 这里就是用直接的随机来做来了。
|
||||
var entryCount = RandomHelper.RandomNumber(equipEntryConfig.Min, equipEntryConfig.Max);
|
||||
// 获得当前随机附加属性的列表
|
||||
var configAttrs = equipEntryConfig.Attrs;
|
||||
var entryIndex = 0;
|
||||
for (var i = 0; i < entryCount; i++)
|
||||
{
|
||||
var equipAttr = Entity.Create<EquipAttr>(self.Scene, true, true);
|
||||
equipAttr.Key = configAttrs[entryIndex];
|
||||
equipAttr.Value = RandomHelper.RandomNumber(configAttrs[entryIndex + 1], configAttrs[entryIndex + 2]);
|
||||
self.EntryAttrs.Add(equipAttr.Key, equipAttr);
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitAffix(this EquipComponent self, ItemConfig itemConfig, EquipValueConfig equipValueConfig)
|
||||
{
|
||||
var equipEntryConfigId = equipValueConfig.EquipEntryConfigId;
|
||||
|
||||
if (equipEntryConfigId == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EquipEntryConfigData.Instance.TryGet(equipEntryConfigId, out var equipEntryConfig))
|
||||
{
|
||||
// 也可以在这里打印出一个错误,方便排查,找到这个错误告诉策划,让策划修改下。
|
||||
// (推荐做法)也可以一个单独的Scene,在这里Scene里把这些所有配置加载出来,按个的排查,如果有错误就打印出来。
|
||||
return;
|
||||
}
|
||||
|
||||
if (equipEntryConfig.Affix.Length == 0)
|
||||
{
|
||||
// 有可能没有词缀,所以这里就不进行下面的逻辑了。
|
||||
return;
|
||||
}
|
||||
|
||||
// 随机词缀的数量
|
||||
// 这里还是只做最简单的随机,如果想加权重的随机,可以自己实现下。
|
||||
var configAffix = equipEntryConfig.Affix;
|
||||
var affixCount = RandomHelper.RandomNumber(equipEntryConfig.AffixMin, equipEntryConfig.AffixMax);
|
||||
for (var i = 0; i < affixCount; i++)
|
||||
{
|
||||
self.Affixs.Add(configAffix[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static EquipInfo ToEquipInfo(this EquipComponent self)
|
||||
{
|
||||
var equipInfo = new EquipInfo();
|
||||
equipInfo.Durable = self.Durable;
|
||||
equipInfo.DurableMax = self.DurableMax;
|
||||
|
||||
foreach (var (key,equipAttr) in self.MainAttrs)
|
||||
{
|
||||
equipInfo.MainKeys.Add(key);
|
||||
equipInfo.EquipAttrKeys.Add(key);
|
||||
equipInfo.EquipAttrValues.Add(equipAttr.Value);
|
||||
equipInfo.EquipAttrSValues.Add(equipAttr.SValue);
|
||||
}
|
||||
|
||||
return equipInfo;
|
||||
}
|
||||
}
|
||||
137
物品和背包的完整代码/Server/Hotfix/Gate/Container/Equip/EquipHelper.cs
Normal file
137
物品和背包的完整代码/Server/Hotfix/Gate/Container/Equip/EquipHelper.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
namespace Fantasy;
|
||||
|
||||
public static class EquipHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 装载一个装备
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="mountEquipItem"></param>
|
||||
/// <returns></returns>
|
||||
public static uint MountEquip(Account account, Item mountEquipItem)
|
||||
{
|
||||
var itemConfig = mountEquipItem.Config;
|
||||
|
||||
if (!itemConfig.IsEquip())
|
||||
{
|
||||
// 这里返回的是不是装备的错误码。
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mountEquipItem.Container.Config.Type != (int)ContainerType.Bag)
|
||||
{
|
||||
// 只有在背包里的物品才可以装备到装备栏里的错误码。
|
||||
return 2;
|
||||
}
|
||||
|
||||
var mountEquipPosition = itemConfig.Position;
|
||||
// 如果在目标装备栏上有装备,那就先卸载装备。
|
||||
UnMountEquip(account, (EquipPosition)mountEquipPosition, true);
|
||||
// 下面要执行把装备添加到装备栏上。
|
||||
// 先在背包中移除该装备,因为已经得到了装备了,所以可以直接通过物品拿到背包的容器。
|
||||
var removeItem = mountEquipItem.Container.RemoveItem(mountEquipItem, ItemReason.MountEquipRemove, true, false);
|
||||
if (removeItem != 0)
|
||||
{
|
||||
// 移除装备的时候,发生了错误,直接返回错误码。
|
||||
return removeItem;
|
||||
}
|
||||
// 把装备添加到对应的装备栏上。
|
||||
var addItem = ContainerHelper.AddItem(account, ContainerType.Equip, mountEquipItem, mountEquipPosition,
|
||||
ItemReason.MountEquipAdd, true);
|
||||
if (addItem != 0)
|
||||
{
|
||||
// 添加装备的时候,发生了错误,直接返回错误码。
|
||||
return addItem;
|
||||
}
|
||||
// 这里要执行添加装备后,因为装备有增加属性或词缀Buff,所以需要在添加的时候把这些也要给添加下。
|
||||
// 因为本课程胡总没有数值系统和Buff系统,所以这里就不处理了。
|
||||
Log.Debug($"执行了装备装备的效果逻辑。");
|
||||
Log.Debug($"装载装备完成。mountEquipItem:{mountEquipItem.Id}");
|
||||
// 可以合包优化下这个协议的数量,优化成一个,能节省流量。
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 卸载一个装备
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="equipPosition"></param>
|
||||
/// <param name="isSendClient"></param>
|
||||
/// <returns></returns>
|
||||
public static uint UnMountEquip(Account account, EquipPosition equipPosition, bool isSendClient)
|
||||
{
|
||||
if (!ContainerHelper.GetItemByCell(account, ContainerType.Equip, (long)equipPosition, out var unMountEquipItem))
|
||||
{
|
||||
// 没有找到该位置的装备的错误码。
|
||||
return 1;
|
||||
}
|
||||
|
||||
return UnMountEquip(account, unMountEquipItem, isSendClient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 卸载一个装备
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="unMountEquipItem"></param>
|
||||
/// <param name="isSendClient"></param>
|
||||
/// <returns></returns>
|
||||
public static uint UnMountEquip(Account account, Item unMountEquipItem, bool isSendClient)
|
||||
{
|
||||
// 首先在装备栏容器中移除装备。
|
||||
var removeItem = unMountEquipItem.Container.RemoveItem(unMountEquipItem, ItemReason.UnMountEquipRemove, isSendClient, false);
|
||||
if (removeItem != 0)
|
||||
{
|
||||
// 移除失败了,要返回错误码,就不要执行后面的程序了。
|
||||
return removeItem;
|
||||
}
|
||||
// 这里要执行移除装备后,因为装备有增加属性或词缀Buff,所以需要在移除的时候把这些也要给移除下。
|
||||
// 因为本课程胡总没有数值系统和Buff系统,所以这里就不处理了。
|
||||
// 把移除成功的装备再次添加到背包容器中。
|
||||
Log.Debug("执行了装备卸载的效果逻辑。");
|
||||
return ContainerHelper.AddItem(account, ContainerType.Bag, unMountEquipItem, ItemReason.UnMountEquipAdd, isSendClient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据装备的位置获取装备
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="equipPosition"></param>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetEquipItem(Account account, EquipPosition equipPosition, out Item item)
|
||||
{
|
||||
return ContainerHelper.GetItemByCell(account, ContainerType.Equip, (long)equipPosition, out item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否是装备
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsEquip(this Item item)
|
||||
{
|
||||
return item.Config.IsEquip();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得装备所在的装备栏位置
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
public static EquipPosition GetEquipPosition(this Item item)
|
||||
{
|
||||
return (EquipPosition)item.GetEquipPositionInt();
|
||||
}
|
||||
|
||||
private static int GetEquipPositionInt(this Item item)
|
||||
{
|
||||
return item.Config.Position;
|
||||
}
|
||||
|
||||
private static bool IsEquip(this ItemConfig itemConfig)
|
||||
{
|
||||
var configType = (ItemType)itemConfig.Type;
|
||||
return configType == ItemType.Equip;
|
||||
}
|
||||
}
|
||||
44
物品和背包的完整代码/Server/Hotfix/Gate/Container/ItemSystem.cs
Normal file
44
物品和背包的完整代码/Server/Hotfix/Gate/Container/ItemSystem.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Equip;
|
||||
// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public sealed class ItemDestroySystem : DestroySystem<Item>
|
||||
{
|
||||
protected override void Destroy(Item self)
|
||||
{
|
||||
self.CellId = 0;
|
||||
self.Count = 0;
|
||||
self.ConfigId = 0;
|
||||
self.Container = null;
|
||||
self.IsBind = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ItemSystem
|
||||
{
|
||||
public static ItemInfo ToItemInfo(this Item self)
|
||||
{
|
||||
// 创建基础的物品信息
|
||||
var mItemInfo = new ItemInfo()
|
||||
{
|
||||
ItemId = self.Id,
|
||||
CellId = self.CellId,
|
||||
Count = self.Count,
|
||||
IsBind = self.IsBind,
|
||||
ConfigId = (int)self.ConfigId,
|
||||
Container = self.Container.Config.Type
|
||||
};
|
||||
// 添加装备信息
|
||||
var equipComponent = self.GetComponent<EquipComponent>();
|
||||
if (equipComponent != null)
|
||||
{
|
||||
mItemInfo.EquipInfo = equipComponent.ToEquipInfo();
|
||||
}
|
||||
return mItemInfo;
|
||||
}
|
||||
}
|
||||
73
物品和背包的完整代码/Server/Hotfix/Gate/Container/ItemUseHelper.cs
Normal file
73
物品和背包的完整代码/Server/Hotfix/Gate/Container/ItemUseHelper.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
namespace Fantasy;
|
||||
|
||||
public static class ItemUseHelper
|
||||
{
|
||||
public static uint UseBagItem(Account account, long itemId, int count)
|
||||
{
|
||||
return UseItem(account, ContainerType.Bag, itemId, count);
|
||||
}
|
||||
|
||||
public static uint CanUseBagItem(Account account, long itemId, int count, out Container container, out ItemConfig itemConfig, out ItemUseComponent itemUseComponent)
|
||||
{
|
||||
return CanUseItem(account, ContainerType.Bag, itemId, count, out container, out itemConfig, out itemUseComponent);
|
||||
}
|
||||
|
||||
public static uint UseItem(Account account, ContainerType containerType, long itemId, int count)
|
||||
{
|
||||
var errorCode = CanUseItem(account, containerType, itemId, count, out var container, out var itemConfig, out var itemUseComponent);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
errorCode = container.RemoveItem(itemId, count, ItemReason.ItemUse, true);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
itemUseComponent.Use(account, itemConfig, ref count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static uint CanUseItem(Account account, ContainerType containerType, long itemId, int count, out Container container, out ItemConfig itemConfig, out ItemUseComponent itemUseComponent)
|
||||
{
|
||||
itemConfig = null;
|
||||
itemUseComponent = null;
|
||||
var errorCode = ContainerHelper.TryGetContainer(account, containerType, out container);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
if (!container.GetItemById(itemId, out var item))
|
||||
{
|
||||
// 这里是找不到该物品的错误码。
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (item.Count < count)
|
||||
{
|
||||
// 这里是物品数量不足的错误码。
|
||||
return 2;
|
||||
}
|
||||
|
||||
itemConfig = item.Config;
|
||||
|
||||
if (itemConfig.Params.Length <= 0)
|
||||
{
|
||||
// 这里是物品没有配置参数的错误码。
|
||||
return 3;
|
||||
}
|
||||
|
||||
// 这里还可以增加一些其他的判定,比如物品是否过期,物品是否被锁定等。
|
||||
// 甚至还有物品使用的CD。
|
||||
// 使用物品效果来判定
|
||||
itemUseComponent = account.Scene.GetComponent<ItemUseComponent>();
|
||||
return itemUseComponent.CanUse(account, item.Config, ref count);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user