using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using GameCore; using Newtonsoft.Json; using UnityEngine; using UnityEngine.Assertions; /// /// 邮件类型枚举 /// public enum EMailType { Global, Personal, AutoDelivery, } /// /// 邮件状态标志枚举 /// [Flags] public enum EMailState { None = 1 << 0, // 通知未读 HasRead = 1 << 1, // 已读通知 RewardTaken = 1 << 2, // 奖励已领取,表示用户已经领取了通知中的奖励 HasDeleted = 1 << 3, // 通知已删除 } /// /// 游戏内邮件服务接口 /// public interface IInGameMailService { /// /// 是否解锁邮件功能。 /// bool IsUnlock { get; set; } /// /// 初始化邮件服务。 /// void Init(); /// /// 重置邮件服务。 /// void Reset(); /// /// 异步获取新邮件。 /// /// 一个任务,表示邮件获取操作。 Task FetchMail(); /// /// 异步获取所有游戏邮件。 /// /// 一个任务,包含一个列表,列表中包含所有游戏邮件。 IList GetAllMail(); /// /// 异步标记指定邮件为已读。 /// /// 要标记为已读的邮件。 /// 一个任务,表示邮件标记操作是否成功。 Task MarkRead(GameMail mail); /// /// 异步标记指定邮件为已读。 /// /// 要标记为已读的邮件。null 标记搜有已读 /// 一个任务,表示邮件标记操作是否成功。 Task MarkRead(GameMail[] mails = null); /// /// 异步删除指定邮件。 /// /// 要删除的邮件。 /// 一个任务,表示邮件删除操作是否成功。 Task DelMail(GameMail mail); /// /// 异步删除指定邮件。 /// /// 要删除的邮件。null 删除所有已读邮件 /// 一个任务,表示邮件删除操作是否成功。 Task DelMail(GameMail[] mails = null); /// /// 异步领取指定邮件的奖励。 /// /// 要领取奖励的邮件。 /// 一个任务,表示奖励领取操作是否成功。 Task TakeReward(GameMail mail); /// /// 异步领取指定邮件的奖励。 /// /// 要领取奖励的邮件。领取所有奖励 /// 一个任务,表示奖励领取操作是否成功。 Task TakeReward(GameMail[] mails = null); } /// /// 邮件缓存类 /// public class MailCache { private Dictionary _dicMails; private Dictionary _autoDeliveryMail; private string _mail_key; private string _sync_time_key; private string _userId; public MailCache(cfg.TbAutoDeliveryMail tbAutoDeliveryMail) { _autoDeliveryMail = tbAutoDeliveryMail.DataMap .ToDictionary(e => e.Key.ToString(), v => v.Value); } /// /// 加载指定用户的邮件缓存 /// /// 用户ID public void Load(string userId) { if (userId != this._userId) { Debug.Log($"load mail cache for user: {userId}"); this._userId = userId; _mail_key = $"mail_cache__{userId}"; _sync_time_key = $"mail_sync_Time_{userId}"; var jdata = PlayerPrefs.GetString(_mail_key, string.Empty); _dicMails = string.IsNullOrEmpty(jdata) ? new Dictionary() : JsonConvert.DeserializeObject>(jdata); } } public void Unload() { this._userId = null; _mail_key = null; _sync_time_key = null; _dicMails = null; } public DateTime? LastSyncTime { get { #if UNITY_EDITOR Assert.IsNotNull(_userId); #endif return PlayerPrefs.HasKey(_sync_time_key) ? DateTime.Parse(PlayerPrefs.GetString(_sync_time_key)) : null; } } /// /// 对邮件列表进行排序 /// /// 邮件列表 private void SortMails(List mails) { //by send time Desc mails.Sort((a, b) => b.SendTime.CompareTo(a.SendTime)); } /// /// 保存邮件缓存到持久化存储 /// public void Save() { #if UNITY_EDITOR Assert.IsNotNull(_userId); #endif var jdata = JsonConvert.SerializeObject(_dicMails); PlayerPrefs.SetString(_mail_key, jdata); PlayerPrefs.SetString(_sync_time_key, ZZTimeHelper.UtcNow().ToString()); PlayerPrefs.Save(); } public void UpdateSyncTime() { PlayerPrefs.SetString(_sync_time_key, ZZTimeHelper.UtcNow().ToString()); PlayerPrefs.Save(); } /// /// 缓存单封邮件 /// /// 邮件对象 public void Cache(GameMail mail) { #if UNITY_EDITOR Assert.IsNotNull(_userId); #endif if(_dicMails.ContainsKey(mail.Id)) { _dicMails[mail.Id].Copy(mail); } else { FillMail(mail); _dicMails.Add(mail.Id, mail); } } private void FillMail(GameMail mail) { if (mail.Type == EMailType.AutoDelivery) { var mailData = _autoDeliveryMail[mail.Id]; mail.Title = LocalizationMgr.GetText(mailData.Title_l10n_key); mail.Content = LocalizationMgr.GetText(mailData.Content_l10n_key); mail.From = LocalizationMgr.GetText(mailData.Inscribe_l10n_key); } } /// /// 缓存多封邮件 /// /// 邮件集合 public void Cache(IEnumerable mails) { #if UNITY_EDITOR Assert.IsNotNull(_userId); #endif foreach (var mail in mails) { Cache(mail); } } public GameMail GetMail(string id) { #if UNITY_EDITOR Assert.IsNotNull(_userId); #endif if (_dicMails.TryGetValue(id, out var mail)) { return mail; } return null; } public bool HasMail(string id) { #if UNITY_EDITOR Assert.IsNotNull(_userId); #endif return _dicMails.ContainsKey(id); } /// /// 获取所有未过期且未删除的邮件 /// /// 邮件列表 public IList GetAll() { #if UNITY_EDITOR Assert.IsNotNull(_userId); #endif var now = ZZTimeHelper.UtcNow(); var mails = _dicMails.Values .Where(m => m.ExpireTime > now && !m.IsDeleted) .ToList(); SortMails(mails); return mails; } public int UnreadMailCount { get{ #if UNITY_EDITOR Assert.IsNotNull(_userId); #endif var utcNow = ZZTimeHelper.UtcNow(); return _dicMails.Values.Count(m => m.ExpireTime > utcNow && !m.IsDeleted && (!m.IsRead || !m.HasReward)); } } public string PrintCacheMails() { return JsonConvert.SerializeObject(_dicMails,Formatting.Indented); } } /// /// 邮件处理器接口 /// public interface IMailHandler { /// /// 获取游戏邮件列表 /// /// 游戏邮件列表的枚举 Task FetchMail(); /// /// 发送邮件 /// /// 发送是否成功 Task SendMail(MailInfo[] mailInfos); /// /// 将指定邮件标记为已读 /// /// 邮件 /// 标记是否成功 Task MarkAsRead(GameMail mail); /// /// 将多个指定邮件标记为已读 /// /// 邮件数组, null 标记所有为已读 /// 标记是否成功 Task MarkAsRead(GameMail[] mails = null); /// /// 领取指定邮件的奖励 /// /// 邮件 /// 领取是否成功 Task TakeReward(GameMail mail); /// /// 领取多个指定邮件的奖励 /// /// 邮件数组, null 领取所有奖励 /// 领取是否成功 Task TakeReward(GameMail[] mails= null); /// /// 删除指定邮件 /// /// 邮件 /// 删除是否成功 Task DeleteMail(GameMail mail); /// /// 删除多个指定邮件 /// /// 邮件数组, null 删除所有 已读邮件 /// 删除是否成功 Task DeleteMail(GameMail[] mails = null); } /// /// 游戏邮件类 /// public class GameMail { // 邮件ID,用于唯一标识一封邮件 public string Id { get; set; } // 邮件类型,表示邮件的性质或用途 public EMailType Type { get; set; } // 邮件发送时间,记录邮件发送的时刻 public DateTime SendTime { get; set; } // 邮件过期时间,表示邮件有效的截止时间 public DateTime ExpireTime { get; set; } // 邮件状态,表示邮件当前的各种状态(如是否已读、是否删除等) public EMailState State { get; set; } // 邮件标题,简短概括邮件内容的主题 public string Title { get; set; } // 邮件发送方,记录邮件发送方 public string From { get; set; } // 邮件内容,详细描述邮件的信息 public string Content { get; set; } // 邮件附带的物品ID数组,表示邮件可能附带的物品或奖励 public int[] DropIds { get; set; } // 判断邮件是否含有附带物品 public bool HasDrops => DropIds != null && DropIds.Length > 0; // 判断邮件是否含有奖励,如果含有附带物品且奖励未被领取,则返回true public bool HasReward => !HasDrops || (State & EMailState.RewardTaken) == EMailState.RewardTaken; // 判断邮件是否已被阅读 public bool IsRead => (State & EMailState.HasRead) == EMailState.HasRead; // 判断邮件是否已被删除 public bool IsDeleted => (State & EMailState.HasDeleted) == EMailState.HasDeleted; public void Copy(GameMail mail) { Id = mail.Id; Type = mail.Type; SendTime = mail.SendTime; ExpireTime = mail.ExpireTime; State = mail.State; Title = mail.Title; From = mail.From; Content = mail.Content; DropIds = mail.DropIds; } }