您不能選擇超過 %s 個話題 話題必須以字母或數字為開頭,可包含連接號 ('-') 且最長為 35 個字
 
 
 

353 行
14 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net.Sockets;
  4. using System.Net;
  5. using CIG;
  6. using CIG.Extensions;
  7. using CIG.Translation;
  8. using CIG3.ExtensionMethods;
  9. using CIGEnums;
  10. using Cysharp.Threading.Tasks;
  11. using SUISS.Core;
  12. using SUISSEngine;
  13. using UnityEngine;
  14. using UnityEngine.Purchasing;
  15. public class ShopPopupState : PopupBaseState
  16. {
  17. public override void Enter(State oldState)
  18. {
  19. base.Enter(oldState);
  20. if (SingletonMonobehaviour<CIGPurchasedBuildingsManager>.IsAvailable && SingletonMonobehaviour<GameObjectManager>.IsAvailable)
  21. {
  22. GameObjectManager instance = SingletonMonobehaviour<GameObjectManager>.Instance;
  23. Dictionary<string, int> unconsumedBuildings = SingletonMonobehaviour<CIGPurchasedBuildingsManager>.Instance.GetUnconsumedBuildings();
  24. Dictionary<ShopMenuTabs, int> dictionary = new Dictionary<ShopMenuTabs, int>();
  25. foreach (KeyValuePair<string, int> keyValuePair in unconsumedBuildings)
  26. {
  27. if (keyValuePair.Value > 0)
  28. {
  29. CIGBuilding building = instance.GetBuilding(keyValuePair.Key);
  30. if (building != null)
  31. {
  32. Type type = building.GetType();
  33. if (ShopPopupState.BuildingTypesWithBadgesToShopMenuTabMapping.ContainsKey(type))
  34. {
  35. ShopMenuTabs shopMenuTabs = ShopPopupState.BuildingTypesWithBadgesToShopMenuTabMapping[type];
  36. if (!dictionary.ContainsKey(shopMenuTabs))
  37. {
  38. dictionary[shopMenuTabs] = 0;
  39. }
  40. (dictionary)[shopMenuTabs] = dictionary[shopMenuTabs] + keyValuePair.Value;
  41. }
  42. }
  43. }
  44. }
  45. foreach (KeyValuePair<Type, ShopMenuTabs> keyValuePair2 in ShopPopupState.BuildingTypesWithBadgesToShopMenuTabMapping)
  46. {
  47. ShopMenuTabs value = keyValuePair2.Value;
  48. ((ShopPopupView)this.View).UpdateBadge(value, (!dictionary.ContainsKey(value)) ? 0 : dictionary[value]);
  49. }
  50. }
  51. ((ShopPopupView)this.View).UpdateBadge(ShopMenuTabs.Cash, SingletonMonobehaviour<CIGSaleManager>.Instance.CurrentSale.Cash);
  52. ((ShopPopupView)this.View).UpdateBadge(ShopMenuTabs.Gold, SingletonMonobehaviour<CIGSaleManager>.Instance.CurrentSale.Gold);
  53. }
  54. public void OpenPopup(ShopMenuTabs shopMenuTab, bool reopenLastTab = false)
  55. {
  56. this.InvokeNextFrame(delegate
  57. {
  58. this.SwitchTab(shopMenuTab, true, reopenLastTab);
  59. });
  60. }
  61. public void SwitchTab(ShopMenuTabs shopMenuTab, bool forceUpdate = true, bool reopenLastTab = false)
  62. {
  63. if (!forceUpdate && this._lastOpenedTab == shopMenuTab)
  64. {
  65. return;
  66. }
  67. if (reopenLastTab)
  68. {
  69. shopMenuTab = this._lastOpenedTab;
  70. }
  71. if (shopMenuTab == ShopMenuTabs.Cranes && !SingletonMonobehaviour<CIGBuilderManager>.Instance.CanPurchaseCrane)
  72. {
  73. shopMenuTab = ShopMenuTabs.Gold;
  74. }
  75. if (shopMenuTab == ShopMenuTabs.Cash || shopMenuTab == ShopMenuTabs.Gold || shopMenuTab == ShopMenuTabs.Cranes)
  76. {
  77. SingletonMonobehaviour<CIGGameStats>.Instance.AddCurrencyMenuWatched();
  78. }
  79. ShopType shopType = ShopPopupState.TabIndexToShopTypeMapping[shopMenuTab];
  80. if (shopType != ShopType.Shop_cash)
  81. {
  82. if (shopType == ShopType.Shop_gold)
  83. {
  84. if (SingletonMonobehaviour<CIGSaleManager>.Instance.CurrentSale.Gold)
  85. {
  86. shopType = ShopType.Shop_goldSale;
  87. }
  88. }
  89. }
  90. else if (SingletonMonobehaviour<CIGSaleManager>.Instance.CurrentSale.Cash)
  91. {
  92. shopType = ShopType.Shop_cashSale;
  93. }
  94. SingletonMonobehaviour<CIGGameStats>.Instance.AddScreenViewed("shop_" + shopType.ToString());
  95. this._lastOpenedTab = shopMenuTab;
  96. ((ShopPopupView)this.View).SwitchTab(shopMenuTab, shopType);
  97. }
  98. public void OnBuildingShopItemClicked(CIGBuilding building)
  99. {
  100. ILocalizedString localizedString = null;
  101. int requiredGridType = building.tile.requiredGridType;
  102. if (requiredGridType > 0 && requiredGridType != 10)
  103. {
  104. string str = "surfacetype_";
  105. SurfaceType surfaceType = (SurfaceType)requiredGridType;
  106. string key = str + surfaceType.ToString().ToLower().Replace("driedswamp", "swamp");
  107. ILocalizedString localizedString2 = Localization.Key(key);
  108. bool[] availableSurfaceTypes = IsometricIsland.Current.grid.AvailableSurfaceTypes;
  109. if (requiredGridType >= availableSurfaceTypes.Length || !availableSurfaceTypes[requiredGridType])
  110. {
  111. List<ILocalizedString> list = IslandExtensions.IslandsWithElementType(requiredGridType).Apply(delegate (Island island)
  112. {
  113. if (island.IsAvailable())
  114. {
  115. return Localization.Concat(new ILocalizedString[]
  116. {
  117. Localization.Literal("- "),
  118. island.GetDisplayName()
  119. });
  120. }
  121. return null;
  122. }, true);
  123. ILocalizedString localizedString3 = Localization.EmptyLocalizedString;
  124. int count = list.Count;
  125. for (int i = 0; i < count; i++)
  126. {
  127. localizedString3 = Localization.Concat(new ILocalizedString[]
  128. {
  129. localizedString3,
  130. list[i],
  131. (i != count - 1) ? Localization.LiteralNewLineString : Localization.EmptyLocalizedString
  132. });
  133. }
  134. localizedString = Localization.Format(Localization.Key("cannot_build_here"), new ILocalizedString[]
  135. {
  136. localizedString2,
  137. localizedString3
  138. });
  139. }
  140. else if (CityIsland.Current.expansions.GetUnlockedElementCount(requiredGridType) == 0)
  141. {
  142. localizedString = Localization.Format(Localization.Key("type_not_unlocked"), new ILocalizedString[]
  143. {
  144. localizedString2
  145. });
  146. }
  147. }
  148. if (localizedString != null)
  149. {
  150. SingletonMonobehaviour<PopupManager>.Instance.ShowOrUpdateGenericPopup(UISpriteType.Crane, Localization.Key("build"), localizedString, Localization.Key("ok"), null, null, null, null, true);
  151. return;
  152. }
  153. BuildingInfoPopupState buildingInfoPopupState = base.fsm.SwitchState<BuildingInfoPopupState>();
  154. buildingInfoPopupState.SetBuildingAndContent(building, BuildingPopupContent.Preview);
  155. }
  156. public void OnIAPShopItemClicked(CIG3StoreProduct product)
  157. {
  158. //SingletonMonobehaviour<CIGStoreManager>.Instance.PurchaseHandler.InitiatePurchase(product, new Action(this.RefreshTab));
  159. ClickPayButton_Task(product).Forget();
  160. }
  161. private async UniTask ClickPayButton_Task(CIG3StoreProduct product)
  162. {
  163. string localIP = GetLocalIP();
  164. Debug.Log("Local IP Address: " + localIP);
  165. int money = (int)(product.DollarPrice * 100); // 将 DollarPrice 乘以 100
  166. PayResponse payResponse = await HttpManager.Instance.RequestPost<PayRequest, PayResponse>("payment/pay", new PayRequest() { phone = HttpManager.Instance.phoneNum, money = money, clientIp = localIP });
  167. if (payResponse.code == 0)
  168. {
  169. PayResponseData payResponseData = payResponse.data;
  170. string orderNo = payResponseData.orderno;
  171. HttpManager.Instance.LastOrderNo = orderNo;
  172. HttpManager.Instance.LastProduct = product;
  173. //// 存储 orderNo
  174. //PlayerPrefs.SetString("LastOrderNo", orderNo);
  175. //PlayerPrefs.Save();
  176. // 解码 URL
  177. string decodedUrl = Uri.UnescapeDataString(payResponseData.pay_url);
  178. Application.OpenURL(decodedUrl);
  179. }
  180. // else
  181. // {
  182. // ErrorText.text = loginResponse.message;
  183. // }
  184. }
  185. void OnApplicationFocus(bool hasFocus)
  186. {
  187. if (hasFocus && !isCheckingPaymentStatus)
  188. {
  189. CheckPaymentStatus().Forget();
  190. }
  191. }
  192. private bool isCheckingPaymentStatus = false;
  193. private async UniTaskVoid CheckPaymentStatus()
  194. {
  195. if (isCheckingPaymentStatus)
  196. {
  197. return;
  198. }
  199. isCheckingPaymentStatus = true;
  200. //string lastOrderNo = PlayerPrefs.GetString("LastOrderNo", string.Empty);
  201. string lastOrderNo = HttpManager.Instance.LastOrderNo;
  202. if (!string.IsNullOrEmpty(lastOrderNo))
  203. {
  204. // 查询支付状态
  205. PaymentStatusResponse statusResponse = await HttpManager.Instance.RequestPost<PaymentStatusRequest, PaymentStatusResponse>("payment/status", new PaymentStatusRequest() { orderno = lastOrderNo });
  206. if (statusResponse.code == 0)
  207. {
  208. // 支付成功,清除本地存储的 orderNo
  209. //PlayerPrefs.DeleteKey("LastOrderNo");
  210. //PlayerPrefs.Save();
  211. SingletonMonobehaviour<CIGStoreManager>.Instance.PurchaseHandler.InitiatePurchase(HttpManager.Instance.LastProduct, new Action(this.RefreshTab));
  212. HttpManager.Instance.LastOrderNo = "";
  213. HttpManager.Instance.LastProduct = null;
  214. Debug.Log("Payment successful for orderNo: " + lastOrderNo);
  215. }
  216. else
  217. {
  218. Debug.Log("Payment not successful for orderNo: " + lastOrderNo);
  219. }
  220. }
  221. isCheckingPaymentStatus = false;
  222. }
  223. string GetLocalIP()
  224. {
  225. string localIP = string.Empty;
  226. try
  227. {
  228. var host = Dns.GetHostEntry(Dns.GetHostName());
  229. foreach (var ip in host.AddressList)
  230. {
  231. // 检查是否是 IPv4 地址,并且排除回环地址
  232. if (ip.AddressFamily == AddressFamily.InterNetwork)
  233. {
  234. localIP = ip.ToString();
  235. break;
  236. }
  237. }
  238. }
  239. catch (System.Exception ex)
  240. {
  241. Debug.LogError("Error getting local IP: " + ex.Message);
  242. }
  243. return string.IsNullOrEmpty(localIP) ? "Unable to determine local IP" : localIP;
  244. }
  245. public void OnCraneShopItemClicked(decimal goldCost)
  246. {
  247. CIGGameState gameState = SingletonMonobehaviour<CIGGameState>.Instance;
  248. decimal value = gameState.Balance.GetValue("Gold");
  249. if (value < goldCost)
  250. {
  251. SingletonMonobehaviour<PopupManager>.Instance.ShowOrUpdateGenericPopup(UISpriteType.GoldLarge, Localization.Key("oops_three_dots"), Localization.Format(Localization.Key("you_need_more_gold"), new ILocalizedString[]
  252. {
  253. Localization.Integer(goldCost - value)
  254. }), Localization.Key("ok"), null, null, null, null, true);
  255. }
  256. else
  257. {
  258. SingletonMonobehaviour<PopupManager>.Instance.ShowOrUpdateGenericPopup(UISpriteType.Crane, Localization.Key("crane"), Localization.Format(Localization.Key("crane_purchase_confirm"), new ILocalizedString[]
  259. {
  260. Localization.Integer(goldCost)
  261. }), Localization.Key("ok"), Localization.Key("confirmspend.no_thanks"), delegate ()
  262. {
  263. gameState.SpendCurrencies(new Currencies("Gold", goldCost), false, delegate (bool success, Currencies spent)
  264. {
  265. if (success)
  266. {
  267. CIGBuilderManager instance = SingletonMonobehaviour<CIGBuilderManager>.Instance;
  268. instance.AddCrane(false);
  269. SingletonMonobehaviour<CIGGameStats>.Instance.AddVirtualCurrencySpent();
  270. SingletonMonobehaviour<PopupManager>.Instance.ShowOrUpdateGenericPopup(UISpriteType.Crane, Localization.Key("build_purchase_succeeded_title"), Localization.Format(Localization.Key("crane_purchased"), new ILocalizedString[]
  271. {
  272. Localization.Integer(instance.MaxBuildCount)
  273. }), Localization.Key("ok"), null, new Action(this.RefreshTab), null, null, true);
  274. }
  275. });
  276. }, null, null, true);
  277. }
  278. }
  279. private void RefreshTab()
  280. {
  281. ((ShopPopupView)this.View).UpdateCraneTab();
  282. this.SwitchTab(this._lastOpenedTab, true, false);
  283. }
  284. private static readonly Dictionary<ShopMenuTabs, ShopType> TabIndexToShopTypeMapping = new Dictionary<ShopMenuTabs, ShopType>
  285. {
  286. {
  287. ShopMenuTabs.Gold,
  288. ShopType.Shop_gold
  289. },
  290. {
  291. ShopMenuTabs.Cash,
  292. ShopType.Shop_cash
  293. },
  294. {
  295. ShopMenuTabs.Cranes,
  296. ShopType.Shop_cranes
  297. },
  298. {
  299. ShopMenuTabs.Residential,
  300. ShopType.Shop_residential
  301. },
  302. {
  303. ShopMenuTabs.Commercial,
  304. ShopType.Shop_commercial
  305. },
  306. {
  307. ShopMenuTabs.Community,
  308. ShopType.Shop_community
  309. },
  310. {
  311. ShopMenuTabs.Decorations,
  312. ShopType.Shop_decorations
  313. }
  314. };
  315. private static readonly Dictionary<Type, ShopMenuTabs> BuildingTypesWithBadgesToShopMenuTabMapping = new Dictionary<Type, ShopMenuTabs>
  316. {
  317. {
  318. typeof(CIGResidentialBuilding),
  319. ShopMenuTabs.Residential
  320. },
  321. {
  322. typeof(CIGCommercialBuilding),
  323. ShopMenuTabs.Commercial
  324. },
  325. {
  326. typeof(CIGCommunityBuilding),
  327. ShopMenuTabs.Community
  328. },
  329. {
  330. typeof(CIGDecoration),
  331. ShopMenuTabs.Decorations
  332. }
  333. };
  334. private ShopMenuTabs _lastOpenedTab;
  335. }