using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using TcgEngine; using TcgEngine.Gameplay; using TcgEngine.Client; using System.Threading.Tasks; namespace TcgEngine.Gameplay { /// /// 任务管理器,负责任务的分配、进度追踪和奖励发放等功能 /// public class TaskManager : MonoBehaviour { public static TaskManager Instance; [Header("Player Data")] public List playerTasks = new List(); public bool isClearPlayerTasks = false; public long lastDailyTaskAssigned = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); public int maxTasks = 5; // 玩家最多持有任务数 private GameLogic gameLogic; private System.Random random = new System.Random(); public Action> refreshTaskUI; private GameClient gameClient; public string userID; // 任务缓存处 public Dictionary taskConfigs = new Dictionary(); private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } private void Start() { userID = ApiClient.Get().UserID; } private void OnEnable() { // 订阅游戏事件 gameClient = FindFirstObjectByType(); gameClient = GameClient.Get(); if (gameClient != null) { LoadTasks(); LoadPlayerData(); gameClient.onGameStart += OnGameStart; gameClient.onGameEnd += OnGameEnd; // gameClient.onConnectServer?.Invoke(); } // 移除对GameLogic.Instance的错误引用,改为检查gameLogic变量 if (gameLogic != null) { SubscribeToGameEvents(); } } private void OnDisable() { // 取消订阅游戏事件 gameClient = FindFirstObjectByType(); gameClient = GameClient.Get(); if (gameClient != null) { gameClient.onGameStart -= OnGameStart; gameClient.onGameEnd -= OnGameEnd; } // 移除对GameLogic.Instance的错误引用,改为检查gameLogic变量 if (gameLogic != null) { UnsubscribeFromGameEvents(); } } public void SetGameLogic(GameLogic logic) { gameLogic = logic; SubscribeToGameEvents(); } private void SubscribeToGameEvents() { if (gameLogic != null) { gameLogic.onCardPlayed += OnCardPlayed; gameLogic.onCardSummoned += OnCardSummoned; gameLogic.onAbilityStart += OnAbilityUsed; gameLogic.onCardDiscarded += OnCardDiscarded; // 用于检测击败英雄 } } private void UnsubscribeFromGameEvents() { if (gameLogic != null) { gameLogic.onCardPlayed -= OnCardPlayed; gameLogic.onCardSummoned -= OnCardSummoned; gameLogic.onAbilityStart -= OnAbilityUsed; gameLogic.onCardDiscarded -= OnCardDiscarded; } } private async void LoadTasks() { // 从服务器加载所有任务配置 await LoadTasksFromServer(); } private async Task LoadTasksFromServer() { if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn()) { // 从服务器API获取任务配置 string url = ApiClient.ServerURL + "/api/tasks"; WebResponse res = await ApiClient.Get().SendGetRequest(url); Debug.LogError("从服务器API获取任务配置" + res.data + res.status); Debug.LogError(res.success); if (res.success) { // 解析任务配置数据 try { TaskDataResponse[] taskResponses = ApiTool.JsonToArray(res.data); // 在实际项目中,这里应该将服务器数据转换为TaskData对象并存储在内存中 // 供后续使用,而不是每次都从Resources加载 foreach (var item in taskResponses) { Debug.Log($"缓存ID处{item.id}"); taskConfigs[item.id] = CreateFromResponse(item); } Debug.Log("共储存:" + taskConfigs.Count + "条信息"); foreach (var kvp in taskConfigs) { TaskData task = kvp.Value; Debug.Log($"分别为 {task.id}"); } } catch (Exception e) { Debug.LogError("Failed to parse task data from server: " + e.Message); } } else { Debug.LogWarning("Failed to load tasks from server: " + res.error); // 如果无法从服务器加载,则使用本地Resources作为后备 TaskData[] localTasks = Resources.LoadAll("Tasks"); Debug.Log("Loaded " + localTasks.Length + " tasks from local resources as fallback"); } } } // 服务器下发的缓存存储处 public TaskData CreateFromResponse(TaskDataResponse response) { TaskData task = ScriptableObject.CreateInstance(); task.id = response.id; task.name = response.name; task.desc = response.desc; task.condition = (TaskConditionType)response.condition; task.value1 = response.value1; task.value2 = response.value2; task.value3 = response.value3; if (response.rewardTypes != null) { task.rewardTypes = new TaskRewardType[response.rewardTypes.Length]; for (int i = 0; i < response.rewardTypes.Length; i++) { task.rewardTypes[i] = (TaskRewardType)response.rewardTypes[i]; } } else { task.rewardTypes = new TaskRewardType[0]; } task.rewardNums = response.rewardNums != null ? response.rewardNums : new int[0]; task.isDailyTask = response.isDailyTask; task.durationHours = response.durationHours; return task; } private async void LoadPlayerData() { // 从服务器加载玩家任务数据 await LoadPlayerTasksFromServer(); } private async Task LoadPlayerTasksFromServer() { if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn()) { // 从服务器获取玩家任务数据 string url = ApiClient.ServerURL + $"/api/tasks/"+ApiClient.Get().UserID; WebResponse res = await ApiClient.Get().SendGetRequest(url); // Debug.Log($"LoadPlayerTasksFromServer:{url}"); Debug.LogWarning($"从服务器获取玩家任务数据res_data--:{res.data},{res.status}"); if (res.success) { // 解析玩家任务数据 try { PlayerTasksResponse response = ApiTool.JsonToObject(res.data); lastDailyTaskAssigned = response.lastDailyTaskAssigned; // 清除现有任务 playerTasks.Clear(); // 转换并添加任务 foreach (var taskResponse in response.tasks) { PlayerTask playerTask = new PlayerTask(taskResponse); playerTasks.Add(playerTask); Debug.Log(playerTask); } Debug.Log("Player tasks loaded from server: " + playerTasks.Count + " tasks"); } catch (Exception e) { Debug.LogError("Failed to parse player tasks from server: " + e.Message); } } else { Debug.LogWarning("Failed to load player tasks from server: " + res.error); } } } public async void SavePlayerData() { // 将玩家任务数据保存到服务器 if (ApiClient.Get() != null) { // 准备要发送的数据 PlayerTasksResponse saveData = new PlayerTasksResponse(); // 转换任务数据 PlayerTaskResponse[] taskResponses = new PlayerTaskResponse[playerTasks.Count]; for (int i = 0; i < playerTasks.Count; i++) { taskResponses[i] = playerTasks[i].ToResponse(); Debug.Log($"数据[{i}]:{taskResponses[i].taskId}"); } foreach (PlayerTaskResponse item in taskResponses) { Debug.Log($"id:{item.taskId}" + $"开始时间:{item.assignedTime}" + $"结束时间:{item.expireTime}" + $"状态:{item.status}" + $"进度:{item.progress}" + $""); } Debug.Log($"{taskResponses.Length}"); saveData.tasks = taskResponses; saveData.lastDailyTaskAssigned = lastDailyTaskAssigned; Debug.Log($"saveData.tasks---{saveData.tasks.Length}"); string json = ApiTool.ToJson(saveData); string url = ApiClient.ServerURL + $"/api/tasks/{userID}"; WebResponse res = await ApiClient.Get().SendPostRequest(url, json); Debug.Log(json); Debug.Log($"SavePlayerData:{url}"); if (isClearPlayerTasks) { Debug.Log($"数据清除后SavePlayerData:{url}"); isClearPlayerTasks = false; } if (res.success) { Debug.Log("玩家任务已保存到服务器"); } else { Debug.LogWarning("未能将玩家任务保存到服务器:" + res.error+"错误码:"+res.status); } } } private void Update() { if (isClearPlayerTasks) { ClearAllSaveData(); } } private void ClearAllSaveData() { if (!isClearPlayerTasks) { Debug.LogWarning("清除失败"); return; } playerTasks.Clear(); SavePlayerData(); Debug.Log("清除成功"); } // 每日任务分配 public void AssignDailyTaskIfNeeded() { long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); long secondsSinceLastTask = now - lastDailyTaskAssigned; // 转换为小时 double hoursSinceLastTask = secondsSinceLastTask / 3600.0; if (hoursSinceLastTask < 24) return; // 检查玩家是否已达到最大任务数 if (playerTasks.Count >= maxTasks) return; TaskData[] allTasks; if (taskConfigs.Count!=0) { // 从缓存中取 Value 部分(TaskData),转成数组 allTasks = taskConfigs.Values.ToArray(); Debug.Log("读取任务缓存成功!"); } else { // 如果缓存没有任务采用本地任务 allTasks = Resources.LoadAll("Tasks"); Debug.LogError("读取任务缓存失败,采用本地任务"); } var dailyTasks = allTasks .Where(t => t.isDailyTask && t.condition != 0 && !string.IsNullOrEmpty(t.id)) .ToArray(); if (dailyTasks.Length == 0) return; // 避免重复分配相同任务 int maxRetries = 3; TaskData selectedTask = null; HashSet triedTasks = new HashSet(); while (maxRetries-- > 0 && selectedTask == null) { // 随机选择一个任务 TaskData candidateTask = dailyTasks[random.Next(dailyTasks.Length)]; // 如果任务已经尝试过则跳过 if (triedTasks.Contains(candidateTask.id)) continue; triedTasks.Add(candidateTask.id); // 检查任务是否有效(未被玩家完成过或未在进度中) if (!playerTasks.Any(pt => pt.taskId == candidateTask.id)) { selectedTask = candidateTask; break; } } // 如果没有找到合适的任务则返回 if (selectedTask == null) { Debug.LogWarning("Failed to assign daily task after multiple retries"); return; } // 创建玩家任务实例 PlayerTask playerTask = new PlayerTask(selectedTask); playerTasks.Add(playerTask); lastDailyTaskAssigned = now; SavePlayerData(); Debug.Log($"分配任务: {selectedTask.name}"); } // 检查并更新过期任务 public void CheckExpiredTasks() { long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); // 当前时间戳(秒) foreach (var task in playerTasks) { if (task.status == TaskStatus.Active && now > task.expireTime) { task.status = TaskStatus.Expired; } } } // 检查任务是否完成 public bool CheckTaskCompletion(PlayerTask task) { TaskData taskConfig = GetTaskConfig(task.taskId); if (taskConfig == null) return false; return task.progress >= taskConfig.value1; } // 领取任务奖励 public bool ClaimTaskReward(PlayerTask task) { if (task.status != TaskStatus.Completed) return false; TaskData taskConfig = GetTaskConfig(task.taskId); if (taskConfig == null) return false; // 发放奖励 for (int i = 0; i < taskConfig.rewardTypes.Length && i < taskConfig.rewardNums.Length; i++) { GiveReward(taskConfig.rewardTypes[i], taskConfig.rewardNums[i]); } task.status = TaskStatus.Claimed; SavePlayerData(); return true; } private void GiveReward(TaskRewardType rewardType, int amount) { // 根据奖励类型发放奖励 switch (rewardType) { case TaskRewardType.Coins: // 增加金币(需要与游戏现有金币系统集成) UserData userData = Authenticator.Get().UserData; if (userData != null) { userData.coins += amount; Debug.Log($"Gave {amount} coins as reward"); // 保存用户数据更新 if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn()) { Authenticator.Get().SaveUserData(); } } break; } } private TaskData GetTaskConfig(string taskId) { TaskData[] allTasks = Resources.LoadAll("Tasks"); return allTasks.FirstOrDefault(t => t.id == taskId); } // 更新任务进度 private void UpdateTaskProgress(TaskConditionType conditionType, string parameter1 = null, string parameter2 = null) { bool progressUpdated = false; refreshTaskUI?.Invoke(playerTasks); foreach (var task in playerTasks) { if (task.status != TaskStatus.Active) continue; TaskData taskConfig = GetTaskConfig(task.taskId); if (taskConfig == null || taskConfig.condition != conditionType) continue; bool shouldUpdate = false; // 根据任务类型检查条件 switch (conditionType) { case TaskConditionType.LoginGame: case TaskConditionType.PlayGames: case TaskConditionType.WinGames: // 这些任务类型直接增加进度 shouldUpdate = true; break; case TaskConditionType.DefeatHeroWithAttributes: case TaskConditionType.SummonHeroWithAttributes: case TaskConditionType.UseHeroSkillWithAttributes: // 检查参数是否匹配(支持多个参数匹配) if (!string.IsNullOrEmpty(parameter1) && (!string.IsNullOrEmpty(taskConfig.value2) && taskConfig.value2 == parameter1 || !string.IsNullOrEmpty(taskConfig.value3) && taskConfig.value3 == parameter1)) { shouldUpdate = true; } else if (!string.IsNullOrEmpty(parameter2) && (!string.IsNullOrEmpty(taskConfig.value2) && taskConfig.value2 == parameter2 || !string.IsNullOrEmpty(taskConfig.value3) && taskConfig.value3 == parameter2)) { shouldUpdate = true; } break; } if (shouldUpdate && task.progress < taskConfig.value1) { task.progress++; progressUpdated = true; // 检查任务是否完成 if (CheckTaskCompletion(task)) { task.status = TaskStatus.Completed; Debug.Log($"Task completed: {taskConfig.name}"); } } } if (progressUpdated) { Debug.LogError("读到了"); SavePlayerData(); } } // 事件处理方法 private void OnGameStart() { // 进行对战任务进度+1 UpdateTaskProgress(TaskConditionType.PlayGames); } private void OnGameEnd(int winner) { int player_id = GameClient.Get().GetPlayerID(); // 胜利任务进度+1 if (winner == player_id) { UpdateTaskProgress(TaskConditionType.WinGames); } // 检查是否有任务完成并自动领取奖励 CheckAndClaimCompletedTasks(); } private void OnCardPlayed(Card card, Slot slot) { // 召唤特定属性英雄任务 if (card.CardData.type == CardType.Character) { string cardCamp = card.CardData.camp.ToString(); UpdateTaskProgress(TaskConditionType.SummonHeroWithAttributes, cardCamp); } } private void OnCardSummoned(Card card, Slot slot) { // 召唤特定属性英雄任务 if (card.CardData.type == CardType.Character) { string cardCamp = card.CardData.camp.ToString(); UpdateTaskProgress(TaskConditionType.SummonHeroWithAttributes, cardCamp); } } private void OnAbilityUsed(AbilityData ability, Card caster) { // 使用特定属性英雄技能任务 string cardCamp = caster.CardData.camp.ToString(); UpdateTaskProgress(TaskConditionType.UseHeroSkillWithAttributes, cardCamp); } private void OnCardDiscarded(Card card) { // 击败特定属性英雄任务 if (card.CardData.type == CardType.Character) { string cardCamp = card.CardData.camp.ToString(); UpdateTaskProgress(TaskConditionType.DefeatHeroWithAttributes, cardCamp); } } // 检查并自动领取已完成任务的奖励 public void CheckAndClaimCompletedTasks() { bool claimedAny = false; foreach (var task in playerTasks) { if (task.status == TaskStatus.Completed) { if (ClaimTaskReward(task)) { claimedAny = true; } } } if (claimedAny) { SavePlayerData(); } } // 玩家登录时检查任务 public void OnPlayerLogin() { // 检查是否已有登录任务 bool hasLoginTask = playerTasks.Any(t => { TaskData config = GetTaskConfig(t.taskId); return config != null && config.condition == TaskConditionType.LoginGame; }); // 如果没有登录任务,就分配一个 if (!hasLoginTask) { AssignLoginTask(); } else { // 如过有就随机分配一个新任务 AssignDailyTaskIfNeeded(); } // 登录任务完成 UpdateTaskProgress(TaskConditionType.LoginGame); // 检查是否有任务完成并自动领取奖励 CheckAndClaimCompletedTasks(); } /// /// 专门分配一个登录任务 /// private void AssignLoginTask() { TaskData[] allTasks = Resources.LoadAll("Tasks"); var loginTask = allTasks.FirstOrDefault(t => t.isDailyTask && t.condition == TaskConditionType.LoginGame); if (loginTask != null) { PlayerTask playerTask = new PlayerTask(loginTask); playerTasks.Add(playerTask); lastDailyTaskAssigned = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); SavePlayerData(); Debug.Log($"分配登录任务: {loginTask.name}"); } else { Debug.LogWarning("未找到登录任务配置!"); } } // 获取活跃任务 public List GetActiveTasks() { return playerTasks.Where(t => t.status == TaskStatus.Active).ToList(); } // 获取已完成任务 public List GetCompletedTasks() { return playerTasks.Where(t => t.status == TaskStatus.Completed).ToList(); } // 获取所有任务 public List GetAllTasks() { return playerTasks; } } }