ET实现游戏中邮件系统逻辑思路(服务端)

ET是一个游戏框架,用的编程语言是C#,游戏引擎是Unity,框架作者:熊猫 ET社区

在游戏中我们通常都会看到有邮件系统,邮件系统的作用有给玩家通知、发放奖励等

下面小编使用ET框架带大家看一下邮件系统的一种实现方式。

一、实现思路

小编所理解的ECS编程是这样的:组件实体组件实体之间组装(类似于拼积木)

按照这个想法我们要实现一个邮件系统这就需要邮件的实体和组件了。

玩家的实体是Unit,邮件组件作为玩家的一部分挂到Unit上,那邮件的收发操作是怎么实现的呢?


看美剧一般小镇上每户人家家门口都会有一个小邮箱,邮递员会把邮件放到这个小邮箱里。家里人发现有邮件来了就到这个小邮箱查看并拿回家给具体的收件人。

实现邮件系统思路和拿邮件是类似的,这里我们就需要一个邮件管理组件EmailManagerComponent 来作为小邮箱。

1、邮件管理组件EmailManagerComponent和玩家组件处在同一层级(家门口的小邮箱可以存放不同人的邮件)

2、邮件组件EmailComponent是玩家组件的子组件(邮件要给具体的收件人)

3、当系统或者其他玩家发送邮件时会先保存到邮件管理组件EmailManagerComponent中(邮递员把邮件放入小邮箱)

4、当玩家点击邮件按钮时会通过自身的Id标识到邮件管理组件去找自己的邮件

5、如果发现有自己的邮件则保存到玩家自己身上(邮件给到具体收件人)

6、保存好后邮件管理组件会将移除玩家已领取的邮件。(释放邮件管理组件资源)

7、发送邮件(收件人的Id作为唯一标识暂时保存到邮件管理组件中等待收件人领取)

二、编码

2.1 EmailInfo

邮件一般会有发送时间、发件人、收件人、标题、内容等等(根据实际情况自己定义)。

那这个邮件实体我们命名为EmailInfo

cs 复制代码
namespace ET.Server
{
    [ChildOf(typeof(EmailComponent))]
    public class EmailInfo: Entity, IAwake,IDestroy
    {
        //奖励
        public List<int> ItemId;        //奖励物品Id列表
        public List<long> ItemValue;    //奖励物品数量列表
        
        //邮件领取状态  0:未领取,1:已领取
        public int Status;
        
        //发件人
        public string Sender;
        
        //收件人
        public string Receiver;
        
        //发送时间
        public int SenderTime;
        
        //标题
        public string Title;
        
        //内容
        public string Text;
        
        //邮件删除状态:1 删除,0 未删除
        public int DelteType = 0;
        
        
    }
}

2.2 EmailComponent

定义好实体后我们来定义邮件组件EmailComponent来作为EmailInfo的载体挂到玩家身上

cs 复制代码
namespace ET.Server
{
    [ComponentOf(typeof(Unit))]
    public class EmailComponent : Entity, IAwake, IDestroy, IDeserialize, ITransfer, IUnitCache
    {
        //邮件Id
        public int EmailId = 1;
        

        [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
        public Dictionary<int, EmailInfo> Emails = new Dictionary<int, EmailInfo>();
    }
}

2.3 EmailManagerComponent

邮件管理组件挂载到Scene上和玩家组件处于同一层级

cs 复制代码
namespace ET.Server
{
    [ComponentOf(typeof(Scene))]
    public class EmailManagerComponent : Entity,IAwake,IDestroy
    {
        public long Timer;

        // 玩家接收新的邮件 字典Key存储玩家ID,Value采用List是一个玩家可能会收到多封邮件
        [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfArrays)]
        public Dictionary<long, List<EmailInfo>> EmailUnitInfos = new Dictionary<long, List<EmailInfo>>();
    }
}

2.4 EmailComponentSystem

邮件组件所实现的动作:EmailComponentSystem

cs 复制代码
using System.Collections.Generic;
using System.Linq;

namespace ET.Server
{
    
    public class EmailInfoComponentDestroySystem: DestroySystem<EmailComponent>
    {
        protected override void Destroy(EmailComponent self)
        {
            self.Emails.Clear();
        }
    }

