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^)┛

相关推荐
初九之潜龙勿用32 分钟前
C#校验画布签名图片是否为空白
开发语言·ui·c#·.net
九州ip动态2 小时前
做网络推广及游戏注册为什么要换IP
网络·tcp/ip·游戏
吾与谁归in2 小时前
【C#设计模式(13)——代理模式(Proxy Pattern)】
设计模式·c#·代理模式
吾与谁归in2 小时前
【C#设计模式(14)——责任链模式( Chain-of-responsibility Pattern)】
设计模式·c#·责任链模式
神仙别闹3 小时前
基于C#和Sql Server 2008实现的(WinForm)订单生成系统
开发语言·c#
向宇it13 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
九鼎科技-Leo13 小时前
什么是 WPF 中的依赖属性?有什么作用?
windows·c#·.net·wpf
Heaphaestus,RC14 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
baivfhpwxf202314 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
直裾14 小时前
Scala全文单词统计
开发语言·c#·scala