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

news2024/12/23 17:03:05

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

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 的载体挂到玩家身上

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上和玩家组件处于同一层级

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1859923.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新型基坑气膜:施工开挖的得力干将—轻空间

随着城市建设的加速推进&#xff0c;施工过程中的环境问题日益受到关注。新型基坑气膜以其卓越的防尘、降噪、节能和防火功能&#xff0c;成为施工开挖领域中的得力干将&#xff0c;极大地提升了绿色施工的水平。 基坑气膜的作用 基坑气膜在施工现场形成了一个完全封闭的作业空…

数据模型(models)

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 &#xff08;1&#xff09;在App中添加数据模型 在app1的models.py中添加如下代码&#xff1a; from django.db import models # 引入django.…

打造智能家居:用ESP32轻松实现无线控制与环境监测

ESP32是一款集成了Wi-Fi和蓝牙功能的微控制器&#xff0c;广泛应用于物联网项目。它由Espressif Systems公司开发&#xff0c;具有强大的处理能力和丰富的外设接口。下面我们将详细介绍ESP32的基础功能和引脚功能&#xff0c;并通过具体的实例项目展示其应用。 主要功能 双核处…

YOLOv10(6):YOLOv10基于TensorRT的部署(基于INetworkDefinition)

1. 写在前面 我们在前面已经讲过很多关于YOLOv10的一些知识点&#xff0c;也简单理了一下如何训练自己的数据。 现在本篇文章主要是讲解一下如何在TensorRT中部署YOLOv10&#xff0c;相信经过这一步&#xff0c;各位小伙伴已经能够无限的接近于将YOLOv10产品化了。 另一个需要说…

qt creator在windows上配置调试器

从微软下载winsdk&#xff1a;https://developer.microsoft.com/zh-cn/windows/downloads/sdk-archive/ 运行winsdksetup.exe 选择下载 选择debugging tools for windows 选择安装x64版本debug工具 重新打开qt&#xff0c;自动选择安装的编译器

[汇总] Docker容器详解 Macvlan 创建不同容器独立跑仿真(持续更新中)

一、概念介绍 1.1 什么是macvlan macvlan是一种网卡虚拟化技术&#xff0c;能够将一张网卡&#xff08;Network Interface Card, NIC&#xff09;虚拟出多张网卡&#xff0c;这意味着每个虚拟网卡都能拥有独立的MAC地址和IP地址&#xff0c;从而在系统层面表现为完全独立的网络…

下一代广域网技术-Segment Routing(SR)

1.SR MPLS 1.1.广域网VPN技术的演进 特殊的EVPN&#xff1a;从L2VPN发展的EVPN 以VPLS为例的L2VPN存在多种问题&#xff0c;例如业务部署复杂、网络规模受限、不支持双归等&#xff0c;IETF提出EVPN来解决这些问题EVPN最初被设计为一个基于BGP扩展的L2VPN技术&#xff0c;但…

DataWhale - 吃瓜教程学习笔记(三)

学习视频&#xff1a;第3章-对数几率回归_哔哩哔哩_bilibili 西瓜书对应章节&#xff1a; 3.3 对数几率回归 sigmoid函数 极大似然估计建模 信息论 以概率论、随机过程为基本研究工具&#xff0c;研究广义通信系统的整个过程 - 信息熵 &#xff08;信息期望&#xff09; 度…

上海亚商投顾:三大指数均跌超1% 全市场下跌个股近5000只

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 三大指数昨日震荡调整&#xff0c;尾盘集体跌超1%&#xff0c;微盘股指数跌逾4%&#xff0c;黄白二线分化明显…

【Hadoop集群搭建】实验3:JDK安装及配置、Hadoop本地模式部署及测试

