using System; using System.Collections.Generic; using asap.core; using UnityEngine; namespace Activity { /// /// 入账/扣账成功后由 发布, /// 供各活动自行判断是否刷新入口合并红点等(避免订阅者与具体玩法耦合)。 /// public readonly struct ActivityEventTokenBalanceChanged { public int EventId { get; } public ActivityEventTokenBalanceChanged(int eventId) { EventId = eventId; } } } namespace Activity.Services { /// /// 活动代币服务实现 /// 负责管理所有活动的代币数据,提供统一的存储接口 /// public class EventTokenService : IEventTokenService { #region 常量与字段 private const string TransitionDataKey = "TransitionData"; private readonly Dictionary _tokenData = new Dictionary(); private readonly object _lock = new object(); private bool _isInitialized = false; #endregion #region 初始化 /// /// 初始化服务,从 PlayFab 加载代币数据 /// public void Initialize() { if (_isInitialized) return; lock (_lock) { if (_isInitialized) return; try { // 从 PlayFab 加载数据 LoadFromPlayFab(); _isInitialized = true; #if UNITY_EDITOR Debug.Log($"[EventTokenService] Initialized successfully. Token count: {_tokenData.Count}"); #endif } catch (Exception e) { Debug.LogError($"[EventTokenService] Initialization failed: {e.Message}\n{e.StackTrace}"); } } } /// /// 从 PlayFab 加载代币数据 /// private void LoadFromPlayFab() { try { var dataStr = PlayFabMgr.Instance?.GetLocalData(TransitionDataKey); if (!string.IsNullOrEmpty(dataStr)) { _tokenData.Clear(); var data = Newtonsoft.Json.JsonConvert.DeserializeObject>(dataStr); if (data != null) { foreach (var kvp in data) { _tokenData[kvp.Key] = kvp.Value; } } } #if UNITY_EDITOR Debug.Log($"[EventTokenService] Loaded {_tokenData.Count} token entries from PlayFab"); #endif } catch (Exception e) { Debug.LogError($"[EventTokenService] Failed to load from PlayFab: {e.Message}"); } } /// /// 保存数据到 PlayFab /// private void SaveToPlayFab() { try { var json = Newtonsoft.Json.JsonConvert.SerializeObject(_tokenData); PlayFabMgr.Instance?.UpdateUserDataValue(TransitionDataKey, json); #if UNITY_EDITOR Debug.Log($"[EventTokenService] Saved {_tokenData.Count} token entries to PlayFab"); #endif } catch (Exception e) { Debug.LogError($"[EventTokenService] Failed to save to PlayFab: {e.Message}"); throw; } } #endregion #region 基础操作 public void AddToken(int eventId, int count) { if (eventId <= 0) { Debug.LogWarning($"[EventTokenService] Invalid eventId: {eventId}"); return; } if (count == 0) return; lock (_lock) { try { EnsureInitialized(); var currentCount = GetTokenCount(eventId); _tokenData[eventId] = currentCount + count; SaveToPlayFab(); #if UNITY_EDITOR Debug.Log($"[EventTokenService] Added {count} tokens to event {eventId}, new total: {_tokenData[eventId]}"); #endif } catch (Exception e) { Debug.LogError($"[EventTokenService] AddToken failed for event {eventId}: {e.Message}"); throw; } } PublishActivityEventTokenBalanceChanged(eventId); } public int RemoveToken(int eventId, int count) { if (eventId <= 0) { Debug.LogWarning($"[EventTokenService] Invalid eventId: {eventId}"); return 0; } int actualRemoved = 0; lock (_lock) { try { EnsureInitialized(); var currentCount = GetTokenCount(eventId); actualRemoved = Mathf.Min(count, currentCount); var newCount = currentCount - actualRemoved; if (newCount <= 0) { _tokenData.Remove(eventId); } else { _tokenData[eventId] = newCount; } SaveToPlayFab(); #if UNITY_EDITOR Debug.Log($"[EventTokenService] Removed {actualRemoved} tokens from event {eventId}, remaining: {newCount}"); #endif } catch (Exception e) { Debug.LogError($"[EventTokenService] RemoveToken failed for event {eventId}: {e.Message}"); throw; } } PublishActivityEventTokenBalanceChanged(eventId); return actualRemoved; } public int GetTokenCount(int eventId) { if (eventId <= 0) return 0; lock (_lock) { try { EnsureInitialized(); return _tokenData.GetValueOrDefault(eventId, 0); } catch (Exception e) { Debug.LogError($"[EventTokenService] GetTokenCount failed for event {eventId}: {e.Message}"); return 0; } } } public void SetToken(int eventId, int count) { if (eventId <= 0) { Debug.LogWarning($"[EventTokenService] Invalid eventId: {eventId}"); return; } lock (_lock) { try { EnsureInitialized(); _tokenData[eventId] = count; SaveToPlayFab(); #if UNITY_EDITOR Debug.Log($"[EventTokenService] Set event {eventId} token count to {count}"); #endif } catch (Exception e) { Debug.LogError($"[EventTokenService] SetToken failed for event {eventId}: {e.Message}"); throw; } } } public void ClearToken(int eventId) { if (eventId <= 0) return; lock (_lock) { try { EnsureInitialized(); if (_tokenData.Remove(eventId)) { SaveToPlayFab(); } } catch (Exception e) { Debug.LogError($"[EventTokenService] ClearToken failed for event {eventId}: {e.Message}"); throw; } } } #endregion #region 批量操作 public Dictionary GetAllTokens() { lock (_lock) { EnsureInitialized(); return new Dictionary(_tokenData); } } public void SetTokens(Dictionary tokens) { if (tokens == null) return; lock (_lock) { try { EnsureInitialized(); _tokenData.Clear(); foreach (var kvp in tokens) { if (kvp.Key > 0) { _tokenData[kvp.Key] = kvp.Value; } } SaveToPlayFab(); #if UNITY_EDITOR Debug.Log($"[EventTokenService] Set {tokens.Count} token entries"); #endif } catch (Exception e) { Debug.LogError($"[EventTokenService] SetTokens failed: {e.Message}"); throw; } } } public void ClearTokens(IEnumerable eventIds) { if (eventIds == null) return; lock (_lock) { try { EnsureInitialized(); bool changed = false; foreach (var eventId in eventIds) { if (_tokenData.Remove(eventId)) { changed = true; } } if (changed) { SaveToPlayFab(); } } catch (Exception e) { Debug.LogError($"[EventTokenService] ClearTokens failed: {e.Message}"); throw; } } } #endregion #region 私有辅助方法 private void EnsureInitialized() { if (!_isInitialized) { Initialize(); } } private static void PublishActivityEventTokenBalanceChanged(int eventId) { try { GContext.Publish(new Activity.ActivityEventTokenBalanceChanged(eventId)); } catch { // GContext 未就绪等 } } #endregion } }