EscapeShooter/My project/Assets/Project Files/Modules/Advertisement/Scripts/Runtime/AdsManager.cs

700 lines
22 KiB
C#

#pragma warning disable 0649
#pragma warning disable 0162
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
namespace Watermelon
{
public class AdsManager
{
private const int DEFAULT_BANNER_HEIGHT = 110;
private const int INIT_ATTEMPTS_AMOUNT = 30;
private const double FORCED_AD_DISABLED_FOREVER = -1;
private const string FIRST_LAUNCH_PREFS = "FIRST_LAUNCH";
private static AdsManager instance;
private static AdProviderHandler activeHandler;
private static bool debugMode;
public static bool DebugMode => debugMode;
private static AdsSettings settings;
public static AdsSettings Settings => settings;
private static double lastInterstitialTime;
private static AdProviderHandler.AdvertisementCallback rewardedVideoCallback;
private static AdProviderHandler.AdvertisementCallback interstitalCallback;
private static MainThreadDispatcher dispatcher;
private static bool isFirstAdLoaded = false;
private static bool waitingForRewardVideoCallback;
private static bool isBannerActive = true;
public static bool IsBannerActive => isBannerActive;
private static float bannerHeight = DEFAULT_BANNER_HEIGHT;
public static float BannerHeight => bannerHeight;
private static Coroutine loadingCoroutine;
private static TweenCase delayTweenCase;
private static float intFirstStartDelay;
private static float intStartDelay;
private static float intShowingDelay;
// Events
public static event SimpleCallback ForcedAdDisabled;
public static event AdsModuleCallback AdProviderInitialized;
public static event AdsEventsCallback AdLoaded;
public static event AdsEventsCallback AdDisplayed;
public static event AdsEventsCallback AdClosed;
public static AdsBoolCallback InterstitialConditions;
private static AdSave save;
#region Initialize
public void Init(AdsSettings adsSettings, MonoBehaviour host)
{
if (instance != null)
{
LogManager.LogWarning("[AdsManager]: Module already exists!", LogCategory.Services);
return;
}
instance = this;
dispatcher = new MainThreadDispatcher(host);
isFirstAdLoaded = false;
debugMode = adsSettings.DebugMode;
settings = adsSettings;
intFirstStartDelay = settings.InterstitialFirstStartDelay;
intStartDelay = settings.InterstitialStartDelay;
intShowingDelay = settings.InterstitialShowingDelay;
#if MODULE_REMOTE_CONFIG
AdsRemoteConfigData remoteConfigData = RemoteConfigController.TryGetConfig<AdsRemoteConfigData>("ads");
if (remoteConfigData != null)
{
intFirstStartDelay = remoteConfigData.intFSDelay;
intStartDelay = remoteConfigData.intSDelay;
intShowingDelay = remoteConfigData.intDelay;
if (!remoteConfigData.useBanner)
settings.DisableBanner();
if (!remoteConfigData.useInterstitials)
settings.DisableInterstitial();
if (!remoteConfigData.useRewardedVideo)
settings.DisableRewardedVideo();
}
#endif
save = SaveController.GetSaveObject<AdSave>("advertisement_forced_ad");
if (settings == null)
{
Debug.LogError("[AdsManager]: Settings don't exist!");
return;
}
if (!PlayerPrefs.HasKey(FIRST_LAUNCH_PREFS))
{
lastInterstitialTime = Time.time + intFirstStartDelay;
PlayerPrefs.SetInt(FIRST_LAUNCH_PREFS, 1);
}
else
{
lastInterstitialTime = Time.time + intStartDelay;
}
// Check if ad-free period has expired and send analytics event only once
if (save.ForcedAdDisabledUntil != 0 && save.ForcedAdDisabledUntil != FORCED_AD_DISABLED_FOREVER && IsForcedAdEnabled())
{
#if MODULE_ANALYTICS
Analytics.TrackEvent(AdsAnalytics.AdFreePeriodExpired);
#endif
save.ForcedAdDisabledUntil = 0;
}
activeHandler = settings.GetContainer(settings.ActiveProvider)?.CreateHandler();
if (activeHandler != null)
{
activeHandler.LinkSettings(settings);
}
else
{
Debug.LogError($"[AdsManager]: Provider '{settings.ActiveProvider}' not found or SDK not installed!");
}
InitializeModules(settings.LoadAdsOnStart);
}
private static async void InitializeModules(bool loadAds)
{
if (activeHandler == null)
return;
LogManager.Log($"[AdsManager]: {activeHandler.ProviderName} is trying to initialize!", LogCategory.Services);
bool isInitialized = await activeHandler.InitAsync();
if (isInitialized)
{
LogManager.Log($"[AdsManager]: {activeHandler.ProviderName} initialized successfully.", LogCategory.Services);
}
else
{
Debug.LogError($"[AdsManager]: {activeHandler.ProviderName} failed to initialize.");
}
if (loadAds)
{
TryToLoadFirstAds();
}
}
#endregion
public static void Unload()
{
debugMode = false;
settings = null;
lastInterstitialTime = 0;
rewardedVideoCallback = null;
interstitalCallback = null;
dispatcher = null;
isFirstAdLoaded = false;
waitingForRewardVideoCallback = false;
isBannerActive = true;
bannerHeight = DEFAULT_BANNER_HEIGHT;
loadingCoroutine = null;
ForcedAdDisabled = null;
AdProviderInitialized = null;
AdLoaded = null;
AdDisplayed = null;
AdClosed = null;
InterstitialConditions = null;
save = null;
instance = null;
}
public static void TryToLoadFirstAds()
{
if (loadingCoroutine == null)
{
LogManager.Log("[AdsManager]: Loading first ads..", LogCategory.Services);
loadingCoroutine = Tween.InvokeCoroutine(TryToLoadAdsCoroutine());
}
}
private static IEnumerator TryToLoadAdsCoroutine()
{
int initAttemps = 0;
yield return new WaitForSeconds(1.0f);
while (!isFirstAdLoaded && initAttemps < INIT_ATTEMPTS_AMOUNT)
{
if (LoadFirstAds())
break;
yield return new WaitForSeconds(1.0f * (initAttemps + 1));
initAttemps++;
}
LogManager.Log("[AdsManager]: First ads have loaded!", LogCategory.Services);
}
private static bool LoadFirstAds()
{
if (instance == null)
return false;
if (isFirstAdLoaded)
return true;
bool isProviderInitialized = activeHandler != null && activeHandler.IsInitialized;
LogManager.Log($"[AdsManager]: LoadFirstAds — provider={settings?.ActiveProvider}, initialized={isProviderInitialized}", LogCategory.Services);
if (!isProviderInitialized)
return false;
if (settings.RewardedVideoEnabled)
RequestRewardBasedVideo();
bool isForcedAdEnabled = IsForcedAdEnabled();
LogManager.Log($"[AdsManager]: LoadFirstAds — IsForcedAdEnabled={isForcedAdEnabled}", LogCategory.Services);
if (settings.InterstitialEnabled && isForcedAdEnabled)
RequestInterstitial();
if (settings.BannerEnabled && isForcedAdEnabled)
ShowBanner();
isFirstAdLoaded = true;
return true;
}
public static void CallEventInMainThread(SimpleCallback callback)
{
dispatcher?.Dispatch(callback);
}
public static void ShowErrorMessage()
{
SystemMessage.ShowMessage("Network error. Please try again later");
}
public static bool IsProviderActive()
{
return instance != null && activeHandler != null;
}
public static bool IsProviderInitialized()
{
return instance != null && activeHandler != null && activeHandler.IsInitialized;
}
public static AdProviderHandler GetActiveProvider()
{
return activeHandler;
}
#region Interstitial
public static bool IsInterstitialLoaded()
{
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
return false;
}
if (!IsForcedAdEnabled() || activeHandler == null)
return false;
return activeHandler.IsInterstitialLoaded();
}
public static void RequestInterstitial()
{
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
return;
}
if (!IsForcedAdEnabled() || activeHandler == null || !activeHandler.IsInitialized || activeHandler.IsInterstitialLoaded())
return;
activeHandler.RequestInterstitial();
}
public static void ShowInterstitial(AdProviderHandler.AdvertisementCallback callback, string analyticsEvent = "Default", bool ignoreConditions = false)
{
interstitalCallback = callback;
interstitalCallback += (result) =>
{
if (string.IsNullOrEmpty(analyticsEvent))
analyticsEvent = "Default";
#if MODULE_ANALYTICS
Analytics.TrackEvent(AdsAnalytics.InterstitialDisplayed, new AdsAnalytics.AnalyticsIntData(analyticsEvent));
#endif
};
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
ExecuteInterstitialCallback(false);
return;
}
if (!IsForcedAdEnabled() || activeHandler == null || (!ignoreConditions && (!CheckInterstitialTime() || !CheckExtraInterstitialCondition())) || !activeHandler.IsInitialized || !activeHandler.IsInterstitialLoaded())
{
ExecuteInterstitialCallback(false);
return;
}
delayTweenCase.KillActive();
if (settings.LoadingAdDuration > 0)
{
SystemMessage.ShowLoadingPanel();
SystemMessage.ChangeLoadingMessage(settings.LoadingMessage);
delayTweenCase.KillActive();
delayTweenCase = Tween.DelayedCall(settings.LoadingAdDuration, () =>
{
activeHandler.ShowInterstitial(callback);
SystemMessage.HideLoadingPanel();
}, unscaledTime: true);
}
else
{
activeHandler.ShowInterstitial(callback);
}
}
public static void ExecuteInterstitialCallback(bool result)
{
if (interstitalCallback != null)
{
CallEventInMainThread(() => interstitalCallback.Invoke(result));
}
}
public static void SetInterstitialDelayTime(float time)
{
lastInterstitialTime = Time.time + time;
}
public static void ResetInterstitialDelayTime()
{
lastInterstitialTime = Time.time + intShowingDelay;
}
private static bool CheckInterstitialTime()
{
LogManager.Log("[AdsManager]: Interstitial Time: " + lastInterstitialTime + "; Time: " + Time.time, LogCategory.Services);
return lastInterstitialTime < Time.time;
}
public static bool CheckExtraInterstitialCondition()
{
if (InterstitialConditions != null)
{
bool state = true;
System.Delegate[] listDelegates = InterstitialConditions.GetInvocationList();
for (int i = 0; i < listDelegates.Length; i++)
{
if (!(bool)listDelegates[i].DynamicInvoke())
{
state = false;
break;
}
}
LogManager.Log("[AdsManager]: Extra condition interstitial state: " + state, LogCategory.Services);
return state;
}
return true;
}
#endregion
#region Rewarded Video
public static bool IsRewardBasedVideoLoaded()
{
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
return false;
}
if (activeHandler == null || !activeHandler.IsInitialized)
return false;
return activeHandler.IsRewardedVideoLoaded();
}
public static void RequestRewardBasedVideo()
{
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
return;
}
if (!settings.RewardedVideoEnabled || activeHandler == null || !activeHandler.IsInitialized || activeHandler.IsRewardedVideoLoaded())
return;
activeHandler.RequestRewardedVideo();
}
public static void ShowRewardBasedVideo(AdProviderHandler.AdvertisementCallback callback, string analyticsEvent = "Default", bool showErrorMessage = true)
{
rewardedVideoCallback = callback;
waitingForRewardVideoCallback = true;
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
ExecuteRewardVideoCallback(false);
return;
}
if (!settings.RewardedVideoEnabled || activeHandler == null || !activeHandler.IsInitialized || !activeHandler.IsRewardedVideoLoaded())
{
ExecuteRewardVideoCallback(false);
if (showErrorMessage)
ShowErrorMessage();
return;
}
if (string.IsNullOrEmpty(analyticsEvent))
analyticsEvent = "Default";
#if MODULE_ANALYTICS
Analytics.TrackEvent(AdsAnalytics.RVClicked, new AdsAnalytics.AnalyticsRVData(analyticsEvent));
#endif
delayTweenCase.KillActive();
if (settings.LoadingAdDuration > 0)
{
SystemMessage.ShowLoadingPanel();
SystemMessage.ChangeLoadingMessage(settings.LoadingMessage);
delayTweenCase.KillActive();
delayTweenCase = Tween.DelayedCall(settings.LoadingAdDuration, () =>
{
activeHandler.ShowRewardedVideo(callback);
SystemMessage.HideLoadingPanel();
}, unscaledTime: true);
}
else
{
activeHandler.ShowRewardedVideo(callback);
}
}
public static void ExecuteRewardVideoCallback(bool result)
{
if (rewardedVideoCallback != null && waitingForRewardVideoCallback)
{
CallEventInMainThread(() => rewardedVideoCallback.Invoke(result));
waitingForRewardVideoCallback = false;
LogManager.Log("[AdsManager]: Reward received: " + result, LogCategory.Services);
}
}
#endregion
#region Banner
public static void ShowBanner()
{
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
return;
}
if (!isBannerActive)
{
LogManager.Log("[AdsManager]: ShowBanner — skipped: isBannerActive=false", LogCategory.Services);
return;
}
bool forcedEnabled = IsForcedAdEnabled();
bool initialized = activeHandler != null && activeHandler.IsInitialized;
LogManager.Log($"[AdsManager]: ShowBanner — provider={settings?.ActiveProvider}, forcedEnabled={forcedEnabled}, initialized={initialized}", LogCategory.Services);
if (!forcedEnabled || !initialized)
return;
activeHandler.ShowBanner();
}
public static void DestroyBanner()
{
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
return;
}
if (activeHandler == null || !activeHandler.IsInitialized)
return;
activeHandler.DestroyBanner();
}
public static void HideBanner()
{
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
return;
}
if (activeHandler == null || !activeHandler.IsInitialized)
return;
activeHandler.HideBanner();
}
public static void EnableBanner()
{
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
return;
}
isBannerActive = true;
SafeAreaAdapter.Refresh(true);
ShowBanner();
}
public static void DisableBanner()
{
if (instance == null)
{
LogManager.LogWarning("[AdsManager]: Mobile monetization is disabled!", LogCategory.Services);
return;
}
isBannerActive = false;
SafeAreaAdapter.Refresh(true);
HideBanner();
}
public static void ResetBannerHeight()
{
bannerHeight = DEFAULT_BANNER_HEIGHT;
SafeAreaAdapter.Refresh(true);
}
public static void SetBannerHeight(float height)
{
bannerHeight = height;
SafeAreaAdapter.Refresh(true);
}
public static float GetBannerHeight()
{
if (Settings != null && Settings.BannerEnabled && IsForcedAdEnabled() && IsBannerActive)
{
return bannerHeight;
}
return 0.0f;
}
#endregion
#region Forced Ad
public static bool IsForcedAdEnabled()
{
if (save == null) return true;
if (save.ForcedAdDisabledUntil == FORCED_AD_DISABLED_FOREVER)
return false;
return TimeUtils.GetCurrentUnixTimestamp() >= save.ForcedAdDisabledUntil;
}
public static void DisableForcedAdForever()
{
DisableForcedAdInternal(FORCED_AD_DISABLED_FOREVER);
}
public static void DisableForcedAd(int durationSeconds)
{
if (durationSeconds < 0)
{
LogManager.LogWarning("[AdsManager]: Invalid duration for ad disable: " + durationSeconds, LogCategory.Services);
return;
}
double targetTime = TimeUtils.GetCurrentUnixTimestamp() + durationSeconds;
if (targetTime <= save.ForcedAdDisabledUntil)
return;
DisableForcedAdInternal(targetTime);
}
private static void DisableForcedAdInternal(double targetTime)
{
LogManager.Log("[AdsManager]: Banners and interstitials are disabled!", LogCategory.Services);
save.ForcedAdDisabledUntil = targetTime;
SaveController.MarkAsSaveIsRequired();
SafeAreaAdapter.Refresh(true);
ForcedAdDisabled?.Invoke();
DestroyBanner();
}
#endregion
public static void OnProviderInitialized(string providerName)
{
AdProviderInitialized?.Invoke(providerName);
}
public static void OnProviderAdLoaded(string providerName, AdType advertisingType)
{
AdLoaded?.Invoke(providerName, advertisingType);
}
public static void OnProviderAdDisplayed(string providerName, AdType advertisingType)
{
AdDisplayed?.Invoke(providerName, advertisingType);
if (advertisingType == AdType.Interstitial || advertisingType == AdType.RewardedVideo)
{
ResetInterstitialDelayTime();
}
}
public static void OnProviderAdClosed(string providerName, AdType advertisingType)
{
AdClosed?.Invoke(providerName, advertisingType);
if (advertisingType == AdType.Interstitial || advertisingType == AdType.RewardedVideo)
{
ResetInterstitialDelayTime();
}
}
public delegate void AdsModuleCallback(string providerName);
public delegate void AdsEventsCallback(string providerName, AdType advertisingType);
public delegate bool AdsBoolCallback();
}
}
// -----------------
// Advertisement v1.5.0
// -----------------