417 lines
11 KiB
C#
417 lines
11 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Threading.Tasks;
|
||
using GameCore;
|
||
using Newtonsoft.Json;
|
||
using UnityEngine;
|
||
using UnityEngine.Assertions;
|
||
|
||
/// <summary>
|
||
/// 邮件类型枚举
|
||
/// </summary>
|
||
public enum EMailType
|
||
{
|
||
Global,
|
||
Personal,
|
||
AutoDelivery,
|
||
}
|
||
|
||
/// <summary>
|
||
/// 邮件状态标志枚举
|
||
/// </summary>
|
||
[Flags]
|
||
public enum EMailState
|
||
{
|
||
None = 1 << 0, // 通知未读
|
||
HasRead = 1 << 1, // 已读通知
|
||
RewardTaken = 1 << 2, // 奖励已领取,表示用户已经领取了通知中的奖励
|
||
HasDeleted = 1 << 3, // 通知已删除
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 游戏内邮件服务接口
|
||
/// </summary>
|
||
public interface IInGameMailService
|
||
{
|
||
/// <summary>
|
||
/// 是否解锁邮件功能。
|
||
/// </summary>
|
||
bool IsUnlock { get; set; }
|
||
|
||
/// <summary>
|
||
/// 初始化邮件服务。
|
||
/// </summary>
|
||
void Init();
|
||
|
||
/// <summary>
|
||
/// 重置邮件服务。
|
||
/// </summary>
|
||
void Reset();
|
||
|
||
/// <summary>
|
||
/// 异步获取新邮件。
|
||
/// </summary>
|
||
/// <returns>一个任务,表示邮件获取操作。</returns>
|
||
Task FetchMail();
|
||
|
||
/// <summary>
|
||
/// 异步获取所有游戏邮件。
|
||
/// </summary>
|
||
/// <returns>一个任务,包含一个列表,列表中包含所有游戏邮件。</returns>
|
||
IList<GameMail> GetAllMail();
|
||
|
||
/// <summary>
|
||
/// 异步标记指定邮件为已读。
|
||
/// </summary>
|
||
/// <param name="mail">要标记为已读的邮件。</param>
|
||
/// <returns>一个任务,表示邮件标记操作是否成功。</returns>
|
||
Task<bool> MarkRead(GameMail mail);
|
||
|
||
/// <summary>
|
||
/// 异步标记指定邮件为已读。
|
||
/// </summary>
|
||
/// <param name="mails">要标记为已读的邮件。null 标记搜有已读</param>
|
||
/// <returns>一个任务,表示邮件标记操作是否成功。</returns>
|
||
Task<bool> MarkRead(GameMail[] mails = null);
|
||
|
||
/// <summary>
|
||
/// 异步删除指定邮件。
|
||
/// </summary>
|
||
/// <param name="mail">要删除的邮件。</param>
|
||
/// <returns>一个任务,表示邮件删除操作是否成功。</returns>
|
||
Task<bool> DelMail(GameMail mail);
|
||
|
||
/// <summary>
|
||
/// 异步删除指定邮件。
|
||
/// </summary>
|
||
/// <param name="mails">要删除的邮件。null 删除所有已读邮件</param>
|
||
/// <returns>一个任务,表示邮件删除操作是否成功。</returns>
|
||
Task<bool> DelMail(GameMail[] mails = null);
|
||
|
||
/// <summary>
|
||
/// 异步领取指定邮件的奖励。
|
||
/// </summary>
|
||
/// <param name="mail">要领取奖励的邮件。</param>
|
||
/// <returns>一个任务,表示奖励领取操作是否成功。</returns>
|
||
Task<bool> TakeReward(GameMail mail);
|
||
|
||
/// <summary>
|
||
/// 异步领取指定邮件的奖励。
|
||
/// </summary>
|
||
/// <param name="mails">要领取奖励的邮件。领取所有奖励</param>
|
||
/// <returns>一个任务,表示奖励领取操作是否成功。</returns>
|
||
Task<bool> TakeReward(GameMail[] mails = null);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 邮件缓存类
|
||
/// </summary>
|
||
public class MailCache
|
||
{
|
||
private Dictionary<string,GameMail> _dicMails;
|
||
private Dictionary<string,cfg.AutoDeliveryMail> _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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载指定用户的邮件缓存
|
||
/// </summary>
|
||
/// <param name="userId">用户ID</param>
|
||
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<string, GameMail>()
|
||
: JsonConvert.DeserializeObject<Dictionary<string, GameMail>>(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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 对邮件列表进行排序
|
||
/// </summary>
|
||
/// <param name="mails">邮件列表</param>
|
||
private void SortMails(List<GameMail> mails)
|
||
{
|
||
//by send time Desc
|
||
mails.Sort((a, b) => b.SendTime.CompareTo(a.SendTime));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存邮件缓存到持久化存储
|
||
/// </summary>
|
||
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();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 缓存单封邮件
|
||
/// </summary>
|
||
/// <param name="mail">邮件对象</param>
|
||
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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 缓存多封邮件
|
||
/// </summary>
|
||
/// <param name="mails">邮件集合</param>
|
||
public void Cache(IEnumerable<GameMail> 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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有未过期且未删除的邮件
|
||
/// </summary>
|
||
/// <returns>邮件列表</returns>
|
||
public IList<GameMail> 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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 邮件处理器接口
|
||
/// </summary>
|
||
public interface IMailHandler
|
||
{
|
||
/// <summary>
|
||
/// 获取游戏邮件列表
|
||
/// </summary>
|
||
/// <returns>游戏邮件列表的枚举</returns>
|
||
Task<bool> FetchMail();
|
||
|
||
/// <summary>
|
||
/// 发送邮件
|
||
/// </summary>
|
||
/// <returns>发送是否成功</returns>
|
||
Task<bool> SendMail(MailInfo[] mailInfos);
|
||
|
||
/// <summary>
|
||
/// 将指定邮件标记为已读
|
||
/// </summary>
|
||
/// <param name="mail">邮件</param>
|
||
/// <returns>标记是否成功</returns>
|
||
Task<bool> MarkAsRead(GameMail mail);
|
||
|
||
/// <summary>
|
||
/// 将多个指定邮件标记为已读
|
||
/// </summary>
|
||
/// <param name="mails">邮件数组, null 标记所有为已读</param>
|
||
/// <returns>标记是否成功</returns>
|
||
Task<bool> MarkAsRead(GameMail[] mails = null);
|
||
|
||
/// <summary>
|
||
/// 领取指定邮件的奖励
|
||
/// </summary>
|
||
/// <param name="mail">邮件</param>
|
||
/// <returns>领取是否成功</returns>
|
||
Task<bool> TakeReward(GameMail mail);
|
||
|
||
/// <summary>
|
||
/// 领取多个指定邮件的奖励
|
||
/// </summary>
|
||
/// <param name="mails">邮件数组, null 领取所有奖励</param>
|
||
/// <returns>领取是否成功</returns>
|
||
Task<bool> TakeReward(GameMail[] mails= null);
|
||
|
||
/// <summary>
|
||
/// 删除指定邮件
|
||
/// </summary>
|
||
/// <param name="mail">邮件</param>
|
||
/// <returns>删除是否成功</returns>
|
||
Task<bool> DeleteMail(GameMail mail);
|
||
|
||
/// <summary>
|
||
/// 删除多个指定邮件
|
||
/// </summary>
|
||
/// <param name="mails">邮件数组, null 删除所有 已读邮件</param>
|
||
/// <returns>删除是否成功</returns>
|
||
Task<bool> DeleteMail(GameMail[] mails = null);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 游戏邮件类
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
|