1. 安装 SSH 工具 SSH Secure Shell Client 传输软件 FinalShell(推荐使用) 1.1使用SSH工具将JDK安装包上传至虚拟主机hadoop01, hadoop02, hadoop03&#xff0c;sogou500w 数据上传至 hadoop01。 a. 在虚拟主机/usr 目录下创建文件夹 java&#xff0c;JDK 上传至此目录&…

昇思25天学习打卡营第1天|初学教程

文章目录 背景创建环境熟悉环境打卡记录学习总结展望未来 背景 参加了昇思的25天学习记录&#xff0c;这里给自己记录一下所学内容笔记。 创建环境 首先在平台注册账号&#xff0c;然后登录&#xff0c;按下图操作&#xff0c;创建环境即可 创建好环境后进入即可&#xff0…

死锁的条件、预防、避免、检测

死锁的条件、预防、避免、检测 死锁的必要条件 互斥条件&#xff1a;一个资源一次只能给一个进程使用&#xff0c;非共享请求与保持条件&#xff1a;保持自己资源的同时请求其他资源&#xff0c;该资源可能被占有非剥夺条件&#xff1a;不能强行夺走资源&#xff0c;只能等别的…

【10】交易-交易的结构

1. 交易的结构 1.1 引言 需要说明的是,在我们之前的例子中,区块中的交易(data)是用字符串数据来表示的,但在真正的比特币网络中,交易是一个复杂的数据结构,记录了不同地址之间的价值转移信息。在比特币系统中没有账号或身份信息的概念的,也不会记录地址和身份之间的关…

iOS之如何创建.a静态库

番外&#xff1a;想要查看如何创建.framework静态库可前往看我​​​​​​​iOS之如何创建.framework静态库-CSDN博客这篇文章。 一、创建静态库项目 ①、打开 Xcode 并创建一个新的 Xcode 项目。 ②、选择 "macOS" -> "Framework & Library" -&…

“拿来主义”学习元素裁剪(附源码)

“拿来主义”学习元素裁剪 欢迎关注&#xff1a; 小拾岁月&#xff0c;获取源码。 参考链接&#xff1a;https://mp.weixin.qq.com/s/TsOOhUAff6OeqPW7A9JuaQ 预期效果图 需求分析 首先从需求上来看&#xff0c;需要一个主元素用于展示用户头像。例外&#xff0c;在页面无操…

[保姆级教程]uniapp设置字体引入字体格式

文章目录 在 UniApp 中设置和引入自定义字体&#xff08;如 .ttf、.woff、.woff2 等格式&#xff09;通常涉及几个步骤。 准备字体文件&#xff1a; 首先&#xff0c;你需要有字体文件。这些文件通常以 .ttf、.woff 或 .woff2 格式提供。确保有权使用这些字体&#xff0c;并遵守…

Docker配置国内镜像加速-2

Docker 官方镜像仓库&#xff08;如 Docker Hub&#xff09;可能由于网络原因&#xff0c;在某些地区或网络环境下下载速度较慢。使用镜像加速可以从距离用户更近、网络条件更好的镜像服务器获取镜像&#xff0c;从而显著提高下载速度&#xff0c;节省时间。 1.测试是否安装 d…

基于Java少儿编程管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

PyTorch实战:借助torchviz可视化计算图与梯度传递

文章目录 Tensor计算的可视化&#xff08;线性回归为例&#xff09; 如何使用可视化库torchviz 安装graphviz软件 安装torchviz库使用 torchviz.make_dot() 在学习Tensor时&#xff0c;将张量y用张量x表示&#xff0c;它们背后会有一个函数表达关系&#xff0c;y的 grad_f…

2024 年首份软件漏洞报告

Action1 Corporation 发布了其首份 2024 年软件漏洞评级报告。 该报告旨在为首席信息安全官 (CISO) 和首席信息官 (CIO) 提供有关其软件生态系统的战略见解。 它根据软件供应商的安全记录对其进行评估&#xff0c;以便做出更明智的采购决策。 此次发布是在国家漏洞数据库 (N…