LoginController.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. using System;
  2. using UnityEngine;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using Newtonsoft.Json;
  6. using UnityEngine.SceneManagement;
  7. using Cinemachine;
  8. using UnityEngine.UI;
  9. using TMPro;
  10. /* 使用login token进行登录和数据读取保存
  11. * TestDataInjection 是测试用的假数据注入
  12. * LoginTokenCheck 验证login token是否有效,和服务器比对
  13. * 比较版本是否可以符合游戏可以允许最低版本
  14. * 弹出用户注册窗口
  15. */
  16. public class LoginController : MonoBehaviour
  17. {
  18. // Start is called once before the first execution of Update after the MonoBehaviour is created
  19. private GameObject canvasPlaceholder, regCanvas, createAdoptCanvas, loginCanvas;
  20. public static LoginController instance; // 用于在其他脚本中调用LoginController的函数
  21. private void Awake()
  22. {
  23. // 确保loginController在Awake阶段被正确赋值
  24. if (instance == null)
  25. {
  26. instance = this;
  27. }
  28. }
  29. void Start()
  30. {
  31. canvasPlaceholder = GameObject.Find("Canvas Placeholder");
  32. regCanvas = canvasPlaceholder.transform.Find("Register Canvas").gameObject;
  33. createAdoptCanvas = canvasPlaceholder.transform.Find("Create Or Adopt Canvas").gameObject;
  34. loginCanvas = canvasPlaceholder.transform.Find("Login Canvas").gameObject;
  35. StartCoroutine(PingServer());
  36. // 判断是否要切换到注册狗的子场景
  37. if (GameData.subScene == "Login_InitDog")
  38. {
  39. SwitchToInitDogScene();
  40. GameData.subScene = null;
  41. }
  42. else
  43. {
  44. //启动自动采用Login Token 登录。其他登录方式为手动登录。
  45. StartCoroutine(LoginTokenRequest());
  46. }
  47. }
  48. // Update is called once per frame
  49. //void Update()
  50. //{
  51. //}
  52. // 检测是否可以ping到服务器
  53. IEnumerator PingServer()
  54. {
  55. Uri uri = new Uri(EnviromentSetting.serverIP);
  56. var ping = new Ping(uri.Host);
  57. float pingStartTime = Time.time;
  58. while (!ping.isDone)
  59. {
  60. yield return null;
  61. }
  62. if (ping.time == -1)
  63. {
  64. Debug.LogError("Ping失败");
  65. string textValue = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "network_error", EnviromentSetting.languageCode });
  66. MessageBoxController.ShowMessage(textValue, ShutDown);
  67. }
  68. }
  69. // LoginToken登录方法
  70. IEnumerator LoginTokenRequest()
  71. {
  72. Debug.Log("LoginToken Request start");
  73. string UUID = SystemInfo.deviceUniqueIdentifier; // 这里需要考虑这段代码执行在Enviroment Controller之前
  74. string LoginToken = PlayerPrefs.GetString("LoginToken", null);
  75. string LoginTokenTime = PlayerPrefs.GetString("LoginTokenTime", null);
  76. // 比较LoginTokenTime 如果超时直接放弃后面代码。比较UUID是否是null如果是直接放弃后面代码
  77. if (LoginToken == null) { yield break; }
  78. ;
  79. if (LoginTokenTime == null) { yield break; }
  80. ;
  81. DateTime tokenTime;
  82. DateTime now = DateTime.Now;
  83. if (DateTime.TryParse(LoginTokenTime, out tokenTime))
  84. {
  85. TimeSpan span = now - tokenTime;
  86. if (span.TotalHours > 7 * 24)
  87. {
  88. yield break;
  89. }
  90. }
  91. else { yield break; }
  92. // 提交POST
  93. string url = "/api/login/token/";
  94. WWWForm form = new();
  95. form.AddField("login_token", LoginToken);
  96. form.AddField("UUID", UUID);
  97. StartCoroutine(WebController.PostRequest(url, form, callback: LoginTokenCallback));
  98. }
  99. // Post之后callback的函数
  100. void LoginTokenCallback(string json)
  101. {
  102. LoginSucessHandler(json);
  103. if (UserProperty.userId != null && EnviromentSetting.accessToken != null)
  104. {
  105. // 启动获取用户信息请求
  106. GetUserData();
  107. }
  108. else
  109. {
  110. Debug.Log("LoginTokenCallback 登陆失败");
  111. Debug.Log(json);
  112. }
  113. }
  114. void LoginSucessHandler(string json)
  115. {
  116. var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  117. if (data != null && data["status"] == "success")
  118. {
  119. Debug.Log("Login Token sucess!");
  120. PlayerPrefs.SetString("LoginToken", data["login_token"]);
  121. PlayerPrefs.SetString("LoginTokenTime", DateTime.Now.ToString());
  122. EnviromentSetting.accessToken = data["access_token"];
  123. EnviromentSetting.accessTokenReceivedTime = DateTime.Now;
  124. UserProperty.userId = data["user_id"];
  125. // 比较游戏版本
  126. // TODO 等后台更改后删除
  127. //string allowed_client_ver = data["allowed_client_ver"];
  128. string allowed_client_ver = "0.1";
  129. string current_ver = EnviromentSetting.version;
  130. Version curVer = new Version(current_ver);
  131. Version allowVer = new Version(allowed_client_ver);
  132. int verCompare = curVer.CompareTo(allowVer);
  133. if (verCompare < 0)
  134. {
  135. // 弹窗,然后退出
  136. string err_msg;
  137. if (EnviromentSetting.platform == "IPhonePlayer")
  138. {
  139. err_msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "not_allow_version_IOS", EnviromentSetting.languageCode });
  140. }
  141. else if (EnviromentSetting.platform == "Android")
  142. {
  143. if (EnviromentSetting.languageCode == "zh-cn") // 安卓中文环境
  144. {
  145. err_msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "not_allow_version_Andriod_CN", EnviromentSetting.languageCode });
  146. }
  147. else
  148. {
  149. // 安卓其他语言
  150. err_msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "not_allow_version_Andriod_WW", EnviromentSetting.languageCode });
  151. }
  152. }
  153. else
  154. {
  155. // 不明操作系统
  156. err_msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "not_allow_version_Generic", EnviromentSetting.languageCode });
  157. }
  158. MessageBoxController.ShowMessage(err_msg, ShutDown);
  159. }
  160. }
  161. else
  162. {
  163. Debug.Log("Login Token fail!");
  164. Debug.Log(json);
  165. }
  166. }
  167. // 当版本检查不符合游戏时退出游戏
  168. public void ShutDown()
  169. {
  170. Application.Quit();
  171. }
  172. public void GetUserData()
  173. {
  174. Debug.Log("GetUserData request");
  175. // 提交POST
  176. string url = "/api/user/info/";
  177. WWWForm form = new();
  178. form.AddField("user_id", UserProperty.userId);
  179. StartCoroutine(WebController.PostRequest(url, form, callback: GetUserDataCallback));
  180. }
  181. void GetUserDataCallback(string json)
  182. {
  183. var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
  184. if (data != null && data["status"].ToString() == "success")
  185. {
  186. var user_info = data["user_info"].ToString();
  187. UserProperty.RefreshUserInfo(user_info);
  188. var user_info_dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(user_info);
  189. // todo 将用户运行环境保存到设定中
  190. // EnviromentSetting.runEnv = user_info_dict["runEnv"].ToString();
  191. // 保存狗的数据
  192. string dogsJson = data["dogs"].ToString();
  193. UserProperty.RefreshDogInfo(dogsJson);
  194. // 保存道具数据
  195. UserProperty.RefreshUserItems(data["props"].ToString());
  196. // 判断用户狗的数量,如果为0就跳转用户创建狗。
  197. if (UserProperty.dogs.Count < 1)
  198. {
  199. SwitchToInitDogScene();
  200. }
  201. // 如果非注册用户,提示用户注册
  202. else if (!UserProperty.isRegUser)
  203. {
  204. // 如果没有提醒过
  205. if (!GameData.hasRemindedRegister)
  206. {
  207. GameData.hasRemindedRegister = true;
  208. var canvasPlaceholder = GameObject.Find("Canvas Placeholder");
  209. var loginCanvas = canvasPlaceholder.transform.Find("Login Canvas").gameObject;
  210. loginCanvas.SetActive(false);
  211. string msg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "reg_reminder", EnviromentSetting.languageCode });
  212. //MessageBoxController.YorN_Message(msg, ()=> regCanvas.SetActive(true), ()=> SceneManager.LoadScene("Home"));
  213. MessageBoxController.YorN_Message(msg, () => regCanvas.SetActive(true), () => MaskTransitions.TransitionManager.Instance.LoadLevel("Home"));
  214. }
  215. else
  216. {
  217. MaskTransitions.TransitionManager.Instance.LoadLevel("Home");
  218. }
  219. }
  220. else
  221. {
  222. ShowStartGameUI();
  223. }
  224. }
  225. else
  226. {
  227. Debug.Log(data["message"]);
  228. }
  229. }
  230. void ShowStartGameUI()
  231. {
  232. var uiPlaceholder = GameObject.Find("Canvas Placeholder");
  233. if (uiPlaceholder != null)
  234. {
  235. var startGameUI = uiPlaceholder.transform.Find("Start Game Canvas").gameObject;
  236. startGameUI.SetActive(true);
  237. var loginCanvas = uiPlaceholder.transform.Find("Login Canvas").gameObject;
  238. loginCanvas.SetActive(false);
  239. }
  240. }
  241. // Quick Start 登录方式,用UUID换取Login Token
  242. public void QuickStart()
  243. {
  244. Debug.Log("Quick start post request.");
  245. string url = "/api/game/quick_start/";
  246. Dictionary<string, string> formData = new();
  247. WWWForm form = new();
  248. form.AddField("UUID", EnviromentSetting.UUID);
  249. StartCoroutine(WebController.PostRequest(url, form, callback: QuickStartCallback));
  250. }
  251. void QuickStartCallback(string json)
  252. {
  253. var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  254. if (data != null && data["status"] == "success")
  255. {
  256. PlayerPrefs.SetString("LoginToken", data["login_token"]);
  257. PlayerPrefs.SetString("LoginTokenTime", DateTime.Now.ToString());
  258. UserProperty.userId = data["user_id"];
  259. StartCoroutine(LoginTokenRequest());
  260. }
  261. else
  262. {
  263. string errMsg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "login_fail", EnviromentSetting.languageCode });
  264. MessageBoxController.ShowMessage(errMsg);
  265. }
  266. }
  267. public void ResetPassword()
  268. {
  269. var uiPlaceholder = GameObject.Find("Canvas Placeholder");
  270. if (uiPlaceholder != null)
  271. {
  272. var resetUI = uiPlaceholder.transform.Find("Reset Pasword").gameObject;
  273. var loginCanvas = uiPlaceholder.transform.Find("Login Canvas").gameObject;
  274. resetUI.SetActive(true);
  275. loginCanvas.SetActive(false);
  276. }
  277. }
  278. // 切换到生成狗的子场景
  279. void SwitchToInitDogScene()
  280. {
  281. createAdoptCanvas.SetActive(true);
  282. loginCanvas.SetActive(false);
  283. regCanvas.SetActive(false);
  284. var loginCam = GameObject.Find("V Cam Login").GetComponent<CinemachineVirtualCamera>();
  285. var initDogCam = GameObject.Find("V Cam Init Dog").GetComponent<CinemachineVirtualCamera>();
  286. loginCam.Priority = 0;
  287. initDogCam.Priority = 10;
  288. }
  289. // 使用账户密码登录方法
  290. public void Login()
  291. {
  292. string account = GameObject.Find("Account input").GetComponent<TMP_InputField>().text;
  293. string password = GameObject.Find("Password input").GetComponent<TMP_InputField>().text;
  294. string url = "/api/login/";
  295. Dictionary<string, string> formData = new();
  296. WWWForm form = new();
  297. form.AddField("client_language", EnviromentSetting.languageCode);
  298. if (EnviromentSetting.languageCode == "zh-cn")
  299. {
  300. form.AddField("mobile_number", account.Trim());
  301. }
  302. else
  303. {
  304. form.AddField("email", account.Trim());
  305. }
  306. form.AddField("password", password.Trim());
  307. StartCoroutine(WebController.PostRequest(url, form, callback: LoginCallback));
  308. }
  309. void LoginCallback(string json)
  310. {
  311. var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
  312. if (data != null && data["status"].ToString() == "success")
  313. {
  314. LoginSucessHandler(json);
  315. if (UserProperty.userId != null && EnviromentSetting.accessToken != null)
  316. {
  317. // 启动获取用户信息请求
  318. GetUserData();
  319. }
  320. else
  321. {
  322. Debug.Log("LoginTokenCallback 登陆失败");
  323. Debug.Log(json);
  324. }
  325. }
  326. else
  327. {
  328. string errMsg = GameTool.GetValueAtPath(EnviromentSetting.languageData, new string[] { "game_message", "login_fail", EnviromentSetting.languageCode });
  329. MessageBoxController.ShowMessage(errMsg);
  330. }
  331. }
  332. }