Files
back_cantanBuilding/Assets/Scripts/Services/InGameMailHandler.cs
2026-05-26 16:15:54 +08:00

503 lines
14 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using asap.core;
using game;
using GameCore;
using Newtonsoft.Json;
using UniRx;
public class FetchMailRequest
{
public DateTime? lastSyncTime;
}
public class FetchMailResp
{
public bool success;
public List<GameMail> mails;
public string error;
}
public class MailStateInfo
{
public string Id {get; set;}
public EMailState state {get; set;}
public MailStateInfo(GameMail mail, EMailState newState)
{
Id = mail.Id.ToString();
state = mail.State | newState;
}
}
public class UpdateMailStateRequest
{
public MailStateInfo[] mailStates;
}
public class UpdateMailStateResp
{
public bool success;
public MailStateInfo[] states;
}
public class FetchMailEvt
{
DateTime TimeStamp;
}
public class MailInfo
{
public string Id { get; set; }
public EMailType Type { get; set; }
public int expireDays { get; set; }
public string Title { get; set; }
public string From { get; set; }
public string Content { get; set; }
public int[] DropIds { get; set; }
}
public class SendMailRequest
{
public MailInfo[] mailInfos;
}
public class SendMailResp
{
public bool success;
public List<GameMail> mails;
public string error;
}
public class AutoMailData
{
public string Id;
public int levelMin;
public int levelMax;
public DateTime accountCreateTime;
public DateTime loginTimeMin;
public DateTime loginTimeMax;
public int expireDays;
public int DropID;
public AutoMailData(cfg.AutoDeliveryMail mail)
{
Id = mail.MailID.ToString();
levelMin = mail.AccountLevelRange[0];
levelMax = mail.AccountLevelRange[1] == -1 ? int.MaxValue : mail.AccountLevelRange[1];
accountCreateTime = DateTime.Parse(mail.AccountCreateTimestamp);
loginTimeMin = DateTime.Parse(mail.LoginTimestampRange[0]);
loginTimeMax = DateTime.Parse(mail.LoginTimestampRange[1]);
DropID = mail.DropID;
expireDays = mail.ExpireDay;
}
public bool IsSatisfy(DateTime loginTime, DateTime CreateTime, int level)
{
return loginTime >= loginTimeMin && loginTime <= loginTimeMax
&& CreateTime < accountCreateTime
&& level >= levelMin && level <= levelMax;
}
public MailInfo ToMailInfo()
{
return new MailInfo {
Id = Id.ToString(),
Type = EMailType.AutoDelivery,
DropIds = new[] { DropID },
expireDays = expireDays
};
}
}
public static class MailUrls
{
public const string Fetch = "mail/fetch";
public const string UpdateState = "mail/updateState";
public const string Send = "mail/send";
}
public class InGameMailService : IInGameMailService
{
private MailCache _mailCache;
private IMailHandler _handler;
private List<AutoMailData> _autoMailDatas;
private CompositeDisposable _disposables;
private bool _forceFetch = false;
//private const int Fetch_Interval = 3;
public bool IsUnlock { get; set; }
public InGameMailService(ICustomServerMgr customServerMgr, cfg.Tables tables)
{
this._mailCache = new MailCache(tables.TbAutoDeliveryMail);
this._handler = new BaseMailHandler(_mailCache, customServerMgr) ;
_autoMailDatas = tables.TbAutoDeliveryMail.DataList
.Select(x => new AutoMailData(x)).ToList();
}
public void Init()
{
var userService = GContext.container.Resolve<IUserService>();
_mailCache.Load(userService.UserId);
_disposables = new CompositeDisposable();
var minActiveLevel = _autoMailDatas.Min(x => x.levelMin) -1;
if(userService.IsAuthorized)
_handler.FetchMail();
else
GContext.OnEvent<game.EvtAPISvrLoginSuccess>().Subscribe(_ => _handler.FetchMail()).AddTo(_disposables);
GContext.OnEvent<OnLvChangeEvent>()
.Skip(1)
.Where(x => x.lvl >= minActiveLevel)
.Subscribe(OnLevelChange)
.AddTo(_disposables);
//GContext.OnEvent<RestartShowHomeUIEvent>()
//.Skip(1)
//.Subscribe(OnHomeUIShow)
//.AddTo(_disposables);
var rtService = GContext.container.Resolve<IRTService>();
rtService.OnEvent<FetchMailEvt>(async evt => await _handler.FetchMail())
.AddTo(_disposables);
}
public void Reset()
{
_mailCache?.Unload();
_disposables?.Dispose();
_disposables = null;
}
public async Task FetchMail()
{
await _handler.FetchMail();
}
public IList<GameMail> GetAllMail()
{
return _mailCache.GetAll();
}
public async Task<bool> MarkRead(GameMail mail)
{
return await _handler.MarkAsRead(mail);
}
public async Task<bool> MarkRead(GameMail[] mails = null)
{
return await _handler.MarkAsRead(mails);
}
public async Task<bool> DelMail(GameMail mail)
{
return await _handler.DeleteMail(mail);
}
public async Task<bool> DelMail(GameMail[] mails = null)
{
return await _handler.DeleteMail(mails);
}
public async Task<bool> TakeReward(GameMail mail)
{
return await _handler.TakeReward(mail);
}
public async Task<bool> TakeReward(GameMail[] mails)
{
return await _handler.TakeReward(mails);
}
private void OnLevelChange(OnLvChangeEvent evt)
{
#if UNITY_EDITOR
UnityEngine.Debug.Log("[InGameMailService] OnLevelChange");
#endif
GenAutoDeliveryMail();
}
//private async void OnHomeUIShow(RestartShowHomeUIEvent evt)
//{
//#if UNITY_EDITOR
//var deltaTime = _mailCache.LastSyncTime == null ? 0 : (ZZTimeHelper.UtcNow() - _mailCache.LastSyncTime.Value).TotalSeconds;
//UnityEngine.Debug.Log($"[InGameMailService] OnHomeUIShow deltaTime {deltaTime}");
//#endif
//if(_mailCache.LastSyncTime == null
//|| _forceFetch
//|| ZZTimeHelper.UtcNow() - _mailCache.LastSyncTime.Value > TimeSpan.FromMinutes(Fetch_Interval))
//{
//if(await _handler.FetchMail())
//{
//_forceFetch = false;
//}
//}
//}
private async void GenAutoDeliveryMail()
{
var playerData = GContext.container.Resolve<PlayerData>();
var userData = GContext.container.Resolve<IUserService>();
var mailsToSend = _autoMailDatas.Where(m => !_mailCache.HasMail(m.Id)
&& m.IsSatisfy(userData.LoginTime, userData.CreateTime, playerData.lv))
.Select(m => m.ToMailInfo())
.ToArray();
if(mailsToSend.Length > 0)
{
if(await _handler.SendMail(mailsToSend))
{
_forceFetch = true;
}
}
#if UNITY_EDITOR
var mailids = mailsToSend.Select(m => m.Id);
var mailidsStr = string.Join(',', mailids);
UnityEngine.Debug.Log($"[InGameMailService] GenAutoDeliveryMail {mailidsStr}");
#endif
}
public void PrintCacheMail()
{
UnityEngine.Debug.Log(_mailCache.PrintCacheMails());
}
}
public class BaseMailHandler : IMailHandler
{
protected MailCache _cache;
protected ICustomServerMgr _customServerMgr;
public BaseMailHandler(MailCache cache, ICustomServerMgr customServerMgr)
{
this._cache = cache;
this._customServerMgr = customServerMgr;
}
public virtual async Task<bool> FetchMail()
{
try
{
await Awaiters.NextFrame;
#if UNITY_EDITOR
UnityEngine.Debug.Log($"[InGameMailService] Start Fetch Mails");
#endif
var req = new FetchMailRequest()
{
lastSyncTime = _cache.LastSyncTime
};
var result = await _customServerMgr.CustomServerPost(MailUrls.Fetch, JsonConvert.SerializeObject(req));
if (result != null)
{
var resp = JsonConvert.DeserializeObject<FetchMailResp>(result);
if (resp.success )
{
if(resp.mails != null && resp.mails.Count > 0)
{
_cache.Cache(resp.mails);
_cache.Save();
var UnreadMailCount = _cache.UnreadMailCount;
RedPointManager.Instance.SetRedPointState(RedPointName.Unread_Mail, UnreadMailCount > 0, UnreadMailCount);
#if UNITY_EDITOR
UnityEngine.Debug.Log($"[InGameMailService] FetchMail {UnreadMailCount} LastSyncTime = {_cache.LastSyncTime}");
#endif
}
else
{
_cache.UpdateSyncTime();
#if UNITY_EDITOR
UnityEngine.Debug.Log($"[InGameMailService] No Mails Fetch Fetched LastSyncTime = {_cache.LastSyncTime}");
#endif
}
return true;
}
else
{
UnityEngine.Debug.LogError($"[InGameMailService] FetchMail Failed {resp.error} ");
}
}
}
catch(Exception e)
{
UnityEngine.Debug.LogException(e);
}
UnityEngine.Debug.LogWarning("[InGameMailService] FetchMail Failed");
return false;
}
public async Task<bool> SendMail(MailInfo[] mailInfos)
{
try
{
var req = new SendMailRequest()
{
mailInfos = mailInfos
};
var result = await _customServerMgr.CustomServerPost(MailUrls.Send, JsonConvert.SerializeObject(req));
if (result != null)
{
var resp = JsonConvert.DeserializeObject<SendMailResp>(result);
if (!resp.success)
{
UnityEngine.Debug.LogError($"[InGameMailService] SendMail Failed {resp.error} ");
}
return resp.success;
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError(e);
}
return false;
}
protected virtual async Task<bool> UpdateMailState(GameMail[] mails, EMailState state)
{
var req = new UpdateMailStateRequest()
{
mailStates = mails.Select(m => new MailStateInfo(m, state)).ToArray()
};
var result = await _customServerMgr.CustomServerPost(MailUrls.UpdateState, JsonConvert.SerializeObject(req));
if (result != null)
{
var resp = JsonConvert.DeserializeObject<UpdateMailStateResp>(result);
if (resp.success)
{
foreach(var s in req.mailStates)
{
var mail = _cache.GetMail(s.Id);
if (mail != null) mail.State = s.state;
}
return true;
}
}
return false;
}
public virtual async Task<bool> MarkAsRead(GameMail mail)
{
if (mail.IsRead) return false;
var result = await UpdateMailState(new[] { mail }, EMailState.HasRead);
if(result) _cache.Save();
return result;
}
public virtual async Task<bool> MarkAsRead(GameMail[] mails = null)
{
if (mails == null)
{
mails = _cache.GetAll()
.Where(m => !m.IsRead)
.ToArray();
}
return await UpdateMailState( mails, EMailState.HasRead);
}
public async Task<bool> TakeReward(GameMail mail)
{
if (!mail.HasDrops || mail.HasReward)
return false;
var result = await UpdateMailState(new[] { mail }, EMailState.RewardTaken);
if (result)
{
_cache.Save();
GContext.container.Resolve<PlayerItemData>().AddItemByDropList(mail.DropIds.ToList());
GContext.Publish(new ShowData());
}
return result;
}
public async Task<bool> TakeReward(GameMail[] mails = null)
{
if (mails == null)
{
mails = _cache.GetAll()
.Where(m => m.HasDrops && !m.HasReward)
.ToArray();
}
else
{
mails = mails.Where(m => m.HasDrops && !m.HasReward)
.ToArray();
}
if(mails.Length == 0 ) return false;
var result = await UpdateMailState( mails, EMailState.HasRead);
if (result)
{
_cache.Save();
var drops = mails.Where(m => m.HasReward)
.SelectMany(m => m.DropIds).ToList();
GContext.container.Resolve<PlayerItemData>().AddItemByDropList(drops);
GContext.Publish(new ShowData());
}
return result;
}
public async Task<bool> DeleteMail(GameMail mail)
{
if (mail.IsDeleted)
return false;
var result = await UpdateMailState(new[] { mail }, EMailState.HasDeleted);
if(result) _cache.Save();
return result;
}
public async Task<bool> DeleteMail(GameMail[] mails = null)
{
if (mails == null)
{
mails = _cache.GetAll()
.Where(m => m.IsRead && m.HasReward )
.ToArray();
}
else
{
mails = mails.Where(m => !m.IsDeleted)
.ToArray();
}
if (mails.Length == 0) return false;
var result = await UpdateMailState(mails, EMailState.HasDeleted);
if(result) _cache.Save();
return result;
}
}