LoginMgr.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. using AdaptUI;
  2. using AppUI;
  3. using AppUI.Bluetooth;
  4. using AppUI.Config;
  5. using AppUI.Localization;
  6. using AppUI.Manager;
  7. using AppUI.Manager.View;
  8. using AppUI.View.Component;
  9. using JCUnityLib;
  10. using Newtonsoft.Json;
  11. using System;
  12. using System.Collections;
  13. using System.Collections.Generic;
  14. using TMPro;
  15. using UnityEngine;
  16. using UnityEngine.SceneManagement;
  17. using UnityEngine.UI;
  18. /* 登录管理者,用户数据定义和存储 */
  19. public class LoginMgr : MonoBehaviour
  20. {
  21. [SerializeField] GameObject loginAndRegister;
  22. [SerializeField] GameObject loginView;
  23. [SerializeField] GameObject registerView;
  24. [SerializeField] GameObject loginView_iPad;
  25. [SerializeField] GameObject registerView_iPad;
  26. public static UserInfo myUserInfo = new UserInfo();
  27. /// <summary>Entry 冷启动 Token 校验失败时,进入 Login 场景后弹一次提示。</summary>
  28. public enum BootLoginTipKind { None, NetworkError, AuthExpired }
  29. public static BootLoginTipKind PendingBootLoginTip;
  30. const string VersionTextKey = "appui-login-version";
  31. [SerializeField]
  32. TMP_Text deviceInfo;
  33. [SerializeField]
  34. Text deviceInfoLegacy;
  35. AppUITextAutoLanguage _deviceInfoLocalized;
  36. AppUITextAutoLanguage _deviceInfoLegacyLocalized;
  37. public void showRegisterView()
  38. {
  39. // loginView.SetActive(false);
  40. // registerView.SetActive(true);
  41. //获取设备类型
  42. DeviceTypeHelper.DeviceType detectedType = DeviceTypeHelper.DetectDeviceType();
  43. //Debug.Log($"showRegisterView设备类型: {detectedType}");
  44. //根据设备类型显示不同的登录界面
  45. if(detectedType == DeviceTypeHelper.DeviceType.iPad)
  46. {
  47. loginView_iPad.SetActive(false);
  48. registerView_iPad.SetActive(true);
  49. }
  50. else
  51. {
  52. loginView.SetActive(false);
  53. registerView.SetActive(true);
  54. }
  55. //AgreenmentOption.ins.gameObject.SetActive(true);
  56. //UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(AgreenmentOption.ins.gameObject.GetComponent<RectTransform>());
  57. }
  58. public void showLoginView()
  59. {
  60. //loginView.SetActive(true);
  61. //registerView.SetActive(false);
  62. DeviceTypeHelper.DeviceType detectedType = DeviceTypeHelper.DetectDeviceType();
  63. Debug.Log($"[LoginMgr]showLoginView设备类型: {detectedType}");
  64. //根据设备类型显示不同的登录界面
  65. loginAndRegister.SetActive(true);
  66. if (detectedType == DeviceTypeHelper.DeviceType.iPad)
  67. {
  68. loginView.SetActive(false);
  69. loginView_iPad.SetActive(true);
  70. registerView_iPad.SetActive(false);
  71. }
  72. else
  73. {
  74. loginView.SetActive(true);
  75. loginView_iPad.SetActive(false);
  76. registerView.SetActive(false);
  77. }
  78. //AgreenmentOption.ins.gameObject.SetActive(true);
  79. RefreshDeviceInfoText(AppUILocalization.GetLanguage());
  80. }
  81. public void showGuestView()
  82. {
  83. ModuleGuestView guestView = ModuleGuestView.Show();
  84. guestView.onLogin = () =>
  85. {
  86. //切换到登陆UI
  87. };
  88. guestView.onSignUp = () =>
  89. {
  90. //切换到注册
  91. showRegisterView();
  92. };
  93. guestView.onGuestMode = () =>
  94. {
  95. //进入访客模式
  96. entryGuestMode();
  97. };
  98. }
  99. public void entryGuestMode()
  100. {
  101. CommonConfig.StandaloneMode = true;
  102. ScreenOrientationHelper.SwitchToLandscapeAndLoadScene("Home");
  103. }
  104. public void showForgetPWD_View()
  105. {
  106. Instantiate(ViewManager.GetPrefabByType(UIPrefabType.RetrievePasswordView));
  107. //Instantiate(SceneResourceManager.Instance.GetPrefab("RetrievePasswordView"));
  108. }
  109. public const string LoginTokenKey = "LoginToken";
  110. public static bool HasToken()
  111. {
  112. string loginToken = PlayerPrefs.GetString(LoginMgr.LoginTokenKey, "");
  113. return string.IsNullOrEmpty(loginToken) ? false : true;
  114. }
  115. void Awake()
  116. {
  117. AppUILocalization.Init();
  118. TryAutoBindDeviceInfo();
  119. ResolveDeviceInfoLocalized();
  120. transform.Find("AgreementPopup").gameObject.SetActive(true);
  121. //ViewMgr.Instance.DestroyAllViews();
  122. }
  123. void OnEnable()
  124. {
  125. TryAutoBindDeviceInfo();
  126. ResolveDeviceInfoLocalized();
  127. AppUILocalization.OnLanguageChanged += RefreshDeviceInfoText;
  128. RefreshDeviceInfoText(AppUILocalization.GetLanguage());
  129. }
  130. void OnDisable()
  131. {
  132. AppUILocalization.OnLanguageChanged -= RefreshDeviceInfoText;
  133. }
  134. //#if UNITY_EDITOR
  135. // void OnValidate()
  136. // {
  137. // TryAutoBindDeviceInfo();
  138. // ResolveDeviceInfoLocalized();
  139. // if (!Application.isPlaying)
  140. // RefreshDeviceInfoText(AppUILocalization.GetLanguage());
  141. // }
  142. //#endif
  143. void Start()
  144. {
  145. //显示登录界面
  146. showLoginView();
  147. RefreshDeviceInfoText(AppUILocalization.GetLanguage());
  148. ShowPendingBootLoginTipIfAny();
  149. //退出到登录界面,也要把蓝牙断开
  150. if (SmartBowDeviceHub.ins) {
  151. if (SmartBowDeviceHub.ins.GetSdkStatus(BluetoothPlayer.FIRST_PLAYER) == SmartBowSDK.BluetoothStatusEnum.Connected) SmartBowDeviceHub.ins.Ble.DoConnect();
  152. else SmartBowDeviceHub.ins.Ble.connectCanceled = true;
  153. }
  154. }
  155. void ShowPendingBootLoginTipIfAny()
  156. {
  157. if (PendingBootLoginTip == BootLoginTipKind.None)
  158. return;
  159. BootLoginTipKind tipKind = PendingBootLoginTip;
  160. PendingBootLoginTip = BootLoginTipKind.None;
  161. StartCoroutine(ShowBootLoginTipDelayed(tipKind));
  162. }
  163. IEnumerator ShowBootLoginTipDelayed(BootLoginTipKind tipKind)
  164. {
  165. yield return null;
  166. string message = tipKind switch
  167. {
  168. BootLoginTipKind.NetworkError => AppUILocalization.GetTextByKey("appui-net-loginAuthFail"),
  169. BootLoginTipKind.AuthExpired => AppUILocalization.GetTextByKey("appui-net-loginExpired"),
  170. _ => null
  171. };
  172. if (!string.IsNullOrEmpty(message))
  173. ModuleViewMgr.ins.Show(message);
  174. }
  175. void TryAutoBindDeviceInfo()
  176. {
  177. if (loginAndRegister == null)
  178. return;
  179. foreach (Transform tr in loginAndRegister.GetComponentsInChildren<Transform>(true))
  180. {
  181. if (deviceInfo == null && tr.name == "Info (TMP)")
  182. {
  183. TMP_Text tmp = tr.GetComponent<TMP_Text>();
  184. if (tmp != null)
  185. deviceInfo = tmp;
  186. }
  187. if (deviceInfoLegacy == null && tr.name == "Info")
  188. {
  189. Text legacy = tr.GetComponent<Text>();
  190. if (legacy != null)
  191. deviceInfoLegacy = legacy;
  192. }
  193. }
  194. }
  195. void ResolveDeviceInfoLocalized()
  196. {
  197. if (deviceInfo != null)
  198. _deviceInfoLocalized = deviceInfo.GetComponent<AppUITextAutoLanguage>();
  199. if (deviceInfoLegacy != null)
  200. _deviceInfoLegacyLocalized = deviceInfoLegacy.GetComponent<AppUITextAutoLanguage>();
  201. }
  202. void RefreshDeviceInfoText(LanguageEnum _)
  203. {
  204. RefreshVersionText(deviceInfo, ref _deviceInfoLocalized);
  205. RefreshVersionText(deviceInfoLegacy, ref _deviceInfoLegacyLocalized);
  206. }
  207. void RefreshVersionText(TMP_Text text, ref AppUITextAutoLanguage localized)
  208. {
  209. if (text == null)
  210. return;
  211. string platform = GlobalConfig.GetPlatformDisplayName();
  212. string version = Application.version;
  213. #if UNITY_EDITOR
  214. if (!Application.isPlaying && string.IsNullOrEmpty(version))
  215. version = "1.0.0";
  216. #endif
  217. if (localized != null)
  218. {
  219. localized.textFormatArgs = new object[] { platform, version };
  220. if (string.IsNullOrEmpty(localized.GetTextKey()))
  221. localized.SetTextKey(VersionTextKey);
  222. else
  223. localized.ApplyToText();
  224. return;
  225. }
  226. text.text = string.Format(
  227. AppUILocalization.GetTextByKey(VersionTextKey),
  228. platform,
  229. version);
  230. }
  231. void RefreshVersionText(Text text, ref AppUITextAutoLanguage localized)
  232. {
  233. if (text == null)
  234. return;
  235. string platform = GlobalConfig.GetPlatformDisplayName();
  236. string version = Application.version;
  237. #if UNITY_EDITOR
  238. if (!Application.isPlaying && string.IsNullOrEmpty(version))
  239. version = "1.0.0";
  240. #endif
  241. if (localized != null)
  242. {
  243. localized.textFormatArgs = new object[] { platform, version };
  244. if (string.IsNullOrEmpty(localized.GetTextKey()))
  245. localized.SetTextKey(VersionTextKey);
  246. else
  247. localized.ApplyToText();
  248. return;
  249. }
  250. text.text = string.Format(
  251. AppUILocalization.GetTextByKey(VersionTextKey),
  252. platform,
  253. version);
  254. }
  255. }
  256. public class UserInfo
  257. {
  258. public int id;
  259. public int avatarID = 0;
  260. public string avatarUrl = "";
  261. public string nickname = "超级射手";
  262. public int gender = 1;
  263. public string phone = "";
  264. public string email = "";
  265. public string birthday = "";
  266. public string country = "";
  267. public string state = "";
  268. public string city = "";
  269. public int integral = 0;
  270. public int coin = 0;
  271. public int diamond = 1000;
  272. public string mac = "";
  273. public List<PropInfo> bagList = new List<PropInfo>();
  274. public List<DeviceInfo> deviceList = new List<DeviceInfo>();
  275. /// <summary>
  276. /// 显示游戏最高分(不同距离分数独立)
  277. /// 2023-7-16兼容WildAttack最高分纪录
  278. /// </summary>
  279. public Dictionary<string, float> timeLimitGameScores = new Dictionary<string, float>();
  280. //闯关记录(gameType:通关数)(野兔、野鸡、野狼的通关数)
  281. public Dictionary<int, int> challengeLevels = new Dictionary<int, int>();
  282. public string guideRecord = "";
  283. public static UserInfo LoadLocal(int id)
  284. {
  285. UserInfo result = null;
  286. if (CommonConfig.StandaloneMode)
  287. {
  288. try
  289. {
  290. result = JsonConvert.DeserializeObject<UserInfo>(PlayerPrefs.GetString("UserInfo_" + id));
  291. if (result == null) throw new Exception("UserInfo.LoadLocal Null");
  292. }
  293. catch (Exception e)
  294. {
  295. Debug.LogError(e);
  296. }
  297. }
  298. return result;
  299. }
  300. public void Save()
  301. {
  302. if (CommonConfig.StandaloneMode)
  303. {
  304. PlayerPrefs.SetString("UserInfo_" + id, JsonConvert.SerializeObject(this));
  305. return;
  306. }
  307. try { UserComp.Instance.saveUserInfo(this); } catch (System.Exception e) { Debug.LogError(e.Message); }
  308. }
  309. public void SetChallengeLevelPass(int gameType, int level)
  310. {
  311. if (gameType != 3 && gameType != 4 && gameType != 5) return;
  312. if (challengeLevels.ContainsKey(gameType))
  313. {
  314. if (level <= challengeLevels[gameType])
  315. {
  316. return;
  317. }
  318. }
  319. challengeLevels.Remove(gameType);
  320. challengeLevels.Add(gameType, level);
  321. }
  322. public int GetChallengeLevelPass(int gameType)
  323. {
  324. if (challengeLevels.ContainsKey(gameType))
  325. {
  326. return challengeLevels[gameType];
  327. }
  328. return 0;
  329. }
  330. //判断引导是否完成(服务端保存)
  331. //index0: 新手引导NewUserGuide
  332. public bool IsGuideFinish(int index)
  333. {
  334. if (index == 0)
  335. {
  336. return PlayerPrefs.GetInt("NewUserGuideFinish_" + LoginMgr.myUserInfo.id, 0) == 1;
  337. }
  338. char[] chars = guideRecord.ToCharArray();
  339. if (index < chars.Length)
  340. {
  341. return chars[index] == '1';
  342. }
  343. return false;
  344. }
  345. public void SaveGuideFinish(int index)
  346. {
  347. if (index == 0)
  348. {
  349. PlayerPrefs.SetInt("NewUserGuideFinish_" + LoginMgr.myUserInfo.id, 1);
  350. return;
  351. }
  352. char[] chars = guideRecord.ToCharArray();
  353. if (index < chars.Length)
  354. {
  355. if (chars[index] == '1') return;
  356. chars[index] = '1';
  357. }
  358. else
  359. {
  360. int newLen = index + 1;
  361. char[] newChars = new char[newLen];
  362. for (int i = 0; i < newLen; i++)
  363. {
  364. newChars[i] = i < chars.Length ? chars[i] : '0';
  365. }
  366. newChars[index] = '1';
  367. chars = newChars;
  368. }
  369. this.guideRecord = string.Join("", chars);
  370. UserPlayer.ins?.call("userComp.saveGuideRecord", this.guideRecord);
  371. }
  372. }
  373. public class UserSettings
  374. {
  375. //打开BGM
  376. public bool openBGM = true;
  377. //打开音效
  378. public bool openEffect = true;
  379. //是否打开准心
  380. public bool openCrossHair = true;
  381. //射击难度
  382. public int shootLevel = 0;
  383. //游戏里的箭重,单位克
  384. public float actualArrowWeight = 20;
  385. //弓箭旋转转化
  386. public BowRotateConvert bowRotateConvert = new BowRotateConvert();
  387. //游戏中是否固定镜头
  388. public bool bowCameraFixed = true;
  389. //训练模式
  390. public bool trainMode = false;
  391. //游戏里面视角重置时间(3秒改成默认5秒)
  392. public float calibrationTime = 5f;
  393. //游戏里面的弓箭手臂(在所有游戏中,游戏设置里的‘手臂弓箭’这个选项,默认为关;即在游戏中,不出现手臂和弓箭的模型)
  394. public bool openBowAndArrow = false;
  395. //选择的红外连接设备
  396. public string selectDevicesName = "";
  397. //b端 每一局的设置
  398. public int PerRoundCoin = 2; //投币
  399. public int PerRoundSeconds = 1200;//时间
  400. //设备校准引导-是否已经完成
  401. public bool deviceCalibrateGuideFinish = false;
  402. //游戏规则引导-是否已经完成(完成则保存对应的GameType)
  403. public HashSet<int> gameRuleGuideFinish = new HashSet<int>();
  404. private static UserSettings _ins;
  405. public static UserSettings ins
  406. {
  407. get
  408. {
  409. if (_ins == null)
  410. {
  411. string dataStr = PlayerPrefs.GetString("UserSettings", "{}");
  412. try
  413. {
  414. _ins = JsonConvert.DeserializeObject<UserSettings>(dataStr);
  415. }
  416. catch (System.Exception) { }
  417. if (_ins == null)
  418. {
  419. _ins = new UserSettings();
  420. }
  421. if (CommonConfig.SpecialVersion1)
  422. {
  423. if (PlayerPrefs.GetInt("sv1_UserSettings_2", 0) == 0)
  424. {
  425. PlayerPrefs.SetInt("sv1_UserSettings_2", 1);
  426. UserSettings us = _ins;
  427. us.bowRotateConvert.screenSize = 60;
  428. us.bowRotateConvert.screenDistance = 1.5f;
  429. us.Save();
  430. }
  431. }
  432. }
  433. return _ins;
  434. }
  435. }
  436. public void Save()
  437. {
  438. PlayerPrefs.SetString("UserSettings", JsonConvert.SerializeObject(this));
  439. }
  440. }
  441. /*
  442. 描述1
  443. 已知:
  444. 屏幕宽高比例w:h=16:9,屏幕尺寸s=60.11英寸,屏幕距离d=2.50米,实际指向右边树的角度为e=5.56°。
  445. 可知:
  446. 屏幕尺寸s1 = (s * 0.0254)米
  447. 屏幕单位大小为unit,关系式(w*unit)^2 + (h*unit)^2 = s1^2
  448. 结果:
  449. 向量(玩家->右边树)在屏幕上投影的长度比例q = tan(e) * d / unit
  450. */
  451. /*
  452. 描述2(适配各种尺寸的屏幕)
  453. 已知:
  454. 屏幕宽高比例w:h=16:9,屏幕尺寸s=(任意)英寸,屏幕距离d=(任意)米,游戏指向右边树的角度为r=27.30°。
  455. 借用描述1的结果q
  456. 可知:
  457. 屏幕尺寸s1 = (s * 0.0254)米
  458. 屏幕单位大小为unit,关系式(w*unit)^2 + (h*unit)^2 = s1^2
  459. 实际指向右边树的角度为e = atan(q * unit / d)
  460. 结果:
  461. 游戏转动角度:实际转动角度 = r / e
  462. */
  463. public class BowRotateConvert
  464. {
  465. public float screenSize = 60; //屏幕尺寸(英寸)
  466. public float screenDistance = 2.5f; //玩家距离屏幕多远(米)
  467. [NonSerialized] public float fieldOfView = 25;
  468. //获取建议的屏幕距离
  469. public float GetAdviseScreenDistance()
  470. {
  471. float w = 16;
  472. float h = 9;
  473. float s1 = screenSize * 0.0254f;
  474. float unit = s1 / Mathf.Sqrt(w * w + h * h);
  475. float screenHeight = 9 * unit;
  476. return screenHeight * 0.5f / Mathf.Tan(fieldOfView / 2 / 180 * Mathf.PI);
  477. }
  478. // 游戏旋转角度 : 实际旋转角度 (这个版本丢弃掉这个功能-所以直接返回1)
  479. public float GetRate()
  480. {
  481. return 1;
  482. }
  483. // 游戏旋转角度 : 实际旋转角度
  484. // public float GetRate() {
  485. // double w = 16;
  486. // double h = 9;
  487. // double s = Convert.ToDouble(screenSize);
  488. // double d = Convert.ToDouble(screenDistance);
  489. // double r = 27.3 / 180 * Math.PI;
  490. // double q = get_q();
  491. // double s1 = s * 0.0254;
  492. // double unit = Math.Sqrt(Math.Pow(s1, 2) / (Math.Pow(w, 2) + Math.Pow(h, 2)));
  493. // double e = Math.Atan(q * unit / d);
  494. // return (float) (r / e);
  495. // }
  496. // private double get_q() {
  497. // double w = 16;
  498. // double h = 9;
  499. // double s = 60.11;
  500. // double d = 2.5;
  501. // double e = 5.56 / 180 * Math.PI;
  502. // double s1 = s * 0.0254;
  503. // double unit = Math.Sqrt(Math.Pow(s1, 2) / (Math.Pow(w, 2) + Math.Pow(h, 2)));
  504. // double q = Math.Tan(e) * d / unit;
  505. // return q;
  506. // }
  507. }