161 lines
4.8 KiB
C#
161 lines
4.8 KiB
C#
using System;
|
||
using asap.core;
|
||
using game;
|
||
using GameCore;
|
||
using TimeManager.Event;
|
||
using UniRx;
|
||
using UnityEngine;
|
||
|
||
namespace TimeManager
|
||
{
|
||
/// <summary>
|
||
/// 时间刷新管理器 - 检测跨天、跨小时并触发刷新。须在启动链中显式 <c>Resolve<TimeRefreshManager>()</c>(见 ActivityManager.Init)。
|
||
/// </summary>
|
||
public class TimeRefreshManager : IDisposable
|
||
{
|
||
public TimeRefreshManager(ITimeTickService tickService, IUserService userService)
|
||
{
|
||
_tickService = tickService;
|
||
_userService = userService;
|
||
|
||
_sessionStartTime = ZZTimeHelper.UtcNow().UtcNowOffset();
|
||
_lastCheckedHour = _sessionStartTime.Hour;
|
||
CheckLastLogin();
|
||
_tickService.MinuteTick
|
||
.Subscribe(_ =>
|
||
{
|
||
CheckSessionCrossDay();
|
||
CheckSessionCrossHour();
|
||
})
|
||
.AddTo(_disposables);
|
||
}
|
||
|
||
private readonly ITimeTickService _tickService;
|
||
private readonly IUserService _userService;
|
||
|
||
private int _lastCheckedDayOfYear = -1;
|
||
private int _lastCheckedHour = -1;
|
||
private DateTime _sessionStartTime;
|
||
private CompositeDisposable _disposables = new();
|
||
|
||
#region Check登录时间
|
||
|
||
private void CheckLastLogin()
|
||
{
|
||
if (IsLastLoginToday()) return;
|
||
Debug.Log("上次登录不是今天");
|
||
OnCrossDayRefresh();
|
||
}
|
||
private void CheckSessionCrossDay()
|
||
{
|
||
if (!IsSessionCrossDay()) return;
|
||
OnCrossDayRefresh();
|
||
_sessionStartTime = ZZTimeHelper.UtcNow().UtcNowOffset();
|
||
}
|
||
|
||
private void CheckSessionCrossHour()
|
||
{
|
||
if (!IsSessionCrossHour()) return;
|
||
OnCrossHourRefresh();
|
||
var now = ZZTimeHelper.UtcNow().UtcNowOffset();
|
||
_lastCheckedHour = now.Hour;
|
||
}
|
||
|
||
#endregion
|
||
#region 登录时间相关
|
||
|
||
/// <summary>
|
||
/// 判断上次登录是否是今天
|
||
/// 从 UserService 获取 PlayFab 记录的真实上次登录时间
|
||
/// </summary>
|
||
public bool IsLastLoginToday()
|
||
{
|
||
var lastLoginTime = GetLastLoginTime();
|
||
if (!lastLoginTime.HasValue)
|
||
{
|
||
return false; // 从未登录过
|
||
}
|
||
|
||
var now = ZZTimeHelper.UtcNow().UtcNowOffset();
|
||
return lastLoginTime.Value.DayOfYear == now.DayOfYear &&
|
||
lastLoginTime.Value.Year == now.Year;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断当前会话是否跨天(从登录到现在的过程中是否跨过了午夜)
|
||
/// </summary>
|
||
public bool IsSessionCrossDay()
|
||
{
|
||
var now = ZZTimeHelper.UtcNow().UtcNowOffset();
|
||
return _sessionStartTime.DayOfYear != now.DayOfYear ||
|
||
_sessionStartTime.Year != now.Year;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断当前会话是否跨小时(从上次检查到现在是否跨过了整点)
|
||
/// </summary>
|
||
public bool IsSessionCrossHour()
|
||
{
|
||
var now = ZZTimeHelper.UtcNow().UtcNowOffset();
|
||
return now.Hour != _lastCheckedHour;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取上次登录时间(从 UserService 获取)
|
||
/// </summary>
|
||
public DateTime? GetLastLoginTime()
|
||
{
|
||
return _userService?.LastLoginTime;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取会话开始时间(本次游戏启动时间)
|
||
/// </summary>
|
||
public DateTime GetSessionStartTime()
|
||
{
|
||
return _sessionStartTime;
|
||
}
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 跨天刷新逻辑
|
||
/// </summary>
|
||
private void OnCrossDayRefresh()
|
||
{
|
||
try
|
||
{
|
||
// 1. 发送活动跨天刷新事件
|
||
GContext.Publish(new ActivityCrossDayRefreshEvent());
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"[TimeRefreshManager] Error during cross day refresh: {e.Message}\n{e.StackTrace}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 跨小时刷新逻辑
|
||
/// </summary>
|
||
private void OnCrossHourRefresh()
|
||
{
|
||
try
|
||
{
|
||
// 发送跨小时刷新事件
|
||
GContext.Publish(new ActivityCrossHourRefreshEvent());
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"[TimeRefreshManager] Error during cross hour refresh: {e.Message}\n{e.StackTrace}");
|
||
}
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
_disposables?.Dispose();
|
||
_disposables = null;
|
||
Debug.Log("[TimeRefreshManager] Disposed.");
|
||
}
|
||
}
|
||
}
|