提交示例代码
This commit is contained in:
12
物品和背包的完整代码/Server/Entity/Gate/Components/BagComponent.cs
Normal file
12
物品和背包的完整代码/Server/Entity/Gate/Components/BagComponent.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Bson.Serialization.Options;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public class BagComponent : Entity, ISupportedDataBase
|
||||
{
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<long, Item> Items = new Dictionary<long, Item>();
|
||||
}
|
||||
240
物品和背包的完整代码/Server/Entity/Gate/Components/ItemUseComponent.cs
Normal file
240
物品和背包的完整代码/Server/Entity/Gate/Components/ItemUseComponent.cs
Normal file
@@ -0,0 +1,240 @@
|
||||
using Fantasy.Assembly;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Entitas;
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public class ItemUseComponent : Entity, IAssembly
|
||||
{
|
||||
private readonly Dictionary<int, IItemUse> _handlers = new Dictionary<int, IItemUse>();
|
||||
private readonly OneToManyList<long, int> _assemblyHandlers = new OneToManyList<long, int>();
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
_handlers.Clear();
|
||||
_assemblyHandlers.Clear();
|
||||
}
|
||||
|
||||
#region Assembly
|
||||
|
||||
public async FTask Initialize()
|
||||
{
|
||||
await AssemblySystem.Register(this);
|
||||
}
|
||||
|
||||
public async FTask Load(long assemblyIdentity)
|
||||
{
|
||||
var tcs = FTask.Create(false);
|
||||
Scene.ThreadSynchronizationContext.Post(() =>
|
||||
{
|
||||
InnerLoad(assemblyIdentity);
|
||||
tcs.SetResult();
|
||||
});
|
||||
await tcs;
|
||||
}
|
||||
|
||||
public async FTask ReLoad(long assemblyIdentity)
|
||||
{
|
||||
var tcs = FTask.Create(false);
|
||||
Scene.ThreadSynchronizationContext.Post(() =>
|
||||
{
|
||||
InnerUnLoad(assemblyIdentity);
|
||||
InnerLoad(assemblyIdentity);
|
||||
tcs.SetResult();
|
||||
});
|
||||
await tcs;
|
||||
}
|
||||
|
||||
public async FTask OnUnLoad(long assemblyIdentity)
|
||||
{
|
||||
var tcs = FTask.Create(false);
|
||||
Scene.ThreadSynchronizationContext.Post(() =>
|
||||
{
|
||||
InnerUnLoad(assemblyIdentity);
|
||||
tcs.SetResult();
|
||||
});
|
||||
await tcs;
|
||||
}
|
||||
|
||||
private void InnerLoad(long assemblyIdentity)
|
||||
{
|
||||
foreach (var type in AssemblySystem.ForEach(assemblyIdentity,typeof(IItemUse)))
|
||||
{
|
||||
var customAttributes = type.GetCustomAttributes(typeof(ItemUseAttribute), false);
|
||||
if (customAttributes.Length == 0)
|
||||
{
|
||||
Log.Warning($"type {type.FullName} Implemented the interface of IItemUse, requiring the implementation of ItemUseAttribute");
|
||||
continue;
|
||||
}
|
||||
var instance = (IItemUse)Activator.CreateInstance(type);
|
||||
foreach (ItemUseAttribute customAttribute in customAttributes)
|
||||
{
|
||||
var customAttributeType = (int)customAttribute.Type;
|
||||
_handlers.Add(customAttributeType, instance);
|
||||
_assemblyHandlers.Add(assemblyIdentity, customAttributeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InnerUnLoad(long assemblyIdentity)
|
||||
{
|
||||
if (!_assemblyHandlers.TryGetValue(assemblyIdentity, out var assemblyHandlers))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var assemblyHandler in assemblyHandlers)
|
||||
{
|
||||
_handlers.Remove(assemblyHandler);
|
||||
}
|
||||
|
||||
_assemblyHandlers.RemoveByKey(assemblyIdentity);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public uint CanUse(Account account, ItemConfig config, ref int count)
|
||||
{
|
||||
var itemUseEffect = (ItemUseEffect)config.Effect;
|
||||
|
||||
if (itemUseEffect == ItemUseEffect.None)
|
||||
{
|
||||
Log.Error($"config.Effect is zero!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return CanUse(account, config, itemUseEffect, ref count);
|
||||
}
|
||||
|
||||
public void Use(Account account, ItemConfig config, ref int count)
|
||||
{
|
||||
var itemUseEffect = (ItemUseEffect)config.Effect;
|
||||
|
||||
if (itemUseEffect == ItemUseEffect.None)
|
||||
{
|
||||
Log.Error($"config.Effect is zero!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_handlers.TryGetValue((int)itemUseEffect, out var handler))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler.Use(account, config, ref count);
|
||||
}
|
||||
|
||||
public uint UseHandler(Account account, ItemConfig config, ref int count)
|
||||
{
|
||||
var itemUseEffect = (ItemUseEffect)config.Effect;
|
||||
|
||||
if (itemUseEffect == ItemUseEffect.None)
|
||||
{
|
||||
Log.Error($"config.Effect is zero!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!_handlers.TryGetValue((int)itemUseEffect, out var handler))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var canUse = handler.CanUse(account, config, ref count);
|
||||
if (canUse != 0)
|
||||
{
|
||||
return canUse;
|
||||
}
|
||||
|
||||
handler.Use(account, config, ref count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public uint CanUse(Account account, ItemConfig config, ItemUseEffect itemUseEffect, ref int count)
|
||||
{
|
||||
if (!_handlers.TryGetValue((int)itemUseEffect, out var handler))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return handler.CanUse(account, config, ref count);
|
||||
}
|
||||
|
||||
public void Use(Account account, ItemConfig config, ItemUseEffect itemUseEffect, ref int count)
|
||||
{
|
||||
if (!_handlers.TryGetValue((int)itemUseEffect, out var handler))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler.Use(account, config, ref count);
|
||||
}
|
||||
|
||||
public uint UseHandler(Account account, ItemConfig config, ItemUseEffect itemUseEffect, ref int count)
|
||||
{
|
||||
if (!_handlers.TryGetValue((int)itemUseEffect, out var handler))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var canUse = handler.CanUse(account, config, ref count);
|
||||
if (canUse != 0)
|
||||
{
|
||||
return canUse;
|
||||
}
|
||||
|
||||
handler.Use(account, config, ref count);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// public static class ItemUseHelper
|
||||
// {
|
||||
// private static readonly Dictionary<int, IItemUse> Handlers = new Dictionary<int, IItemUse>();
|
||||
//
|
||||
// public static void Init()
|
||||
// {
|
||||
// Handlers.Add((int)ItemType.Drug, new ItemUse_Drug());
|
||||
// Handlers.Add((int)ItemType.Equip , new ItemUse_Equip());
|
||||
// }
|
||||
//
|
||||
// public static uint CanUse(Account account, ItemConfig config, ref int count)
|
||||
// {
|
||||
// if (!Handlers.TryGetValue((int)config.Type, out var handler))
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// return handler.CanUse(account, config, ref count);
|
||||
// }
|
||||
//
|
||||
// public static void Use(Account account, ItemConfig config, ref int count)
|
||||
// {
|
||||
// if (!Handlers.TryGetValue((int)config.Type, out var handler))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// handler.Use(account, config, ref count);
|
||||
// }
|
||||
//
|
||||
// public static uint UseHandler(Account account, ItemConfig config, ref int count)
|
||||
// {
|
||||
// if (!Handlers.TryGetValue((int)config.Type, out var handler))
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// var canUse = handler.CanUse(account, config, ref count);
|
||||
// if (canUse != 0)
|
||||
// {
|
||||
// return canUse;
|
||||
// }
|
||||
//
|
||||
// handler.CanUse(account, config, ref count);
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
51
物品和背包的完整代码/Server/Entity/Gate/Container/Container.cs
Normal file
51
物品和背包的完整代码/Server/Entity/Gate/Container/Container.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Entitas;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Bson.Serialization.Options;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
/// <summary>
|
||||
/// 代表一个容器的实体
|
||||
/// </summary>
|
||||
public sealed class Container : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 配置表ID
|
||||
/// </summary>
|
||||
public uint ConfigId;
|
||||
/// <summary>
|
||||
/// 账户的实体
|
||||
/// </summary>
|
||||
[BsonIgnore]
|
||||
public Account Account;
|
||||
/// <summary>
|
||||
/// 对应的Config配置文件
|
||||
/// </summary>
|
||||
[BsonIgnore]
|
||||
public ContainerConfig Config => ContainerConfigData.Instance.Get(ConfigId);
|
||||
/// <summary>
|
||||
/// 当前已经使用的格子的数量
|
||||
/// </summary>
|
||||
public int CurrentCellCount;
|
||||
/// <summary>
|
||||
/// 容器内的物品
|
||||
/// </summary>
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<long, Item> Items = new Dictionary<long, Item>();
|
||||
/// <summary>
|
||||
/// 容器内的物品,按照格子进行存储
|
||||
/// </summary>
|
||||
[BsonIgnore]
|
||||
public Dictionary<long, Item> ItemsByCell = new Dictionary<long, Item>();
|
||||
/// <summary>
|
||||
/// 容器内的物品,按照物品配置ID进行分组
|
||||
/// </summary>
|
||||
[BsonIgnore]
|
||||
public readonly OneToManyList<uint, Item> ItemsByConfigId = new OneToManyListPool<uint, Item>();
|
||||
/// <summary>
|
||||
/// 容器内的物品,按照物品类型进行分组
|
||||
/// </summary>
|
||||
[BsonIgnore]
|
||||
public readonly OneToManyList<uint, Item> ItemsByType = new OneToManyListPool<uint, Item>();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Bson.Serialization.Options;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
/// <summary>
|
||||
/// 把用户的所有容器都放在一个组件里,这样保存的时候也会存储在一个文档里。
|
||||
/// 如果物品数据过多,可能会超过数据库单条的限制。
|
||||
/// MongoDB的数据库的单个文档的最大大小限制为16MB。
|
||||
/// 所以这个几乎不会出现的,完全不需要考虑这个大小的问题了。因为几乎把玩家可能有16MB的物品。
|
||||
/// </summary>
|
||||
public sealed class ContainerComponent : Entity, ISupportedDataBase
|
||||
{
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<int, Container> Containers = new Dictionary<int, Container>();
|
||||
}
|
||||
// 如果不放心,可以把每个容器单独做一个组件存起来
|
||||
// 例如下面
|
||||
/// <summary>
|
||||
/// 背包容器组件
|
||||
/// </summary>
|
||||
public sealed class BagContainerComponent : Entity, ISupportedDataBase
|
||||
{
|
||||
public Container Container;
|
||||
}
|
||||
/// <summary>
|
||||
/// 装备容器组件
|
||||
/// </summary>
|
||||
public sealed class EquipContainerComponent : Entity, ISupportedDataBase
|
||||
{
|
||||
public Container Container;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Bson.Serialization.Options;
|
||||
|
||||
namespace Fantasy;
|
||||
/// <summary>
|
||||
/// 代表装备的某一个属性
|
||||
/// </summary>
|
||||
public class EquipAttr : Entity
|
||||
{
|
||||
[BsonElement("K")]
|
||||
public int Key; // 属性数值对应的Key
|
||||
[BsonElement("V")]
|
||||
public int Value; // 属性对应额数值
|
||||
[BsonElement("S")]
|
||||
public int SValue; // 附加或强化属性的对应数值
|
||||
[BsonIgnore]
|
||||
public int ValidValue => Value + SValue; // 真实的数值
|
||||
}
|
||||
/// <summary>
|
||||
/// 挂载到Item下的组件,用来表示这个Item是一个装备
|
||||
/// </summary>
|
||||
public class EquipComponent : Entity, ISupportedDataBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 主属性
|
||||
/// </summary>
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<int, EquipAttr> MainAttrs = new Dictionary<int, EquipAttr>();
|
||||
/// <summary>
|
||||
/// 附加(副)属性
|
||||
/// </summary>
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<int, EquipAttr> EntryAttrs = new Dictionary<int, EquipAttr>();
|
||||
/// <summary>
|
||||
/// 词缀
|
||||
/// </summary>
|
||||
public List<uint> Affixs = new List<uint>();
|
||||
public int DurableMax; // 耐久度上限
|
||||
public int Durable; // 耐久度
|
||||
}
|
||||
|
||||
/*
|
||||
* {"sdfsdfsdfsdf":111}
|
||||
* {"s":111}
|
||||
* 2000,100 = 150 - 50 = 100
|
||||
* 2001,200
|
||||
*
|
||||
* 优化后的处理方式
|
||||
* 2000,100 ,50 = 100 + 50 = 150
|
||||
* 50 - 50 = 0 , 100 + 0 = 100
|
||||
* 力量 + 50 (+20)
|
||||
*/
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace Fantasy;
|
||||
|
||||
public enum EquipPosition
|
||||
{
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// 武器
|
||||
/// </summary>
|
||||
Weapon = 1,
|
||||
/// <summary>
|
||||
/// 头盔
|
||||
/// </summary>
|
||||
Helmet = 2,
|
||||
/// <summary>
|
||||
/// 衣服
|
||||
/// </summary>
|
||||
Clothing = 3,
|
||||
/// <summary>
|
||||
/// 护腿
|
||||
/// </summary>
|
||||
Leggings = 4,
|
||||
/// <summary>
|
||||
/// 护腕
|
||||
/// </summary>
|
||||
Bracer = 5,
|
||||
/// <summary>
|
||||
/// 鞋子
|
||||
/// </summary>
|
||||
Shoe = 6,
|
||||
}
|
||||
21
物品和背包的完整代码/Server/Entity/Gate/Container/ItemReason.cs
Normal file
21
物品和背包的完整代码/Server/Entity/Gate/Container/ItemReason.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace Fantasy;
|
||||
|
||||
/// <summary>
|
||||
/// 物品操作原因
|
||||
/// </summary>
|
||||
public enum ItemReason
|
||||
{
|
||||
None = 0,
|
||||
ContainerAdd = 1, // 容器初始化添加物品
|
||||
ContainerRemove = 2, // 容器移除物品
|
||||
ContainerSplit = 3, // 容器拆分物品
|
||||
Drop = 4, // 掉落物品
|
||||
Mail = 5, // 邮件领取物品
|
||||
Sort = 6, // 物品排序
|
||||
ItemUse = 7, // 物品使用扣除
|
||||
ItemTestAdd = 8, // 测试添加物品
|
||||
UnMountEquipAdd = 9, // 卸载装备添加(一般是装备容器移除,然后添加到背包容器中)
|
||||
UnMountEquipRemove = 10, // 卸载装备移除(一般是在装备容器里移除掉)
|
||||
MountEquipAdd = 11, // 装备添加(一般是在装备容器里添加)
|
||||
MountEquipRemove = 12, // 装备移除(一般是在装备容器里添加,背包容器里移除)
|
||||
}
|
||||
16
物品和背包的完整代码/Server/Entity/Gate/Entity/Account.cs
Normal file
16
物品和背包的完整代码/Server/Entity/Gate/Entity/Account.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Network;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public sealed class Account : Entity
|
||||
{
|
||||
public string UserName;
|
||||
public string Password;
|
||||
public uint ConfigId;
|
||||
[BsonIgnore]
|
||||
public UnitConfig UnitConfig => UnitConfigData.Instance.Get(ConfigId);
|
||||
[BsonIgnore]
|
||||
public Session Session;
|
||||
}
|
||||
29
物品和背包的完整代码/Server/Entity/Gate/Entity/Item.cs
Normal file
29
物品和背包的完整代码/Server/Entity/Gate/Entity/Item.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Fantasy.Entitas;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
/// <summary>
|
||||
/// 代表游戏中的一个物品
|
||||
/// </summary>
|
||||
public class Item : Entity
|
||||
{
|
||||
public long CellId; // 格子Id x , y x | y = long
|
||||
public int Count; // 数量(叠加)
|
||||
public bool IsBind; // 是否绑定
|
||||
public uint ConfigId; // 配置表Id
|
||||
[BsonIgnore]
|
||||
public Container Container;
|
||||
[BsonIgnore]
|
||||
public ItemConfig Config => ItemConfigData.Instance.Get(ConfigId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于创建Item使用
|
||||
/// </summary>
|
||||
public struct ItemCreateParams
|
||||
{
|
||||
public uint ConfigId;
|
||||
public int Count;
|
||||
public bool IsBind;
|
||||
}
|
||||
34
物品和背包的完整代码/Server/Entity/Gate/ItemUse/IItemUse.cs
Normal file
34
物品和背包的完整代码/Server/Entity/Gate/ItemUse/IItemUse.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Fantasy;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true,Inherited = false)]
|
||||
public sealed class ItemUseAttribute : Attribute
|
||||
{
|
||||
public ItemUseEffect Type { get; }
|
||||
|
||||
public ItemUseAttribute(ItemUseEffect type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IItemUse
|
||||
{
|
||||
/// <summary>
|
||||
/// 正常的情况下,应该是使用Unit,因为这个代表的是某一个单位。
|
||||
/// 由于课程中没有这个Unit,所以暂时用Account来代替。
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
uint CanUse(Account account, ItemConfig config, ref int count);
|
||||
/// <summary>
|
||||
/// 使用物品的逻辑。
|
||||
/// </summary>
|
||||
/// <param name="account"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <param name="count"></param>
|
||||
void Use(Account account, ItemConfig config, ref int count);
|
||||
}
|
||||
Reference in New Issue
Block a user