Files
ServerStudy/邮件系统课程完整代码/Server/Hotfix/Mail/Components/MailUnitManageComponentSystem.cs
2026-03-05 11:39:06 +08:00

176 lines
6.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Fantasy.Async;
using Fantasy.Entitas;
using Fantasy.Entitas.Interface;
using Fantasy.Helper;
// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
#pragma warning disable CS8601 // Possible null reference assignment.
namespace Fantasy;
public sealed class MailUnitManageComponentDestroySystem : DestroySystem<MailUnitManageComponent>
{
protected override void Destroy(MailUnitManageComponent self)
{
// 如果不是在.net8的环境下比如是Unity里。这个的foreach有可能会出现问题
// 问题的原因是有可能你在mailUnit组件的销毁的时候去UnitByAccountId删除。
// 这样就会出现了一个经典的错误就是无法再foreach里删除或改变元素。
foreach (var (_, mailUnit) in self.UnitByAccountId)
{
mailUnit.Dispose();
}
self.UnitByAccountId.Clear();
self.UnitByName.Clear();
self.Online.Clear();
}
}
public static class MailUnitManageComponentSystem
{
public static async FTask Init(this MailUnitManageComponent self)
{
var units = await self.Scene.World.DataBase.Query<MailUnit>(d => true, true);
foreach (var mailUnit in units)
{
self.UnitByName.Add(mailUnit.Name, mailUnit);
self.UnitByAccountId.Add(mailUnit.AccountId,mailUnit);
}
Log.Debug($"MailUnitManageComponent Init units:{units.Count}");
}
/// <summary>
/// 用户中心登录逻辑,如果有更新的数据,会自动更新。
/// </summary>
/// <param name="self"></param>
/// <param name="accountId"></param>
/// <param name="unitName"></param>
/// <param name="gateRouteId"></param>
/// <returns></returns>
public static async FTask<MailUnit> Online(this MailUnitManageComponent self, long accountId, string unitName, long gateRouteId)
{
var selfScene = self.Scene;
if (self.UnitByAccountId.TryGetValue(accountId, out var mailUnit))
{
Log.Debug($"用户已经存在行不需要重新创建 Name:{unitName} mailUnit:{mailUnit.RuntimeId}");
if (mailUnit.Name != unitName)
{
// 如果不一致的情况,要先删除之前的缓存,然后再添加到缓存。
self.UnitByName.Remove(mailUnit.Name);
self.UnitByName.Add(unitName, mailUnit);
mailUnit.Name = unitName;
}
}
else
{
// 创建新的MailUnit实体。
mailUnit = Entity.Create<MailUnit>(selfScene,accountId, true, true);
mailUnit.Name = unitName;
mailUnit.AccountId = accountId;
mailUnit.CreateTime = TimeHelper.Now;
// 把创建好的实体添加到缓存中,方便后面使用。
self.UnitByAccountId.Add(accountId, mailUnit);
self.UnitByName.Add(unitName,mailUnit);
Log.Debug($"用户不存在行需要创建 Name:{unitName} mailUnit:{mailUnit.RuntimeId}");
}
// 设置GateRouteId
mailUnit.GateRouteId = gateRouteId;
// 设置MailComponent
if (mailUnit.GetComponent<MailComponent>() == null)
{
// 数据库中查询这个组件是否存在。
var mailComponent = await selfScene.World.DataBase.Query<MailComponent>(mailUnit.Id, true);
if (mailComponent == null)
{
// MailUnit没有这个MailComponent组件就给添加一个新的组件。
mailUnit.AddComponent<MailComponent>();
}
else
{
mailUnit.AddComponent(mailComponent);
}
}
// 可选,如果你不需要保存到数据库,那么可以忽略下面的代码。
await selfScene.World.DataBase.Save(mailUnit);
// 领取下离线的邮件。如果有的情况下。
await selfScene.GetComponent<MailBoxManageComponent>().GetHaveMail(mailUnit, true);
// 把用户添加到在线的列表
self.Online.Add(mailUnit.Id, mailUnit);
// 返回MailUnit实体。
return mailUnit;
}
/// <summary>
/// 退出登录逻辑,会自动保存数据。
/// </summary>
/// <param name="self"></param>
/// <param name="mailUnit"></param>
public static async FTask Exit(this MailUnitManageComponent self, MailUnit mailUnit)
{
var mailComponent = mailUnit.GetComponent<MailComponent>();
if (mailComponent == null)
{
return;
}
// 保存mailComponent到数据库中。
await self.Scene.World.DataBase.Save(mailComponent);
// 移除这个组件。
mailUnit.RemoveComponent<MailComponent>();
// 在在线列表的容器中移除这个MailUnit实体。
self.Online.Remove(mailUnit.Id);
Log.Debug($"AccountId:{mailUnit.AccountId} Name:{mailUnit.Name} Exit!");
}
/// <summary>
/// 根据UnitName获取MailUnit实体
/// </summary>
/// <param name="self"></param>
/// <param name="unitName"></param>
/// <param name="mailUnit"></param>
/// <returns></returns>
public static bool TryGet(this MailUnitManageComponent self, string unitName, out MailUnit mailUnit)
{
return self.UnitByName.TryGetValue(unitName, out mailUnit);
}
/// <summary>
/// 根据AccountId获取MailUnit实体
/// </summary>
/// <param name="self"></param>
/// <param name="accountId"></param>
/// <param name="mailUnit"></param>
/// <returns></returns>
public static bool TryGet(this MailUnitManageComponent self, long accountId, out MailUnit mailUnit)
{
return self.UnitByAccountId.TryGetValue(accountId, out mailUnit);
}
/// <summary>
/// 删除MailUnit实体。
/// </summary>
/// <param name="self"></param>
/// <param name="accountId"></param>
/// <returns></returns>
public static async FTask<uint> Remove(this MailUnitManageComponent self, long accountId)
{
// if (!self.UnitByAccountId.TryGetValue(accountId, out var mailUnit))
// {
// // 这个1代表的是没有找到对应的MailUnit
// return 1;
// }
if (!self.UnitByAccountId.Remove(accountId, out var mailUnit))
{
// 这个1代表的是没有找到对应的MailUnit
return 1;
}
self.UnitByName.Remove(mailUnit.Name);
// 在数据库中删除MailUnit实体
await self.Scene.World.DataBase.Remove<MailUnit>(mailUnit.Id);
// 销毁这个MailUnit
mailUnit.Dispose();
return 0;
}
}