提交修改
This commit is contained in:
@@ -19,6 +19,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Game\Condition\" />
|
||||
<Folder Include="Game\FishFarm\" />
|
||||
<Folder Include="Game\Map\Weather\" />
|
||||
<Folder Include="Generate\ConfigTable\" />
|
||||
<Folder Include="Generate\NetworkProtocol\" />
|
||||
|
||||
42
Entity/Game/Item/IItemUse.cs
Normal file
42
Entity/Game/Item/IItemUse.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
namespace NB.Game;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
|
||||
public sealed class ItemUseAttribute : Attribute
|
||||
{
|
||||
public ItemUseEffect Type { get; }
|
||||
|
||||
public ItemUseAttribute(ItemUseEffect type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ItemUseEffect
|
||||
{
|
||||
None = 0,
|
||||
Equip = 1, // 装备到身上
|
||||
UnEquip = 2, // 从身上卸下
|
||||
AddAttr = 3, // 增加属性
|
||||
CutAttr = 4, // 减少属性
|
||||
}
|
||||
|
||||
public interface IItemUse
|
||||
{
|
||||
/// <summary>
|
||||
/// 正常的情况下,应该是使用Unit,因为这个代表的是某一个单位。
|
||||
/// 由于课程中没有这个Unit,所以暂时用Account来代替。
|
||||
/// </summary>
|
||||
/// <param name="player"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
uint CanUse(Player player, cfg.Item config, ref int count);
|
||||
|
||||
/// <summary>
|
||||
/// 使用物品的逻辑。
|
||||
/// </summary>
|
||||
/// <param name="player"></param>
|
||||
/// <param name="config"></param>
|
||||
/// <param name="count"></param>
|
||||
void Use(Player player, cfg.Item config, ref int count);
|
||||
}
|
||||
@@ -9,7 +9,7 @@ public enum ItemBasicType
|
||||
Currency = 1,
|
||||
Item = 2,
|
||||
Rod = 3,
|
||||
Reel =4,
|
||||
Reel = 4,
|
||||
Bobber = 5,
|
||||
Line = 6,
|
||||
Bait = 7,
|
||||
@@ -60,4 +60,4 @@ public class Item : Entity
|
||||
/// 正则使用中
|
||||
/// </summary>
|
||||
[BsonIgnore] public bool InUse;
|
||||
}
|
||||
}
|
||||
|
||||
196
Entity/Game/Item/ItemUseComponent.cs
Normal file
196
Entity/Game/Item/ItemUseComponent.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Assembly;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NB.Game;
|
||||
|
||||
public class ItemUseComponent : Entity, IAssemblyLifecycle
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public async FTask Initialize()
|
||||
{
|
||||
// 注册到生命周期中
|
||||
await AssemblyLifecycle.Add(this);
|
||||
}
|
||||
|
||||
#region Assembly
|
||||
|
||||
public async FTask OnLoad(AssemblyManifest assemblyManifest)
|
||||
{
|
||||
var tcs = FTask.Create(false);
|
||||
Scene.ThreadSynchronizationContext.Post(() =>
|
||||
{
|
||||
InnerLoad(assemblyManifest);
|
||||
tcs.SetResult();
|
||||
});
|
||||
await tcs;
|
||||
}
|
||||
|
||||
public async FTask OnUnload(AssemblyManifest assemblyManifest)
|
||||
{
|
||||
var tcs = FTask.Create(false);
|
||||
Scene.ThreadSynchronizationContext.Post(() =>
|
||||
{
|
||||
InnerUnLoad(assemblyManifest);
|
||||
tcs.SetResult();
|
||||
});
|
||||
await tcs;
|
||||
}
|
||||
|
||||
private void InnerLoad(AssemblyManifest assemblyManifest)
|
||||
{
|
||||
var assembly = assemblyManifest.Assembly;
|
||||
var assemblyIdentity = assemblyManifest.AssemblyManifestId;
|
||||
|
||||
foreach (var type in assembly.GetTypes())
|
||||
{
|
||||
if (!typeof(IItemUse).IsAssignableFrom(type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type.IsInterface || type.IsAbstract)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
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(AssemblyManifest assemblyManifest)
|
||||
{
|
||||
var assemblyIdentity = assemblyManifest.AssemblyManifestId;
|
||||
if (!_assemblyHandlers.TryGetValue(assemblyIdentity, out var assemblyHandlers))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var assemblyHandler in assemblyHandlers)
|
||||
{
|
||||
_handlers.Remove(assemblyHandler);
|
||||
}
|
||||
|
||||
_assemblyHandlers.Remove(assemblyIdentity);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public uint CanUse(Player account, cfg.Item 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(Player account, cfg.Item 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(Player account, cfg.Item 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(Player account, cfg.Item 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(Player account, cfg.Item config, ItemUseEffect itemUseEffect, ref int count)
|
||||
{
|
||||
if (!_handlers.TryGetValue((int)itemUseEffect, out var handler))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handler.Use(account, config, ref count);
|
||||
}
|
||||
|
||||
public uint UseHandler(Player account, cfg.Item 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;
|
||||
}
|
||||
}
|
||||
36
Entity/Game/Mail/Components/MailBoxManageComponent.cs
Normal file
36
Entity/Game/Mail/Components/MailBoxManageComponent.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Fantasy;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NB;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件物流中转中心,用来存放所有离线的邮件。
|
||||
/// 玩家可以在上线的第一时间去这里领取属于自己的邮件。
|
||||
/// </summary>
|
||||
public class MailBoxManageComponent : Entity
|
||||
{
|
||||
// 定时清楚过期邮件的时间
|
||||
public const int MailCheckTIme = 10000;
|
||||
|
||||
// 存放所有邮箱都会在这里,包括发送给个人的和所有人的邮件。
|
||||
public readonly Dictionary<long, MailBox> MailBoxes = new Dictionary<long, MailBox>();
|
||||
|
||||
// 个人领取邮件列表
|
||||
public readonly OneToManyList<long, MailBox> MailsByAccount = new OneToManyList<long, MailBox>();
|
||||
|
||||
// 按照邮件箱类型存储
|
||||
public readonly OneToManyList<int, MailBox> MailsByMailBoxType = new OneToManyList<int, MailBox>();
|
||||
|
||||
// 按照时间排序的邮件箱
|
||||
public readonly SortedOneToManyList<long, long> Timers = new SortedOneToManyList<long, long>();
|
||||
|
||||
// 临时的存放过期时间的队列
|
||||
public readonly Queue<long> TimeOutQueue = new Queue<long>();
|
||||
|
||||
// 时间任务的Id
|
||||
public long TimerId;
|
||||
|
||||
// 最小的时间
|
||||
public long MinTime;
|
||||
}
|
||||
27
Entity/Game/Mail/Components/MailComponent.cs
Normal file
27
Entity/Game/Mail/Components/MailComponent.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Helper;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Bson.Serialization.Options;
|
||||
|
||||
namespace NB;
|
||||
|
||||
/// <summary>
|
||||
/// 这个代表一个用户身上所有邮件的组件
|
||||
/// </summary>
|
||||
public sealed class MailComponent : Entity
|
||||
{
|
||||
// 最大的邮件数量
|
||||
public const int MaxMailCount = 50;
|
||||
|
||||
// 邮件的过期时间,这个是过期7天时间。
|
||||
public const int MailExpireTime = 1000 * 60 * 60 * 24 * 7;
|
||||
|
||||
// 玩家的邮件
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<long, Mail> Mails = new Dictionary<long, Mail>();
|
||||
|
||||
// 按照时间进行排序
|
||||
[BsonIgnore] public readonly SortedOneToManyList<long, long> Timer = new SortedOneToManyList<long, long>();
|
||||
}
|
||||
26
Entity/Game/Mail/Entity/Mail.cs
Normal file
26
Entity/Game/Mail/Entity/Mail.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.Entitas;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB;
|
||||
|
||||
/// <summary>
|
||||
/// 代表游戏中的一封邮件实体
|
||||
/// </summary>
|
||||
public sealed class Mail : Entity
|
||||
{
|
||||
// 这个代表里游戏中的一封邮件
|
||||
// 标题、内容、金钱、物品
|
||||
public long OwnerId; // 邮件拥有者的Id(AccountId、UnitId、RoleId)
|
||||
public string Title; // 邮件的标题
|
||||
public string Content; // 邮件的内容
|
||||
public long CreateTime; // 邮件的创建时间
|
||||
public long ExpireTime; // 邮件的过期时间(决定这个实体的生命周期)
|
||||
public int Money; // 邮件的中钱
|
||||
public MailState MailState; // 邮件的状态
|
||||
public MailType MailType; // 邮件的类型
|
||||
public List<Item> Items = new List<Item>(); // 邮件中的物品
|
||||
// [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
// public Dictionary<long,Item> Items = new Dictionary<long,Item>();
|
||||
}
|
||||
25
Entity/Game/Mail/Entity/MailBox.cs
Normal file
25
Entity/Game/Mail/Entity/MailBox.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.Entitas;
|
||||
using NB;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件箱
|
||||
/// </summary>
|
||||
public sealed class MailBox : Entity
|
||||
{
|
||||
// 快递
|
||||
// 快递包装、用盒子。然后这个盒子上有一个标签、收件人、发件人、快递的公司。
|
||||
// 这个盒子了。可以装任何不同种类的东西。
|
||||
// 一对一、我发一个快递,给张三和李四。
|
||||
|
||||
// 但是邮件可能会有这个的功能,比如给某一个范围的人发送同一份邮件,比如补偿、或者奖励。
|
||||
public Mail Mail; // 邮件
|
||||
public long CreateTime; // 箱子的创建时间
|
||||
public long ExpireTime; // 箱子的过期时间
|
||||
public MailBoxType MailBoxType; // 箱子的类型
|
||||
public HashSet<long> AccountId = new HashSet<long>(); // 收件人
|
||||
public HashSet<long> Received = new HashSet<long>(); // 领取过的人
|
||||
public long SendAccountId; // 发件人/发送人
|
||||
}
|
||||
58
Entity/Game/Mail/Entity/MailConversation.cs
Normal file
58
Entity/Game/Mail/Entity/MailConversation.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
// using System.Collections.Generic;
|
||||
// using Fantasy.Entitas;
|
||||
// using MongoDB.Bson.Serialization.Attributes;
|
||||
//
|
||||
// namespace NB.Chat;
|
||||
//
|
||||
// public class MailConversation : Entity
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// 第一id
|
||||
// /// </summary>
|
||||
// [BsonElement("id1")] public long FirstId;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 第二id
|
||||
// /// </summary>
|
||||
// [BsonElement("id2")] public long SecondId;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 会话
|
||||
// /// </summary>
|
||||
// [BsonElement("list")] public List<Mail> Mails = new List<Mail>();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 第一个阅读时间
|
||||
// /// </summary>
|
||||
// [BsonElement("ft")] public long FirstReadTime;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 第二阅读时间
|
||||
// /// </summary>
|
||||
// [BsonElement("st")] public long SecondReadTime;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 最后更新时间
|
||||
// /// </summary>
|
||||
// [BsonElement("ut")] public long UpdateTime;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 删除人标志
|
||||
// /// </summary>
|
||||
// [BsonElement("rid")] public HashSet<long> RemoveId = new HashSet<long>();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 会话key,id-id,按大小排序
|
||||
// /// </summary>
|
||||
// [BsonIgnore] public string Key = string.Empty;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 最后保存时间
|
||||
// /// </summary>
|
||||
// [BsonIgnore] public long NeedSaveTime = 0;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 需要保存
|
||||
// /// </summary>
|
||||
// [BsonIgnore] public bool NeedSave;
|
||||
// }
|
||||
35
Entity/Game/Mail/Enum/MailEnum.cs
Normal file
35
Entity/Game/Mail/Enum/MailEnum.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
namespace NB;
|
||||
|
||||
public enum MailType
|
||||
{
|
||||
None = 0,
|
||||
System = 1, // 系统邮件
|
||||
Rewards = 2, // 奖励邮件(擂台、有奖问答)
|
||||
User = 3, // 个人邮件(玩家给玩家之间发送)
|
||||
}
|
||||
|
||||
public enum MailState
|
||||
{
|
||||
None = 0,
|
||||
Unread = 1, // 未读
|
||||
HaveRead = 2, // 已读
|
||||
NotClaimed = 3, // 未领取
|
||||
Received = 4, // 已领取
|
||||
}
|
||||
|
||||
public enum MailBoxType
|
||||
{
|
||||
None = 0,
|
||||
Specify = 1, // 指定目标
|
||||
Online = 2, // 给在线所有人发送邮件
|
||||
All = 3, // 所有人
|
||||
AllToDate = 4, // 根据玩家注册的时间发送邮件
|
||||
}
|
||||
|
||||
public enum MailRemoveActionType
|
||||
{
|
||||
None = 0,
|
||||
Remove = 1, // 手动移除
|
||||
ExpireTimeRemove = 2, // 过期时间移除
|
||||
Overtop = 3, // 超过邮件上限移除
|
||||
}
|
||||
@@ -62,6 +62,11 @@ public sealed class Player : Entity
|
||||
/// </summary>
|
||||
[BsonElement("vExTime")] public long VipExpirationTime;
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public long CreateTime;
|
||||
|
||||
|
||||
[BsonIgnore] public long SessionRunTimeId;
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Helper;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Bson.Serialization.Options;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// 玩家邮件组件
|
||||
/// </summary>
|
||||
public class MailComponent : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 最大邮件数据
|
||||
/// </summary>
|
||||
public const int MaxMailCount = 50;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件最大保留时间
|
||||
/// </summary>
|
||||
public const long MaxExpireTime = TimeHelper.OneDay * 365;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件列表
|
||||
/// </summary>
|
||||
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
|
||||
public Dictionary<long, Mail> Mails = new Dictionary<long, Mail>();
|
||||
|
||||
/// <summary>
|
||||
/// 按照时间进行排序
|
||||
/// </summary>
|
||||
[BsonIgnore] public readonly SortedOneToManyListPool<long, long> Timer = new SortedOneToManyListPool<long, long>();
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件管理组件
|
||||
/// </summary>
|
||||
public class MailManageComponent : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 会话列表
|
||||
/// </summary>
|
||||
public Dictionary<string, MailConversation> Conversations = new Dictionary<string, MailConversation>();
|
||||
|
||||
/// <summary>
|
||||
/// 缓存了的列表
|
||||
/// </summary>
|
||||
public HashSet<long> CacheRoleIds = new HashSet<long>();
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.Entitas;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public sealed class Mail : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 邮件发送者
|
||||
/// </summary>
|
||||
[BsonElement("send")] public long Sender;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件拥有者
|
||||
/// </summary>
|
||||
[BsonElement("owner")] public long OwnerId;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件状态
|
||||
/// </summary>
|
||||
[BsonElement("state")] public MailState State = MailState.None;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件状态
|
||||
/// </summary>
|
||||
[BsonElement("type")] public MailType MailType = MailType.None;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件内容
|
||||
/// </summary>
|
||||
[BsonElement("con")] public string Content;
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
[BsonElement("ct")] public long CreateTime;
|
||||
|
||||
/// <summary>
|
||||
/// 过期时间
|
||||
/// </summary>
|
||||
[BsonElement("et")] public long ExpireTime;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件的附件内容
|
||||
/// </summary>
|
||||
[BsonElement("item")] public List<AwardItem> Items = new List<AwardItem>();
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.Entitas;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// 邮件箱,系统群发用
|
||||
/// </summary>
|
||||
public class MailBox : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 邮件
|
||||
/// </summary>
|
||||
public Mail Mail;
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间
|
||||
/// </summary>
|
||||
public long CreateTime;
|
||||
|
||||
/// <summary>
|
||||
/// 失效时间
|
||||
/// </summary>
|
||||
public long ExpireTime;
|
||||
|
||||
/// <summary>
|
||||
/// 邮箱类型
|
||||
/// </summary>
|
||||
public MailBoxType BoxType;
|
||||
|
||||
/// <summary>
|
||||
/// 发送人
|
||||
/// </summary>
|
||||
public long SendAccountId = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 收件人
|
||||
/// </summary>
|
||||
public HashSet<long> AccountId = new HashSet<long>();
|
||||
|
||||
/// <summary>
|
||||
/// 领取过的人
|
||||
/// </summary>
|
||||
public HashSet<long> Received = new HashSet<long>();
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy.Entitas;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public class MailConversation : Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 第一id
|
||||
/// </summary>
|
||||
[BsonElement("id1")] public long FirstId;
|
||||
|
||||
/// <summary>
|
||||
/// 第二id
|
||||
/// </summary>
|
||||
[BsonElement("id2")] public long SecondId;
|
||||
|
||||
/// <summary>
|
||||
/// 会话
|
||||
/// </summary>
|
||||
[BsonElement("list")] public List<Mail> Mails = new List<Mail>();
|
||||
|
||||
/// <summary>
|
||||
/// 第一个阅读时间
|
||||
/// </summary>
|
||||
[BsonElement("ft")] public long FirstReadTime;
|
||||
|
||||
/// <summary>
|
||||
/// 第二阅读时间
|
||||
/// </summary>
|
||||
[BsonElement("st")] public long SecondReadTime;
|
||||
|
||||
/// <summary>
|
||||
/// 最后更新时间
|
||||
/// </summary>
|
||||
[BsonElement("ut")] public long UpdateTime;
|
||||
|
||||
/// <summary>
|
||||
/// 删除人标志
|
||||
/// </summary>
|
||||
[BsonElement("rid")] public HashSet<long> RemoveId = new HashSet<long>();
|
||||
|
||||
/// <summary>
|
||||
/// 会话key,id-id,按大小排序
|
||||
/// </summary>
|
||||
[BsonIgnore] public string Key = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 最后保存时间
|
||||
/// </summary>
|
||||
[BsonIgnore] public long NeedSaveTime = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 需要保存
|
||||
/// </summary>
|
||||
[BsonIgnore] public bool NeedSave;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
namespace NB.Chat;
|
||||
|
||||
public enum MailType
|
||||
{
|
||||
None = 0,
|
||||
System = 1, //系统邮件
|
||||
Rewards = 2, //奖励邮件
|
||||
User = 3, //个人邮件
|
||||
}
|
||||
|
||||
public enum MailState
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 未读
|
||||
/// </summary>
|
||||
Unread = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 已读
|
||||
/// </summary>
|
||||
HaveRead = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 未领取
|
||||
/// </summary>
|
||||
NotClaimed = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 已领取
|
||||
/// </summary>
|
||||
Received = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 已删除
|
||||
/// </summary>
|
||||
Deleted = 5,
|
||||
}
|
||||
|
||||
public enum MailBoxType
|
||||
{
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 指定目标
|
||||
/// </summary>
|
||||
Specify = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 全部人
|
||||
/// </summary>
|
||||
All = 2
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// using Fantasy;
|
||||
// using Fantasy.Entitas;
|
||||
//
|
||||
// namespace NB.Chat;
|
||||
//
|
||||
// public sealed class SocialUnit : Entity
|
||||
// {
|
||||
// public long GateRouteId;
|
||||
//
|
||||
// public RoleSimpleInfo Role;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 当前所在地图
|
||||
// /// </summary>
|
||||
// public long MapId;
|
||||
//
|
||||
//
|
||||
// public readonly Dictionary<long, ChatChannelComponent> Channels = new();
|
||||
// public readonly Dictionary<int, long> SendTime = new Dictionary<int, long>();
|
||||
//
|
||||
//
|
||||
// public override void Dispose()
|
||||
// {
|
||||
// if (IsDisposed)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// GateRouteId = 0;
|
||||
// Role = null;
|
||||
// base.Dispose();
|
||||
// }
|
||||
// }
|
||||
@@ -1,17 +0,0 @@
|
||||
// using System.Collections.Generic;
|
||||
// using Fantasy;
|
||||
// using Fantasy.DataStructure.Collection;
|
||||
// using Fantasy.Entitas;
|
||||
//
|
||||
// namespace NB.Chat;
|
||||
//
|
||||
// public class SocialUnitManageComponent : Entity
|
||||
// {
|
||||
// public readonly Dictionary<long, SocialUnit> Units = new();
|
||||
//
|
||||
// // public List<MailBox>
|
||||
// // /// <summary>
|
||||
// // /// 不在线消息缓存
|
||||
// // /// </summary>
|
||||
// // public readonly OneToManyList<long, ChatMessageInfo> NotSendMessage = new();
|
||||
// }
|
||||
@@ -25,6 +25,7 @@ public sealed partial class Fish : Luban.BeanBase
|
||||
MinWeight = (int)_obj.GetValue("min_weight");
|
||||
MaxWeight = (int)_obj.GetValue("max_weight");
|
||||
Accept = (int)_obj.GetValue("accept");
|
||||
Water = (int)_obj.GetValue("water");
|
||||
}
|
||||
|
||||
public static Fish DeserializeFish(JToken _buf)
|
||||
@@ -52,6 +53,10 @@ public sealed partial class Fish : Luban.BeanBase
|
||||
/// 接受的鱼饵配置组
|
||||
/// </summary>
|
||||
public readonly int Accept;
|
||||
/// <summary>
|
||||
/// 需要的水
|
||||
/// </summary>
|
||||
public readonly int Water;
|
||||
|
||||
|
||||
public const int __ID__ = 2189944;
|
||||
@@ -69,6 +74,7 @@ public sealed partial class Fish : Luban.BeanBase
|
||||
+ "minWeight:" + MinWeight + ","
|
||||
+ "maxWeight:" + MaxWeight + ","
|
||||
+ "accept:" + Accept + ","
|
||||
+ "water:" + Water + ","
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ public sealed partial class Item : Luban.BeanBase
|
||||
Length = (int)_obj.GetValue("length");
|
||||
Max = (int)_obj.GetValue("max");
|
||||
AutoUse = (int)_obj.GetValue("auto_use");
|
||||
Effect = (int)_obj.GetValue("effect");
|
||||
{ var __json0 = _obj.GetValue("result1"); Result1 = new System.Collections.Generic.List<int>((__json0 as JArray).Count); foreach(JToken __e0 in __json0) { int __v0; __v0 = (int)__e0; Result1.Add(__v0); } }
|
||||
{ var __json0 = _obj.GetValue("result2"); Result2 = new System.Collections.Generic.List<string>((__json0 as JArray).Count); foreach(JToken __e0 in __json0) { string __v0; __v0 = (string)__e0; Result2.Add(__v0); } }
|
||||
}
|
||||
@@ -70,6 +71,10 @@ public sealed partial class Item : Luban.BeanBase
|
||||
/// </summary>
|
||||
public readonly int AutoUse;
|
||||
/// <summary>
|
||||
/// 使用效果
|
||||
/// </summary>
|
||||
public readonly int Effect;
|
||||
/// <summary>
|
||||
/// 使用参数1
|
||||
/// </summary>
|
||||
public readonly System.Collections.Generic.List<int> Result1;
|
||||
@@ -97,6 +102,7 @@ public sealed partial class Item : Luban.BeanBase
|
||||
+ "length:" + Length + ","
|
||||
+ "max:" + Max + ","
|
||||
+ "autoUse:" + AutoUse + ","
|
||||
+ "effect:" + Effect + ","
|
||||
+ "result1:" + Luban.StringUtil.CollectionToString(Result1) + ","
|
||||
+ "result2:" + Luban.StringUtil.CollectionToString(Result2) + ","
|
||||
+ "}";
|
||||
|
||||
64
Entity/Generate/ConfigTable/Leader.cs
Normal file
64
Entity/Generate/ConfigTable/Leader.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using Luban;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
|
||||
|
||||
namespace cfg
|
||||
{
|
||||
|
||||
public sealed partial class Leader : Luban.BeanBase
|
||||
{
|
||||
public Leader(JToken _buf)
|
||||
{
|
||||
JObject _obj = _buf as JObject;
|
||||
Id = (int)_obj.GetValue("id");
|
||||
Strength = (int)_obj.GetValue("strength");
|
||||
Size = (int)_obj.GetValue("size");
|
||||
}
|
||||
|
||||
public static Leader DeserializeLeader(JToken _buf)
|
||||
{
|
||||
return new Leader(_buf);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public readonly int Id;
|
||||
/// <summary>
|
||||
/// 强度
|
||||
/// </summary>
|
||||
public readonly int Strength;
|
||||
/// <summary>
|
||||
/// 尺寸
|
||||
/// </summary>
|
||||
public readonly int Size;
|
||||
|
||||
|
||||
public const int __ID__ = -2022887127;
|
||||
public override int GetTypeId() => __ID__;
|
||||
|
||||
public void ResolveRef(Tables tables)
|
||||
{
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "{ "
|
||||
+ "id:" + Id + ","
|
||||
+ "strength:" + Strength + ","
|
||||
+ "size:" + Size + ","
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ public partial class Tables
|
||||
/// </summary>
|
||||
public TbItem TbItem {get; }
|
||||
/// <summary>
|
||||
/// 引线
|
||||
/// </summary>
|
||||
public TbLeader TbLeader {get; }
|
||||
/// <summary>
|
||||
/// 鱼线
|
||||
/// </summary>
|
||||
public TbLine TbLine {get; }
|
||||
@@ -82,6 +86,7 @@ public partial class Tables
|
||||
TbHook = new TbHook(loader("tbhook"));
|
||||
TbInitItemConfig = new TbInitItemConfig(loader("tbinititemconfig"));
|
||||
TbItem = new TbItem(loader("tbitem"));
|
||||
TbLeader = new TbLeader(loader("tbleader"));
|
||||
TbLine = new TbLine(loader("tbline"));
|
||||
TbLure = new TbLure(loader("tblure"));
|
||||
TbReel = new TbReel(loader("tbreel"));
|
||||
@@ -101,6 +106,7 @@ public partial class Tables
|
||||
TbHook.ResolveRef(this);
|
||||
TbInitItemConfig.ResolveRef(this);
|
||||
TbItem.ResolveRef(this);
|
||||
TbLeader.ResolveRef(this);
|
||||
TbLine.ResolveRef(this);
|
||||
TbLure.ResolveRef(this);
|
||||
TbReel.ResolveRef(this);
|
||||
|
||||
58
Entity/Generate/ConfigTable/TbLeader.cs
Normal file
58
Entity/Generate/ConfigTable/TbLeader.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Luban;
|
||||
|
||||
|
||||
|
||||
namespace cfg
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 引线
|
||||
/// </summary>
|
||||
public partial class TbLeader
|
||||
{
|
||||
private readonly System.Collections.Generic.Dictionary<int, Leader> _dataMap;
|
||||
private readonly System.Collections.Generic.List<Leader> _dataList;
|
||||
|
||||
public TbLeader(JArray _buf)
|
||||
{
|
||||
_dataMap = new System.Collections.Generic.Dictionary<int, Leader>(_buf.Count);
|
||||
_dataList = new System.Collections.Generic.List<Leader>(_buf.Count);
|
||||
|
||||
foreach(JObject _ele in _buf)
|
||||
{
|
||||
Leader _v;
|
||||
_v = global::cfg.Leader.DeserializeLeader(_ele);
|
||||
_dataList.Add(_v);
|
||||
_dataMap.Add(_v.Id, _v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public System.Collections.Generic.Dictionary<int, Leader> DataMap => _dataMap;
|
||||
public System.Collections.Generic.List<Leader> DataList => _dataList;
|
||||
|
||||
public Leader GetOrDefault(int key) => _dataMap.TryGetValue(key, out var v) ? v : default;
|
||||
public Leader Get(int key) => _dataMap[key];
|
||||
public Leader this[int key] => _dataMap[key];
|
||||
|
||||
public void ResolveRef(Tables tables)
|
||||
{
|
||||
foreach(var _v in _dataList)
|
||||
{
|
||||
_v.ResolveRef(tables);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,4 +678,89 @@ namespace Fantasy
|
||||
[ProtoMember(1)]
|
||||
public ChatInfoTree ChatInfoTree { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 其他服务器发送邮件
|
||||
/// </summary>
|
||||
////////// ******** 邮件 *******/////////////
|
||||
public partial class Other2Mail_SendMailRequest : AMessage, IAddressRequest
|
||||
{
|
||||
public static Other2Mail_SendMailRequest Create(bool autoReturn = true)
|
||||
{
|
||||
var other2Mail_SendMailRequest = MessageObjectPool<Other2Mail_SendMailRequest>.Rent();
|
||||
other2Mail_SendMailRequest.AutoReturn = autoReturn;
|
||||
|
||||
if (!autoReturn)
|
||||
{
|
||||
other2Mail_SendMailRequest.SetIsPool(false);
|
||||
}
|
||||
|
||||
return other2Mail_SendMailRequest;
|
||||
}
|
||||
|
||||
public void Return()
|
||||
{
|
||||
if (!AutoReturn)
|
||||
{
|
||||
SetIsPool(true);
|
||||
AutoReturn = true;
|
||||
}
|
||||
else if (!IsPool())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!IsPool()) return;
|
||||
MailBox = default;
|
||||
MessageObjectPool<Other2Mail_SendMailRequest>.Return(this);
|
||||
}
|
||||
public uint OpCode() { return InnerOpcode.Other2Mail_SendMailRequest; }
|
||||
[BsonIgnore]
|
||||
public Mail2Other_SendMailResponse ResponseType { get; set; }
|
||||
public MailBox MailBox { get; set; }
|
||||
}
|
||||
[Serializable]
|
||||
[ProtoContract]
|
||||
public partial class Mail2Other_SendMailResponse : AMessage, IAddressResponse
|
||||
{
|
||||
public static Mail2Other_SendMailResponse Create(bool autoReturn = true)
|
||||
{
|
||||
var mail2Other_SendMailResponse = MessageObjectPool<Mail2Other_SendMailResponse>.Rent();
|
||||
mail2Other_SendMailResponse.AutoReturn = autoReturn;
|
||||
|
||||
if (!autoReturn)
|
||||
{
|
||||
mail2Other_SendMailResponse.SetIsPool(false);
|
||||
}
|
||||
|
||||
return mail2Other_SendMailResponse;
|
||||
}
|
||||
|
||||
public void Return()
|
||||
{
|
||||
if (!AutoReturn)
|
||||
{
|
||||
SetIsPool(true);
|
||||
AutoReturn = true;
|
||||
}
|
||||
else if (!IsPool())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!IsPool()) return;
|
||||
ErrorCode = 0;
|
||||
MessageObjectPool<Mail2Other_SendMailResponse>.Return(this);
|
||||
}
|
||||
public uint OpCode() { return InnerOpcode.Mail2Other_SendMailResponse; }
|
||||
[ProtoMember(1)]
|
||||
public uint ErrorCode { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -20,5 +20,7 @@ namespace Fantasy
|
||||
public const uint Map2G_ExiRoomResponse = 1207969557;
|
||||
public const uint Chat2G_ChatMessage = 939534099;
|
||||
public const uint Other2Chat_ChatMessage = 939534100;
|
||||
public const uint Other2Mail_SendMailRequest = 1082140438;
|
||||
public const uint Mail2Other_SendMailResponse = 1207969558;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,63 +27,69 @@ namespace Fantasy
|
||||
public const uint Game2C_RewardNotify = 2147493651;
|
||||
public const uint C2Game_GMRequest = 2281711385;
|
||||
public const uint Game2C_GMResponse = 2415929113;
|
||||
public const uint C2Game_CreateRoomRequest = 2281711386;
|
||||
public const uint Game2C_CreateRoomResponse = 2415929114;
|
||||
public const uint C2Mail_TestRequest = 2281711386;
|
||||
public const uint Mail2C_TestResponse = 2415929114;
|
||||
public const uint Mail2C_HaveMail = 2147493652;
|
||||
public const uint Mail2C_MailState = 2147493653;
|
||||
public const uint C2Mail_GetHaveMailRequest = 2281711387;
|
||||
public const uint Mail2C_GetHaveMailResposne = 2415929115;
|
||||
public const uint C2Mail_OpenMailRequest = 2281711388;
|
||||
public const uint Mail2C_OpenMailResposne = 2415929116;
|
||||
public const uint C2Mail_ReceiveMailRequest = 2281711389;
|
||||
public const uint Mail2C_ReceiveMailResponse = 2415929117;
|
||||
public const uint C2Mail_RemoveMailRequest = 2281711390;
|
||||
public const uint Mail2C_RemoveMailResponse = 2415929118;
|
||||
public const uint C2Mail_SendMailRequest = 2281711391;
|
||||
public const uint Mail2C_SendMailResponse = 2415929119;
|
||||
public const uint C2Game_CreateRoomRequest = 2281711392;
|
||||
public const uint Game2C_CreateRoomResponse = 2415929120;
|
||||
public const uint C2G_ExitRoomRequest = 268445457;
|
||||
public const uint G2C_ExitRoomResponse = 402663185;
|
||||
public const uint C2G_EnterMapRequest = 268445458;
|
||||
public const uint G2C_EnterMapResponse = 402663186;
|
||||
public const uint Game2C_ChangeMap = 2147493652;
|
||||
public const uint Game2C_ChangeMap = 2147493654;
|
||||
public const uint C2A_LoginRequest = 268445459;
|
||||
public const uint A2C_LoginResponse = 402663187;
|
||||
public const uint C2G_LoginRequest = 268445460;
|
||||
public const uint G2C_LoginResponse = 402663188;
|
||||
public const uint G2C_RepeatLogin = 134227729;
|
||||
public const uint C2Game_GetRoleInfoRequest = 2281711387;
|
||||
public const uint Game2C_GetRoleInfoResponse = 2415929115;
|
||||
public const uint Game2C_RoleEnterRoomNotify = 2147493653;
|
||||
public const uint Game2C_RoleExitRoomNotify = 2147493654;
|
||||
public const uint C2Game_TakeItemRequest = 2281711388;
|
||||
public const uint Game2C_TakeItemResponse = 2415929116;
|
||||
public const uint C2Game_RolePropertyChange = 2147493655;
|
||||
public const uint Game2C_RoleStateNotify = 2147493656;
|
||||
public const uint Game2C_RoleGearChangeNotify = 2147493657;
|
||||
public const uint Game2C_RolePropertyChangeNotify = 2147493658;
|
||||
public const uint C2Game_Move = 2147493659;
|
||||
public const uint C2Game_Look = 2147493660;
|
||||
public const uint Game2C_MoveNotify = 2147493661;
|
||||
public const uint Game2C_LookeNotify = 2147493662;
|
||||
public const uint C2Game_GetConversationsRequest = 2281711389;
|
||||
public const uint Game2C_GetConversationsResponse = 2415929117;
|
||||
public const uint C2Game_SendMailRequest = 2281711390;
|
||||
public const uint Game2C_SendMailResponse = 2415929118;
|
||||
public const uint C2Game_DeleteMailRequest = 2281711391;
|
||||
public const uint Game2C_DeleteMailResponse = 2415929119;
|
||||
public const uint Game2C_HaveMail = 2147493663;
|
||||
public const uint Game2C_MailState = 2147493664;
|
||||
public const uint C2Game_SendMessageRequest = 2281711392;
|
||||
public const uint Game2C_SendMessageResponse = 2415929120;
|
||||
public const uint C2Game_GetRoleInfoRequest = 2281711393;
|
||||
public const uint Game2C_GetRoleInfoResponse = 2415929121;
|
||||
public const uint Game2C_RoleEnterRoomNotify = 2147493655;
|
||||
public const uint Game2C_RoleExitRoomNotify = 2147493656;
|
||||
public const uint C2Game_TakeItemRequest = 2281711394;
|
||||
public const uint Game2C_TakeItemResponse = 2415929122;
|
||||
public const uint C2Game_RolePropertyChange = 2147493657;
|
||||
public const uint Game2C_RoleStateNotify = 2147493658;
|
||||
public const uint Game2C_RoleGearChangeNotify = 2147493659;
|
||||
public const uint Game2C_RolePropertyChangeNotify = 2147493660;
|
||||
public const uint C2Game_Move = 2147493661;
|
||||
public const uint C2Game_Look = 2147493662;
|
||||
public const uint Game2C_MoveNotify = 2147493663;
|
||||
public const uint Game2C_LookeNotify = 2147493664;
|
||||
public const uint C2Game_SendMessageRequest = 2281711395;
|
||||
public const uint Game2C_SendMessageResponse = 2415929123;
|
||||
public const uint Game2C_Message = 2147493665;
|
||||
public const uint C2Game_CreateChannelRequest = 2281711393;
|
||||
public const uint Game2C_CreateChannelResponse = 2415929121;
|
||||
public const uint C2Game_JoinChannelRequest = 2281711394;
|
||||
public const uint Game2C_JoinChannelResponse = 2415929122;
|
||||
public const uint C2Game_CreateClubRequest = 2281711395;
|
||||
public const uint Game2C_CreateClubResponse = 2415929123;
|
||||
public const uint C2Game_GetClubInfoRequest = 2281711396;
|
||||
public const uint Game2C_GetClubInfoResponse = 2415929124;
|
||||
public const uint C2Game_GetMemberListRequest = 2281711397;
|
||||
public const uint Game2C_GetMemberListResponse = 2415929125;
|
||||
public const uint C2Game_GetClubListRequest = 2281711398;
|
||||
public const uint Game2C_GetClubListResponse = 2415929126;
|
||||
public const uint C2Game_JoinClubRequest = 2281711399;
|
||||
public const uint Game2C_JoinClubResponse = 2415929127;
|
||||
public const uint C2Game_LeaveClubRequest = 2281711400;
|
||||
public const uint Game2C_LeaveClubResponse = 2415929128;
|
||||
public const uint C2Game_DissolveClubRequest = 2281711401;
|
||||
public const uint Game2C_DissolveClubResponse = 2415929129;
|
||||
public const uint C2Game_DisposeJoinRequest = 2281711402;
|
||||
public const uint Game2C_DisposeJoinResponse = 2415929130;
|
||||
public const uint C2Game_CreateChannelRequest = 2281711396;
|
||||
public const uint Game2C_CreateChannelResponse = 2415929124;
|
||||
public const uint C2Game_JoinChannelRequest = 2281711397;
|
||||
public const uint Game2C_JoinChannelResponse = 2415929125;
|
||||
public const uint C2Game_CreateClubRequest = 2281711398;
|
||||
public const uint Game2C_CreateClubResponse = 2415929126;
|
||||
public const uint C2Game_GetClubInfoRequest = 2281711399;
|
||||
public const uint Game2C_GetClubInfoResponse = 2415929127;
|
||||
public const uint C2Game_GetMemberListRequest = 2281711400;
|
||||
public const uint Game2C_GetMemberListResponse = 2415929128;
|
||||
public const uint C2Game_GetClubListRequest = 2281711401;
|
||||
public const uint Game2C_GetClubListResponse = 2415929129;
|
||||
public const uint C2Game_JoinClubRequest = 2281711402;
|
||||
public const uint Game2C_JoinClubResponse = 2415929130;
|
||||
public const uint C2Game_LeaveClubRequest = 2281711403;
|
||||
public const uint Game2C_LeaveClubResponse = 2415929131;
|
||||
public const uint C2Game_DissolveClubRequest = 2281711404;
|
||||
public const uint Game2C_DissolveClubResponse = 2415929132;
|
||||
public const uint C2Game_DisposeJoinRequest = 2281711405;
|
||||
public const uint Game2C_DisposeJoinResponse = 2415929133;
|
||||
public const uint Game2C_ClubChange = 2147493666;
|
||||
}
|
||||
}
|
||||
74
Hotfix/Game/Item/Helper/ItemUseHelper.cs
Normal file
74
Hotfix/Game/Item/Helper/ItemUseHelper.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
namespace NB.Game;
|
||||
|
||||
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(Player account, long itemId, int count, out cfg.Item 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);
|
||||
// }
|
||||
}
|
||||
51
Hotfix/Game/Item/UseEffect/ItemUse_Drug_AddAttr.cs
Normal file
51
Hotfix/Game/Item/UseEffect/ItemUse_Drug_AddAttr.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Fantasy;
|
||||
|
||||
namespace NB.Game;
|
||||
|
||||
[ItemUse(ItemUseEffect.AddAttr)]
|
||||
public class ItemUse_Drug_AddAttr : IItemUse
|
||||
{
|
||||
// public uint CanUse(Account account, ItemConfig config, ref int count)
|
||||
// {
|
||||
// if (config.Params.Length < 2)
|
||||
// {
|
||||
// Log.Error($"configId:{config.Id} config.Params.Length({config.Params.Length}) < 2");
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
// Log.Debug($"CanUse 使用了药品增加属性 configId:{config.Id} count:{count}");
|
||||
// return 0;
|
||||
// }
|
||||
//
|
||||
// public void Use(Account account, ItemConfig config, ref int count)
|
||||
// {
|
||||
// for (int i = 0; i < config.Params.Length; i += 2)
|
||||
// {
|
||||
// var attrKey = config.Params[i];
|
||||
// var attrValue = config.Params[i + 1];
|
||||
// Log.Debug($"Use 使用了药品增加属性 configId:{config.Id} attrKey:{attrKey} attrValue:{attrValue}");
|
||||
// }
|
||||
// }
|
||||
public uint CanUse(Player player, cfg.Item config, ref int count)
|
||||
{
|
||||
// if (config.Params.Length < 2)
|
||||
// {
|
||||
// Log.Error($"configId:{config.Id} config.Params.Length({config.Params.Length}) < 2");
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
Log.Debug($"CanUse 使用了药品增加属性 configId:{config.Id} count:{count}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void Use(Player player, cfg.Item config, ref int count)
|
||||
{
|
||||
// for (int i = 0; i < config.Params.Length; i += 2)
|
||||
// {
|
||||
// var attrKey = config.Params[i];
|
||||
// var attrValue = config.Params[i + 1];
|
||||
// Log.Debug($"Use 使用了药品增加属性 configId:{config.Id} attrKey:{attrKey} attrValue:{attrValue}");
|
||||
// }
|
||||
Log.Debug($"Use 使用了药品增加属性 configId:{config.Id} count:{count}");
|
||||
}
|
||||
}
|
||||
18
Hotfix/Game/Item/UseEffect/ItemUse_Equip_Equip.cs
Normal file
18
Hotfix/Game/Item/UseEffect/ItemUse_Equip_Equip.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Fantasy;
|
||||
|
||||
namespace NB.Game;
|
||||
|
||||
[ItemUse(ItemUseEffect.Equip)]
|
||||
public class ItemUse_Equip_Equip : IItemUse
|
||||
{
|
||||
public uint CanUse(Player player, cfg.Item config, ref int count)
|
||||
{
|
||||
Log.Debug($"CanUse 使用了装备装备到身上 configId:{config.Id} count:{count}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void Use(Player player, cfg.Item config, ref int count)
|
||||
{
|
||||
Log.Debug($"Use 使用了装备装备到身上 configId:{config.Id} count:{count}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network.Interface;
|
||||
using NBF;
|
||||
|
||||
namespace NB;
|
||||
|
||||
public class Other2Mail_SendRequestHandler : AddressRPC<Scene, Other2Mail_SendMailRequest, Mail2Other_SendMailResponse>
|
||||
{
|
||||
protected override async FTask Run(Scene scene, Other2Mail_SendMailRequest request, Mail2Other_SendMailResponse response, Action reply)
|
||||
{
|
||||
await MailHelper.Send(scene, request.MailBox);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network.Interface;
|
||||
using NB.Game;
|
||||
using NBF;
|
||||
|
||||
// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||
|
||||
namespace NB;
|
||||
|
||||
public sealed class C2Mail_GetHaveMailRequestHandler : AddressRPC<Player, C2Mail_GetHaveMailRequest, Mail2C_GetHaveMailResposne>
|
||||
{
|
||||
protected override async FTask Run(Player mailUnit, C2Mail_GetHaveMailRequest request, Mail2C_GetHaveMailResposne response, Action reply)
|
||||
{
|
||||
var mailComponent = mailUnit.GetComponent<MailComponent>();
|
||||
|
||||
// 这个mailComponent是不是可能会为空?答案是可能的。
|
||||
// 那如果是空的怎么办呢,这样情况只能是别人恶意发包了。
|
||||
|
||||
if (mailComponent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// 检查是否有超时的邮件。如果有那就清楚掉
|
||||
await mailComponent.CheckTimeOut();
|
||||
// 领取当前的邮件
|
||||
mailComponent.GetMailSimplifyInfos(response.Mails);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network.Interface;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
using NBF;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public class C2Mail_OpenMailRequestHandler : AddressRPC<Player, C2Mail_OpenMailRequest, Mail2C_OpenMailResposne>
|
||||
{
|
||||
protected override async FTask Run(Player mailUnit, C2Mail_OpenMailRequest request, Mail2C_OpenMailResposne response, Action reply)
|
||||
{
|
||||
if (request.MailId <= 0)
|
||||
{
|
||||
response.ErrorCode = 100;
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据这个MailId来拿到邮件的详细信息
|
||||
var (errorCode, mail) = await mailUnit.GetComponent<MailComponent>().OpenMail(request.MailId);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
response.ErrorCode = errorCode;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!request.ReturnMailInfo)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
response.MailInfo = mail.ToMailInfo();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network.Interface;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
using NBF;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public class C2Mail_ReceiveMailRequestHandler : AddressRPC<Player, C2Mail_ReceiveMailRequest, Mail2C_ReceiveMailResponse>
|
||||
{
|
||||
protected override async FTask Run(Player mailUnit, C2Mail_ReceiveMailRequest request, Mail2C_ReceiveMailResponse response, Action reply)
|
||||
{
|
||||
if (request.MailId <= 0)
|
||||
{
|
||||
response.ErrorCode = 100;
|
||||
return;
|
||||
}
|
||||
|
||||
response.ErrorCode = await mailUnit.GetComponent<MailComponent>()
|
||||
.Receive(request.MailId, request.Money, request.ItemId, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network.Interface;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
using NBF;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public class C2Mail_RemoveMailRequestHandler : AddressRPC<Player,C2Mail_RemoveMailRequest, Mail2C_RemoveMailResponse>
|
||||
{
|
||||
protected override async FTask Run(Player mailUnit, C2Mail_RemoveMailRequest request, Mail2C_RemoveMailResponse response, Action reply)
|
||||
{
|
||||
if (request.MailId <= 0)
|
||||
{
|
||||
// 这里的1代表MailId不正确。
|
||||
response.ErrorCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
response.ErrorCode = await mailUnit.GetComponent<MailComponent>()
|
||||
.Remove(request.MailId, MailRemoveActionType.Remove, true);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using Fantasy.Async;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Network.Interface;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
using NBF;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public class C2Mail_SendMailRequestHandler : AddressRPC<Player, C2Mail_SendMailRequest, Mail2C_SendMailResponse>
|
||||
{
|
||||
protected override async FTask Run(Player mailUnit, C2Mail_SendMailRequest request,
|
||||
Mail2C_SendMailResponse response, Action reply)
|
||||
{
|
||||
if (request.UserId < 1)
|
||||
{
|
||||
// 这里的1代表的是发送的接收玩家名字不正确。
|
||||
response.ErrorCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(request.Title) || string.IsNullOrEmpty(request.Content))
|
||||
{
|
||||
// 这里的2代表的是发送的邮件标题或者内容不正确。
|
||||
response.ErrorCode = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.ItemId.Count > 10)
|
||||
{
|
||||
// 这里的3代表的是发送的邮件附件超出了最大范围。
|
||||
response.ErrorCode = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mailUnit.Scene.GetComponent<PlayerManageComponent>().TryGet(request.UserId, out var receiveMailUnit))
|
||||
{
|
||||
// 这里的4代表的是没有该玩家。
|
||||
response.ErrorCode = 4;
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.Money > 0)
|
||||
{
|
||||
// 如果大于0,就要调用某一个接口去货币所在的服务器上面去扣除玩家的钱。
|
||||
// var moneyResposne = await MoneyHelper.Cost(mailUnit.Scene, request.Money);
|
||||
// if (moneyResposne.ErrorCode != 0)
|
||||
// {
|
||||
// response.ErrorCode = moneyResposne.ErrorCode;
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
using var mailItems = ListPool<Item>.Create();
|
||||
if (request.ItemId.Count > 0)
|
||||
{
|
||||
// var itemResposne = await BagHelper.Get(mailUnit.Scene, request.ItemId);
|
||||
// if (itemResposne.ErrorCode != 0)
|
||||
// {
|
||||
// response.ErrorCode = itemResposne.ErrorCode;
|
||||
// return;
|
||||
// }
|
||||
// mailItems.AddRange(itemResposne.Items);
|
||||
}
|
||||
|
||||
var accountId = ListPool<long>.Create(receiveMailUnit.Id);
|
||||
var mail = MailFactory.Create(mailUnit.Scene, MailType.User, request.Title, request.Content, request.Money,
|
||||
mailItems);
|
||||
var mailBox = MailBoxFactory.Create(mailUnit.Scene, MailBoxType.Specify, mailUnit.Id, mail,
|
||||
1000 * 60 * 60, accountId);
|
||||
await MailHelper.Send(mailUnit.Scene, mailBox);
|
||||
}
|
||||
}
|
||||
22
Hotfix/Game/Mail/Handler/Outer/C2Mail_TestRequestHandler.cs
Normal file
22
Hotfix/Game/Mail/Handler/Outer/C2Mail_TestRequestHandler.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Fantasy.Async;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Network.Interface;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
using NBF;
|
||||
|
||||
namespace Fantasy;
|
||||
|
||||
public class C2Mail_TestRequestHandler : AddressRPC<Player, C2Mail_TestRequest, Mail2C_TestResponse>
|
||||
{
|
||||
protected override async FTask Run(Player mailUnit, C2Mail_TestRequest request, Mail2C_TestResponse response, Action reply)
|
||||
{
|
||||
Log.Debug($"这是一个测试的自定义消息协议 Tag:{mailUnit.Id}");
|
||||
response.Tag = "666";
|
||||
// using var accountId = ListPool<long>.Create(65491190472245249);
|
||||
var mail = MailFactory.Create(mailUnit.Scene, MailType.System, "测试所有人指定日期玩家邮件", "测试所有人指定日期玩家邮件内容", 9991);
|
||||
var mailBox = MailBoxFactory.Create(mailUnit.Scene, MailBoxType.AllToDate, mailUnit.Id, mail,
|
||||
1000 * 60 * 60);
|
||||
await MailHelper.Send(mailUnit.Scene, mailBox);
|
||||
}
|
||||
}
|
||||
65
Hotfix/Game/Mail/Helper/MailBoxFactory.cs
Normal file
65
Hotfix/Game/Mail/Helper/MailBoxFactory.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Helper;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
|
||||
namespace NBF;
|
||||
|
||||
public static class MailBoxFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建一个邮件箱
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="mailBoxType"></param>
|
||||
/// <param name="sendAccountId"></param>
|
||||
/// <param name="mail"></param>
|
||||
/// <param name="expireTime"></param>
|
||||
/// <param name="accountId"></param>
|
||||
/// <returns></returns>
|
||||
public static MailBox Create(Scene scene, MailBoxType mailBoxType, long sendAccountId, Mail mail, int expireTime,
|
||||
List<long> accountId = null)
|
||||
{
|
||||
var mailBox = Entity.Create<MailBox>(scene, true, true);
|
||||
mailBox.SendAccountId = sendAccountId;
|
||||
mailBox.Mail = mail;
|
||||
mailBox.MailBoxType = mailBoxType;
|
||||
mailBox.CreateTime = TimeHelper.Now;
|
||||
mailBox.ExpireTime = mailBox.CreateTime + expireTime;
|
||||
|
||||
if (accountId == null || accountId.Count <= 0)
|
||||
{
|
||||
return mailBox;
|
||||
}
|
||||
|
||||
foreach (var raId in accountId)
|
||||
{
|
||||
mailBox.AccountId.Add(raId);
|
||||
}
|
||||
|
||||
return mailBox;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个邮件箱
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="mailType"></param>
|
||||
/// <param name="mailBoxType"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="money"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="sendAccountId"></param>
|
||||
/// <param name="expireTime"></param>
|
||||
/// <param name="accountId"></param>
|
||||
/// <returns></returns>
|
||||
public static MailBox Create(Scene scene, MailType mailType, MailBoxType mailBoxType, string title, string content,
|
||||
int money, List<Item> items,
|
||||
long sendAccountId, int expireTime, List<long> accountId = null)
|
||||
{
|
||||
var mail = MailFactory.Create(scene, mailType, title, content, money, items);
|
||||
return Create(scene, mailBoxType, sendAccountId, mail, expireTime, accountId);
|
||||
}
|
||||
}
|
||||
45
Hotfix/Game/Mail/Helper/MailFactory.cs
Normal file
45
Hotfix/Game/Mail/Helper/MailFactory.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Serialize;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
|
||||
namespace NBF;
|
||||
|
||||
public static class MailFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建一个基础的邮件
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="money"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <param name="mailType"></param>
|
||||
/// <returns></returns>
|
||||
public static Mail Create(Scene scene, MailType mailType, string title, string content, int money = 0,
|
||||
List<Item> items = null)
|
||||
{
|
||||
var mail = Entity.Create<Mail>(scene, true, true);
|
||||
mail.Title = title;
|
||||
mail.Content = content;
|
||||
mail.Money = money;
|
||||
mail.MailType = mailType;
|
||||
mail.MailState = MailState.Unread;
|
||||
|
||||
|
||||
if (items != null && items.Count > 0)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
// 最好的是要个这个Item给克隆出一份来。
|
||||
// 这样就可以保证,无论外面怎么改变也不会影响这个邮件的东西了。
|
||||
var cloneItem = SerializerManager.BsonPack.CloneEntity(item);
|
||||
mail.Items.Add(cloneItem);
|
||||
}
|
||||
}
|
||||
|
||||
return mail;
|
||||
}
|
||||
}
|
||||
205
Hotfix/Game/Mail/Helper/MailHelper.cs
Normal file
205
Hotfix/Game/Mail/Helper/MailHelper.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Platform.Net;
|
||||
using Fantasy.Serialize;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
|
||||
namespace NBF;
|
||||
|
||||
/// <summary>
|
||||
/// 发送邮件的唯一接口
|
||||
/// 如果不是通过这个接口发送的邮件、出现任何问题,后果自负
|
||||
/// </summary>
|
||||
public static class MailHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 发送邮件
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="mailBox">发送完成后,记着一定要销毁这个MailBox,不然会有GC。</param>
|
||||
public static async FTask Send(Scene scene, MailBox mailBox)
|
||||
{
|
||||
if (scene.SceneType == SceneType.Game)
|
||||
{
|
||||
await InnerSend(scene, mailBox);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果不在同一个Scene下,就需要发送内部的网络消息给这个Scene了
|
||||
var mailSceneConfig = SceneConfigData.Instance.GetSceneBySceneType(SceneType.Game)[0];
|
||||
// await scene.NetworkMessagingComponent.CallInnerRoute(mailSceneConfig.RouteId, new Other2Mail_SendMailRequest()
|
||||
// {
|
||||
// MailBox = mailBox
|
||||
// });
|
||||
scene.NetworkMessagingComponent.Send(mailSceneConfig.Address, new Other2Mail_SendMailRequest()
|
||||
{
|
||||
MailBox = mailBox
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送邮件
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="mailBox"></param>
|
||||
/// <returns></returns>
|
||||
private static async FTask InnerSend(Scene scene, MailBox mailBox)
|
||||
{
|
||||
// 现在的情况,这个接口只能是在Mail这个服务器下可以操作
|
||||
// 但是真实的情况,其他同时开发的逻辑,调用这个接口一般都是在其他的服务器。
|
||||
// 这个问题其实很好解决,只需要判定当前Scene不是Mail、那就做一个协议,自动发送到这个MailScene就可以了。
|
||||
|
||||
if (mailBox.MailBoxType == MailBoxType.None)
|
||||
{
|
||||
Log.Error("MailBoxType MailBoxType.None not support!");
|
||||
return;
|
||||
}
|
||||
|
||||
var playerManageComponent = scene.GetComponent<PlayerManageComponent>();
|
||||
var mailBoxManageComponent = scene.GetComponent<MailBoxManageComponent>();
|
||||
mailBoxManageComponent.MailBoxes.Add(mailBox.Id, mailBox);
|
||||
|
||||
switch (mailBox.MailBoxType)
|
||||
{
|
||||
case MailBoxType.Specify:
|
||||
{
|
||||
if (mailBox.AccountId.Count <= 0)
|
||||
{
|
||||
Log.Error($"{mailBox.Id} AccountId is 0!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 这里可能有几种情况
|
||||
// 1、AccountId里面可能只有一个人。
|
||||
// 2、AccountId里面有多个人。
|
||||
|
||||
using var sendAccountIds = ListPool<long>.Create();
|
||||
|
||||
foreach (var accountId in mailBox.AccountId)
|
||||
{
|
||||
if (!playerManageComponent.TryGet(accountId, out var mailUnit))
|
||||
{
|
||||
// 如果没有的话,代表这个用户根本不存在。
|
||||
// 那这样的情况就不需要做任何处理。
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果有的话,那么就给这个用户发送邮件。
|
||||
// 这个玩家是否在线?
|
||||
var mailComponent = mailUnit.GetComponent<MailComponent>();
|
||||
// 在线的话,就直接发送邮件给这个玩家就可以了。
|
||||
if (mailComponent != null)
|
||||
{
|
||||
await mailComponent.Add(SerializerManager.BsonPack.CloneEntity(mailBox.Mail), true);
|
||||
sendAccountIds.Add(accountId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 不在线
|
||||
// 首先
|
||||
// 1、如果玩家不在线,那就把这个邮件在数据库中拿出来,然后把邮件插入到玩家的邮件列表里。然后再保存
|
||||
// 这样的做法是不推荐的,因为咱们游戏所有的东西都是有状态的,但是你拿出来的邮件是没有状态的。这样可能会导致一些问题的出现。
|
||||
// 正确的做做法:
|
||||
// 把这个邮件方法一个地方,比如是一个处理中心,当玩家上线的时候,主动去这个中心领取这个邮件。
|
||||
// 快递驿站、菜鸟、
|
||||
mailBoxManageComponent.MailsByAccount.Add(accountId, mailBox);
|
||||
Log.Debug("发送离线邮件成功,用户上线第一时间会领取这个邮件。");
|
||||
}
|
||||
}
|
||||
|
||||
// 移除掉发送成功的账号。
|
||||
|
||||
foreach (var sendAccountId in sendAccountIds)
|
||||
{
|
||||
mailBox.AccountId.Remove(sendAccountId);
|
||||
}
|
||||
|
||||
// 如果没有任何收件人了、就可以把这个邮箱给删除了。
|
||||
|
||||
if (mailBox.AccountId.Count <= 0)
|
||||
{
|
||||
mailBox.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 当这个邮件箱还有没有接收的玩家时候,要保存到数据库中,方便下次停服维护再重新启动的时候,加载这个邮件箱。
|
||||
await scene.World.Database.Save(mailBox);
|
||||
Log.Debug("保存离线邮件成功");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MailBoxType.Online:
|
||||
{
|
||||
// // 这里有个问题,如何知道在线的人呢?
|
||||
// foreach (var (_, mailUnit) in mailUnitManageComponent.UnitByAccountId)
|
||||
// {
|
||||
// var mailComponent = mailUnit.GetComponent<MailComponent>();
|
||||
// if (mailComponent == null)
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// // 能指定到这里的都是在线的玩家。
|
||||
// await mailComponent.Add(MailFactory.Serializer.Clone(mailBox.Mail), true);
|
||||
// }
|
||||
try
|
||||
{
|
||||
foreach (var (_, mailUnit) in playerManageComponent.Players)
|
||||
{
|
||||
await mailUnit.GetComponent<MailComponent>()
|
||||
.Add(SerializerManager.BsonPack.CloneEntity(mailBox.Mail), true);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mailBox.Dispose();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MailBoxType.All:
|
||||
{
|
||||
// 要保证这个邮件一定要有一个生命周期。并且这个周期一定要短,如果是想要实现永久的,可以比如30天发送一次。
|
||||
mailBoxManageComponent.MailsByMailBoxType.Add((int)MailBoxType.All, mailBox);
|
||||
// 首先给所有在线的玩家发送。
|
||||
foreach (var (_, mailUnit) in playerManageComponent.Players)
|
||||
{
|
||||
await mailUnit.GetComponent<MailComponent>()
|
||||
.Add(SerializerManager.BsonPack.CloneEntity(mailBox.Mail), true);
|
||||
// 在邮件盒子中记录下玩家领取的记录,避免重复领取。
|
||||
mailBox.Received.Add(mailUnit.Id);
|
||||
}
|
||||
|
||||
// 保存邮件箱到数据库。
|
||||
await scene.World.Database.Save(mailBox);
|
||||
break;
|
||||
}
|
||||
case MailBoxType.AllToDate:
|
||||
{
|
||||
mailBoxManageComponent.MailsByMailBoxType.Add((int)MailBoxType.AllToDate, mailBox);
|
||||
foreach (var (_, player) in playerManageComponent.Players)
|
||||
{
|
||||
if (player.CreateTime > mailBox.CreateTime)
|
||||
{
|
||||
// 如果执行到这里,表示这里用户是这个邮件创建之后的用户。这个就不要发送了
|
||||
continue;
|
||||
}
|
||||
|
||||
// 所以这个邮件类型的逻辑就是,给当前邮件创建时间之前的玩家发送。
|
||||
await player.GetComponent<MailComponent>()
|
||||
.Add(SerializerManager.BsonPack.CloneEntity(mailBox.Mail), true);
|
||||
// 在邮件盒子中记录下玩家领取的记录,避免重复领取。
|
||||
mailBox.Received.Add(player.Id);
|
||||
}
|
||||
|
||||
// 保存邮件箱到数据库。
|
||||
await scene.World.Database.Save(mailBox);
|
||||
break;
|
||||
}
|
||||
// 根据玩家等级、等等这样的邮件箱类型,都可以自行扩展了
|
||||
// 课下作业、自己实现一个起来类型的邮箱。
|
||||
}
|
||||
}
|
||||
}
|
||||
230
Hotfix/Game/Mail/System/MailBoxManageComponentSystem.cs
Normal file
230
Hotfix/Game/Mail/System/MailBoxManageComponentSystem.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
using Fantasy.Serialize;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
|
||||
namespace NBF;
|
||||
|
||||
|
||||
public class MailBoxManageComponentDestroySystem : DestroySystem<MailBoxManageComponent>
|
||||
{
|
||||
protected override void Destroy(MailBoxManageComponent self)
|
||||
{
|
||||
if (self.TimerId != 0)
|
||||
{
|
||||
self.Scene.TimerComponent.Net.Remove(ref self.TimerId);
|
||||
}
|
||||
|
||||
foreach (var (_, mailBox) in self.MailBoxes)
|
||||
{
|
||||
mailBox.Dispose();
|
||||
}
|
||||
|
||||
self.MinTime = 0;
|
||||
self.MailsByAccount.Clear();
|
||||
self.MailsByMailBoxType.Clear();
|
||||
self.Timers.Clear();
|
||||
self.TimeOutQueue.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MailBoxManageComponentSystem
|
||||
{
|
||||
public static async FTask Init(this MailBoxManageComponent self)
|
||||
{
|
||||
// 获取数据库中所有的没有处理完成的MailBox
|
||||
|
||||
var mailBoxes = await self.Scene.World.Database.Query<MailBox>(d => true);
|
||||
|
||||
foreach (var mailBox in mailBoxes)
|
||||
{
|
||||
self.MailBoxes.Add(mailBox.Id, mailBox);
|
||||
|
||||
switch (mailBox.MailBoxType)
|
||||
{
|
||||
case MailBoxType.Specify:
|
||||
{
|
||||
foreach (var accountId in mailBox.AccountId)
|
||||
{
|
||||
self.MailsByAccount.Add(accountId, mailBox);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MailBoxType.All:
|
||||
case MailBoxType.AllToDate:
|
||||
{
|
||||
self.MailsByMailBoxType.Add((int)mailBox.MailBoxType, mailBox);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.TimerId = self.Scene.TimerComponent.Net.RepeatedTimer(MailBoxManageComponent.MailCheckTIme, self.Timeout);
|
||||
}
|
||||
|
||||
private static void Timeout(this MailBoxManageComponent self)
|
||||
{
|
||||
var currentTime = TimeHelper.Now;
|
||||
|
||||
if (currentTime < self.MinTime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查当然时候有过期的邮件箱需要处理
|
||||
|
||||
foreach (var (timeKey, _) in self.Timers)
|
||||
{
|
||||
if (timeKey > currentTime)
|
||||
{
|
||||
self.MinTime = timeKey;
|
||||
break;
|
||||
}
|
||||
|
||||
self.TimeOutQueue.Enqueue(timeKey);
|
||||
}
|
||||
|
||||
while (self.TimeOutQueue.TryDequeue(out var timeKey))
|
||||
{
|
||||
foreach (var mailBoxId in self.Timers[timeKey])
|
||||
{
|
||||
Log.Info($"MailBox:{mailBoxId} 过期了!");
|
||||
self.Remove(mailBoxId).Coroutine();
|
||||
}
|
||||
|
||||
self.Timers.RemoveKey(timeKey);
|
||||
}
|
||||
}
|
||||
|
||||
public static async FTask Remove(this MailBoxManageComponent self, long mailBoxId)
|
||||
{
|
||||
if (!self.MailBoxes.Remove(mailBoxId, out var mailBox))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 先删除按照分类存储的邮箱
|
||||
self.MailsByMailBoxType.RemoveValue((int)mailBox.MailBoxType, mailBox);
|
||||
// 删除个人邮件的邮件箱
|
||||
self.MailsByAccount.RemoveValue(mailBoxId, mailBox);
|
||||
// 在数据库中删除这个邮件
|
||||
await self.Scene.World.Database.Remove<MailBox>(mailBoxId);
|
||||
// 销毁这个MailBox
|
||||
mailBox.Dispose();
|
||||
}
|
||||
|
||||
public static async FTask GetHaveMail(this MailBoxManageComponent self, Player mailUnit, bool sync)
|
||||
{
|
||||
var now = TimeHelper.Now;
|
||||
var worldDataBase = self.Scene.World.Database;
|
||||
var mailComponent = mailUnit.GetComponent<MailComponent>();
|
||||
|
||||
// 玩家领取范围邮件的逻辑处理
|
||||
|
||||
foreach (var (mailBoxType, mailBoxList) in self.MailsByMailBoxType)
|
||||
{
|
||||
using var removeMailBox = ListPool<MailBox>.Create();
|
||||
switch ((MailBoxType)mailBoxType)
|
||||
{
|
||||
// 发送给所有人的邮件
|
||||
case MailBoxType.All:
|
||||
{
|
||||
foreach (var mailBox in mailBoxList)
|
||||
{
|
||||
if (!mailBox.Received.Contains(mailUnit.Id))
|
||||
{
|
||||
// 如果是没有领取过这个邮件,首先要把自己添加到领取过的名单中。
|
||||
mailBox.Received.Add(mailUnit.Id);
|
||||
// 发送给自己的邮件列表里添加邮件。
|
||||
await mailUnit.GetComponent<MailComponent>().Add(SerializerManager.BsonPack.CloneEntity(mailBox.Mail), true);
|
||||
}
|
||||
|
||||
if (mailBox.ExpireTime <= now)
|
||||
{
|
||||
// 邮件已经过期了,要进行清理这个邮件的操作了
|
||||
removeMailBox.Add(mailBox);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 保存邮件箱状态到数据库中。
|
||||
await worldDataBase.Save(mailBox);
|
||||
}
|
||||
|
||||
foreach (var mailBox in removeMailBox)
|
||||
{
|
||||
await self.Remove(mailBox.Id);
|
||||
}
|
||||
|
||||
// 这里有一个小的细节要处理,这里大家课下自己实现一下。
|
||||
break;
|
||||
}
|
||||
case MailBoxType.AllToDate:
|
||||
{
|
||||
foreach (var mailBox in mailBoxList)
|
||||
{
|
||||
Log.Debug($"mailBox.CreateTime >= mailUnit.CreateTime {mailBox.CreateTime} >= {mailUnit.CreateTime}");
|
||||
if (mailBox.CreateTime >= mailUnit.CreateTime && !mailBox.Received.Contains(mailUnit.Id))
|
||||
{
|
||||
// 如果是没有领取过这个邮件,首先要把自己添加到领取过的名单中。
|
||||
mailBox.Received.Add(mailUnit.Id);
|
||||
// 发送给自己的邮件列表里添加邮件。
|
||||
await mailUnit.GetComponent<MailComponent>().Add(SerializerManager.BsonPack.CloneEntity(mailBox.Mail), true);
|
||||
}
|
||||
|
||||
if (mailBox.ExpireTime <= now)
|
||||
{
|
||||
// 邮件已经过期了,要进行清理这个邮件的操作了
|
||||
removeMailBox.Add(mailBox);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 保存邮件箱状态到数据库中。
|
||||
await worldDataBase.Save(mailBox);
|
||||
}
|
||||
|
||||
foreach (var mailBox in removeMailBox)
|
||||
{
|
||||
await self.Remove(mailBox.Id);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (self.MailsByAccount.TryGetValue(mailUnit.Id, out var mailBoxes))
|
||||
{
|
||||
using var removeMailBox = ListPool<MailBox>.Create();
|
||||
foreach (var mailBox in mailBoxes)
|
||||
{
|
||||
var cloneMail = SerializerManager.BsonPack.CloneEntity(mailBox.Mail);
|
||||
await mailComponent.Add(cloneMail, sync);
|
||||
mailBox.AccountId.Remove(mailUnit.Id);
|
||||
Log.Debug($"领取了一个离线邮件 MailId:{cloneMail.Id}");
|
||||
|
||||
if (mailBox.AccountId.Count <= 0)
|
||||
{
|
||||
// 当邮件箱里没有要发送的玩家了,就表示这个邮件箱已经没有用处,可以删除了。
|
||||
removeMailBox.Add(mailBox);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var mailBox in removeMailBox)
|
||||
{
|
||||
await self.Remove(mailBox.Id);
|
||||
}
|
||||
|
||||
if (mailBoxes.Count <= 0)
|
||||
{
|
||||
// 如果MailsByAccount里的邮件箱已经没有邮件了,就删除这个邮件箱的缓存。
|
||||
self.MailsByAccount.Remove(mailUnit.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using NB;
|
||||
|
||||
namespace NB.Chat;
|
||||
namespace NBF;
|
||||
|
||||
public class MailBoxDestroySystem : DestroySystem<MailBox>
|
||||
{
|
||||
@@ -12,7 +14,7 @@ public class MailBoxDestroySystem : DestroySystem<MailBox>
|
||||
self.Mail = null;
|
||||
}
|
||||
|
||||
self.BoxType = MailBoxType.None;
|
||||
self.MailBoxType = MailBoxType.None;
|
||||
self.CreateTime = 0;
|
||||
self.ExpireTime = 0;
|
||||
self.SendAccountId = 0;
|
||||
234
Hotfix/Game/Mail/System/MailComponentSystem.cs
Normal file
234
Hotfix/Game/Mail/System/MailComponentSystem.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.DataStructure.Collection;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
using NB;
|
||||
using NB.Game;
|
||||
|
||||
namespace NBF;
|
||||
|
||||
public class MailComponentDestroySystem : DestroySystem<MailComponent>
|
||||
{
|
||||
protected override void Destroy(MailComponent self)
|
||||
{
|
||||
foreach (var (_, mail) in self.Mails)
|
||||
{
|
||||
mail.Dispose();
|
||||
}
|
||||
|
||||
self.Mails.Clear();
|
||||
self.Timer.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public class MailComponentDeserializeSystem : DeserializeSystem<MailComponent>
|
||||
{
|
||||
protected override void Deserialize(MailComponent self)
|
||||
{
|
||||
self.Timer.Clear();
|
||||
foreach (var (_, mail) in self.Mails)
|
||||
{
|
||||
self.Timer.Add(mail.ExpireTime, mail.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class MailComponentSystem
|
||||
{
|
||||
public static async FTask Add(this MailComponent self, Mail mail, bool sync)
|
||||
{
|
||||
mail.CreateTime = TimeHelper.Now;
|
||||
mail.ExpireTime = mail.CreateTime + MailComponent.MailExpireTime;
|
||||
|
||||
// 如果身上的邮件数量,大于了设置的最大数量怎么办?
|
||||
// 先不用考虑,稍后咱们再解决问题。
|
||||
if (self.Mails.Count >= MailComponent.MaxMailCount)
|
||||
{
|
||||
// 删除最老的邮件。
|
||||
var (_, value) = self.Timer.First();
|
||||
var removeId = value[0];
|
||||
await self.Remove(removeId, MailRemoveActionType.Overtop, sync);
|
||||
}
|
||||
|
||||
self.Mails.Add(mail.Id, mail);
|
||||
self.Timer.Add(mail.ExpireTime, mail.Id);
|
||||
|
||||
if (sync)
|
||||
{
|
||||
// 同步邮件状态给客户端。
|
||||
self.Scene.NetworkMessagingComponent.Send(self.GetParent<Player>().SessionRunTimeId,
|
||||
new Mail2C_HaveMail()
|
||||
{
|
||||
Mail = mail.ToMailSimplifyInfo()
|
||||
});
|
||||
}
|
||||
|
||||
// 这里的保存,也可以不用,这里看情况而定。
|
||||
await self.Scene.World.Database.Save(self);
|
||||
Log.Info($"MailComponentSystem Add {mail.Id} Count:{self.Mails.Count}");
|
||||
}
|
||||
|
||||
public static async FTask<uint> Remove(this MailComponent self, long mailId,
|
||||
MailRemoveActionType mailRemoveActionType, bool sync)
|
||||
{
|
||||
if (!self.Mails.Remove(mailId, out var mail))
|
||||
{
|
||||
// 这里的1代表的没有找到对应邮件。
|
||||
return 1;
|
||||
}
|
||||
|
||||
self.Timer.RemoveValue(mail.ExpireTime, mail.Id);
|
||||
mail.Dispose();
|
||||
|
||||
if (sync)
|
||||
{
|
||||
// 同步给客户端,邮件删除的消息。
|
||||
self.Scene.NetworkMessagingComponent.Send(self.GetParent<Player>().SessionRunTimeId,
|
||||
new Mail2C_MailState()
|
||||
{
|
||||
MailState = (int)mailRemoveActionType, MailId = mailId
|
||||
});
|
||||
}
|
||||
|
||||
// 保存下数据库。
|
||||
await self.Scene.World.Database.Save(self);
|
||||
Log.Info(
|
||||
$"MailComponentSystem Remove {mailId} mailRemoveActionType:{mailRemoveActionType} Count:{self.Mails.Count}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static async FTask CheckTimeOut(this MailComponent self)
|
||||
{
|
||||
var now = TimeHelper.Now;
|
||||
using var listPool = ListPool<long>.Create();
|
||||
|
||||
foreach (var (_, mail) in self.Mails)
|
||||
{
|
||||
if (mail.ExpireTime > now)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
listPool.Add(mail.Id);
|
||||
}
|
||||
|
||||
foreach (var mailId in listPool)
|
||||
{
|
||||
await self.Remove(mailId, MailRemoveActionType.ExpireTimeRemove, false);
|
||||
}
|
||||
|
||||
Log.Info($"MailComponentSystem CheckTimeOut Count:{listPool.Count}");
|
||||
}
|
||||
|
||||
public static async FTask<(uint ErrorCode, Mail mail)> OpenMail(this MailComponent self, long mailId)
|
||||
{
|
||||
if (!self.Mails.TryGetValue(mailId, out var mail))
|
||||
{
|
||||
// 这个1代表的是没有找到对应邮件
|
||||
return (1, null);
|
||||
}
|
||||
|
||||
if (mail.ExpireTime < TimeHelper.Now)
|
||||
{
|
||||
// 如果邮件已经过期了,需要清楚这个邮件。
|
||||
await self.Remove(mailId, MailRemoveActionType.ExpireTimeRemove, true);
|
||||
// 这里2代表的是邮件已经过期。
|
||||
return (2, null);
|
||||
}
|
||||
|
||||
mail.MailState = MailState.HaveRead;
|
||||
// 这个保存数据库不是必须要保存的,因为一个邮件的查看状态并不能影响游戏的逻辑。
|
||||
// 这里的话,大家看自己的需求而定。
|
||||
await self.Scene.World.Database.Save(self);
|
||||
return (0, mail);
|
||||
}
|
||||
|
||||
public static void GetMailSimplifyInfos(this MailComponent self, ICollection<MailSimplifyInfo> mailSimplifyInfos)
|
||||
{
|
||||
foreach (var (_, mail) in self.Mails)
|
||||
{
|
||||
mailSimplifyInfos.Add(mail.ToMailSimplifyInfo());
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetMailSimplifyInfos(this MailComponent self, ICollection<MailSimplifyInfo> mailSimplifyInfos,
|
||||
int pageIndex, int pageSize)
|
||||
{
|
||||
foreach (var (_, mail) in self.Mails.Skip((pageIndex - 1) * pageSize).Take(pageSize))
|
||||
{
|
||||
mailSimplifyInfos.Add(mail.ToMailSimplifyInfo());
|
||||
}
|
||||
}
|
||||
|
||||
public static async FTask<uint> Receive(this MailComponent self, long mailId, bool money, List<long> item,
|
||||
bool sync)
|
||||
{
|
||||
if (!self.Mails.TryGetValue(mailId, out var mail))
|
||||
{
|
||||
// 这里的1代表是没有找到该邮件。
|
||||
return 1;
|
||||
}
|
||||
|
||||
var needSave = false;
|
||||
|
||||
if (money && mail.Money > 0)
|
||||
{
|
||||
// 领取金钱一般都是在玩家身上,但现在咱们所在的服务器是Mail服务器,玩家并不在这个服务器.
|
||||
// 所以一般金钱的操作会有一个专用的接口来操作。这个接口无论在什么服务器上,都会正确的发送到用户所在的服务器上进行金钱操作。
|
||||
// 假设下面的增加金钱的一个异步接口。
|
||||
// var resposne = await MoneyHelper.Add(self.Scene, mail.Money, sync);
|
||||
// if (resposne.ErrorCode != 0)
|
||||
// {
|
||||
// // 这里的2代表的是金钱添加失败。
|
||||
// return 2;
|
||||
// }
|
||||
// 再假设增加金钱是成功的,那么咱们就要处理邮件相关信息了。
|
||||
mail.Money = 0;
|
||||
needSave = true;
|
||||
}
|
||||
|
||||
if (item != null && item.Count > 0)
|
||||
{
|
||||
using var listItem = ListPool<Item>.Create();
|
||||
foreach (var itemId in item)
|
||||
{
|
||||
var rItem = mail.Items.FirstOrDefault(d => d.Id == itemId);
|
||||
if (rItem == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
listItem.Add(rItem);
|
||||
}
|
||||
|
||||
// 假设背包在其他服务器,需要调用某一个接口来添加物品到目标服务器的背包身上。
|
||||
// var response = await BagHelper.Add(self.Scene, listItem, sync);
|
||||
// if (response.ErrorCode != 0)
|
||||
// {
|
||||
// return 2;
|
||||
// }
|
||||
// 还有一种情况,就是背包里的空间只有一个空余位置了,也就是只能放进一个物品了,但是邮件领取的是2个物品.
|
||||
// 会有下面2中情况,当然这个情况是要策划来决定怎么处理:
|
||||
// 1、只领取一个物品到背包中,另外一个不领取,然后提示用户背包已满。
|
||||
// 2、一个都不领取,直接提示用户背包已满。
|
||||
// 如果是是第一种情况下,把BagHelper.Add接口,就需要返回添加成功的物品ID,方便邮件来处理。
|
||||
// 假设全部物品都领取成功了,就可以执行下面的逻辑了。
|
||||
|
||||
foreach (var item1 in listItem)
|
||||
{
|
||||
mail.Items.Remove(item1);
|
||||
item1.Dispose();
|
||||
}
|
||||
|
||||
needSave = true;
|
||||
}
|
||||
|
||||
if (needSave)
|
||||
{
|
||||
await self.Scene.World.Database.Save(self);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
77
Hotfix/Game/Mail/System/MailSystem.cs
Normal file
77
Hotfix/Game/Mail/System/MailSystem.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using NB;
|
||||
|
||||
namespace NBF;
|
||||
|
||||
|
||||
public sealed class MailDestroySystem : DestroySystem<Mail>
|
||||
{
|
||||
protected override void Destroy(Mail self)
|
||||
{
|
||||
self.OwnerId = 0;
|
||||
self.Title = null;
|
||||
self.Content = null;
|
||||
self.CreateTime = 0;
|
||||
self.ExpireTime = 0;
|
||||
self.Money = 0;
|
||||
self.MailState = MailState.None;
|
||||
self.MailType = MailType.None;
|
||||
|
||||
foreach (var selfItem in self.Items)
|
||||
{
|
||||
selfItem.Dispose();
|
||||
}
|
||||
|
||||
self.Items.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MailSystem
|
||||
{
|
||||
public static MailSimplifyInfo ToMailSimplifyInfo(this Mail self)
|
||||
{
|
||||
return new MailSimplifyInfo()
|
||||
{
|
||||
MailId = self.Id,
|
||||
OwnerId = self.OwnerId,
|
||||
Title = self.Title,
|
||||
Content = self.Content,
|
||||
CreateTime = self.CreateTime,
|
||||
ExpireTime = self.ExpireTime,
|
||||
MailState = (int)self.MailState,
|
||||
MailType = (int)self.MailType
|
||||
};
|
||||
}
|
||||
|
||||
public static MailInfo ToMailInfo(this Mail self)
|
||||
{
|
||||
var mailInfo = new MailInfo()
|
||||
{
|
||||
MailId = self.Id,
|
||||
OwnerId = self.OwnerId,
|
||||
Title = self.Title,
|
||||
Content = self.Content,
|
||||
CreateTime = self.CreateTime,
|
||||
ExpireTime = self.ExpireTime,
|
||||
Money = self.Money,
|
||||
MailState = (int)self.MailState,
|
||||
MailType = (int)self.MailType
|
||||
};
|
||||
|
||||
foreach (var selfItem in self.Items)
|
||||
{
|
||||
mailInfo.Items.Add(new ItemInfo()
|
||||
{
|
||||
Id = selfItem.Id,
|
||||
ConfigId = selfItem.ConfigId,
|
||||
Count = selfItem.Count,
|
||||
ExpirationTime = selfItem.ExpirationTime,
|
||||
GetTime = selfItem.GetTime,
|
||||
Abrasion = selfItem.Abrasion
|
||||
});
|
||||
}
|
||||
|
||||
return mailInfo;
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,6 @@ public static class RoomManageComponentSystem
|
||||
return null;
|
||||
}
|
||||
|
||||
// roomManageComponent.on
|
||||
var room = Entity.Create<MapRoom>(self.Scene, true, true);
|
||||
room.Owner = ownerId;
|
||||
room.RoomId = roomId;
|
||||
|
||||
@@ -91,7 +91,7 @@ public static class PlayerManageComponentSystem
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// account.Statistics.LoginTime = TimeHelper.Now;
|
||||
// account.SetTestData();
|
||||
|
||||
@@ -157,6 +157,7 @@ public static class PlayerManageComponentSystem
|
||||
player.Country = "cn";
|
||||
player.Exp = 999;
|
||||
player.Head = "xxx.png";
|
||||
player.CreateTime = TimeHelper.Now;
|
||||
|
||||
// var list = InitConfig.GetList();
|
||||
var list = Configs.Tables.TbInitItemConfig.DataList;
|
||||
|
||||
@@ -5,6 +5,7 @@ using Fantasy.Async;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
using NB.Chat;
|
||||
|
||||
#pragma warning disable CS8625 // 无法将 null 字面量转换为非 null 的引用类型。
|
||||
|
||||
@@ -31,6 +32,16 @@ public sealed class PlayerDestroySystem : DestroySystem<Player>
|
||||
// self.Statistics.Dispose();
|
||||
// self.Statistics = null;
|
||||
|
||||
// 退出当前ChatUnit拥有的所有频道
|
||||
foreach (var (_, chatChannelComponent) in self.Channels)
|
||||
{
|
||||
chatChannelComponent.ExitChannel(self.Id, false);
|
||||
}
|
||||
|
||||
// 理论情况下,这个self.Channels不会存在因为数据的,因为上面已经给清空掉了。
|
||||
// 但是self.Channels.Clear();还是加上吧,防止以后忘记了。
|
||||
self.Channels.Clear();
|
||||
|
||||
self.SessionRunTimeId = 0;
|
||||
}
|
||||
}
|
||||
@@ -47,7 +58,6 @@ public static class PlayerSystem
|
||||
/// <param name="items"></param>
|
||||
public static async FTask AddItems(this Player self, Dictionary<int, int> items)
|
||||
{
|
||||
|
||||
var itemContainer = self.GetComponent<PlayerItemContainerComponent>();
|
||||
HashSet<ItemBasicType> addType = new HashSet<ItemBasicType>();
|
||||
foreach (var (key, value) in items)
|
||||
@@ -64,7 +74,7 @@ public static class PlayerSystem
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public static MapUnitInfo ToMapUnitInfo(this Player self)
|
||||
{
|
||||
var ret = new MapUnitInfo()
|
||||
@@ -79,11 +89,11 @@ public static class PlayerSystem
|
||||
ret.Position.x = mapUnit.Position.x;
|
||||
ret.Position.y = mapUnit.Position.y;
|
||||
ret.Position.z = mapUnit.Position.z;
|
||||
|
||||
|
||||
ret.Rotation.x = mapUnit.Rotation.x;
|
||||
ret.Rotation.y = mapUnit.Rotation.y;
|
||||
ret.Rotation.z = mapUnit.Rotation.z;
|
||||
|
||||
|
||||
// ret.Gears
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
using System;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network.Interface;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public class C2Game_DeleteMailRequestHandler : AddressRPC<Player, C2Game_DeleteMailRequest, Game2C_DeleteMailResponse>
|
||||
{
|
||||
protected override async FTask Run(Player entity, C2Game_DeleteMailRequest request,
|
||||
Game2C_DeleteMailResponse response, Action reply)
|
||||
{
|
||||
if (request.Id < 1)
|
||||
{
|
||||
response.ErrorCode = ErrorCode.ErrArgs;
|
||||
return;
|
||||
}
|
||||
|
||||
var mailManageComponent = entity.Scene.GetComponent<MailManageComponent>();
|
||||
if (mailManageComponent == null)
|
||||
{
|
||||
Log.Error("组件不存在 MailManageComponent");
|
||||
response.ErrorCode = ErrorCode.ErrServer;
|
||||
return;
|
||||
}
|
||||
|
||||
var conversation = await mailManageComponent.GetConversation(entity.Id, request.Id);
|
||||
if (conversation == null)
|
||||
{
|
||||
response.ErrorCode = ErrorCode.ErrArgs;
|
||||
return;
|
||||
}
|
||||
|
||||
conversation.RemoveId.Add(entity.Id);
|
||||
if (conversation.RemoveId.Count > 1)
|
||||
{
|
||||
//都删除了,则吧会话直接移除掉
|
||||
await mailManageComponent.DeleteConversation(entity.Id, request.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
await conversation.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network.Interface;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public class
|
||||
C2Game_GetConversationsRequestHandler : AddressRPC<Player, C2Game_GetConversationsRequest, Game2C_GetConversationsResponse>
|
||||
{
|
||||
protected override async FTask Run(Player entity, C2Game_GetConversationsRequest request,
|
||||
Game2C_GetConversationsResponse response, Action reply)
|
||||
{
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
var mailManageComponent = entity.Scene.GetComponent<MailManageComponent>();
|
||||
var list = await mailManageComponent.GetConversations(entity.Id);
|
||||
response.List = await list.ToInfo(entity.Scene, entity.Id);
|
||||
stopwatch.Stop();
|
||||
Log.Info($"查询会话列表耗时={stopwatch.ElapsedMilliseconds}");
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Network.Interface;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public class C2Game_SendMailRequestHandler : AddressRPC<Player, C2Game_SendMailRequest, Game2C_SendMailResponse>
|
||||
{
|
||||
protected override async FTask Run(Player entity, C2Game_SendMailRequest request, Game2C_SendMailResponse response,
|
||||
Action reply)
|
||||
{
|
||||
if (request.Target < 1)
|
||||
{
|
||||
response.ErrorCode = ErrorCode.ErrArgs;
|
||||
return;
|
||||
}
|
||||
|
||||
var mailManageComponent = entity.Scene.GetComponent<MailManageComponent>();
|
||||
if (mailManageComponent == null)
|
||||
{
|
||||
Log.Error("组件不存在 MailManageComponent");
|
||||
response.ErrorCode = ErrorCode.ErrServer;
|
||||
return;
|
||||
}
|
||||
|
||||
var chatUnitManage = entity.Scene.GetComponent<PlayerManageComponent>();
|
||||
if (chatUnitManage == null)
|
||||
{
|
||||
Log.Error("组件不存在 SocialUnitManageComponent");
|
||||
response.ErrorCode = ErrorCode.ErrServer;
|
||||
return;
|
||||
}
|
||||
|
||||
var conversation = await mailManageComponent.GetConversation(entity.Id, request.Target);
|
||||
if (conversation == null)
|
||||
{
|
||||
response.ErrorCode = ErrorCode.ErrArgs;
|
||||
return;
|
||||
}
|
||||
//检查是否可以发消息,如果会话只有一句,则不允许再发
|
||||
if (!conversation.CanSend(entity.Id))
|
||||
{
|
||||
response.ErrorCode = ErrorCode.MailNotReply;
|
||||
return;
|
||||
}
|
||||
|
||||
var mail = MailFactory.Create(entity.Scene, request.Content);
|
||||
mail.Sender = entity.Id;
|
||||
mail.OwnerId = request.Target;
|
||||
await conversation.Add(mail);
|
||||
|
||||
var res = new Game2C_HaveMail()
|
||||
{
|
||||
Mail = mail.ToMailInfo(),
|
||||
Key = conversation.Key
|
||||
};
|
||||
//同步客户端
|
||||
entity.Scene.NetworkMessagingComponent.Send(entity.SessionRunTimeId, res);
|
||||
|
||||
// var chatUnit = chatUnitManage.Get(request.Target);
|
||||
//
|
||||
// if (chatUnit != null)
|
||||
// {
|
||||
// //对方在线
|
||||
// entity.Scene.NetworkMessagingComponent.Send(chatUnit.GateRouteId, res);
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Helper;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public static class MailBoxFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建一个邮件箱
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="sendAccountId"></param>
|
||||
/// <param name="mail"></param>
|
||||
/// <param name="expireTime"></param>
|
||||
/// <param name="accountIds"></param>
|
||||
/// <returns></returns>
|
||||
public static MailBox Create(Scene scene, long sendAccountId, Mail mail, int expireTime, List<long> accountIds)
|
||||
{
|
||||
var mailBox = Entity.Create<MailBox>(scene, true, true);
|
||||
mailBox.SendAccountId = sendAccountId;
|
||||
mailBox.Mail = mail;
|
||||
mailBox.ExpireTime = TimeHelper.Now + expireTime;
|
||||
mailBox.CreateTime = TimeHelper.Now;
|
||||
if (accountIds == null || accountIds.Count <= 0)
|
||||
{
|
||||
return mailBox;
|
||||
}
|
||||
|
||||
foreach (var accountId in accountIds)
|
||||
{
|
||||
mailBox.AccountId.Add(accountId);
|
||||
}
|
||||
|
||||
return mailBox;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个邮件箱
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="sendAccountId"></param>
|
||||
/// <param name="expireTime"></param>
|
||||
/// <param name="accountIds"></param>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
public static MailBox Create(Scene scene, long sendAccountId, int expireTime, List<long> accountIds,
|
||||
string content, List<AwardItem> items = null)
|
||||
{
|
||||
var mail = MailFactory.Create(scene, content, items);
|
||||
return Create(scene, sendAccountId, mail, expireTime, accountIds);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public static class MailConversationHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 从数据库中读取GameAccount
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="firstId"></param>
|
||||
/// <param name="secondId"></param>
|
||||
/// <returns></returns>
|
||||
public static async FTask<MailConversation> LoadDataBase(Scene scene, long firstId, long secondId)
|
||||
{
|
||||
var conversation =
|
||||
await scene.World.Database.First<MailConversation>(d => d.FirstId == firstId && d.SecondId == secondId);
|
||||
if (conversation == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
conversation.Deserialize(scene);
|
||||
return conversation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从数据库中移除
|
||||
/// </summary>
|
||||
/// <param name="scene"></param>
|
||||
/// <param name="id"></param>
|
||||
public static async FTask DeleteDataBase(Scene scene,long id)
|
||||
{
|
||||
await scene.World.Database.Remove<MailConversation>(id);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Helper;
|
||||
using Fantasy.Serialize;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public static class MailFactory
|
||||
{
|
||||
private static readonly ISerialize _serializer = SerializerManager.BsonPack;
|
||||
|
||||
public static Mail Create(Scene scene, string content, List<AwardItem> items = null)
|
||||
{
|
||||
|
||||
var mail = Entity.Create<Mail>(scene, true, true);
|
||||
mail.Content = content;
|
||||
mail.State = MailState.Unread;
|
||||
mail.CreateTime = TimeHelper.Now;
|
||||
|
||||
if (items != null && items.Count > 0)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
// mail.Items.Add(_serializer.Clone(item));
|
||||
}
|
||||
}
|
||||
|
||||
return mail;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
/// <summary>
|
||||
/// 发送邮件接口
|
||||
/// </summary>
|
||||
public static class MailHelper
|
||||
{
|
||||
|
||||
public static async FTask Send(Scene scene, MailBox mailBox)
|
||||
{
|
||||
if (mailBox.BoxType == MailBoxType.None)
|
||||
{
|
||||
Log.Error("不支持的邮件类型");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mailBox.BoxType)
|
||||
{
|
||||
case MailBoxType.All:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MailBoxType.Specify:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using System.Linq;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public class MailComponentDestroySystem : DestroySystem<MailComponent>
|
||||
{
|
||||
protected override void Destroy(MailComponent self)
|
||||
{
|
||||
foreach (var (_, mail) in self.Mails)
|
||||
{
|
||||
mail.Dispose();
|
||||
}
|
||||
|
||||
self.Mails.Clear();
|
||||
self.Timer.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MailComponentSystem
|
||||
{
|
||||
public static async FTask Add(this MailComponent self, Mail mail, bool sync)
|
||||
{
|
||||
mail.CreateTime = TimeHelper.Now;
|
||||
mail.ExpireTime = TimeHelper.Now + MailComponent.MaxExpireTime;
|
||||
|
||||
if (self.Mails.Count >= MailComponent.MaxMailCount)
|
||||
{
|
||||
//删除最老的邮件
|
||||
var (_, value) = self.Timer.First();
|
||||
foreach (var removeId in value)
|
||||
{
|
||||
await self.Remove(removeId, sync);
|
||||
}
|
||||
}
|
||||
|
||||
self.Mails.Add(mail.Id, mail);
|
||||
self.Timer.Add(mail.ExpireTime, mail.Id);
|
||||
|
||||
if (sync)
|
||||
{
|
||||
//同步客户端
|
||||
self.Scene.NetworkMessagingComponent.Send(0,new Game2C_HaveMail()
|
||||
{
|
||||
Mail = mail.ToMailInfo(),
|
||||
});
|
||||
}
|
||||
|
||||
await self.Scene.World.Database.Save(self);
|
||||
Log.Info($"MailComponent Add id:{self.Id} mailId:{mail.Id} count:{self.Mails.Count}");
|
||||
}
|
||||
|
||||
public static async FTask<uint> Remove(this MailComponent self, long mailId, bool sync)
|
||||
{
|
||||
if (!self.Mails.Remove(mailId, out var mail))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
self.Timer.RemoveValue(mail.ExpireTime, mail.Id);
|
||||
mail.Dispose();
|
||||
|
||||
if (sync)
|
||||
{
|
||||
//同步客户端
|
||||
self.Scene.NetworkMessagingComponent.Send(0,new Game2C_MailState()
|
||||
{
|
||||
MailState = (int)MailState.Deleted,
|
||||
MailId = mailId,
|
||||
});
|
||||
}
|
||||
|
||||
await self.Scene.World.Database.Save(self);
|
||||
Log.Info($"MailComponent Remove id:{self.Id} mailId:{mail.Id} count:{self.Mails.Count}");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public class MailConversationDeserializeSystem : DeserializeSystem<MailConversation>
|
||||
{
|
||||
protected override void Deserialize(MailConversation self)
|
||||
{
|
||||
self.Key = $"{self.FirstId}-{self.SecondId}";
|
||||
}
|
||||
}
|
||||
|
||||
public class MailConversationDestroySystem : DestroySystem<MailConversation>
|
||||
{
|
||||
protected override void Destroy(MailConversation self)
|
||||
{
|
||||
foreach (var mail in self.Mails)
|
||||
{
|
||||
mail.Dispose();
|
||||
}
|
||||
|
||||
self.Mails.Clear();
|
||||
self.FirstId = 0;
|
||||
self.SecondId = 0;
|
||||
self.Key = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MailConversationSystem
|
||||
{
|
||||
public static async FTask Add(this MailConversation self, Mail mail)
|
||||
{
|
||||
self.Mails.Add(mail);
|
||||
if (self.Mails.Count > AppConfig.MaxConversationCount)
|
||||
{
|
||||
self.Mails.RemoveAt(0);
|
||||
}
|
||||
|
||||
if (mail.Items != null && mail.Items.Count > 0)
|
||||
{
|
||||
//有附件需要立马保存
|
||||
await self.Save(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
await self.Save(false);
|
||||
}
|
||||
}
|
||||
|
||||
public static async FTask Save(this MailConversation self, bool forceSave = true)
|
||||
{
|
||||
// self.NeedSave = true;
|
||||
// self.NeedSaveTime = TimeHelper.Now + AppConfig.PlayerDataAutoSaveTime;
|
||||
if (forceSave)
|
||||
{
|
||||
self.UpdateTime = TimeHelper.Now;
|
||||
await self.Scene.World.Database.Save(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.NeedSave = true;
|
||||
self.NeedSaveTime = TimeHelper.Now + AppConfig.ChatDataAutoSaveTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否可以发送邮件
|
||||
/// </summary>
|
||||
/// <param name="self"></param>
|
||||
/// <param name="sendId"></param>
|
||||
/// <returns></returns>
|
||||
public static bool CanSend(this MailConversation self, long sendId)
|
||||
{
|
||||
if (self.Mails.Count < 1) return true;
|
||||
foreach (var mail in self.Mails)
|
||||
{
|
||||
if (mail.Sender != sendId)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#region 转换
|
||||
|
||||
public static async FTask<List<ConversationInfo>> ToInfo(this List<MailConversation> self, Scene scene, long selfId)
|
||||
{
|
||||
List<ConversationInfo> ret = new List<ConversationInfo>();
|
||||
HashSet<long> ids = new HashSet<long>();
|
||||
foreach (var conversation in self)
|
||||
{
|
||||
if (conversation.RemoveId.Contains(selfId)) continue;
|
||||
ids.Add(conversation.FirstId);
|
||||
ids.Add(conversation.SecondId);
|
||||
}
|
||||
|
||||
ids.Remove(selfId);
|
||||
|
||||
var infos = await CacheHandler.GetPlayerBasicCacheInfos(scene, ids.ToList());
|
||||
foreach (var conversation in self)
|
||||
{
|
||||
if (conversation.RemoveId.Contains(selfId)) continue;
|
||||
var item = new ConversationInfo();
|
||||
item.List = conversation.Mails.ToMailInfo();
|
||||
var otherId = conversation.FirstId == selfId ? conversation.SecondId : conversation.FirstId;
|
||||
var info = infos.Find(t => t.RoleId == otherId);
|
||||
if (info != null)
|
||||
{
|
||||
item.RoleInfo = info;
|
||||
}
|
||||
|
||||
ret.Add(item);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Async;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public class MailManageComponentDestroySystem : DestroySystem<MailManageComponent>
|
||||
{
|
||||
protected override void Destroy(MailManageComponent self)
|
||||
{
|
||||
foreach (var (_, conversation) in self.Conversations)
|
||||
{
|
||||
conversation.Dispose();
|
||||
}
|
||||
|
||||
self.Conversations.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MailManageComponentSystem
|
||||
{
|
||||
public static async FTask DeleteConversation(this MailManageComponent self, long selfId, long otherId)
|
||||
{
|
||||
var firstId = selfId;
|
||||
var secondId = otherId;
|
||||
if (otherId < selfId)
|
||||
{
|
||||
firstId = otherId;
|
||||
secondId = selfId;
|
||||
}
|
||||
|
||||
var key = $"{firstId}-{secondId}";
|
||||
|
||||
if (self.Conversations.Remove(key, out var conversation))
|
||||
{
|
||||
await MailConversationHelper.DeleteDataBase(conversation.Scene, conversation.Id);
|
||||
conversation.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public static async FTask<MailConversation?> GetConversation(this MailManageComponent self, long selfId,
|
||||
long otherId)
|
||||
{
|
||||
var firstId = selfId;
|
||||
var secondId = otherId;
|
||||
if (otherId < selfId)
|
||||
{
|
||||
firstId = otherId;
|
||||
secondId = selfId;
|
||||
}
|
||||
|
||||
var key = $"{firstId}-{secondId}";
|
||||
if (!self.Conversations.TryGetValue(key, out var conversation))
|
||||
{
|
||||
//检查数据库中是否存在
|
||||
conversation = await MailConversationHelper.LoadDataBase(self.Scene, firstId, secondId);
|
||||
if (conversation == null)
|
||||
{
|
||||
//检查id是否合法
|
||||
var roleInfo = await CacheHandler.GetPlayerBasicCacheInfo(self.Scene, otherId);
|
||||
if (roleInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
conversation = Entity.Create<MailConversation>(self.Scene, true, true);
|
||||
|
||||
conversation.FirstId = firstId;
|
||||
conversation.SecondId = secondId;
|
||||
|
||||
conversation.Key = key;
|
||||
await conversation.Save(false);
|
||||
}
|
||||
|
||||
self.Conversations.Add(key, conversation);
|
||||
}
|
||||
|
||||
return conversation;
|
||||
}
|
||||
|
||||
public static async FTask<List<MailConversation>> GetConversations(this MailManageComponent self, long id)
|
||||
{
|
||||
List<MailConversation> players =
|
||||
await self.Scene.World.Database.QueryByPageOrderBy<MailConversation>(
|
||||
d => d.FirstId == id || d.SecondId == id, 1, 50,
|
||||
d => d.UpdateTime);
|
||||
|
||||
return players;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using NB.Game;
|
||||
|
||||
namespace NB.Chat;
|
||||
|
||||
public class MailDestroySystem : DestroySystem<Mail>
|
||||
{
|
||||
protected override void Destroy(Mail self)
|
||||
{
|
||||
self.OwnerId = 0;
|
||||
self.Sender = 0;
|
||||
self.Content = string.Empty;
|
||||
self.ExpireTime = 0;
|
||||
self.CreateTime = 0;
|
||||
self.State = MailState.None;
|
||||
self.MailType = MailType.None;
|
||||
foreach (var item in self.Items)
|
||||
{
|
||||
item.Dispose();
|
||||
}
|
||||
|
||||
self.Items.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MailSystem
|
||||
{
|
||||
public static MailInfo ToMailInfo(this Mail mail)
|
||||
{
|
||||
return new MailInfo()
|
||||
{
|
||||
Id = mail.Id,
|
||||
Content = mail.Content,
|
||||
CreateTime = mail.CreateTime,
|
||||
MailState = (int)mail.State,
|
||||
MailType = (int)mail.MailType,
|
||||
Items = mail.Items.ToAwardInfo()
|
||||
};
|
||||
}
|
||||
|
||||
public static List<MailInfo> ToMailInfo(this List<Mail> mails)
|
||||
{
|
||||
var list = new List<MailInfo>();
|
||||
foreach (var mail in mails)
|
||||
{
|
||||
list.Add(mail.ToMailInfo());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
// using Fantasy;
|
||||
// using Fantasy.Async;
|
||||
// using Fantasy.Entitas;
|
||||
// using Fantasy.Entitas.Interface;
|
||||
// using NB.Chat;
|
||||
//
|
||||
// namespace NBF.Social;
|
||||
//
|
||||
// public sealed class ChatUnitManageComponentDestroySystem : DestroySystem<SocialUnitManageComponent>
|
||||
// {
|
||||
// protected override void Destroy(SocialUnitManageComponent self)
|
||||
// {
|
||||
// foreach (var chatUnit in self.Units.Values.ToArray())
|
||||
// {
|
||||
// chatUnit.Dispose();
|
||||
// }
|
||||
//
|
||||
// self.Units.Clear();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public static class SocialUnitManageComponentSystem
|
||||
// {
|
||||
// #region 消息缓存
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 离线消息,进入待领取队列
|
||||
// /// </summary>
|
||||
// /// <param name="self"></param>
|
||||
// /// <param name="targetId"></param>
|
||||
// /// <param name="message"></param>
|
||||
// public static void SaveOfflineMessage(this SocialUnitManageComponent self, long targetId, ChatMessageInfo message)
|
||||
// {
|
||||
// // self.NotSendMessage.Add(targetId, message);
|
||||
// }
|
||||
//
|
||||
// #endregion
|
||||
//
|
||||
// #region 上线下线
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 玩家上线
|
||||
// /// </summary>
|
||||
// /// <param name="self"></param>
|
||||
// /// <param name="scene"></param>
|
||||
// /// <param name="accountId"></param>
|
||||
// /// <param name="gateRouteId"></param>
|
||||
// public static async FTask<SocialUnit?> Online(this SocialUnitManageComponent self, Scene scene,
|
||||
// long accountId,
|
||||
// long gateRouteId)
|
||||
// {
|
||||
// // var accountId = roleSimpleInfo.RoleId;
|
||||
// if (!self.TryGet(accountId, out var account))
|
||||
// {
|
||||
// account = Entity.Create<SocialUnit>(scene, accountId, true, true);
|
||||
// self.Add(account);
|
||||
// }
|
||||
//
|
||||
// if (account != null)
|
||||
// {
|
||||
// await account.TryComponent<MailComponent>();
|
||||
// account.GateRouteId = gateRouteId;
|
||||
// // account.Role = roleSimpleInfo;
|
||||
// }
|
||||
//
|
||||
// await FTask.CompletedTask;
|
||||
// return account;
|
||||
// }
|
||||
//
|
||||
// public static async FTask Offline(this SocialUnitManageComponent self, Scene scene, long accountId,
|
||||
// long gateRouteId)
|
||||
// {
|
||||
// if (self.TryGet(accountId, out var unit) && unit != null)
|
||||
// {
|
||||
// if (unit.GateRouteId == gateRouteId)
|
||||
// {
|
||||
// Log.Info("退出当前聊天服==");
|
||||
// self.Remove(accountId); //如果当前网关和下线的网关一致
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// await FTask.CompletedTask;
|
||||
// }
|
||||
//
|
||||
// #endregion
|
||||
//
|
||||
// #region 获取&移除
|
||||
//
|
||||
// public static void Add(this SocialUnitManageComponent self, SocialUnit account)
|
||||
// {
|
||||
// self.Units.Add(account.Id, account);
|
||||
// }
|
||||
//
|
||||
// public static SocialUnit? Get(this SocialUnitManageComponent self, long accountId)
|
||||
// {
|
||||
// return self.Units.GetValueOrDefault(accountId);
|
||||
// }
|
||||
//
|
||||
// public static bool TryGet(this SocialUnitManageComponent self, long accountId, out SocialUnit? account)
|
||||
// {
|
||||
// return self.Units.TryGetValue(accountId, out account);
|
||||
// }
|
||||
//
|
||||
// public static void Remove(this SocialUnitManageComponent self, long accountId, bool isDispose = true)
|
||||
// {
|
||||
// if (!self.Units.Remove(accountId, out var account))
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// if (!isDispose)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// account.Dispose();
|
||||
// }
|
||||
//
|
||||
// #endregion
|
||||
//
|
||||
// #region 组件
|
||||
//
|
||||
// /// <summary>
|
||||
// /// 尝试给增加相关组件
|
||||
// /// </summary>
|
||||
// /// <param name="socialUnit"></param>
|
||||
// /// <typeparam name="T"></typeparam>
|
||||
// public static async FTask TryComponent<T>(this SocialUnit socialUnit) where T : Entity, new()
|
||||
// {
|
||||
// if (socialUnit.GetComponent<T>() == null)
|
||||
// {
|
||||
// var mailComponent = await socialUnit.Scene.World.Database.Query<T>(socialUnit.Id, true);
|
||||
// if (mailComponent == null)
|
||||
// {
|
||||
// //如果没有邮件组件
|
||||
// socialUnit.AddComponent<T>();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// socialUnit.AddComponent(mailComponent);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #endregion
|
||||
// }
|
||||
@@ -1,22 +0,0 @@
|
||||
// using Fantasy.Entitas.Interface;
|
||||
// #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
||||
//
|
||||
// namespace NB.Chat;
|
||||
//
|
||||
// public sealed class SocialUnitDestroySystem : DestroySystem<SocialUnit>
|
||||
// {
|
||||
// protected override void Destroy(SocialUnit self)
|
||||
// {
|
||||
// self.Role?.Return();
|
||||
// self.Role = null;
|
||||
// self.GateRouteId = 0;
|
||||
// // 退出当前ChatUnit拥有的所有频道
|
||||
// foreach (var (_,chatChannelComponent) in self.Channels)
|
||||
// {
|
||||
// chatChannelComponent.ExitChannel(self.Id, false);
|
||||
// }
|
||||
// // 理论情况下,这个self.Channels不会存在因为数据的,因为上面已经给清空掉了。
|
||||
// // 但是self.Channels.Clear();还是加上吧,防止以后忘记了。
|
||||
// self.Channels.Clear();
|
||||
// }
|
||||
// }
|
||||
@@ -12,4 +12,9 @@
|
||||
<ProjectReference Include="..\Entity\Entity.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Game\Condition\" />
|
||||
<Folder Include="Game\Mail\Handler\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -138,10 +138,9 @@ public sealed class OnCreateSceneEvent : AsyncEventSystem<OnCreateScene>
|
||||
|
||||
private async FTask InitializeSocialScene(Scene scene)
|
||||
{
|
||||
Log.Info($"初始化 Social 场景: {scene.Id}");
|
||||
//用于管理玩家的组件
|
||||
scene.AddComponent<MailManageComponent>();
|
||||
//聊天
|
||||
// Log.Info($"初始化 Social 场景: {scene.Id}");
|
||||
// 离线邮件箱管理组件。
|
||||
await scene.AddComponent<MailBoxManageComponent>().Init();
|
||||
// 聊天频道中控中心组件。
|
||||
scene.AddComponent<ChatChannelCenterComponent>();
|
||||
await FTask.CompletedTask;
|
||||
@@ -154,7 +153,7 @@ public sealed class OnCreateSceneEvent : AsyncEventSystem<OnCreateScene>
|
||||
//用于管理玩家的组件
|
||||
scene.AddComponent<PlayerManageComponent>();
|
||||
scene.AddComponent<PlayerBasicCacheManageComponent>();
|
||||
|
||||
await scene.AddComponent<ItemUseComponent>().Initialize();
|
||||
|
||||
Log.Info("创建地图场景===");
|
||||
var roomManageComponent = scene.AddComponent<RoomManageComponent>();
|
||||
|
||||
@@ -66,5 +66,8 @@
|
||||
<None Update="cfg\tbshop.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="cfg\tbleader.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -4,27 +4,31 @@
|
||||
"name": "鲤鱼",
|
||||
"min_weight": 1,
|
||||
"max_weight": 34,
|
||||
"accept": 2100001
|
||||
"accept": 2100001,
|
||||
"water": 0
|
||||
},
|
||||
{
|
||||
"id": 210002,
|
||||
"name": "金鲫",
|
||||
"min_weight": 1,
|
||||
"max_weight": 34,
|
||||
"accept": 2100001
|
||||
"accept": 2100001,
|
||||
"water": 0
|
||||
},
|
||||
{
|
||||
"id": 210003,
|
||||
"name": "银鲫",
|
||||
"min_weight": 1,
|
||||
"max_weight": 34,
|
||||
"accept": 2100001
|
||||
"accept": 2100001,
|
||||
"water": 0
|
||||
},
|
||||
{
|
||||
"id": 210004,
|
||||
"name": "拟鲤",
|
||||
"min_weight": 1,
|
||||
"max_weight": 34,
|
||||
"accept": 2100001
|
||||
"accept": 2100001,
|
||||
"water": 0
|
||||
}
|
||||
]
|
||||
@@ -8,6 +8,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -20,6 +21,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -32,6 +34,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -44,6 +47,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -56,6 +60,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -68,6 +73,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -80,6 +86,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -92,6 +99,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -104,6 +112,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -116,6 +125,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -128,6 +138,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -140,6 +151,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -152,6 +164,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -164,6 +177,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -176,6 +190,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -188,6 +203,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -200,6 +216,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -212,6 +229,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -224,6 +242,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -236,6 +255,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -248,6 +268,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -260,6 +281,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -272,6 +294,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -284,6 +307,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -296,6 +320,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -308,6 +333,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -320,6 +346,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -332,6 +359,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -344,6 +372,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -356,6 +385,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -368,6 +398,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -380,6 +411,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -392,6 +424,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -404,6 +437,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -416,6 +450,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -428,6 +463,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -440,6 +476,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -452,6 +489,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -464,6 +502,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -476,6 +515,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -488,6 +528,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -500,6 +541,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -512,6 +554,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -524,6 +567,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -536,6 +580,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -548,6 +593,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -560,6 +606,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -572,6 +619,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -584,6 +632,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -596,6 +645,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -608,6 +658,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -620,6 +671,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -632,6 +684,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -644,6 +697,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -656,6 +710,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -668,6 +723,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -680,6 +736,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -692,6 +749,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -704,6 +762,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -716,6 +775,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -728,6 +788,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -740,6 +801,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -752,6 +814,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -764,6 +827,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -776,6 +840,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -788,6 +853,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -800,6 +866,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -812,6 +879,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -824,6 +892,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -836,6 +905,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -848,6 +918,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -860,6 +931,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -872,6 +944,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -884,6 +957,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -896,6 +970,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -908,6 +983,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -920,6 +996,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -932,6 +1009,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -944,6 +1022,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -956,6 +1035,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -968,6 +1048,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -980,6 +1061,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -992,6 +1074,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1004,6 +1087,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1016,6 +1100,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1028,6 +1113,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1040,6 +1126,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1052,6 +1139,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1064,6 +1152,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1076,6 +1165,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1088,6 +1178,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1100,6 +1191,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
},
|
||||
@@ -1112,6 +1204,7 @@
|
||||
"length": 0,
|
||||
"max": 0,
|
||||
"auto_use": 0,
|
||||
"effect": 0,
|
||||
"result1": [],
|
||||
"result2": []
|
||||
}
|
||||
|
||||
12
Main/cfg/tbleader.json
Normal file
12
Main/cfg/tbleader.json
Normal file
@@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"id": 60001,
|
||||
"strength": 40,
|
||||
"size": 1
|
||||
},
|
||||
{
|
||||
"id": 60002,
|
||||
"strength": 40,
|
||||
"size": 1
|
||||
}
|
||||
]
|
||||
@@ -4,13 +4,20 @@
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAssemblyLoadContext_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb241c378a97f4447a2e6baf64e656013e8e910_003F96_003Fd3906b05_003FAssemblyLoadContext_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAssembly_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb241c378a97f4447a2e6baf64e656013e8e910_003F9f_003Fab186807_003FAssembly_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAwakeSystem_00601_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3cbbaf32e578423d8d0163d75da8233f87e00_003Fd6_003F72740830_003FAwakeSystem_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABsonPackHelper_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003Fa9_003F662c90bf_003FBsonPackHelper_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADestroySystem_00601_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3cbbaf32e578423d8d0163d75da8233f87e00_003Fbd_003Fcd9cb7f1_003FDestroySystem_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADictionary_00602_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F76803a04e31b4fee99d90bcbfc5a6bdde8e930_003F33_003F170c5f2b_003FDictionary_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEntity_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003F7f_003F8a76c302_003FEntity_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEntry_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003F31_003Fd222e398_003FEntry_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIAssemblyLifecycle_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003F2f_003F523cab0e_003FIAssemblyLifecycle_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIProtoParser_00601_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003Fcc_003Fc5b3dd8c_003FIProtoParser_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AISerialize_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003F7d_003F9fe3ad36_003FISerialize_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AList_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FSourcesCache_003F1b81cb3be224213a6a73519b6e340a628d9a1fb8629c351a186a26f6376669_003FList_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMemoryPackableAttribute_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fba5a62274184491dacbff186935d11a833600_003F72_003F6c6d24a2_003FMemoryPackableAttribute_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkMessagingComponent_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5935efc3ba8745d5800392d88681b8c2ddc00_003Fdd_003Fc26349d0_003FNetworkMessagingComponent_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANetworkMessagingComponent_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003F6d_003F2f2e114c_003FNetworkMessagingComponent_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AOneToManyList_00602_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003F6a_003Fd828fa89_003FOneToManyList_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AProcessMode_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003F23_003F78c782e6_003FProcessMode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AScene_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3cbbaf32e578423d8d0163d75da8233f87e00_003F6a_003F5adfe93e_003FScene_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASerializerManager_002Ecs_002Fl_003AC_0021_003FUsers_003FFIREBAT_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F199e3c534d1e41cbb9a3a30bbf9ac93bde200_003F9f_003Fa4f53cf4_003FSerializerManager_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASortedOneToManyList_00602_002Ecs_002Fl_003AC_0021_003FUsers_003F60527_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3cbbaf32e578423d8d0163d75da8233f87e00_003F12_003Fcfa98068_003FSortedOneToManyList_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
|
||||
@@ -98,3 +98,14 @@ message Other2Chat_ChatMessage // IAddressMessage
|
||||
ChatInfoTree ChatInfoTree = 1;
|
||||
}
|
||||
|
||||
////////////// ******** 邮件 *******/////////////
|
||||
/// 其他服务器发送邮件
|
||||
// Protocol Bson
|
||||
message Other2Mail_SendMailRequest // IAddressRequest,Mail2Other_SendMailResponse
|
||||
{
|
||||
MailBox MailBox = 1;
|
||||
}
|
||||
message Mail2Other_SendMailResponse // IAddressResponse
|
||||
{
|
||||
|
||||
}
|
||||
102
Tools/NetworkProtocol/Outer/MailMessage.proto
Normal file
102
Tools/NetworkProtocol/Outer/MailMessage.proto
Normal file
@@ -0,0 +1,102 @@
|
||||
syntax = "proto3";
|
||||
package Fantasy.Network.Message;
|
||||
|
||||
/// 测试Mail自定义Route协议
|
||||
message C2Mail_TestRequest // ICustomRouteRequest,Mail2C_TestResponse,GameRoute
|
||||
{
|
||||
string Tag = 1;
|
||||
}
|
||||
message Mail2C_TestResponse // ICustomRouteResponse
|
||||
{
|
||||
string Tag = 1;
|
||||
}
|
||||
/// 一个邮件的完整信息
|
||||
message MailInfo
|
||||
{
|
||||
int64 MailId = 1;
|
||||
int64 OwnerId = 2;
|
||||
string Title = 3;
|
||||
string Content = 4;
|
||||
int64 CreateTime = 5;
|
||||
int64 ExpireTime = 6;
|
||||
int32 Money = 7;
|
||||
int32 MailState = 8;
|
||||
int32 MailType = 9;
|
||||
repeated ItemInfo Items = 10;
|
||||
}
|
||||
/// 一个邮件的简单版消息
|
||||
message MailSimplifyInfo
|
||||
{
|
||||
int64 MailId = 1;
|
||||
int64 OwnerId = 2;
|
||||
string Title = 3;
|
||||
string Content = 4;
|
||||
int64 CreateTime = 5;
|
||||
int64 ExpireTime = 6;
|
||||
int32 MailState = 7;
|
||||
int32 MailType = 8;
|
||||
|
||||
}
|
||||
/// Mail通知客户端有新的邮件
|
||||
message Mail2C_HaveMail // ICustomRouteMessage,GameRoute
|
||||
{
|
||||
MailSimplifyInfo Mail = 1;
|
||||
}
|
||||
/// Mail通知客户端邮件状态变化
|
||||
message Mail2C_MailState // ICustomRouteMessage,GameRoute
|
||||
{
|
||||
int32 MailState = 1;
|
||||
int64 MailId = 2;
|
||||
}
|
||||
/// 客户端获取档期所有邮件的信息
|
||||
message C2Mail_GetHaveMailRequest // ICustomRouteRequest,Mail2C_GetHaveMailResposne,GameRoute
|
||||
{
|
||||
|
||||
}
|
||||
message Mail2C_GetHaveMailResposne // ICustomRouteResponse
|
||||
{
|
||||
repeated MailSimplifyInfo Mails = 1;
|
||||
}
|
||||
/// 客户端发开一个邮件
|
||||
message C2Mail_OpenMailRequest // ICustomRouteRequest,Mail2C_OpenMailResposne,GameRoute
|
||||
{
|
||||
int64 MailId = 1;
|
||||
bool ReturnMailInfo = 2;
|
||||
}
|
||||
message Mail2C_OpenMailResposne // ICustomRouteResponse
|
||||
{
|
||||
MailInfo MailInfo = 1;
|
||||
}
|
||||
/// 客户端领取邮件的附件
|
||||
message C2Mail_ReceiveMailRequest // ICustomRouteRequest,Mail2C_ReceiveMailResponse,GameRoute
|
||||
{
|
||||
int64 MailId = 1;
|
||||
bool Money = 2;
|
||||
repeated int64 ItemId = 3;
|
||||
}
|
||||
message Mail2C_ReceiveMailResponse // ICustomRouteResponse
|
||||
{
|
||||
|
||||
}
|
||||
/// 客户端通知服务器删除一个邮件
|
||||
message C2Mail_RemoveMailRequest // ICustomRouteRequest,Mail2C_RemoveMailResponse,GameRoute
|
||||
{
|
||||
int64 MailId = 1;
|
||||
}
|
||||
message Mail2C_RemoveMailResponse // ICustomRouteResponse
|
||||
{
|
||||
|
||||
}
|
||||
/// 客户端玩家发送邮件到另外一个玩家
|
||||
message C2Mail_SendMailRequest // ICustomRouteRequest,Mail2C_SendMailResponse,GameRoute
|
||||
{
|
||||
int64 UserId = 1;
|
||||
string Title = 2;
|
||||
string Content = 3;
|
||||
int32 Money = 4;
|
||||
repeated int64 ItemId = 5;
|
||||
}
|
||||
message Mail2C_SendMailResponse // ICustomRouteResponse
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,79 +1,6 @@
|
||||
syntax = "proto3";
|
||||
package Fantasy.Network.Message;
|
||||
|
||||
////////////// ******** 私聊/邮件 *******/////////////
|
||||
|
||||
/// 会话信息
|
||||
message ConversationInfo
|
||||
{
|
||||
RoleSimpleInfo RoleInfo = 1; //对方信息
|
||||
repeated MailInfo List = 2;//对话列表
|
||||
}
|
||||
|
||||
message MailInfo
|
||||
{
|
||||
int64 Id = 1; //邮件id
|
||||
int64 Sender = 2; //发送者
|
||||
string Content = 3; //内容
|
||||
int64 CreateTime = 4; //发送时间
|
||||
int32 MailType = 5; //邮件类型
|
||||
int32 MailState = 6; //邮件状态
|
||||
repeated AwardInfo Items = 7; //附件列表
|
||||
}
|
||||
|
||||
|
||||
///请求会话列表
|
||||
message C2Game_GetConversationsRequest // ICustomRouteRequest,Game2C_GetConversationsResponse,GameRoute
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///请求会话列表响应
|
||||
message Game2C_GetConversationsResponse // ICustomRouteResponse
|
||||
{
|
||||
repeated ConversationInfo List = 1;
|
||||
}
|
||||
|
||||
///发送邮件消息
|
||||
message C2Game_SendMailRequest // ICustomRouteRequest,Game2C_SendMailResponse,GameRoute
|
||||
{
|
||||
int64 Target = 1; //目标id
|
||||
string Content = 2; //内容
|
||||
repeated AwardInfo Items = 3; //附件列表
|
||||
}
|
||||
|
||||
///发送邮件消息响应
|
||||
message Game2C_SendMailResponse // ICustomRouteResponse
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///发送删除会话消息
|
||||
message C2Game_DeleteMailRequest // ICustomRouteRequest,Game2C_DeleteMailResponse,GameRoute
|
||||
{
|
||||
int64 Id = 1; //会话id
|
||||
}
|
||||
|
||||
///发送删除会话消息响应
|
||||
message Game2C_DeleteMailResponse // ICustomRouteResponse
|
||||
{
|
||||
int64 Id = 1; //会话id
|
||||
}
|
||||
|
||||
|
||||
///新邮件推送
|
||||
message Game2C_HaveMail // ICustomRouteMessage,GameRoute
|
||||
{
|
||||
MailInfo Mail = 1;
|
||||
string Key = 2;
|
||||
}
|
||||
|
||||
message Game2C_MailState // ICustomRouteMessage,GameRoute
|
||||
{
|
||||
int32 MailState = 1;
|
||||
int64 MailId = 2;
|
||||
}
|
||||
|
||||
////////////// ******** 频道聊天 *******/////////////
|
||||
|
||||
/// 发送一个聊天消息给Chat服务器,中间是经过Gate中转的
|
||||
|
||||
Reference in New Issue
Block a user