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 Dictionary assignedTaskDict = new Dictionary();
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
private void Start()
{
userID = ApiClient.Get().UserID;
}
private void OnEnable()
{
// 订阅游戏事件
gameClient = FindFirstObjectByType();
gameClient = GameClient.Get();
ApiClient client = ApiClient.Get();
if (gameClient != null)
{
LoadTasks();
LoadPlayerData();
gameClient.onGameStart += OnGameStart;
gameClient.onGameEnd += OnGameEnd;
// gameClient.onConnectServer?.Invoke();
}
// else if (client.UserData != null)
// {
// LoadTasks();
// LoadPlayerData();
// client.onLogin += OnGameStart;
// client.onLogin += OnGameEnd;
// }
else
{
Debug.Log("绑定失败!");
}
// 移除对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.Log("从服务器API获取任务配置" + res.data + res.status);
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] =
TaskData.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");
}
}
}
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 = PlayerTask.Iso8601ToTimestamp(response.lastDailyTaskAssigned);
// 清除现有任务
playerTasks.Clear();
assignedTaskDict.Clear();
// 转换并添加任务
foreach (var taskResponse in response.tasks)
{
PlayerTask playerTask = new PlayerTask(taskResponse);
playerTasks.Add(playerTask);
assignedTaskDict[playerTask.taskId] = playerTask;
Debug.Log($"已分配任务: {playerTask.taskId}");
}
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)
{
if (isClearPlayerTasks)
{
playerTasks.Clear();
isClearPlayerTasks = false;
}
// 准备要发送的数据
PlayerTaskSaveRequest saveData = new PlayerTaskSaveRequest();
// 转换任务数据
PlayerTaskResponse[] taskResponses = new PlayerTaskResponse[playerTasks.Count];
for (int i = 0; i < playerTasks.Count; i++)
{
taskResponses[i] = playerTasks[i].ToResponse();
}
Debug.Log($"{taskResponses.Length}");
saveData.tasks = taskResponses;
saveData.lastDailyTaskAssigned = PlayerTask.TimestampToIso8601(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 (res.success)
{
Debug.Log("玩家任务已保存到服务器");
ResetUIPanel();
CheckExpiredTasks(playerTasks);
}
else
{
Debug.LogWarning("未能将玩家任务保存到服务器:" + res.error+"错误码:"+res.status);
}
}
}
private void Update()
{
if (isClearPlayerTasks)
{
ClearAllSaveData();
}
if (Input.GetKeyDown(KeyCode.S))
{
CheckExpiredTasks(playerTasks);
SavePlayerData();
}
}
private void ClearAllSaveData()
{
if (!isClearPlayerTasks)
{
Debug.LogWarning("清除失败");
return;
}
playerTasks.Clear();
assignedTaskDict.Clear();
SavePlayerData();
Debug.Log("清除成功");
}
// 每日任务分配
public void AssignDailyTaskIfNeeded()
{
var now = DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(8)); // 北京时间
var last = DateTimeOffset.FromUnixTimeSeconds(lastDailyTaskAssigned).ToOffset(TimeSpan.FromHours(8));
// 如果还是同一天,并且任务已满,就不分配
if (now.Date == last.Date && assignedTaskDict.Count == maxTasks)
return;
// 如果已经跨天 -> 清空旧任务
if (now.Date != last.Date)
{
playerTasks.Clear();
assignedTaskDict.Clear();
Debug.Log("新的一天,清空旧任务");
// OnPlayerLogin();
}
// 检查是否达到上限
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 (!assignedTaskDict.ContainsKey(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.ToUnixTimeSeconds();
SavePlayerData();
Debug.Log($"分配任务: {selectedTask.name}");
}
// 检查并更新过期任务
public void CheckExpiredTasks(List tasksList)
{
long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); // 当前时间戳(秒)
foreach (var task in tasksList)
{
long unixTime = task.expireTime;
if (task.status == TaskStatus.Active && now > unixTime)
{
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)
{
UserData userData = Authenticator.Get().UserData;
// 根据奖励类型发放奖励
switch (rewardType)
{
case TaskRewardType.Coins:
// 增加金币(需要与游戏现有金币系统集成)
if (userData != null)
{
userData.coins += amount;
Debug.Log($"Gave {amount} coins as reward");
}
break;
case TaskRewardType.Crystal:
if (userData != null)
{
userData.crystal += amount;
Debug.Log($"获取{amount}个钻石");
}
break;
}
// 保存用户数据更新
if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn())
{
Authenticator.Get().SaveUserData();
}
}
private TaskData GetTaskConfig(string taskId)
{
TaskData[] allTasks;
if (taskConfigs!=null)
{
allTasks = taskConfigs.Values.ToArray();
}
else
{
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;
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)
{
SavePlayerData();
}
}
// 事件处理方法
private void OnGameStart()
{
// 进行对战任务进度+1
UpdateTaskProgress(TaskConditionType.PlayGames);
}
private void OnGameStart(LoginResponse login)
{
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 = assignedTaskDict.Values.Any(t =>
{
TaskData config = GetTaskConfig(t.taskId);
return config != null && config.condition == TaskConditionType.LoginGame;
});
Debug.Log("hasLoginTask:"+hasLoginTask);
// 如果没有登录任务,就分配一个
if (!hasLoginTask)
{
AssignLoginTask();
}
else
{
// 如过有就随机分配一个新任务
AssignDailyTaskIfNeeded();
}
}
///
/// 专门分配一个登录任务
///
private void AssignLoginTask()
{
TaskData[] allTasks;
if (taskConfigs != null)
{
allTasks = taskConfigs.Values.ToArray();
}
else
{
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}");
// 登录任务完成
UpdateTaskProgress(TaskConditionType.LoginGame);
}
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;
}
///
/// 重置面板
///
public void ResetUIPanel()
{
refreshTaskUI?.Invoke(playerTasks);
}
}
}