Files
2026-03-05 11:39:06 +08:00

225 lines
8.0 KiB
C#
Raw Permalink 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.DataStructure.Collection;
using Fantasy.Entitas.Interface;
using Fantasy.Helper;
namespace Fantasy;
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, MailUnit 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(MailFactory.Serializer.Clone(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(MailFactory.Serializer.Clone(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.AccountId, out var mailBoxes))
{
using var removeMailBox = ListPool<MailBox>.Create();
foreach (var mailBox in mailBoxes)
{
var cloneMail = MailFactory.Serializer.Clone(mailBox.Mail);
await mailComponent.Add(cloneMail, sync);
mailBox.AccountId.Remove(mailUnit.AccountId);
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.RemoveByKey(mailUnit.AccountId);
}
}
}
}