您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

326 行
9.2 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using CIG.Extensions;
  5. using SUISS.Core;
  6. using SUISSEngine;
  7. using UnityEngine;
  8. namespace CIG
  9. {
  10. [RequireComponent(typeof(Serializing))]
  11. public sealed class VideoAds1Manager : SingletonMonobehaviour<VideoAds1Manager>
  12. {
  13. //[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  14. public event VideoAds1Manager.AvailabilityChangedEventHandler AvailabilityChangedEvent;
  15. private void FireAvailabilityChangedEvent()
  16. {
  17. if (this.AvailabilityChangedEvent != null)
  18. {
  19. this.AvailabilityChangedEvent();
  20. }
  21. }
  22. //[DebuggerBrowsable(DebuggerBrowsableState.Never)]
  23. public event VideoAds1Manager.UnlockedEventHandler UnlockedEvent;
  24. private void FireUnlockedEvent()
  25. {
  26. if (this.UnlockedEvent != null)
  27. {
  28. this.UnlockedEvent();
  29. }
  30. }
  31. protected override void Awake()
  32. {
  33. base.Awake();
  34. if (this._isValidNewInstance)
  35. {
  36. AdProviderType[] array = new AdProviderType[3];
  37. array[0] = AdProviderType.Chartboost;
  38. array[1] = AdProviderType.Vungle;
  39. this._adWaterfall = new AdWaterfall(array);
  40. }
  41. }
  42. protected override void OnDestroy()
  43. {
  44. if (SingletonMonobehaviour<CIGWebService>.IsAvailable)
  45. {
  46. SingletonMonobehaviour<CIGWebService>.Instance.PullRequestCompleted -= this.OnPullRequestCompleted;
  47. }
  48. if (SingletonMonobehaviour<AdProviderPool>.IsAvailable)
  49. {
  50. SingletonMonobehaviour<AdProviderPool>.Instance.AdAvailabilityChangedEvent -= this.OnAdAvailabilityChangedEvent;
  51. }
  52. this.CancelInvoke(new Action(this.OnValidateVideoAvailability));
  53. base.OnDestroy();
  54. }
  55. public bool ShowVideoQuestAd()
  56. {
  57. return this.ShowAd(delegate(bool success, bool clicked)
  58. {
  59. if (success)
  60. {
  61. SingletonMonobehaviour<CIGGameStats>.Instance.AddNumberOfGoldVideosWatched(1);
  62. }
  63. });
  64. }
  65. public bool ShowAd(Action<bool, bool> callback)
  66. {
  67. return this.IsReady && this._adWaterfall.ShowAd(delegate(bool success, bool clicked)
  68. {
  69. this.OnVideoWatched(success, clicked, callback);
  70. });
  71. }
  72. public bool IsReady
  73. {
  74. get
  75. {
  76. return this._adWaterfall != null && this._pullRequestCompleted && Mathf.Approximately(this.RemainingSecondsUntilNextVideo, 0f) && this._adWaterfall.IsReady;
  77. }
  78. }
  79. public float RemainingUnlockSeconds
  80. {
  81. get
  82. {
  83. return Mathf.Max(0f, (float)this._unlockTime.Subtract(DateTime.UtcNow).TotalSeconds);
  84. }
  85. }
  86. public bool IsUnlocked
  87. {
  88. get
  89. {
  90. return Mathf.Approximately(this.RemainingUnlockSeconds, 0f);
  91. }
  92. }
  93. public bool IsAvailableOnPlatform
  94. {
  95. get
  96. {
  97. return this._adWaterfall != null;
  98. }
  99. }
  100. private void OnSerialize(Dictionary<string, object> dict)
  101. {
  102. StorageDictionary storageDictionary = new StorageDictionary(dict);
  103. storageDictionary.Set("UnlockStartTime", this._unlockStartTime);
  104. storageDictionary.Set("UnlockSeconds", this._unlockSeconds);
  105. storageDictionary.Set("WatchedVideoTimestamps", this._watchedVideoTimestamps);
  106. }
  107. private void OnDeserialize(Dictionary<string, object> dict)
  108. {
  109. StorageDictionary storageDictionary = new StorageDictionary(dict);
  110. this._unlockStartTime = storageDictionary.GetDateTime("UnlockStartTime", DateTime.UtcNow);
  111. this._unlockSeconds = storageDictionary.Get<int>("UnlockSeconds", 300);
  112. this._watchedVideoTimestamps = storageDictionary.GetDateTimeList("WatchedVideoTimestamps");
  113. }
  114. private void OnDeserialized()
  115. {
  116. if (this._watchedVideoTimestamps == null)
  117. {
  118. this._unlockStartTime = DateTime.UtcNow;
  119. this._unlockSeconds = 300;
  120. this._watchedVideoTimestamps = new List<DateTime>();
  121. this._unlockTime = this._unlockStartTime.AddSeconds((double)this._unlockSeconds);
  122. this._serializing.Serialize();
  123. }
  124. CIGWebService instance = SingletonMonobehaviour<CIGWebService>.Instance;
  125. instance.PullRequestCompleted += this.OnPullRequestCompleted;
  126. if (instance.HasPulled)
  127. {
  128. this.OnPullRequestCompleted();
  129. }
  130. SingletonMonobehaviour<AdProviderPool>.Instance.AdAvailabilityChangedEvent += this.OnAdAvailabilityChangedEvent;
  131. }
  132. private void OnPullRequestCompleted()
  133. {
  134. bool isReady = this.IsReady;
  135. Dictionary<string, string> properties = SingletonMonobehaviour<CIGWebService>.Instance.Properties;
  136. this._unlockSeconds = properties.GetInt("video_rewards_unlock_seconds", 300);
  137. this._videoTimeoutSeconds = (double)properties.GetInt("video_rewards_timeout_seconds", 14400);
  138. this._watchedVideoTimespan = new TimeSpan(properties.GetInt("video_rewards_timespan_hours", 24), 0, 0);
  139. this._maxWatchedVideosPerTimespan = properties.GetInt("video_rewards_max", 3);
  140. this._unlockTime = this._unlockStartTime.AddSeconds((double)this._unlockSeconds);
  141. this._pullRequestCompleted = true;
  142. bool isReady2 = this.IsReady;
  143. this.CancelInvoke(new Action(this.OnValidateVideoAvailability));
  144. this.CancelInvoke(new Action(this.FireUnlockedEvent));
  145. if (isReady != isReady2)
  146. {
  147. this.FireAvailabilityChangedEvent();
  148. }
  149. if (!isReady2)
  150. {
  151. float time = Mathf.Max(this.RemainingSecondsUntilNextVideo, 30f);
  152. this.Invoke(new Action(this.OnValidateVideoAvailability), time, false);
  153. }
  154. if (!this.IsUnlocked)
  155. {
  156. this.Invoke(new Action(this.OnValidateUnlockedState), Mathf.Max(0f, this.RemainingUnlockSeconds), false);
  157. }
  158. }
  159. private void OnVideoWatched(bool success, bool clicked, Action<bool, bool> callback)
  160. {
  161. this.PruneWatchedVideoTimestamps(false);
  162. this._watchedVideoTimestamps.Add(DateTime.UtcNow);
  163. this._serializing.Serialize();
  164. this.CancelInvoke(new Action(this.OnValidateVideoAvailability));
  165. this.Invoke(new Action(this.OnValidateVideoAvailability), this.RemainingSecondsUntilNextVideo, false);
  166. if (callback != null)
  167. {
  168. callback(success, clicked);
  169. }
  170. }
  171. private void OnValidateUnlockedState()
  172. {
  173. if (this.IsUnlocked)
  174. {
  175. this.FireUnlockedEvent();
  176. }
  177. else
  178. {
  179. this.Invoke(new Action(this.OnValidateUnlockedState), Mathf.Max(0f, this.RemainingUnlockSeconds), false);
  180. }
  181. }
  182. private void OnValidateVideoAvailability()
  183. {
  184. this.PruneWatchedVideoTimestamps(true);
  185. if (this.IsReady)
  186. {
  187. this.FireAvailabilityChangedEvent();
  188. }
  189. else
  190. {
  191. float time = Mathf.Max(this.RemainingSecondsUntilNextVideo, 30f);
  192. this.Invoke(new Action(this.OnValidateVideoAvailability), time, false);
  193. }
  194. }
  195. private void OnAdAvailabilityChangedEvent(AdProviderType providerType)
  196. {
  197. if (this._adWaterfall.ContainsAdProvider(providerType))
  198. {
  199. this.FireAvailabilityChangedEvent();
  200. }
  201. }
  202. private void PruneWatchedVideoTimestamps(bool serialize)
  203. {
  204. DateTime now = DateTime.UtcNow;
  205. int count = this._watchedVideoTimestamps.Count;
  206. this._watchedVideoTimestamps.RemoveAll((DateTime x) => now.Subtract(x) >= this._watchedVideoTimespan);
  207. if (serialize && this._watchedVideoTimestamps.Count != count)
  208. {
  209. this._serializing.Serialize();
  210. }
  211. }
  212. private double RemainingVideoTimeoutSeconds
  213. {
  214. get
  215. {
  216. int count = this._watchedVideoTimestamps.Count;
  217. if (count <= 0)
  218. {
  219. return 0.0;
  220. }
  221. return this._videoTimeoutSeconds - DateTime.UtcNow.Subtract(this._watchedVideoTimestamps[count - 1]).TotalSeconds;
  222. }
  223. }
  224. private double RemainingVideoTimespanTimeoutSeconds
  225. {
  226. get
  227. {
  228. if (this._maxWatchedVideosPerTimespan == 0)
  229. {
  230. return double.MaxValue;
  231. }
  232. int count = this._watchedVideoTimestamps.Count;
  233. if (count < this._maxWatchedVideosPerTimespan || count == 0)
  234. {
  235. return 0.0;
  236. }
  237. return this._watchedVideoTimespan.TotalSeconds - DateTime.UtcNow.Subtract(this._watchedVideoTimestamps[0]).TotalSeconds;
  238. }
  239. }
  240. private float RemainingSecondsUntilNextVideo
  241. {
  242. get
  243. {
  244. if (!this._pullRequestCompleted)
  245. {
  246. return float.MaxValue;
  247. }
  248. return Mathf.Max(new float[]
  249. {
  250. 0f,
  251. this.RemainingUnlockSeconds,
  252. (float)this.RemainingVideoTimeoutSeconds,
  253. (float)this.RemainingVideoTimespanTimeoutSeconds
  254. });
  255. }
  256. }
  257. private const string UnlockSecondsServerKey = "video_rewards_unlock_seconds";
  258. private const string TimeoutSecondsServerKey = "video_rewards_timeout_seconds";
  259. private const string TimespanHoursServerKey = "video_rewards_timespan_hours";
  260. private const string TimespanMaxVideosServerKey = "video_rewards_max";
  261. private const string UnlockStartTimeKey = "UnlockStartTime";
  262. private const string UnlockSecondsKey = "UnlockSeconds";
  263. private const string WatchedVideoTimestampsKey = "WatchedVideoTimestamps";
  264. private const float ProviderAvailabilityValidationDelayInSeconds = 30f;
  265. private const int DefaultUnlockSeconds = 300;
  266. [SerializeField]
  267. private Serializing _serializing;
  268. private int _unlockSeconds;
  269. private double _videoTimeoutSeconds;
  270. private TimeSpan _watchedVideoTimespan;
  271. private int _maxWatchedVideosPerTimespan;
  272. private DateTime _unlockStartTime;
  273. private List<DateTime> _watchedVideoTimestamps;
  274. private bool _pullRequestCompleted;
  275. private AdWaterfall _adWaterfall;
  276. private DateTime _unlockTime;
  277. public delegate void AvailabilityChangedEventHandler();
  278. public delegate void UnlockedEventHandler();
  279. }
  280. }