Implement TapADN commercialization module

This commit is contained in:
2026-06-04 17:16:17 +08:00
commit a671b0d272
91 changed files with 9427 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
using System;
using Dirichlet.Mediation;
using Runtime.ADAggregator;
using UnityEngine;
public sealed class TapadnAdController : IAdController
{
public static TapadnControllerOptions CurrentOptions { get; private set; }
public static string LastSdkVersion { get; private set; }
public static string LastInitError { get; private set; }
private Action<bool> _maskAction;
private Action<string, string> _logEventAction;
private ADConfig _adConfig;
private TapadnControllerOptions _options;
public void Init(ADConfig adConfig, object[] args)
{
_adConfig = adConfig;
_options = TapadnControllerOptions.Resolve(adConfig, args);
CurrentOptions = _options;
var sdkConfig = _options.BuildSdkConfig();
DirichletSdk.Init(
sdkConfig,
result =>
{
LastInitError = null;
LastSdkVersion = DirichletSdk.GetVersion();
EventLog("tapadn_init", "success", result?.Message);
Debug.Log($"[TapADN] Init success. version={LastSdkVersion}, message={result?.Message}");
if (_options.RequestPermissionOnInit)
{
DirichletSdk.RequestPermissionIfNecessary();
}
},
error =>
{
LastInitError = $"{error?.Code}:{error?.Message}";
EventLog("tapadn_init_error", error?.Code ?? "unknown", error?.Message);
Debug.LogError($"[TapADN] Init failed. code={error?.Code}, message={error?.Message}");
});
}
public void SetListener(Action<bool> adMaskAction, Action<string, string> logEventAction)
{
_maskAction = adMaskAction;
_logEventAction = logEventAction;
}
public ADPlayer CreateAdPlayer(AD_Type type)
{
switch (type)
{
case AD_Type.AwardVideo:
return new TapadnAwardVideoPlayer().Init(_adConfig?.BaseAwardAdKeyValue?.value);
case AD_Type.Interaction:
return new TapadnInteractionPlayer().Init(_adConfig?.BaseInteractionAdKeyValue?.value);
case AD_Type.Splash:
return new TapadnSplashPlayer().Init(_adConfig?.BaseSplashAdKeyValue?.value);
default:
return null;
}
}
public void EventLog(string eventTable, string eventValue, string eventMessage = null)
{
_logEventAction?.Invoke(eventTable, eventValue);
}
public void SetMask(bool isOpen)
{
_maskAction?.Invoke(isOpen);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a08780bf18a349b58a35e2dfb79d0743
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,55 @@
using System;
using Dirichlet.Mediation;
using Runtime.ADAggregator;
using UnityEngine;
internal static class TapadnAdRequestFactory
{
public static bool TryParseSlotId(string slotId, out long parsed)
{
return long.TryParse(slotId, out parsed) && parsed > 0;
}
public static DirichletAdRequest BuildRewarded(string slotId, TapadnControllerOptions options)
{
var builder = CreateBaseBuilder(slotId)
.WithUserId(ADManager.Instance.UserId)
.WithRewardName(options?.RewardName ?? "reward")
.WithRewardAmount(options?.RewardAmount ?? 1);
return builder.Build();
}
public static DirichletAdRequest BuildInterstitial(string slotId, TapadnControllerOptions options)
{
return ApplyExpressSize(CreateBaseBuilder(slotId), options).Build();
}
public static DirichletAdRequest BuildSplash(string slotId, TapadnControllerOptions options)
{
var builder = CreateBaseBuilder(slotId);
var width = options?.ExpressWidth ?? Screen.width;
var height = options?.ExpressHeight ?? Screen.height;
return builder.WithExpressViewSize(width, height).Build();
}
private static DirichletAdRequest.Builder CreateBaseBuilder(string slotId)
{
if (!TryParseSlotId(slotId, out var parsed))
{
throw new ArgumentException($"TapADN slot id must be a positive integer. Current value: {slotId}", nameof(slotId));
}
return new DirichletAdRequest.Builder().WithSpaceId(parsed);
}
private static DirichletAdRequest.Builder ApplyExpressSize(DirichletAdRequest.Builder builder, TapadnControllerOptions options)
{
if (options?.ExpressWidth != null || options?.ExpressHeight != null)
{
builder.WithExpressViewSize(options?.ExpressWidth ?? Screen.width, options?.ExpressHeight ?? Screen.height);
}
return builder;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 01ac342b5e1c49cf87b649eddcd34f7c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,159 @@
using System;
using Dirichlet.Mediation;
using Runtime.ADAggregator;
using UnityEngine;
public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAutoAdListener
{
private DirichletAdNative _adNative;
private DirichletRewardVideoAd _loadedAd;
private bool _rewardVerified;
public override int MaxLoadAttempts => TapadnAdController.CurrentOptions?.RewardedMaxLoadAttempts ?? base.MaxLoadAttempts;
public override float LoadRetryDelaySeconds => Math.Max(0f, (TapadnAdController.CurrentOptions?.RewardedLoadRetryDelayMs ?? 500) / 1000f);
public override float ShowPendingTimeoutSeconds => Math.Max(1f, (TapadnAdController.CurrentOptions?.RewardedShowTimeoutMs ?? 20000) / 1000f);
public override bool AutoPreloadOnInit => TapadnAdController.CurrentOptions?.RewardedPrewarmOnInit ?? false;
public override void OnInit()
{
_adNative = DirichletAdManager.CreateAdNative();
}
public override bool IsReadly()
{
if (UseAutoLoad())
{
return TapadnAdRequestFactory.TryParseSlotId(Key, out _);
}
if (_loadedAd != null && _loadedAd.IsLoaded && _loadedAd.IsValid)
{
curState = 2;
return true;
}
return false;
}
public override void LoadAD()
{
if (!TapadnAdRequestFactory.TryParseSlotId(Key, out _))
{
Debug.LogError($"[TapADN] Invalid rewarded slot id: {Key}");
curState = 0;
return;
}
if (UseAutoLoad())
{
curState = 2;
try
{
_adNative.PreLoad(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), 3);
}
catch (Exception exception)
{
Debug.LogWarning($"[TapADN] Rewarded preload skipped: {exception.Message}");
}
return;
}
if (curState == 1 || IsReadly())
{
return;
}
curState = 1;
_adNative.LoadRewardVideoAd(
TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions),
ad =>
{
_loadedAd?.Destroy();
_loadedAd = ad;
_loadedAd.Shown += OnManualShown;
_loadedAd.Clicked += OnManualClicked;
_loadedAd.RewardVerified += OnManualRewardVerify;
_loadedAd.Closed += OnManualClosed;
curState = 2;
Debug.Log($"[TapADN] Rewarded loaded. slot={Key}");
},
error =>
{
curState = 0;
Debug.LogError($"[TapADN] Rewarded load failed. code={error.Code}, message={error.Message}");
});
}
public override void ShowAD(Action onClose, Action<bool> onVideoComplete)
{
adListener.onClose = onClose;
adListener.onVideoComplete = onVideoComplete;
_rewardVerified = false;
curState = 0;
if (UseAutoLoad())
{
_adNative.ShowRewardVideoAutoAd(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), this);
return;
}
if (_loadedAd == null || !_loadedAd.Show())
{
adListener.OnShowError();
return;
}
}
public void OnError(DirichletError error)
{
curState = 0;
Debug.LogError($"[TapADN] Rewarded show failed. code={error?.Code}, message={error?.Message}");
adListener.OnShowError();
}
public void OnAdShow()
{
NotifyShowStarted();
}
public void OnAdClose()
{
adListener.OnRewardVerify(_rewardVerified, TapadnAdController.CurrentOptions?.RewardAmount ?? 1, TapadnAdController.CurrentOptions?.RewardName ?? string.Empty);
adListener.OnAdClose();
}
public void OnRewardVerify(DirichletRewardVerificationEventArgs args)
{
_rewardVerified = args != null && args.IsVerified;
}
public void OnAdClick()
{
}
private bool UseAutoLoad()
{
return TapadnAdController.CurrentOptions?.RewardedAutoLoad ?? true;
}
private void OnManualShown()
{
NotifyShowStarted();
}
private void OnManualClicked()
{
}
private void OnManualRewardVerify(DirichletRewardVerificationEventArgs args)
{
_rewardVerified = args != null && args.IsVerified;
}
private void OnManualClosed()
{
_loadedAd?.Destroy();
_loadedAd = null;
OnAdClose();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fb7643101da94ca69dc8f99128d4e759
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using System;
using Runtime.ADAggregator;
public static class TapadnCommercialization
{
public static TapadnAdController CreateController()
{
return new TapadnAdController();
}
public static void InitADManager(Action onCallback, string userId, ADConfig adConfig, params object[] args)
{
ADManager.Instance.Init(onCallback, userId, adConfig, CreateController(), args);
}
public static ADConfig CreateConfig(
string mediaId,
string mediaKey,
string mediaName,
string rewardSlotId,
string interstitialSlotId = null,
string splashSlotId = null)
{
var config = UnityEngine.ScriptableObject.CreateInstance<ADConfig>();
config.ConfigName = "TapADN";
config.Id = mediaId;
config.Key = mediaKey;
config.Key2 = mediaName;
config.BaseAwardAdKeyValue = new AdKeyValue { key = "reward", value = rewardSlotId };
config.BaseInteractionAdKeyValue = new AdKeyValue { key = "interaction", value = interstitialSlotId };
config.BaseSplashAdKeyValue = new AdKeyValue { key = "splash", value = splashSlotId };
return config;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 295d10d222a8496e872b02eff3556e86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,370 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Dirichlet.Mediation;
using Runtime.ADAggregator;
using UnityEngine;
public sealed class TapadnControllerOptions
{
public const string MediaNameKey = "tapadn.media_name";
public const string MediaIdKey = "tapadn.media_id";
public const string MediaKeyKey = "tapadn.media_key";
public const string ChannelKey = "tapadn.channel";
public const string SubChannelKey = "tapadn.sub_channel";
public const string DebugKey = "tapadn.debug";
public const string TapClientIdKey = "tapadn.tap_client_id";
public const string ShakeEnabledKey = "tapadn.shake_enabled";
public const string CustomConfigJsonKey = "tapadn.custom_config_json";
public const string DataJsonKey = "tapadn.data_json";
public const string ATagsKey = "tapadn.atags";
public const string AllowIdfaAccessKey = "tapadn.allow_idfa_access";
public const string RequestPermissionOnInitKey = "tapadn.request_permission_on_init";
public const string RewardedAutoLoadKey = "tapadn.rewarded_auto_load";
public const string RewardedPrewarmOnInitKey = "tapadn.rewarded_prewarm_on_init";
public const string RewardedMaxLoadAttemptsKey = "tapadn.rewarded_max_load_attempts";
public const string RewardedLoadRetryDelayMsKey = "tapadn.rewarded_load_retry_delay_ms";
public const string RewardedShowTimeoutMsKey = "tapadn.rewarded_show_timeout_ms";
public const string RewardNameKey = "tapadn.reward_name";
public const string RewardAmountKey = "tapadn.reward_amount";
public const string InterstitialAutoLoadKey = "tapadn.interstitial_auto_load";
public const string InterstitialPrewarmOnInitKey = "tapadn.interstitial_prewarm_on_init";
public const string InterstitialMaxLoadAttemptsKey = "tapadn.interstitial_max_load_attempts";
public const string InterstitialLoadRetryDelayMsKey = "tapadn.interstitial_load_retry_delay_ms";
public const string InterstitialShowTimeoutMsKey = "tapadn.interstitial_show_timeout_ms";
public const string SplashAutoLoadKey = "tapadn.splash_auto_load";
public const string SplashPrewarmOnInitKey = "tapadn.splash_prewarm_on_init";
public const string SplashMaxLoadAttemptsKey = "tapadn.splash_max_load_attempts";
public const string SplashLoadRetryDelayMsKey = "tapadn.splash_load_retry_delay_ms";
public const string SplashShowTimeoutMsKey = "tapadn.splash_show_timeout_ms";
public const string ExpressWidthKey = "tapadn.express_width";
public const string ExpressHeightKey = "tapadn.express_height";
public long MediaId { get; set; }
public string MediaName { get; set; }
public string MediaKey { get; set; }
public string Channel { get; set; } = "default";
public string SubChannel { get; set; }
public bool Debug { get; set; }
public string TapClientId { get; set; }
public bool ShakeEnabled { get; set; } = true;
public string CustomConfigJson { get; set; }
public string DataJson { get; set; }
public string ATags { get; set; }
public bool AllowIDFAAccess { get; set; } = true;
public bool RequestPermissionOnInit { get; set; }
public bool RewardedAutoLoad { get; set; } = true;
public bool RewardedPrewarmOnInit { get; set; }
public int RewardedMaxLoadAttempts { get; set; } = 1;
public int RewardedLoadRetryDelayMs { get; set; } = 500;
public int RewardedShowTimeoutMs { get; set; } = 20000;
public string RewardName { get; set; } = "reward";
public int RewardAmount { get; set; } = 1;
public bool InterstitialAutoLoad { get; set; } = true;
public bool InterstitialPrewarmOnInit { get; set; }
public int InterstitialMaxLoadAttempts { get; set; } = 1;
public int InterstitialLoadRetryDelayMs { get; set; } = 500;
public int InterstitialShowTimeoutMs { get; set; } = 20000;
public bool SplashAutoLoad { get; set; } = true;
public bool SplashPrewarmOnInit { get; set; }
public int SplashMaxLoadAttempts { get; set; } = 1;
public int SplashLoadRetryDelayMs { get; set; } = 500;
public int SplashShowTimeoutMs { get; set; } = 20000;
public int? ExpressWidth { get; set; }
public int? ExpressHeight { get; set; }
public static TapadnControllerOptions Resolve(ADConfig adConfig, object[] args)
{
var options = new TapadnControllerOptions();
options.ApplyAdConfig(adConfig);
options.ApplyLegacyArgs(args);
if (args == null)
{
return options;
}
foreach (var arg in args)
{
switch (arg)
{
case TapadnControllerOptions explicitOptions:
options.ApplyExplicitOptions(explicitOptions);
break;
case IDictionary dictionary:
options.ApplyDictionary(dictionary);
break;
}
}
return options;
}
public DirichletAdConfig BuildSdkConfig()
{
return new DirichletAdConfig.Builder()
.WithMediaId(MediaId)
.WithMediaName(string.IsNullOrWhiteSpace(MediaName) ? Application.productName : MediaName)
.WithMediaKey(MediaKey)
.WithGameChannel(string.IsNullOrWhiteSpace(Channel) ? "default" : Channel)
.WithSubChannel(SubChannel)
.EnableDebug(Debug)
.WithTapClientId(TapClientId)
.ShakeEnabled(ShakeEnabled)
.WithCustomConfigJson(CustomConfigJson)
.WithDataJson(DataJson)
.AllowIDFAAccess(AllowIDFAAccess)
.WithATags(ATags)
.Build();
}
private void ApplyAdConfig(ADConfig adConfig)
{
if (adConfig == null)
{
return;
}
MediaId = ParseLong(adConfig.Id) ?? MediaId;
MediaKey = string.IsNullOrWhiteSpace(adConfig.Key) ? MediaKey : adConfig.Key.Trim();
MediaName = string.IsNullOrWhiteSpace(adConfig.Key2) ? MediaName : adConfig.Key2.Trim();
ApplyCommonKeyValues(adConfig.CommonKeyValues);
}
private void ApplyCommonKeyValues(List<AdKeyValue> keyValues)
{
if (keyValues == null || keyValues.Count == 0)
{
return;
}
var map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var keyValue in keyValues)
{
if (keyValue == null || string.IsNullOrWhiteSpace(keyValue.key))
{
continue;
}
map[keyValue.key.Trim()] = keyValue.value;
}
ApplyMap(map);
}
private void ApplyLegacyArgs(object[] args)
{
if (args == null || args.Length == 0)
{
return;
}
if (args.Length > 0 && args[0] is string channel)
{
Channel = channel;
}
if (args.Length > 1 && TryConvertBool(args[1], out var debug))
{
Debug = debug;
}
}
private void ApplyExplicitOptions(TapadnControllerOptions incoming)
{
if (incoming == null)
{
return;
}
MediaId = incoming.MediaId > 0 ? incoming.MediaId : MediaId;
MediaName = incoming.MediaName ?? MediaName;
MediaKey = incoming.MediaKey ?? MediaKey;
Channel = incoming.Channel ?? Channel;
SubChannel = incoming.SubChannel ?? SubChannel;
Debug = incoming.Debug;
TapClientId = incoming.TapClientId ?? TapClientId;
ShakeEnabled = incoming.ShakeEnabled;
CustomConfigJson = incoming.CustomConfigJson ?? CustomConfigJson;
DataJson = incoming.DataJson ?? DataJson;
ATags = incoming.ATags ?? ATags;
AllowIDFAAccess = incoming.AllowIDFAAccess;
RequestPermissionOnInit = incoming.RequestPermissionOnInit;
RewardedAutoLoad = incoming.RewardedAutoLoad;
RewardedPrewarmOnInit = incoming.RewardedPrewarmOnInit;
RewardedMaxLoadAttempts = incoming.RewardedMaxLoadAttempts;
RewardedLoadRetryDelayMs = incoming.RewardedLoadRetryDelayMs;
RewardedShowTimeoutMs = incoming.RewardedShowTimeoutMs;
RewardName = incoming.RewardName ?? RewardName;
RewardAmount = incoming.RewardAmount;
InterstitialAutoLoad = incoming.InterstitialAutoLoad;
InterstitialPrewarmOnInit = incoming.InterstitialPrewarmOnInit;
InterstitialMaxLoadAttempts = incoming.InterstitialMaxLoadAttempts;
InterstitialLoadRetryDelayMs = incoming.InterstitialLoadRetryDelayMs;
InterstitialShowTimeoutMs = incoming.InterstitialShowTimeoutMs;
SplashAutoLoad = incoming.SplashAutoLoad;
SplashPrewarmOnInit = incoming.SplashPrewarmOnInit;
SplashMaxLoadAttempts = incoming.SplashMaxLoadAttempts;
SplashLoadRetryDelayMs = incoming.SplashLoadRetryDelayMs;
SplashShowTimeoutMs = incoming.SplashShowTimeoutMs;
ExpressWidth = incoming.ExpressWidth ?? ExpressWidth;
ExpressHeight = incoming.ExpressHeight ?? ExpressHeight;
}
private void ApplyDictionary(IDictionary dictionary)
{
if (dictionary == null || dictionary.Count == 0)
{
return;
}
var map = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (DictionaryEntry entry in dictionary)
{
if (entry.Key == null)
{
continue;
}
map[entry.Key.ToString()] = ConvertDictionaryValue(entry.Value);
}
ApplyMap(map);
}
private void ApplyMap(IDictionary<string, string> map)
{
MediaId = GetLong(map, MediaIdKey, "media_id") ?? MediaId;
MediaName = GetString(map, MediaNameKey, "media_name") ?? MediaName;
MediaKey = GetString(map, MediaKeyKey, "media_key") ?? MediaKey;
Channel = GetString(map, ChannelKey, "channel") ?? Channel;
SubChannel = GetString(map, SubChannelKey, "sub_channel") ?? SubChannel;
Debug = GetBool(map, DebugKey, "debug") ?? Debug;
TapClientId = GetString(map, TapClientIdKey, "tap_client_id") ?? TapClientId;
ShakeEnabled = GetBool(map, ShakeEnabledKey) ?? ShakeEnabled;
CustomConfigJson = GetString(map, CustomConfigJsonKey) ?? CustomConfigJson;
DataJson = GetString(map, DataJsonKey) ?? DataJson;
ATags = GetString(map, ATagsKey) ?? ATags;
AllowIDFAAccess = GetBool(map, AllowIdfaAccessKey) ?? AllowIDFAAccess;
RequestPermissionOnInit = GetBool(map, RequestPermissionOnInitKey) ?? RequestPermissionOnInit;
RewardedAutoLoad = GetBool(map, RewardedAutoLoadKey) ?? RewardedAutoLoad;
RewardedPrewarmOnInit = GetBool(map, RewardedPrewarmOnInitKey) ?? RewardedPrewarmOnInit;
RewardedMaxLoadAttempts = GetInt(map, RewardedMaxLoadAttemptsKey) ?? RewardedMaxLoadAttempts;
RewardedLoadRetryDelayMs = GetInt(map, RewardedLoadRetryDelayMsKey) ?? RewardedLoadRetryDelayMs;
RewardedShowTimeoutMs = GetInt(map, RewardedShowTimeoutMsKey) ?? RewardedShowTimeoutMs;
RewardName = GetString(map, RewardNameKey) ?? RewardName;
RewardAmount = GetInt(map, RewardAmountKey) ?? RewardAmount;
InterstitialAutoLoad = GetBool(map, InterstitialAutoLoadKey) ?? InterstitialAutoLoad;
InterstitialPrewarmOnInit = GetBool(map, InterstitialPrewarmOnInitKey) ?? InterstitialPrewarmOnInit;
InterstitialMaxLoadAttempts = GetInt(map, InterstitialMaxLoadAttemptsKey) ?? InterstitialMaxLoadAttempts;
InterstitialLoadRetryDelayMs = GetInt(map, InterstitialLoadRetryDelayMsKey) ?? InterstitialLoadRetryDelayMs;
InterstitialShowTimeoutMs = GetInt(map, InterstitialShowTimeoutMsKey) ?? InterstitialShowTimeoutMs;
SplashAutoLoad = GetBool(map, SplashAutoLoadKey) ?? SplashAutoLoad;
SplashPrewarmOnInit = GetBool(map, SplashPrewarmOnInitKey) ?? SplashPrewarmOnInit;
SplashMaxLoadAttempts = GetInt(map, SplashMaxLoadAttemptsKey) ?? SplashMaxLoadAttempts;
SplashLoadRetryDelayMs = GetInt(map, SplashLoadRetryDelayMsKey) ?? SplashLoadRetryDelayMs;
SplashShowTimeoutMs = GetInt(map, SplashShowTimeoutMsKey) ?? SplashShowTimeoutMs;
ExpressWidth = GetInt(map, ExpressWidthKey) ?? ExpressWidth;
ExpressHeight = GetInt(map, ExpressHeightKey) ?? ExpressHeight;
}
private static string GetString(IDictionary<string, string> map, params string[] keys)
{
foreach (var key in keys)
{
if (!string.IsNullOrWhiteSpace(key) &&
map.TryGetValue(key, out var value) &&
!string.IsNullOrWhiteSpace(value))
{
return value.Trim();
}
}
return null;
}
private static bool? GetBool(IDictionary<string, string> map, params string[] keys)
{
var value = GetString(map, keys);
return TryConvertBool(value, out var result) ? result : null;
}
private static int? GetInt(IDictionary<string, string> map, params string[] keys)
{
var value = GetString(map, keys);
return int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) ? result : (int?)null;
}
private static long? GetLong(IDictionary<string, string> map, params string[] keys)
{
return ParseLong(GetString(map, keys));
}
private static long? ParseLong(string value)
{
return long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) ? result : (long?)null;
}
private static bool TryConvertBool(object value, out bool result)
{
switch (value)
{
case bool boolValue:
result = boolValue;
return true;
case string stringValue:
if (bool.TryParse(stringValue, out result))
{
return true;
}
if (string.Equals(stringValue, "1", StringComparison.OrdinalIgnoreCase))
{
result = true;
return true;
}
if (string.Equals(stringValue, "0", StringComparison.OrdinalIgnoreCase))
{
result = false;
return true;
}
break;
}
result = false;
return false;
}
private static string ConvertDictionaryValue(object value)
{
if (value == null)
{
return null;
}
if (value is string stringValue)
{
return stringValue;
}
if (value is IEnumerable enumerable)
{
var items = new List<string>();
foreach (var item in enumerable)
{
if (item != null)
{
items.Add(item.ToString());
}
}
return string.Join(",", items.ToArray());
}
return value.ToString();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cb9de9cc991b4649826dc9683c8ec78e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using System;
using Dirichlet.Mediation;
using Runtime.ADAggregator;
using UnityEngine;
public sealed class TapadnInteractionPlayer : ADPlayer, IDirichletInterstitialAutoAdListener
{
private DirichletAdNative _adNative;
private DirichletInterstitialAd _loadedAd;
public override int MaxLoadAttempts => TapadnAdController.CurrentOptions?.InterstitialMaxLoadAttempts ?? base.MaxLoadAttempts;
public override float LoadRetryDelaySeconds => Math.Max(0f, (TapadnAdController.CurrentOptions?.InterstitialLoadRetryDelayMs ?? 500) / 1000f);
public override float ShowPendingTimeoutSeconds => Math.Max(1f, (TapadnAdController.CurrentOptions?.InterstitialShowTimeoutMs ?? 20000) / 1000f);
public override bool AutoPreloadOnInit => TapadnAdController.CurrentOptions?.InterstitialPrewarmOnInit ?? false;
public override void OnInit()
{
_adNative = DirichletAdManager.CreateAdNative();
}
public override bool IsReadly()
{
if (UseAutoLoad())
{
return TapadnAdRequestFactory.TryParseSlotId(Key, out _);
}
if (_loadedAd != null && _loadedAd.IsLoaded && _loadedAd.IsValid)
{
curState = 2;
return true;
}
return false;
}
public override void LoadAD()
{
if (!TapadnAdRequestFactory.TryParseSlotId(Key, out _))
{
Debug.LogError($"[TapADN] Invalid interstitial slot id: {Key}");
curState = 0;
return;
}
if (UseAutoLoad())
{
curState = 2;
return;
}
if (curState == 1 || IsReadly())
{
return;
}
curState = 1;
_adNative.LoadInterstitialAd(
TapadnAdRequestFactory.BuildInterstitial(Key, TapadnAdController.CurrentOptions),
ad =>
{
_loadedAd?.Destroy();
_loadedAd = ad;
_loadedAd.Shown += OnManualShown;
_loadedAd.Clicked += OnManualClicked;
_loadedAd.Closed += OnManualClosed;
curState = 2;
Debug.Log($"[TapADN] Interstitial loaded. slot={Key}");
},
error =>
{
curState = 0;
Debug.LogError($"[TapADN] Interstitial load failed. code={error.Code}, message={error.Message}");
});
}
public override void ShowAD(Action onClose, Action<bool> onVideoComplete)
{
adListener.onClose = onClose;
adListener.onVideoComplete = onVideoComplete;
curState = 0;
if (UseAutoLoad())
{
_adNative.ShowInterstitialAutoAd(TapadnAdRequestFactory.BuildInterstitial(Key, TapadnAdController.CurrentOptions), this);
return;
}
if (_loadedAd == null || !_loadedAd.Show())
{
adListener.OnShowError();
}
}
public void OnError(DirichletError error)
{
curState = 0;
Debug.LogError($"[TapADN] Interstitial show failed. code={error?.Code}, message={error?.Message}");
adListener.OnShowError();
}
public void OnAdShow()
{
NotifyShowStarted();
}
public void OnAdClose()
{
adListener.OnAdClose();
adListener.OnShowComplete();
}
public void OnAdClick()
{
}
private bool UseAutoLoad()
{
return TapadnAdController.CurrentOptions?.InterstitialAutoLoad ?? true;
}
private void OnManualShown()
{
NotifyShowStarted();
}
private void OnManualClicked()
{
}
private void OnManualClosed()
{
_loadedAd?.Destroy();
_loadedAd = null;
OnAdClose();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b422dcac50a0451a92815d54329fce8b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,137 @@
using System;
using Dirichlet.Mediation;
using Runtime.ADAggregator;
using UnityEngine;
public sealed class TapadnSplashPlayer : ADPlayer, IDirichletSplashAutoAdListener
{
private DirichletAdNative _adNative;
private DirichletSplashAd _loadedAd;
public override int MaxLoadAttempts => TapadnAdController.CurrentOptions?.SplashMaxLoadAttempts ?? base.MaxLoadAttempts;
public override float LoadRetryDelaySeconds => Math.Max(0f, (TapadnAdController.CurrentOptions?.SplashLoadRetryDelayMs ?? 500) / 1000f);
public override float ShowPendingTimeoutSeconds => Math.Max(1f, (TapadnAdController.CurrentOptions?.SplashShowTimeoutMs ?? 20000) / 1000f);
public override bool AutoPreloadOnInit => TapadnAdController.CurrentOptions?.SplashPrewarmOnInit ?? false;
public override void OnInit()
{
_adNative = DirichletAdManager.CreateAdNative();
}
public override bool IsReadly()
{
if (UseAutoLoad())
{
return TapadnAdRequestFactory.TryParseSlotId(Key, out _);
}
if (_loadedAd != null && _loadedAd.IsLoaded && _loadedAd.IsValid)
{
curState = 2;
return true;
}
return false;
}
public override void LoadAD()
{
if (!TapadnAdRequestFactory.TryParseSlotId(Key, out _))
{
Debug.LogError($"[TapADN] Invalid splash slot id: {Key}");
curState = 0;
return;
}
if (UseAutoLoad())
{
curState = 2;
return;
}
if (curState == 1 || IsReadly())
{
return;
}
curState = 1;
_adNative.LoadSplashAd(
TapadnAdRequestFactory.BuildSplash(Key, TapadnAdController.CurrentOptions),
ad =>
{
_loadedAd?.Destroy();
_loadedAd = ad;
_loadedAd.Shown += OnManualShown;
_loadedAd.Clicked += OnManualClicked;
_loadedAd.Closed += OnManualClosed;
curState = 2;
Debug.Log($"[TapADN] Splash loaded. slot={Key}");
},
error =>
{
curState = 0;
Debug.LogError($"[TapADN] Splash load failed. code={error.Code}, message={error.Message}");
});
}
public override void ShowAD(Action onClose, Action<bool> onVideoComplete)
{
adListener.onClose = onClose;
adListener.onVideoComplete = onVideoComplete;
curState = 0;
if (UseAutoLoad())
{
_adNative.ShowSplashAutoAd(TapadnAdRequestFactory.BuildSplash(Key, TapadnAdController.CurrentOptions), this);
return;
}
if (_loadedAd == null || !_loadedAd.Show())
{
adListener.OnShowError();
}
}
public void OnError(DirichletError error)
{
curState = 0;
Debug.LogError($"[TapADN] Splash show failed. code={error?.Code}, message={error?.Message}");
adListener.OnShowError();
}
public void OnAdShow()
{
NotifyShowStarted();
}
public void OnAdClose()
{
adListener.OnAdClose();
adListener.OnShowComplete();
}
public void OnAdClick()
{
}
private bool UseAutoLoad()
{
return TapadnAdController.CurrentOptions?.SplashAutoLoad ?? true;
}
private void OnManualShown()
{
NotifyShowStarted();
}
private void OnManualClicked()
{
}
private void OnManualClosed()
{
_loadedAd?.Destroy();
_loadedAd = null;
OnAdClose();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 372f8c753ddd48d9a9e08012999a05f4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: