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;
}
}