release: 1.0.4

This commit is contained in:
2026-06-17 15:40:25 +08:00
parent 8dc806c1eb
commit 18af360571
8 changed files with 432 additions and 92 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Dirichlet.Mediation;
using Runtime.ADAggregator;
using UnityEngine;
@@ -7,8 +8,11 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
{
private const float RewardCloseSettleDelaySeconds = 0.25f;
private readonly Dictionary<string, RewardedSlotCache> _slotCaches = new Dictionary<string, RewardedSlotCache>(StringComparer.Ordinal);
private DirichletAdNative _adNative;
private DirichletRewardVideoAd _loadedAd;
private string _defaultSlotId;
private string _activeSlotId;
private bool _rewardVerified;
private bool _rewardVerifyReceived;
private bool _closePendingRewardVerify;
@@ -22,30 +26,46 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
public override void OnInit()
{
_defaultSlotId = Key;
_adNative = DirichletAdManager.CreateAdNative();
}
public override bool IsReadly()
{
var slotId = ResolveCurrentSlotId();
if (UseAutoLoad())
{
return TapadnAdRequestFactory.TryParseSlotId(Key, out _);
return TapadnAdRequestFactory.TryParseSlotId(slotId, out _);
}
if (_loadedAd != null && _loadedAd.IsLoaded && _loadedAd.IsValid)
var cache = GetCache(slotId);
if (IsCacheReady(cache))
{
curState = 2;
return true;
}
if (cache != null && cache.Loading)
{
curState = 1;
return false;
}
if (cache != null)
{
RemoveCache(slotId);
}
curState = 0;
return false;
}
public override void LoadAD()
{
if (!TapadnAdRequestFactory.TryParseSlotId(Key, out _))
var slotId = ResolveCurrentSlotId();
if (!TapadnAdRequestFactory.TryParseSlotId(slotId, out _))
{
Debug.LogError($"[TapADN] Invalid rewarded slot id: {Key}");
Debug.LogError($"[TapADN] Invalid rewarded slot id: {slotId}");
curState = 0;
return;
}
@@ -55,7 +75,7 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
curState = 2;
try
{
_adNative.PreLoad(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), 3);
_adNative.PreLoad(TapadnAdRequestFactory.BuildRewarded(slotId, TapadnAdController.CurrentOptions), 3);
}
catch (Exception exception)
{
@@ -64,33 +84,37 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
return;
}
if (curState == 1 || IsReadly())
var cache = GetCache(slotId);
if (cache != null && (cache.Loading || IsCacheReady(cache)))
{
curState = cache.Loading ? 1 : 2;
return;
}
cache = new RewardedSlotCache { Loading = true };
_slotCaches[slotId] = cache;
curState = 1;
TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.AwardVideo, AdScene);
TapadnSmartLoadOrchestrator.OnLoadStarted(AD_Type.AwardVideo, AdScene, slotId);
_adNative.LoadRewardVideoAd(
TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions),
TapadnAdRequestFactory.BuildRewarded(slotId, TapadnAdController.CurrentOptions),
ad =>
{
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, true);
_loadedAd?.Destroy();
_loadedAd = ad;
_loadedAd.Shown += OnManualShown;
_loadedAd.Clicked += OnManualClicked;
_loadedAd.ShowFailed += OnManualShowFailed;
_loadedAd.RewardVerified += OnManualRewardVerify;
_loadedAd.Closed += OnManualClosed;
curState = 2;
Debug.Log($"[TapADN] Rewarded loaded. slot={Key}");
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, true, slotId);
DestroyCachedAd(cache);
cache.Ad = ad;
cache.Loading = false;
cache.LoadedUnix = GetNowUnixSeconds();
RegisterManualEvents(slotId, cache.Ad);
ScheduleCacheExpiration(slotId, cache);
curState = string.Equals(slotId, ResolveCurrentSlotId(), StringComparison.Ordinal) ? 2 : curState;
Debug.Log($"[TapADN] Rewarded loaded. scene={NormalizeScenario(AdScene)}, slot={slotId}");
},
error =>
{
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, false);
curState = 0;
Debug.LogError($"[TapADN] Rewarded load failed. code={error.Code}, message={error.Message}");
TapadnSmartLoadOrchestrator.OnLoadResult(AD_Type.AwardVideo, AdScene, false, slotId);
RemoveCache(slotId);
curState = string.Equals(slotId, ResolveCurrentSlotId(), StringComparison.Ordinal) ? 0 : curState;
Debug.LogError($"[TapADN] Rewarded load failed. slot={slotId}, code={error.Code}, message={error.Message}");
});
}
@@ -104,16 +128,20 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
_showSettled = false;
_rewardCloseSettleHandler?.Kill();
_rewardCloseSettleHandler = null;
_activeSlotId = ResolveCurrentSlotId();
Key = _activeSlotId;
curState = 0;
if (UseAutoLoad())
{
_adNative.ShowRewardVideoAutoAd(TapadnAdRequestFactory.BuildRewarded(Key, TapadnAdController.CurrentOptions), this);
_adNative.ShowRewardVideoAutoAd(TapadnAdRequestFactory.BuildRewarded(_activeSlotId, TapadnAdController.CurrentOptions), this);
return;
}
if (_loadedAd == null || !_loadedAd.Show())
var cache = GetCache(_activeSlotId);
if (!IsCacheReady(cache) || cache.Ad == null || !cache.Ad.Show())
{
RemoveCache(_activeSlotId);
OnError(new DirichletError("show_failed", "ShowRewardVideoAd returned false"));
return;
}
@@ -130,14 +158,14 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
_rewardCloseSettleHandler?.Kill();
_rewardCloseSettleHandler = null;
curState = 0;
TapadnSmartLoadOrchestrator.OnShowError(AD_Type.AwardVideo, AdScene);
Debug.LogError($"[TapADN] Rewarded show failed. code={error?.Code}, message={error?.Message}");
TapadnSmartLoadOrchestrator.OnShowError(AD_Type.AwardVideo, AdScene, _activeSlotId);
Debug.LogError($"[TapADN] Rewarded show failed. slot={_activeSlotId}, code={error?.Code}, message={error?.Message}");
adListener.OnShowError();
}
public void OnAdShow()
{
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.AwardVideo, AdScene);
TapadnSmartLoadOrchestrator.OnShowStart(AD_Type.AwardVideo, AdScene, _activeSlotId);
NotifyShowStarted();
}
@@ -175,12 +203,23 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
public override void OnPlayRequestStarted()
{
TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.AwardVideo, AdScene, !UseAutoLoad() && IsReadly());
var slotId = ResolveCurrentSlotId();
Key = slotId;
TapadnSmartLoadOrchestrator.OnPlayRequestStarted(AD_Type.AwardVideo, AdScene, !UseAutoLoad() && IsReadly(), slotId);
}
public override void EnterAdScenario(string scenario)
{
TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.AwardVideo, scenario, Key);
AdScene = NormalizeScenario(scenario);
var slotId = ResolveCurrentSlotId();
Key = slotId;
TapadnSmartLoadOrchestrator.OnEnterAdScenario(AD_Type.AwardVideo, AdScene, slotId);
}
private string ResolveCurrentSlotId()
{
var slotId = TapadnAdController.CurrentOptions?.ResolveRewardedSlotId(_defaultSlotId, AdScene) ?? _defaultSlotId;
return string.IsNullOrWhiteSpace(slotId) ? _defaultSlotId : slotId.Trim();
}
private bool UseAutoLoad()
@@ -188,8 +227,66 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
return TapadnAdController.CurrentOptions?.RewardedAutoLoad ?? true;
}
private void OnManualShown()
private RewardedSlotCache GetCache(string slotId)
{
return !string.IsNullOrWhiteSpace(slotId) && _slotCaches.TryGetValue(slotId, out var cache) ? cache : null;
}
private bool IsCacheReady(RewardedSlotCache cache)
{
if (cache == null || cache.Loading || cache.Ad == null || !cache.Ad.IsLoaded || !cache.Ad.IsValid)
{
return false;
}
var maxAgeSeconds = TapadnAdController.CurrentOptions?.RewardedCacheMaxAgeSeconds ?? 0;
return maxAgeSeconds <= 0 || GetNowUnixSeconds() - cache.LoadedUnix <= maxAgeSeconds;
}
private void RegisterManualEvents(string slotId, DirichletRewardVideoAd ad)
{
if (ad == null)
{
return;
}
ad.Shown += () => OnManualShown(slotId);
ad.Clicked += OnManualClicked;
ad.ShowFailed += error => OnManualShowFailed(slotId, error);
ad.RewardVerified += OnManualRewardVerify;
ad.Closed += () => OnManualClosed(slotId);
}
private void ScheduleCacheExpiration(string slotId, RewardedSlotCache cache)
{
cache.ExpireHandler?.Kill();
cache.ExpireHandler = null;
var maxAgeSeconds = TapadnAdController.CurrentOptions?.RewardedCacheMaxAgeSeconds ?? 600;
if (maxAgeSeconds <= 0)
{
return;
}
cache.ExpireHandler = ADManager.Instance.CreateTimer(maxAgeSeconds, () =>
{
if (!ReferenceEquals(GetCache(slotId), cache))
{
return;
}
Debug.Log($"[TapADN] Rewarded cache expired. slot={slotId}, maxAgeSeconds={maxAgeSeconds}");
RemoveCache(slotId);
if (string.Equals(slotId, ResolveCurrentSlotId(), StringComparison.Ordinal))
{
curState = 0;
}
});
}
private void OnManualShown(string slotId)
{
_activeSlotId = slotId;
OnAdShow();
}
@@ -197,8 +294,9 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
{
}
private void OnManualShowFailed(DirichletError error)
private void OnManualShowFailed(string slotId, DirichletError error)
{
RemoveCache(slotId);
OnError(error);
}
@@ -207,13 +305,49 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
OnRewardVerify(args);
}
private void OnManualClosed()
private void OnManualClosed(string slotId)
{
_loadedAd?.Destroy();
_loadedAd = null;
RemoveCache(slotId);
OnAdClose();
}
private void RemoveCache(string slotId)
{
var cache = GetCache(slotId);
if (cache == null)
{
return;
}
DestroyCachedAd(cache);
_slotCaches.Remove(slotId);
}
private static void DestroyCachedAd(RewardedSlotCache cache)
{
if (cache?.Ad == null)
{
return;
}
try
{
cache.ExpireHandler?.Kill();
cache.ExpireHandler = null;
cache.Ad.Destroy();
}
catch (Exception exception)
{
Debug.LogWarning($"[TapADN] Rewarded Destroy failed: {exception.Message}");
}
finally
{
cache.Ad = null;
cache.Loading = false;
cache.LoadedUnix = 0;
}
}
private void CompleteRewardedClose()
{
if (_showSettled)
@@ -228,4 +362,22 @@ public sealed class TapadnAwardVideoPlayer : ADPlayer, IDirichletRewardVideoAuto
adListener.OnRewardVerify(_rewardVerified, TapadnAdController.CurrentOptions?.RewardAmount ?? 1, TapadnAdController.CurrentOptions?.RewardName ?? string.Empty);
adListener.OnAdClose();
}
private static string NormalizeScenario(string scenario)
{
return string.IsNullOrWhiteSpace(scenario) ? "__default__" : scenario.Trim();
}
private static long GetNowUnixSeconds()
{
return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
}
private sealed class RewardedSlotCache
{
public DirichletRewardVideoAd Ad;
public bool Loading;
public long LoadedUnix;
public AdTimeHandler ExpireHandler;
}
}