NetworkManager.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. using System;
  2. using System.Text;
  3. using System.Collections;
  4. using UnityEngine;
  5. using UnityEngine.Networking;
  6. public class NetworkManager : MonoBehaviour
  7. {
  8. public static NetworkManager Instance { get; private set; }
  9. [Header("服务器配置")]
  10. public string baseUrl = "http://38.12.23.48:8080/api";
  11. public float timeout = 30f;
  12. [Header("调试选项")]
  13. public bool enableDebugLog = true;
  14. private string authToken;
  15. private void Awake()
  16. {
  17. if (Instance == null)
  18. {
  19. Instance = this;
  20. DontDestroyOnLoad(gameObject);
  21. if (baseUrl.Contains("localhost") || baseUrl.Contains("127.0.0.1"))
  22. {
  23. baseUrl = "http://38.12.23.48:8080/api";
  24. Debug.Log($"[NetworkManager] baseUrl已更新为: {baseUrl}");
  25. }
  26. }
  27. else
  28. {
  29. Destroy(gameObject);
  30. }
  31. }
  32. public void SetAuthToken(string token)
  33. {
  34. authToken = token;
  35. }
  36. public void ClearAuthToken()
  37. {
  38. authToken = null;
  39. }
  40. public IEnumerator PostRequest<T>(string endpoint, object data, Action<T> onSuccess, Action<string> onError)
  41. {
  42. string url = baseUrl + endpoint;
  43. string jsonData = JsonUtility.ToJson(data);
  44. if (enableDebugLog)
  45. {
  46. Debug.Log($"[NetworkManager] POST 请求: {url}");
  47. Debug.Log($"[NetworkManager] 请求数据: {jsonData}");
  48. }
  49. UnityWebRequest request = new UnityWebRequest(url, "POST");
  50. byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonData);
  51. request.uploadHandler = new UploadHandlerRaw(bodyRaw);
  52. request.downloadHandler = new DownloadHandlerBuffer();
  53. request.SetRequestHeader("Content-Type", "application/json");
  54. request.SetRequestHeader("Accept", "application/json");
  55. if (!string.IsNullOrEmpty(authToken))
  56. {
  57. request.SetRequestHeader("Authorization", $"Bearer {authToken}");
  58. }
  59. request.timeout = (int)timeout;
  60. yield return request.SendWebRequest();
  61. if (enableDebugLog)
  62. {
  63. Debug.Log($"[NetworkManager] 响应码: {request.responseCode}");
  64. Debug.Log($"[NetworkManager] 响应内容: {request.downloadHandler?.text ?? "无内容"}");
  65. Debug.Log($"[NetworkManager] 错误: {request.error ?? "无错误"}");
  66. Debug.Log($"[NetworkManager] 结果类型: {request.result}");
  67. }
  68. if (request.result == UnityWebRequest.Result.Success)
  69. {
  70. string responseText = request.downloadHandler.text;
  71. Debug.Log($"[NetworkManager] POST {endpoint} 成功: {responseText}");
  72. try
  73. {
  74. T response = JsonUtility.FromJson<T>(responseText);
  75. onSuccess?.Invoke(response);
  76. }
  77. catch (Exception e)
  78. {
  79. Debug.LogError($"[NetworkManager] 解析响应失败: {e.Message}, 原始响应: {responseText}");
  80. onError?.Invoke($"解析响应失败: {e.Message}");
  81. }
  82. }
  83. else
  84. {
  85. string errorMessage = request.error ?? "网络请求失败";
  86. string responseText = request.downloadHandler?.text ?? "";
  87. Debug.LogError($"[NetworkManager] POST {endpoint} 失败: {errorMessage}, 响应码: {request.responseCode}, 响应: {responseText}");
  88. onError?.Invoke($"{errorMessage} (Code: {request.responseCode})");
  89. }
  90. request.Dispose();
  91. }
  92. public IEnumerator GetRequest<T>(string endpoint, Action<T> onSuccess, Action<string> onError)
  93. {
  94. string url = baseUrl + endpoint;
  95. using (UnityWebRequest request = UnityWebRequest.Get(url))
  96. {
  97. request.SetRequestHeader("Content-Type", "application/json");
  98. if (!string.IsNullOrEmpty(authToken))
  99. {
  100. request.SetRequestHeader("Authorization", $"Bearer {authToken}");
  101. }
  102. request.timeout = (int)timeout;
  103. yield return request.SendWebRequest();
  104. if (request.result == UnityWebRequest.Result.Success)
  105. {
  106. string responseText = request.downloadHandler.text;
  107. Debug.Log($"GET {endpoint} 响应: {responseText}");
  108. try
  109. {
  110. T response = JsonUtility.FromJson<T>(responseText);
  111. onSuccess?.Invoke(response);
  112. }
  113. catch (Exception e)
  114. {
  115. Debug.LogError($"解析响应失败: {e.Message}");
  116. onError?.Invoke($"解析响应失败: {e.Message}");
  117. }
  118. }
  119. else
  120. {
  121. string errorMessage = request.error ?? "网络请求失败";
  122. Debug.LogError($"GET {endpoint} 失败: {errorMessage}");
  123. onError?.Invoke(errorMessage);
  124. }
  125. }
  126. }
  127. public IEnumerator PutRequest<T>(string endpoint, object data, Action<T> onSuccess, Action<string> onError)
  128. {
  129. string url = baseUrl + endpoint;
  130. string jsonData = JsonUtility.ToJson(data);
  131. using (UnityWebRequest request = UnityWebRequest.Put(url, jsonData))
  132. {
  133. request.SetRequestHeader("Content-Type", "application/json");
  134. if (!string.IsNullOrEmpty(authToken))
  135. {
  136. request.SetRequestHeader("Authorization", $"Bearer {authToken}");
  137. }
  138. request.timeout = (int)timeout;
  139. yield return request.SendWebRequest();
  140. if (request.result == UnityWebRequest.Result.Success)
  141. {
  142. string responseText = request.downloadHandler.text;
  143. Debug.Log($"PUT {endpoint} 响应: {responseText}");
  144. try
  145. {
  146. T response = JsonUtility.FromJson<T>(responseText);
  147. onSuccess?.Invoke(response);
  148. }
  149. catch (Exception e)
  150. {
  151. Debug.LogError($"解析响应失败: {e.Message}");
  152. onError?.Invoke($"解析响应失败: {e.Message}");
  153. }
  154. }
  155. else
  156. {
  157. string errorMessage = request.error ?? "网络请求失败";
  158. Debug.LogError($"PUT {endpoint} 失败: {errorMessage}");
  159. onError?.Invoke(errorMessage);
  160. }
  161. }
  162. }
  163. public void SaveGameSession(float playTime, int progress, int difficulty, System.Action<GameSessionResponse> onSuccess, System.Action<string> onError)
  164. {
  165. GameSessionRequest request = new GameSessionRequest
  166. {
  167. playTime = playTime,
  168. progress = progress,
  169. difficulty = difficulty
  170. };
  171. StartCoroutine(PostRequest<GameSessionResponse>("/game/session", request, onSuccess, onError));
  172. }
  173. public void GetDifficultyConfig(System.Action<DifficultyConfigResponse> onSuccess, System.Action<string> onError)
  174. {
  175. StartCoroutine(GetRequest<DifficultyConfigResponse>("/game/difficulty", onSuccess, onError));
  176. }
  177. public void GetQuestionsByDifficulty(int difficulty, System.Action<QuestionListResponse> onSuccess, System.Action<string> onError)
  178. {
  179. StartCoroutine(GetRequest<QuestionListResponse>($"/game/questions?difficulty={difficulty}", onSuccess, onError));
  180. }
  181. public void SaveGameResult(GameResultRequest result, System.Action<GameResultResponse> onSuccess, System.Action<string> onError)
  182. {
  183. StartCoroutine(PostRequest<GameResultResponse>("/game/result", result, onSuccess, onError));
  184. }
  185. public void UpdateStudyAbility(int studyAbility, System.Action<StudyAbilityResponse> onSuccess, System.Action<string> onError)
  186. {
  187. StudyAbilityRequest request = new StudyAbilityRequest
  188. {
  189. studyAbility = studyAbility
  190. };
  191. StartCoroutine(PutRequest<StudyAbilityResponse>("/user/study-ability", request, onSuccess, onError));
  192. }
  193. public void SyncAchievements(AchievementSyncRequest request, System.Action<AchievementSyncResponse> onSuccess, System.Action<string> onError)
  194. {
  195. StartCoroutine(PostRequest<AchievementSyncResponse>("/achievements/sync", request, onSuccess, onError));
  196. }
  197. public void GetAchievements(System.Action<GetAchievementsResponse> onSuccess, System.Action<string> onError)
  198. {
  199. StartCoroutine(GetRequest<GetAchievementsResponse>("/achievements", onSuccess, onError));
  200. }
  201. public void GetUserProfile(System.Action<UserProfileResponse> onSuccess, System.Action<string> onError)
  202. {
  203. StartCoroutine(GetRequest<UserProfileResponse>("/user/profile", onSuccess, onError));
  204. }
  205. public void ReportQuestionStats(int questionId, bool isCorrect, int difficulty, System.Action<QuestionStatsResponse> onSuccess, System.Action<string> onError)
  206. {
  207. QuestionAttemptRequest request = new QuestionAttemptRequest
  208. {
  209. questionId = questionId,
  210. isCorrect = isCorrect,
  211. difficulty = difficulty,
  212. sourceType = "GAME"
  213. };
  214. StartCoroutine(PostRequest<QuestionStatsResponse>("/questions/attempts", request, onSuccess, onError));
  215. }
  216. public void UpdatePlayerLevel(int currentLevel, int experience, System.Action<LevelUpResponse> onSuccess, System.Action<string> onError)
  217. {
  218. LevelUpRequest request = new LevelUpRequest
  219. {
  220. currentLevel = currentLevel,
  221. experience = experience
  222. };
  223. StartCoroutine(PutRequest<LevelUpResponse>("/user/level", request, onSuccess, onError));
  224. }
  225. public void GetReviewQuestions(int difficulty, System.Action<QuestionListResponse> onSuccess, System.Action<string> onError)
  226. {
  227. StartCoroutine(GetRequest<QuestionListResponse>($"/game/review-questions?difficulty={difficulty}", onSuccess, onError));
  228. }
  229. public void AddQuestionToReview(int questionId, System.Action<BaseResponse> onSuccess, System.Action<string> onError)
  230. {
  231. AddReviewQuestionRequest request = new AddReviewQuestionRequest
  232. {
  233. questionId = questionId
  234. };
  235. StartCoroutine(PostRequest<BaseResponse>("/game/review-questions/add", request, onSuccess, onError));
  236. }
  237. }