    [FriendOf(typeof(EmailComponent))]
    [FriendOf(typeof(EmailInfo))]
    public static class EmailComponentSystem
    {
        //Status奖励领取状态  0:未领取,1:已领取
        public static List<EmailProto> GetEmailList(this EmailComponent self,int SystemType)
        {
            List<EmailProto> emailProtos = new List<EmailProto>();
            foreach (var item in self.Emails)
            {
                //DelteType == 0 未删除
                if (item.Value.DelteType == 0)
                {
                    int todayKey = (int)TimeHelper.ClientNowSeconds();
                    if (todayKey >= item.Value.StarAt && todayKey <= item.Value.EndAt)
                    {
                        emailProtos.Add(
                            new EmailProto()
                            {
                                ItemId = item.Value.ItemId,
                                ItemValue = item.Value.ItemValue,
                                Status = item.Value.Status,
                                Sender = item.Value.Sender,
                                Receiver = item.Value.Receiver,
                                SenderTime = (int)item.Value.StarAt,
                                Title = item.Value.Title,
                                Text = item.Value.Text,
                                EmailId = item.Key,
                            });   
                    }
                }
            }
            List<EmailProto> lists =  emailProtos.OrderByDescending(e => e.SenderTime).ToList();
            return lists;
        }

        //获取新邮件
        public static void GetNewEmail(this EmailComponent self,List<EmailInfo> emailInfos)
        {
            if (emailInfos ==null || emailInfos.Count==0)
            {
                return;
            }

            for (int i = 0; i < emailInfos.Count; i++)
            {
                self.Emails.Add(self.EmailId+=1,new EmailInfo
                {
                    ItemId = emailInfos[i].ItemId,
                    ItemValue = emailInfos[i].ItemValue,
                    Status = emailInfos[i].Status,
                    Sender = emailInfos[i].Sender,
                    Receiver = emailInfos[i].Receiver,
                    SenderTime = emailInfos[i].SenderTime,
                    Title = emailInfos[i].Title,
                    Text = emailInfos[i].Text,
                    StarAt = emailInfos[i].StarAt,
                    EndAt = emailInfos[i].EndAt,
                    SystemType = emailInfos[i].SystemType,
                });   
            }
        }
        
  
        //删除邮件
        public static string DeleteEmail(this EmailComponent self, int EmailId)
        {
            string resultMsg = "该邮件不存在"; 
            if (self.Emails.ContainsKey(EmailId) && self.Emails[EmailId].Status == 1)
            {
                //self.Emails.Remove(EmailId); 
                self.Emails[EmailId].DelteType = 1;
                resultMsg = "删除成功";
            }
           
            return resultMsg ;
            
        }
        
    }
}

2.5 EmailManagerComponentSystem

邮件管理组件所实现的动作:EmailManagerComponentSystem

cs 复制代码
namespace ET.Server
{
    
    public class EmailManagerComponentDestroySystem: DestroySystem<EmailManagerComponent>
    {
        protected override void Destroy(EmailManagerComponent self)
        {
            TimerComponent.Instance.Remove(ref self.Timer);
        }
    }

    public class EmailManagerComponentAwakeSystem: AwakeSystem<EmailManagerComponent>
    {
        protected override void Awake(EmailManagerComponent self)
        {
            self.Timer = TimerComponent.Instance.NewRepeatedTimer(10000, TimerInvokeType.EmailManagerUpdate, self);
        }
    }


    //定时器 每隔10秒钟保存一次邮件信息    
    [Invoke(TimerInvokeType.EmailManagerUpdate)]
    public class  EmailManagerComponentTimer : ATimer<EmailManagerComponent>
    {
        protected override void Run(EmailManagerComponent self)
        {
            try
            {
                if ( self.IsDisposed || self.Parent == null )
                {
                    return;
                }
                
                if ( self.DomainScene() == null || self.DomainScene().Name != "Map1")
                {
                    return;
                }
                
                self?.SaveEmailManagerComponent();
            }
            catch (Exception e)
            {
                Log.Error(e.ToString());
            }
        }
    }

    [FriendOf(typeof(EmailManagerComponent))]
    [FriendOf(typeof(DBManagerComponent))]
    [FriendOf(typeof(EmailSystemInfo))]
    [FriendOf(typeof(EmailInfo))]
    public static class EmailManagerComponentSystem
    {
        //系统启动时从数据库加载邮件管理组件信息
        public static async ETTask LoadEmailInfo(this EmailManagerComponent self)
        {
            var EmailManagerList =  await DBManagerComponent.Instance.GetZoneDB(self.DomainZone()).Query<EmailManagerComponent>(d => true,collection:"EmailManagerComponent");
            
        }
        
