You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

409 lines
12 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using SUISS.Core;
  5. using SUISS.Core.Utilities;
  6. using SUISS.Scheduling;
  7. using SUISS.Storage;
  8. using SUISSEngine;
  9. using UnityEngine;
  10. public sealed class IAPPackDealManager : Singleton<IAPPackDealManager>
  11. {
  12. public IAPPackDealManager()
  13. {
  14. if (this.HasDeal)
  15. {
  16. this._timer = SingletonMonobehaviour<TimerManager>.Instance.CreateClockTimer(this.FirstActiveDeal.DealStart + this.FirstActiveDeal.DealDuration, new Action(this.DealEndTimer));
  17. }
  18. }
  19. //[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  20. public event IAPPackDealManager.DealStartedHandler DealStartedEvent;
  21. private void FireDealStartedEvent(IAPPackDealManager.PackDeal deal)
  22. {
  23. if (this.DealStartedEvent != null)
  24. {
  25. this.DealStartedEvent(deal.PackName, deal.DealStart, deal.DealDuration);
  26. }
  27. }
  28. //[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  29. public event IAPPackDealManager.DealEndedHandler DealEndedEvent;
  30. private void FireDealEndedEvent(IAPPackDealManager.PackDeal deal)
  31. {
  32. if (this.DealEndedEvent != null && deal != null)
  33. {
  34. this.DealEndedEvent(deal.PackName);
  35. }
  36. }
  37. public IAPPackDealManager.PackDeal FindFirstActive(string packName)
  38. {
  39. int count = this.ActiveDeals.Count;
  40. for (int i = 0; i < count; i++)
  41. {
  42. if (this.ActiveDeals[i].PackName == packName)
  43. {
  44. return this.ActiveDeals[i];
  45. }
  46. }
  47. return null;
  48. }
  49. public bool StartDeal(string packName, TimeSpan duration)
  50. {
  51. this.StartScheduledDealsRoutine();
  52. if (!IAPPackManager.Instance.AllPackNames.Contains(packName))
  53. {
  54. UnityEngine.Debug.LogError(string.Format("Tried to start IAP pack deal unknown to the IAPPackDealManager", packName));
  55. return false;
  56. }
  57. IAPPackDealManager.PackDeal packDeal = new IAPPackDealManager.PackDeal(packName, duration, DateTime.UtcNow);
  58. IList<IAPPackDealManager.PackDeal> activeDeals = this.ActiveDeals;
  59. activeDeals.Add(packDeal);
  60. this.ActiveDeals = activeDeals;
  61. this.FireDealStartedEvent(packDeal);
  62. if (this._timer != null)
  63. {
  64. this._timer.Cancel();
  65. this._timer = null;
  66. }
  67. IAPPackDealManager.PackDeal firstActiveDeal = this.FirstActiveDeal;
  68. if (firstActiveDeal != null)
  69. {
  70. this._timer = SingletonMonobehaviour<TimerManager>.Instance.CreateClockTimer(firstActiveDeal.DealStart + firstActiveDeal.DealDuration, new Action(this.DealEndTimer));
  71. return true;
  72. }
  73. return false;
  74. }
  75. public void ScheduleDeal(string packName, TimeSpan duration, DateTime time)
  76. {
  77. this.StartScheduledDealsRoutine();
  78. List<IAPPackDealManager.PackDeal> list = this.ScheduledDeals as List<IAPPackDealManager.PackDeal>;
  79. list.Add(new IAPPackDealManager.PackDeal(packName, duration, time));
  80. list.Sort(delegate(IAPPackDealManager.PackDeal lhs, IAPPackDealManager.PackDeal rhs)
  81. {
  82. if (lhs.DealDuration < rhs.DealDuration)
  83. {
  84. return -1;
  85. }
  86. if (lhs.DealDuration > rhs.DealDuration)
  87. {
  88. return 1;
  89. }
  90. return 0;
  91. });
  92. this.ScheduledDeals = list;
  93. }
  94. public void EndDeal(IAPPackDealManager.PackDeal deal)
  95. {
  96. List<IAPPackDealManager.PackDeal> list = this.ActiveDeals.ToList<IAPPackDealManager.PackDeal>();
  97. IAPPackDealManager.PackDeal packDeal = list.Find((IAPPackDealManager.PackDeal d) => d.IsMatch(deal));
  98. if (packDeal == null)
  99. {
  100. UnityEngine.Debug.LogErrorFormat("Deal with packName {0} not found", new object[]
  101. {
  102. deal.PackName
  103. });
  104. return;
  105. }
  106. list.Remove(packDeal);
  107. this.ActiveDeals = list;
  108. if (packDeal == this.FirstActiveDeal && this._timer != null)
  109. {
  110. this._timer.Cancel();
  111. this._timer = null;
  112. }
  113. if (list.Count != 0)
  114. {
  115. IAPPackDealManager.PackDeal firstActiveDeal = this.FirstActiveDeal;
  116. this._timer = SingletonMonobehaviour<TimerManager>.Instance.CreateClockTimer(firstActiveDeal.DealStart + firstActiveDeal.DealDuration, new Action(this.DealEndTimer));
  117. }
  118. this.FireDealEndedEvent(packDeal);
  119. }
  120. public IList<IAPPackDealManager.PackDeal> ActiveDeals
  121. {
  122. get
  123. {
  124. Dictionary<string, object> storage = this._storage;
  125. List<IAPPackDealManager.PackDeal> list = new List<IAPPackDealManager.PackDeal>();
  126. if (!storage.ContainsKey("ActiveSales"))
  127. {
  128. return list;
  129. }
  130. List<object> list2 = storage["ActiveSales"] as List<object>;
  131. int count = list2.Count;
  132. for (int i = 0; i < count; i++)
  133. {
  134. object obj = list2[i];
  135. if (obj == null)
  136. {
  137. UnityEngine.Debug.LogError("Found a null object in storage.");
  138. }
  139. else if (!(obj is Dictionary<string, object>))
  140. {
  141. UnityEngine.Debug.LogError(string.Format("Found an object of type '{0}' in storage. Should be Dictionary<string,object>", obj.GetType()));
  142. }
  143. else
  144. {
  145. IAPPackDealManager.PackDeal packDeal = IAPPackDealManager.PackDeal.FromDictionary((Dictionary<string, object>)obj);
  146. if (!(DateTime.UtcNow > packDeal.DealStart + packDeal.DealDuration))
  147. {
  148. list.Add(packDeal);
  149. }
  150. }
  151. }
  152. return list;
  153. }
  154. private set
  155. {
  156. List<object> list = new List<object>();
  157. int count = value.Count;
  158. for (int i = 0; i < count; i++)
  159. {
  160. list.Add(IAPPackDealManager.PackDeal.ToDictionary(value[i]));
  161. }
  162. this._storage["ActiveSales"] = list;
  163. }
  164. }
  165. public bool HasDeal
  166. {
  167. get
  168. {
  169. return this.ActiveDeals.Count != 0;
  170. }
  171. }
  172. public IAPPackDealManager.PackDeal FirstActiveDeal
  173. {
  174. get
  175. {
  176. Dictionary<string, object> storage = this._storage;
  177. IList<IAPPackDealManager.PackDeal> activeDeals = this.ActiveDeals;
  178. if (storage.ContainsKey("PackForSale") && storage.ContainsKey("SaleStartTime") && storage.ContainsKey("SaleDurationKey"))
  179. {
  180. DateTime dateTime = new DateTime((long)storage["SaleStartTime"], DateTimeKind.Utc);
  181. TimeSpan timeSpan = new TimeSpan((long)storage["SaleDurationKey"]);
  182. if (DateTime.UtcNow >= dateTime && DateTime.UtcNow <= dateTime + timeSpan)
  183. {
  184. activeDeals.Add(new IAPPackDealManager.PackDeal(storage["PackForSale"] as string, timeSpan, dateTime));
  185. this.ActiveDeals = activeDeals;
  186. }
  187. storage.Remove("PackForSale");
  188. storage.Remove("SaleStartTime");
  189. storage.Remove("SaleDurationKey");
  190. }
  191. if (activeDeals.Count == 0)
  192. {
  193. return null;
  194. }
  195. return activeDeals.MinOrMaxObject((IAPPackDealManager.PackDeal x) => x.DealStart + x.DealDuration, true);
  196. }
  197. }
  198. private void StartScheduledDealsRoutine()
  199. {
  200. if (this._routineBeingStarted || this._dealsRoutine != null)
  201. {
  202. return;
  203. }
  204. IScheduler scheduler = ServiceLocator.Find<IScheduler>();
  205. if (scheduler != null)
  206. {
  207. this._routineBeingStarted = true;
  208. this._dealsRoutine = scheduler.StartCoroutine(this.CoScheduledDealsRoutine());
  209. this._routineBeingStarted = false;
  210. }
  211. else
  212. {
  213. UnityEngine.Debug.LogWarning("IAPPackDealManger was unable to start deal timers because IScheduler is null in ServiceLocator.");
  214. }
  215. }
  216. private IEnumerator<IYieldStatement> CoScheduledDealsRoutine()
  217. {
  218. for (;;)
  219. {
  220. while (this.ScheduledDeals.Count == 0)
  221. {
  222. yield return CoYield.On(1f);
  223. }
  224. IAPPackDealManager.PackDeal deal = this.ScheduledDeals[0];
  225. if (DateTime.UtcNow <= deal.DealStart + deal.DealDuration)
  226. {
  227. while (DateTime.UtcNow < deal.DealStart)
  228. {
  229. yield return CoYield.On(1f);
  230. }
  231. if (!this.StartDeal(deal.PackName, deal.DealDuration - (DateTime.UtcNow - deal.DealStart)))
  232. {
  233. UnityEngine.Debug.LogError("No such deal name: " + deal.PackName);
  234. }
  235. }
  236. IList<IAPPackDealManager.PackDeal> scheduledDeals = this.ScheduledDeals;
  237. scheduledDeals.Remove(deal);
  238. this.ScheduledDeals = scheduledDeals;
  239. }
  240. yield break;
  241. }
  242. private void DealEndTimer()
  243. {
  244. if (this._timer != null)
  245. {
  246. this._timer.Cancel();
  247. this._timer = null;
  248. }
  249. if (this.FirstActiveDeal != null)
  250. {
  251. this.EndDeal(this.FirstActiveDeal);
  252. }
  253. }
  254. private Dictionary<string, object> _storage
  255. {
  256. get
  257. {
  258. return Storage.Get(StorageLifecycle.Game).GetDictionary("Storage");
  259. }
  260. }
  261. private IList<IAPPackDealManager.PackDeal> ScheduledDeals
  262. {
  263. get
  264. {
  265. Dictionary<string, object> storage = this._storage;
  266. List<IAPPackDealManager.PackDeal> list = new List<IAPPackDealManager.PackDeal>();
  267. if (!storage.ContainsKey("ScheduledSales"))
  268. {
  269. return list;
  270. }
  271. List<object> list2 = storage["ScheduledSales"] as List<object>;
  272. int count = list2.Count;
  273. for (int i = 0; i < count; i++)
  274. {
  275. object obj = list2[i];
  276. if (obj == null)
  277. {
  278. UnityEngine.Debug.LogError("Found a null object in storage.");
  279. }
  280. else if (!(obj is Dictionary<string, object>))
  281. {
  282. UnityEngine.Debug.LogError(string.Format("Found an object of type '{0}' in storage. Should be Dictionary<string,object>", obj.GetType()));
  283. }
  284. else
  285. {
  286. IAPPackDealManager.PackDeal packDeal = IAPPackDealManager.PackDeal.FromDictionary((Dictionary<string, object>)obj);
  287. if (!(DateTime.UtcNow > packDeal.DealStart + packDeal.DealDuration))
  288. {
  289. list.Add(packDeal);
  290. }
  291. }
  292. }
  293. return list;
  294. }
  295. set
  296. {
  297. List<object> list = new List<object>();
  298. int count = value.Count;
  299. for (int i = 0; i < count; i++)
  300. {
  301. list.Add(IAPPackDealManager.PackDeal.ToDictionary(value[i]));
  302. }
  303. this._storage["ScheduledSales"] = list;
  304. }
  305. }
  306. public const string StorageKey = "Storage";
  307. public const string ScheduledDealsKey = "ScheduledSales";
  308. public const string ActiveDealsKey = "ActiveSales";
  309. public const string PackForSaleKey = "PackForSale";
  310. public const string SaleStartTimeKey = "SaleStartTime";
  311. public const string SaleDurationKey = "SaleDurationKey";
  312. private bool _routineBeingStarted;
  313. private Timer _timer;
  314. private ICoroutine _dealsRoutine;
  315. public delegate void DealStartedHandler(string packName, DateTime start, TimeSpan duration);
  316. public delegate void DealEndedHandler(string oldPackName);
  317. public class PackDeal
  318. {
  319. public PackDeal()
  320. {
  321. }
  322. public PackDeal(string packName, TimeSpan duration, DateTime time)
  323. {
  324. this.PackName = packName;
  325. this.DealDuration = duration;
  326. this.DealStart = time;
  327. }
  328. public static IAPPackDealManager.PackDeal FromDictionary(Dictionary<string, object> dict)
  329. {
  330. return new IAPPackDealManager.PackDeal
  331. {
  332. PackName = (string)dict["PackName"],
  333. DealDuration = new TimeSpan((long)dict["SaleDuration"]),
  334. DealStart = new DateTime((long)dict["SaleTime"], DateTimeKind.Utc)
  335. };
  336. }
  337. public static Dictionary<string, object> ToDictionary(IAPPackDealManager.PackDeal deal)
  338. {
  339. Dictionary<string, object> dictionary = new Dictionary<string, object>();
  340. dictionary["PackName"] = deal.PackName;
  341. dictionary["SaleDuration"] = deal.DealDuration.Ticks;
  342. dictionary["SaleTime"] = deal.DealStart.Ticks;
  343. return dictionary;
  344. }
  345. public bool IsMatch(IAPPackDealManager.PackDeal packDeal)
  346. {
  347. return packDeal != null && packDeal.PackName == this.PackName && packDeal.DealDuration == this.DealDuration && packDeal.DealStart == this.DealStart;
  348. }
  349. public void Extend(TimeSpan addedDuration)
  350. {
  351. this.DealDuration += addedDuration;
  352. }
  353. public string PackName { get; private set; }
  354. public TimeSpan DealDuration { get; private set; }
  355. public DateTime DealStart { get; private set; }
  356. public DateTime DealEnds
  357. {
  358. get
  359. {
  360. return this.DealStart + this.DealDuration;
  361. }
  362. }
  363. public const string PackNameKey = "PackName";
  364. public const string DealDurationKey = "SaleDuration";
  365. public const string DealTimeKey = "SaleTime";
  366. }
  367. }