236 lines
7.2 KiB
C#
236 lines
7.2 KiB
C#
using System;
|
||
using Activity.Data;
|
||
using Activity.Services;
|
||
using asap.core;
|
||
using cfg;
|
||
using GameCore;
|
||
using UniRx;
|
||
using UnityEngine;
|
||
|
||
namespace Activity
|
||
{
|
||
public abstract class AEventDataManager
|
||
{
|
||
protected readonly CompositeDisposable CompositeDisposable = new();
|
||
private Tables _tables;
|
||
|
||
public Tables Tables => _tables ??= GContext.container.Resolve<Tables>();
|
||
|
||
public void Dispose()
|
||
{
|
||
CompositeDisposable?.Dispose();
|
||
}
|
||
|
||
#region 依赖注入
|
||
|
||
private IEventDataRepository _dataRepository;
|
||
private IEventTokenService _tokenService;
|
||
|
||
/// <summary>
|
||
/// 数据仓库 - 负责数据的持久化
|
||
/// </summary>
|
||
protected IEventDataRepository Repository =>
|
||
_dataRepository ??= GContext.container?.Resolve<IEventDataRepository>();
|
||
|
||
/// <summary>
|
||
/// 代币服务 - 负责代币的统一管理
|
||
/// </summary>
|
||
protected IEventTokenService TokenService =>
|
||
_tokenService ??= GContext.container?.Resolve<IEventTokenService>();
|
||
|
||
#endregion
|
||
|
||
#region 数据操作(无状态接口)
|
||
|
||
/// <summary>
|
||
/// 加载数据 - UI/Sentry 调用
|
||
/// </summary>
|
||
public virtual T LoadData<T>() where T : IEventData, new()
|
||
{
|
||
return Repository.Load<T>() ?? new T();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存数据 - 显式保存
|
||
/// </summary>
|
||
public virtual void SaveData<T>(T data) where T : IEventData, new()
|
||
{
|
||
if (data == null) return;
|
||
Repository?.Save(data);
|
||
// 发布数据保存事件,通知订阅者刷新缓存
|
||
GContext.Publish(data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新数据 - Sentry 调用,返回新创建或加载的数据
|
||
/// 基类实现:加载缓存数据,如不存在则创建新数据
|
||
/// </summary>
|
||
public virtual T RefreshData<T>(FishingEvent eventConfig) where T : IEventData, new()
|
||
{
|
||
var cachedData = Repository.Load<T>();
|
||
if (cachedData != null && cachedData.EventID == eventConfig.ID) return cachedData;
|
||
|
||
var newData = CreateData<T>(eventConfig);
|
||
|
||
OnDataInitialized(newData, eventConfig);
|
||
|
||
// 根据子类返回值决定是否自动保存
|
||
if (AutoSaveOnCreate(newData))
|
||
{
|
||
Repository.Save(newData);
|
||
}
|
||
|
||
return newData;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建新数据实例 - 子类可重写
|
||
/// </summary>
|
||
protected virtual T CreateData<T>(FishingEvent eventConfig) where T : IEventData, new()
|
||
{
|
||
var playerData = GContext.container.Resolve<PlayerData>();
|
||
return new T
|
||
{
|
||
EventID = eventConfig.ID,
|
||
FishingEvent = eventConfig,
|
||
InflationRate = playerData.InflationRate,
|
||
VipLevel = playerData.PriceLv
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 数据初始化钩子 - 子类可重写
|
||
/// </summary>
|
||
protected virtual void OnDataInitialized(IEventData data, FishingEvent eventConfig)
|
||
{
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 是否在新数据创建后自动保存 - 子类可重写
|
||
/// </summary>
|
||
protected virtual bool AutoSaveOnCreate<T>(T data) where T : IEventData, new() => true;
|
||
|
||
#endregion
|
||
|
||
#region 代币操作(委托给 IEventTokenService)
|
||
|
||
public virtual void AddToken<T>(T data, int count) where T : IEventData, new()
|
||
{
|
||
try
|
||
{
|
||
if (data == null || data.EventID <= 0) return;
|
||
TokenService?.AddToken(data.EventID, count);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"[AEventDataManager] Failed to add token for {typeof(T).Name}: {e.Message}");
|
||
}
|
||
}
|
||
|
||
public virtual void RemoveToken<T>(T data, int count) where T : IEventData, new()
|
||
{
|
||
try
|
||
{
|
||
if (data == null || data.EventID <= 0) return;
|
||
TokenService?.RemoveToken(data.EventID, count);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"[AEventDataManager] Failed to remove token for {typeof(T).Name}: {e.Message}");
|
||
}
|
||
}
|
||
|
||
public virtual int GetTokenCount<T>(T data) where T : IEventData, new()
|
||
{
|
||
try
|
||
{
|
||
if (data == null || data.EventID <= 0) return 0;
|
||
return TokenService?.GetTokenCount(data.EventID) ?? 0;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"[AEventDataManager] Failed to get token count for {typeof(T).Name}: {e.Message}");
|
||
return 0;
|
||
}
|
||
}
|
||
#endregion
|
||
}
|
||
|
||
public abstract class AEventDataManager<T> : AEventDataManager where T : IEventData, new()
|
||
{
|
||
#region 数据操作(调用基类泛型方法)
|
||
|
||
/// <summary>
|
||
/// 加载数据 - 调用基类泛型方法
|
||
/// </summary>
|
||
public virtual T LoadData()
|
||
{
|
||
return base.LoadData<T>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存数据 - 调用基类泛型方法
|
||
/// </summary>
|
||
public virtual void SaveData(T data)
|
||
{
|
||
base.SaveData(data);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 刷新数据 - 调用基类泛型方法
|
||
/// </summary>
|
||
public virtual T RefreshData(FishingEvent eventConfig)
|
||
{
|
||
var data = base.RefreshData<T>(eventConfig);
|
||
if (this is IActivityEventRedPoint<T> red)
|
||
red.SetRedPoint(data);
|
||
return data;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 数据初始化钩子 - 重写
|
||
/// </summary>
|
||
protected override void OnDataInitialized(IEventData data, FishingEvent eventConfig)
|
||
{
|
||
base.OnDataInitialized(data, eventConfig);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 泛型子类默认自动保存新创建的数据
|
||
/// </summary>
|
||
protected override bool AutoSaveOnCreate<TData>(TData data) => true;
|
||
|
||
#endregion
|
||
|
||
#region 代币操作(委托给基类)
|
||
|
||
public virtual void AddToken(T data, int count)
|
||
{
|
||
base.AddToken(data, count);
|
||
}
|
||
|
||
public virtual void RemoveToken(T data, int count)
|
||
{
|
||
base.RemoveToken(data, count);
|
||
}
|
||
|
||
public virtual int GetTokenCount(T data)
|
||
{
|
||
return base.GetTokenCount(data);
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// 活动入口红点:由具体 <see cref="AEventDataManager{T}"/> 实现。
|
||
/// Key、State、数量等规则放在实现类内部;框架仅通过本接口调用 <see cref="SetRedPoint"/>(如 <see cref="AEventDataManager{T}.RefreshData"/>、代币 <see cref="ActivityEventTokenBalanceChanged"/> 转发)。
|
||
/// </summary>
|
||
public interface IActivityEventRedPoint<T> where T : IEventData, new()
|
||
{
|
||
void SetRedPoint(T data);
|
||
}
|
||
}
|