        //玩家之间发送邮件
        public static void SendNewEmail(this EmailManagerComponent self,long receiveId,EmailProto emailProto)
        {
            //如果邮件中有附件奖励设置可领取状态
            if (emailProto.ItemValue == null && emailProto.ItemId == null)
            {
                emailProto.Status = 1;
            }
            else
            {
                emailProto.Status = 0;  
            }
            
            EmailInfo emailInfo = new EmailInfo
            {
                ItemId = emailProto.ItemId,
                ItemValue = emailProto.ItemValue,
                Status = emailProto.Status,
                Sender = emailProto.Sender,
                Receiver = emailProto.Receiver,
                SenderTime = (int) (TimeHelper.ServerNow()/1000),
                Title = emailProto.Title,
                Text = emailProto.Text,
            };

            if (!self.EmailUnitInfos.ContainsKey(receiveId))
            {
                List<EmailInfo> list = new List<EmailInfo>();
                list.Add(emailInfo);
                self.EmailUnitInfos.Add(receiveId,list);  
            }
            else
            {
                self.EmailUnitInfos[receiveId].Add(emailInfo);   
            }
        }
        
        
        //获取玩家收到的新邮件
        public static List<EmailInfo>  ReceiveNewEmail(this EmailManagerComponent self,long unitId)
        {
            List<EmailInfo> list = new List<EmailInfo>();
            
            if (!self.EmailUnitInfos.ContainsKey(unitId))
            {
                self.EmailUnitInfos.Add(unitId,list);
            }
            else
            {
                //玩家接收了此邮件,接收状态改为已接收
                for (int i = 0; i < self.EmailUnitInfos[unitId].Count; i++)
                {
                    
           
                    list.Add(self.EmailUnitInfos[unitId][i]);
                    
                }

                self.EmailUnitInfos.Remove(unitId);
            }
            //根据时间戳进行排序
            list.OrderByDescending(l => l.SenderTime).ToList();
            return list;
        }

        //获取玩家所有状态的邮件(已接收的和未接收的)
        public static List<EmailInfo> ReceiveAllEmail(this EmailManagerComponent self, long unitId)
        {
            List<EmailInfo> list = new List<EmailInfo>();
        
            if (!self.EmailUnitInfos.ContainsKey(unitId))
            {
                self.EmailUnitInfos.Add(unitId,list);
                return list;
            }
            for (int i = 0; i < self.EmailUnitInfos[unitId].Count; i++)
            {
                list.Add(self.EmailUnitInfos[unitId][i]);
            }
            //根据时间戳进行排序
            list.OrderByDescending(l => l.SenderTime).ToList();
            return list;
        }
        
        //保存
        public static void SaveEmailManagerComponent(this EmailManagerComponent self)
        {
            Log.Debug("---------------------------开始保存邮件信息");
  
DBManagerComponent.Instance.GetZoneDB(self.DomainZone()).Save(self,"EmailManagerComponent").Coroutine();
        }
    }
}

邮件系统的实现思路之一是这样,还要根据具体业务逻辑实现具体动作并写接口去调用组件所实现的这些动作。有不对的地方欢迎大家提出来一起讨论,本篇先介绍到这里,拜拜┏(^0^)┛

相关推荐
△曉風殘月〆1 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
PandaQue5 小时前
《怪物猎人:荒野》游戏可以键鼠直连吗
游戏
m0_656974746 小时前
C#中的集合类及其使用
开发语言·c#
九鼎科技-Leo6 小时前
了解 .NET 运行时与 .NET 框架:基础概念与相互关系
windows·c#·.net
九鼎科技-Leo9 小时前
什么是 ASP.NET Core?与 ASP.NET MVC 有什么区别?
windows·后端·c#·asp.net·mvc·.net
.net开发9 小时前
WPF怎么通过RestSharp向后端发请求
前端·c#·.net·wpf
小乖兽技术9 小时前
C#与C++交互开发系列(二十):跨进程通信之共享内存(Shared Memory)
c++·c#·交互·ipc
幼儿园园霸柒柒9 小时前
第七章: 7.3求一个3*3的整型矩阵对角线元素之和
c语言·c++·算法·矩阵·c#·1024程序员节
白狐欧莱雅9 小时前
使用python中的pygame简单实现飞机大战游戏
经验分享·python·游戏·pygame