com.amanotes.gdk 0.2.61 → 0.2.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.63 - 2024-06-01]
4
+ - [Fix] Do not include default GDK config asset
5
+ - [Fix] Support compare SemVer with an invalid value
6
+ - [Dev] Add ShowBanner/ HideBanner buttons to AmaGDKExample
7
+ - [Fix] Silent null exception when embedRemoteConfig == null (in Editor)
8
+ - [Dev] Improve banner loading with load failed handler (retry or skip)
9
+ - [Fix] Wrong condition flag for Banner enabled check
10
+ - [Dev] Upgrade Firebase 11.8.0, IronSource 7.9.1, GoogleMobileAds 9.0.0
11
+ - - Fix AppsFlyer error in iOS: Type specifier missing, defaults to ???int???
12
+ - - Min iOS 13.0
13
+ - [Klavar] Parse Klavar structure v0.3
14
+
15
+ ## [0.2.62 - 2024-05-27]
16
+ - [Dev] Remove pipeline for unity 2020
17
+ - [Dev] Dispatch changes / support callback for when UserId updated
18
+ - Also: Improve log to show UserId in GDK Ready message
19
+ - [Dev] Add GDK Init callback
20
+ - [Feature] Generate Klavar using template
21
+ - [Dev] Add Scriptable object release config
22
+ - [Dev] Add UserContext
23
+ - [Dev] Add Project Auditor
24
+ - [Dev] Various API improvements & update Unity 2021.3.36f1
25
+ - [Dev] Update Klavar generated files
26
+ - [Feature] Download Klavar config from Airtable
27
+ - [Feature] Add checkpoint event
28
+ - [Dev] Get google target sheet every build time
29
+ - [Dev] Update GDK Example project with Unity2021.3.36f1
30
+ - Also: Update AppsFlyer + GMA SDK
31
+ - [Dev] Fix change log post JSON error
32
+
3
33
  ## [0.2.61 - 2024-04-25]
4
34
  - Add immediate event logging logic
5
35
  - [Feature] Improve handling of locked parameters in Klavar
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -126,7 +126,7 @@ namespace Amanotes.Core
126
126
  }
127
127
  public partial class AmaGDK // Ads module
128
128
  {
129
- public static partial class Event
129
+ partial class Event
130
130
  {
131
131
  public const string INTER_REQUEST = nameof(INTER_REQUEST);
132
132
  public const string INTER_SHOW_CALLED = nameof(INTER_SHOW_CALLED);
@@ -321,23 +321,37 @@ namespace Amanotes.Core
321
321
  public static bool IsRewardedVideoShowing => (context != null) && (context.adType == AdType.VideoReward);
322
322
 
323
323
 
324
- private static bool _isBannerShowing;
324
+ [NonSerialized] private static bool _isBannerShowing = false;
325
325
 
326
326
  public static void ShowBanner()
327
327
  {
328
- if (_config.ad.enableBanner) return;
328
+ if (!_config.ad.enableBanner)
329
+ {
330
+ LogWarning($"Banner not enabled! {_config.ad.enableBanner}");
331
+ return;
332
+ }
333
+
334
+ if (_isBannerShowing)
335
+ {
336
+ LogWarning($"Banner is showing!");
337
+ return;
338
+ }
329
339
 
330
- if (_isBannerShowing) return;
331
340
  _isBannerShowing = true;
332
- if (_adapter == null) return;
341
+
342
+ if (_adapter == null)
343
+ {
344
+ LogWarning($"Adapter is null!");
345
+ return;
346
+ }
333
347
 
334
348
  dispatcher.Dispatch(Event.BANNER_SHOW);
335
- _adapter.ShowBanner();
349
+ _adapter.ShowBanner();
336
350
  }
337
351
 
338
352
  public static void HideBanner()
339
353
  {
340
- if (_config.ad.enableBanner) return;
354
+ if (!_config.ad.enableBanner) return;
341
355
  if (!_isBannerShowing) return;
342
356
  _isBannerShowing = false;
343
357
  if (_adapter == null) return;
@@ -364,7 +378,7 @@ namespace Amanotes.Core
364
378
  /// <param name="interstitialCappingTime"></param>
365
379
  /// <param name="rewardedVideoCappingTime"></param>
366
380
  /// <returns></returns>
367
- public static bool IsCapped(float interstitialCappingTime = 0, float rewardedVideoCappingTime = 0)
381
+ internal static bool IsCapped(float interstitialCappingTime = 0, float rewardedVideoCappingTime = 0)
368
382
  {
369
383
  bool interCapped = (interstitialCappingTime > 0) && TimeSinceLastInterstitialSucceed < interstitialCappingTime;
370
384
  bool rewardCapped = (rewardedVideoCappingTime > 0) && TimeSinceLastVideoRewardSucceed < rewardedVideoCappingTime;
@@ -402,9 +416,9 @@ namespace Amanotes.Core.Internal
402
416
  [Tooltip("When an ad is not ready to show, verify that there is an internet connection by ping the internet check URL .\nIf there is no internet connection, we will not need to wait for adShowTimeout secs")]
403
417
  public bool checkInternet = true;
404
418
 
405
- [HideInInspector] public bool enableInterstitial = true;
406
- [HideInInspector] public bool enableRewarded = true;
407
- [HideInInspector] public bool enableBanner = true;
419
+ [NonSerialized] public bool enableInterstitial = true;
420
+ [NonSerialized] public bool enableRewarded = true;
421
+ [NonSerialized] public bool enableBanner = true;
408
422
 
409
423
  [Tooltip("Before showing an ad: set AudioListener.volume to 0\nAfter the ad is closed: restore the previously saved AudioListener.volume")]
410
424
  public bool autoMute = true;
@@ -929,7 +943,15 @@ namespace Amanotes.Core.Internal
929
943
  protected void OnAdShowFailed()
930
944
  {
931
945
  Log($"[Ad] {adType} OnAdShowFailed");
932
-
946
+
947
+ // 509 Show Fail: No ads to show
948
+ // 520 Show Fail: No internet connection; ShouldTrackNetworkState is enabled
949
+ // 524 Show Fail: Placement %@ has reached its limit as defined per pace
950
+ // 526 Show Fail: Ad unit has reached its daily cap per session
951
+ // 1022 Show Fail: Cannot show an RV while another RV is showing
952
+ // 1023 Show Fail: Show RV called when there are no available ads to show
953
+ // 1036 Show Fail: Cannot show an while another is showing
954
+
933
955
  if (Ads.context != null)
934
956
  {
935
957
  Ads.context.adCallback |= AdCallback.Fail;
@@ -1014,10 +1036,12 @@ namespace Amanotes.Core.Internal
1014
1036
  {
1015
1037
  LogWarning("[Ad] Something wrong? OnAdReady called when no ad is loading! AdType=" + adType);
1016
1038
  }
1017
-
1039
+
1018
1040
  _isRequesting = false;
1019
1041
  }
1020
-
1042
+
1043
+
1044
+
1021
1045
  protected void OnAdLoadFailed(string error)
1022
1046
  {
1023
1047
  Log($"[Ad] {adType} OnAdLoadFailed: {error}");
@@ -38,8 +38,11 @@ namespace Amanotes.Core
38
38
  public HashSet<string> ignoreAdapterIds = null;
39
39
  public HashSet<string> allowAdapterIds = null;
40
40
 
41
+ public int totalCount => detail.totalCount;
42
+ public int totalCountWithinSession => detail.countInSession;
43
+
41
44
  private EventDetail _detail;
42
- public EventDetail EventDetail
45
+ internal EventDetail detail
43
46
  {
44
47
  get
45
48
  {
@@ -47,6 +50,7 @@ namespace Amanotes.Core
47
50
  return _detail = localData.GetEventDetail(eventName, true);
48
51
  }
49
52
  }
53
+ internal bool isLoggedImmediately = false;
50
54
 
51
55
  internal EventParams Init(string eventName)
52
56
  {
@@ -92,7 +96,6 @@ namespace Amanotes.Core
92
96
 
93
97
  public static IEventParamsBuilder LogEvent(string eventName)
94
98
  {
95
- ThrowExceptionIfImmediateEvent(eventName);
96
99
  var result = PrepareEvent(eventName);
97
100
  eventQueue.Enqueue(result);
98
101
  return result;
@@ -100,7 +103,6 @@ namespace Amanotes.Core
100
103
 
101
104
  public static IEventParamsBuilder LogEvent(string eventName, Dictionary<string, object> parameters)
102
105
  {
103
- ThrowExceptionIfImmediateEvent(eventName);
104
106
  var result = PrepareEvent(eventName, parameters);
105
107
  eventQueue.Enqueue(result);
106
108
  return result;
@@ -108,7 +110,6 @@ namespace Amanotes.Core
108
110
 
109
111
  public static IEventParamsBuilder LogEvent(string eventName, params (string, object)[] parameters)
110
112
  {
111
- ThrowExceptionIfImmediateEvent(eventName);
112
113
  var result = PrepareEvent(eventName, parameters);
113
114
  eventQueue.Enqueue(result);
114
115
  return result;
@@ -129,22 +130,22 @@ namespace Amanotes.Core
129
130
  return LogEvent(eventName, parameters).SetAsFunnel(signature);
130
131
  }
131
132
 
133
+ [Obsolete("Please use AmaGDK.Analytics.LogEvent(eventName).LogImmediately() instead")]
132
134
  public static void LogEventImmediately(string eventName)
133
135
  {
134
- var eventParams = PrepareEvent(eventName);
135
- LogEventImmediately(eventParams);
136
+ LogEvent(eventName).LogImmediately();
136
137
  }
137
138
 
139
+ [Obsolete("Please use AmaGDK.Analytics.LogEvent(eventName, parameters).LogImmediately() instead")]
138
140
  public static void LogEventImmediately(string eventName, Dictionary<string, object> parameters)
139
141
  {
140
- var eventParams = PrepareEvent(eventName, parameters);
141
- LogEventImmediately(eventParams);
142
+ LogEvent(eventName, parameters).LogImmediately();
142
143
  }
143
144
 
145
+ [Obsolete("Please use AmaGDK.Analytics.LogEvent(eventName, parameters).LogImmediately() instead")]
144
146
  public static void LogEventImmediately(string eventName, params (string, object)[] parameters)
145
147
  {
146
- var eventParams = PrepareEvent(eventName, parameters);
147
- LogEventImmediately(eventParams);
148
+ LogEvent(eventName, parameters).LogImmediately();
148
149
  }
149
150
 
150
151
  public static int GetAccumulatedCount(string eventName, bool withinSession = false)
@@ -174,12 +175,6 @@ namespace Amanotes.Core
174
175
  s.SetUserProperty(key, value);
175
176
  }
176
177
  }
177
-
178
- private static void ThrowExceptionIfImmediateEvent(string eventName)
179
- {
180
- if (Config.analytics.immediatelyLoggedEvents.Contains(eventName))
181
- throw new GDKException($"This event '{eventName}' must be sent immediately by AmaGDK.Analytics.LogEventImmediately(eventName, params)");
182
- }
183
178
 
184
179
  private static IntegrityFlag MergeData(List<string> funnelEvents, Dictionary<string, int> eventCountMap, bool sumEventCount)
185
180
  {
@@ -401,6 +396,9 @@ namespace Amanotes.Core
401
396
 
402
397
  while (eventQueue.TryDequeue(out var eventData))
403
398
  {
399
+ if (eventData.isLoggedImmediately) continue;
400
+ if (Config.analytics.immediatelyLoggedEvents.Contains(eventData.eventName))
401
+ Utils.ThrowExceptionIfEditor($"This event '{eventData.eventName}' must be sent immediately by AmaGDK.Analytics.LogEvent(eventName).LogImmediately()");
404
402
  var (eventNameToSend, inUseAdapterIDs) = LogEventActually(eventData);
405
403
  sessionStat?.Add(eventNameToSend, eventData, inUseAdapterIDs);
406
404
  epPool.Return(eventData);
@@ -481,7 +479,7 @@ namespace Amanotes.Core
481
479
  if (Config.analytics.migrateAccumulatedCount && !eventData.withinSession)
482
480
  {
483
481
  Log($"[Analytics] Update event count of event <{eventData.eventName}> from {countByGDK} to {oriAccCount}");
484
- eventData.EventDetail.totalCount = oriAccCount;
482
+ eventData.detail.totalCount = oriAccCount;
485
483
  totalCount = oriAccCount;
486
484
  localData._dirty = true;
487
485
  }
@@ -667,7 +665,7 @@ namespace Amanotes.Core
667
665
  public static partial class Analytics
668
666
  {
669
667
  [Serializable]
670
- public class EventDetail
668
+ internal class EventDetail
671
669
  {
672
670
  public string eventName;
673
671
  public int totalCount;
@@ -705,7 +703,7 @@ namespace Amanotes.Core
705
703
  }
706
704
 
707
705
  [Serializable]
708
- public class MigrationLog
706
+ internal class MigrationLog
709
707
  {
710
708
  public string deviceId;
711
709
  public string appVersion;
@@ -892,6 +890,27 @@ namespace Amanotes.Core
892
890
 
893
891
  public static class EventParamsExtension
894
892
  {
893
+ public static void LogImmediately(this IEventParamsBuilder ap)
894
+ {
895
+ if (ap == null) return;
896
+
897
+ var data = ap as EventParams;
898
+ data!.isLoggedImmediately = true;
899
+ LogEventImmediately(data);
900
+ }
901
+
902
+ public static IEventParamsBuilder AttachParam_TimeDiffLastFire(this IEventParamsBuilder ap)
903
+ {
904
+ var data = ap as EventParams;
905
+ return data?.AddParam("time_diff_last_fire", Utils.GetTimeDiffLastFire(data.eventName));
906
+ }
907
+
908
+ public static IEventParamsBuilder AttachParam_InternetConnectionStatus(this IEventParamsBuilder ap)
909
+ {
910
+ var data = ap as EventParams;
911
+ return data?.AddParam("connection", Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork ? "online" : "offline");
912
+ }
913
+
895
914
  public static IEventParamsBuilder SetAsFunnel(this IEventParamsBuilder ap, string signature = null)
896
915
  {
897
916
  if (ap == null) return null;
@@ -1064,13 +1083,12 @@ namespace Amanotes.Core
1064
1083
  return false;
1065
1084
  }
1066
1085
 
1067
- if (value.GetType() == typeof(string))
1086
+ if (value is string stringValue)
1068
1087
  {
1069
- var v = value.ToString();
1070
1088
  var strLimit = 100;
1071
- if (v.Length > strLimit)
1089
+ if (stringValue.Length > strLimit)
1072
1090
  {
1073
- value = v.Substring(0, strLimit);
1091
+ value = stringValue.Substring(0, strLimit);
1074
1092
  LogWarning($"Param value exceeds the length limit ({strLimit}). Event name: {eventName}, key: {key}!");
1075
1093
  }
1076
1094
  }
@@ -0,0 +1,63 @@
1
+ using static Amanotes.Core.Internal.Logging;
2
+
3
+ namespace Amanotes.Core
4
+ {
5
+ public partial class AmaGDK
6
+ {
7
+ public static Context Context = new Context();
8
+ }
9
+
10
+ public partial class Context
11
+ {
12
+ public string Location
13
+ {
14
+ get => _location;
15
+ set => SetStringField(ref _location, value, nameof(Location));
16
+ }
17
+
18
+ public string SongACMid
19
+ {
20
+ get => _songACMid;
21
+ set => SetStringField(ref _songACMid, value, nameof(SongACMid));
22
+ }
23
+
24
+ public string SongName
25
+ {
26
+ get => _songName;
27
+ set => SetStringField(ref _songName, value, nameof(SongName));
28
+ }
29
+
30
+ public string SongUnlockType
31
+ {
32
+ get => _songUnlockType;
33
+ set => SetStringField(ref _songUnlockType, value, nameof(SongUnlockType));
34
+ }
35
+
36
+ public string Reward
37
+ {
38
+ get => _reward;
39
+ set => SetStringField(ref _reward, value, nameof(Reward));
40
+ }
41
+ }
42
+
43
+ public partial class Context // PRIVATE
44
+ {
45
+ private string _location;
46
+ private string _songACMid;
47
+ private string _songName;
48
+ private string _songUnlockType;
49
+ private string _reward;
50
+
51
+ private void SetStringField(ref string field, string value, string name)
52
+ {
53
+ if (string.IsNullOrWhiteSpace(value))
54
+ {
55
+ LogWarning($"[Context] {name} is empty");
56
+ }
57
+ else
58
+ {
59
+ field = value;
60
+ }
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: d8fc30da5e864878af47d27c0caaf2a4
3
+ timeCreated: 1715746839
@@ -69,11 +69,12 @@ namespace Amanotes.Core
69
69
 
70
70
  public static T Get<T>(string key, T defaultValue = default(T))
71
71
  {
72
+ var embed = Config.remoteConfig.embedRemoteConfig;
72
73
  #if UNITY_EDITOR
73
74
  //Override value in editor environment
74
- if (Config.remoteConfig.embedRemoteConfig.overrideInEditor)
75
+ if (embed != null && embed.overrideInEditor)
75
76
  {
76
- foreach (var c in Config.remoteConfig.embedRemoteConfig.overrideConfig)
77
+ foreach (var c in embed.overrideConfig)
77
78
  if (c.key == key)
78
79
  return (T)Convert.ChangeType(c.value, typeof(T));
79
80
  }
@@ -3,14 +3,28 @@ using System.Text.RegularExpressions;
3
3
  using Amanotes.Core.Internal;
4
4
  using System.Collections.Generic;
5
5
  using UnityEngine;
6
- using UnityEngine.Serialization;
7
6
 
8
7
  namespace Amanotes.Core
9
8
  {
10
9
  public partial class AmaGDK //User profile
11
10
  {
11
+ partial class Event
12
+ {
13
+ public const string GDK_USER_ID_UPDATED = nameof(GDK_USER_ID_UPDATED);
14
+ }
15
+
12
16
  public static readonly UserProfile User = new UserProfile();
13
-
17
+
18
+ /// <summary>
19
+ /// We use multiple IDs to do the user mapping between AppsFlyer, IronSource & Firebase
20
+ /// The callback triggers when a better UserID (gaid, idfv, pseudoId,...) was found and replace the current UserId
21
+ /// </summary>
22
+ /// <param name="onUserIdChange"></param>
23
+ public static void SetCallback_OnUserIdUpdated(Action<string> onUserIdChange)
24
+ {
25
+ dispatcher.AddListener(Event.GDK_USER_ID_UPDATED, onUserIdChange, false);
26
+ }
27
+
14
28
  [Serializable]
15
29
  public partial class UserProfile : IJsonFile
16
30
  {
@@ -56,6 +70,8 @@ namespace Amanotes.Core
56
70
  {
57
71
  if (_userId == value) return;
58
72
  _userId = value;
73
+ Logging.Log($"GDK UserID Updated: {_userId}");
74
+ dispatcher.Dispatch(Event.GDK_USER_ID_UPDATED, _userId);
59
75
  Save();
60
76
  }
61
77
  }
package/Runtime/AmaGDK.cs CHANGED
@@ -17,24 +17,23 @@ namespace Amanotes.Core
17
17
  {
18
18
  public partial class AmaGDK : MonoBehaviour
19
19
  {
20
- public const string VERSION = "0.2.61";
20
+ public const string VERSION = "0.2.63";
21
21
 
22
22
  internal static AmaGDK _instance;
23
- internal static Status _status = Status.None;
24
23
  internal static bool _allowInit = false;
25
- public bool autoInit = true;
24
+ internal static Status _status = Status.None;
25
+ private static ConfigAsset _config = null;
26
26
  internal static readonly GDKGeoLocation GeoLocation = new GDKGeoLocation();
27
27
  internal static readonly GDKServerTime ServerTime = new GDKServerTime();
28
- private static ConfigAsset _config = null;
29
28
 
30
- public static partial class Event
29
+
30
+ public bool autoInit = true;
31
+ internal static partial class Event
31
32
  {
32
33
  public const string GDK_HOOK_START = nameof(GDK_HOOK_START);
33
34
  public const string GDK_HOOK_END = nameof(GDK_HOOK_END);
34
35
 
35
- public const string GDK_INIT_START = nameof(GDK_INIT_START);
36
- public const string GDK_INIT_END = nameof(GDK_INIT_END);
37
-
36
+ public const string GDK_INIT = nameof(GDK_INIT);
38
37
  public const string GDK_READY = nameof(GDK_READY);
39
38
  public const string ADAPTER_READY = nameof(ADAPTER_READY);
40
39
  }
@@ -141,7 +140,6 @@ namespace Amanotes.Core
141
140
 
142
141
  IEnumerator InitAdapters(StringBuilder sb)
143
142
  {
144
- _status = Status.Initialize;
145
143
  float TIMEOUT = 1;
146
144
 
147
145
  // sort on priority
@@ -182,12 +180,19 @@ namespace Amanotes.Core
182
180
  }
183
181
 
184
182
  float startTime = Time.realtimeSinceStartup;
185
-
186
- dispatcher.Dispatch(Event.GDK_INIT_START);
187
183
  var sb = new StringBuilder();
184
+
188
185
  InitModules();
189
186
 
187
+ float moduleTime = Time.realtimeSinceStartup - startTime;
188
+ sb.Append($"- InitModules() took (~ {moduleTime:#0.00}s)\n");
189
+
190
190
  yield return InitHook(); //Google CMP takes long at first time (~ 1.7s)
191
+ float hookTime = Time.realtimeSinceStartup - moduleTime - startTime;
192
+ sb.Append($"- InitHook() took (~ {hookTime:#0.00}s)\n\n");
193
+
194
+ _status = Status.Initialize;
195
+ dispatcher.Dispatch(Event.GDK_INIT);
191
196
  yield return WaitForManualInit();
192
197
  yield return InitAdapters(sb);
193
198
 
@@ -199,10 +204,10 @@ namespace Amanotes.Core
199
204
  ServerTime.UpdateTime();
200
205
  }
201
206
 
202
- dispatcher.Dispatch(Event.GDK_INIT_END);
203
-
204
207
  _status = Status.Ready;
205
208
  dispatcher.Dispatch(Event.GDK_READY);
209
+
210
+ sb.Append($"\nMapping UserId: {User.UserId}\n");
206
211
  Debug.Log($"AmaGDK v{VERSION} | {READY} in {Time.realtimeSinceStartup - startTime:#0.00}s\n\n{sb}");
207
212
  }
208
213
 
@@ -230,7 +235,14 @@ namespace Amanotes.Core
230
235
  public partial class AmaGDK // PUBLIC APIS
231
236
  {
232
237
  public static bool isReady => _status == Status.Ready;
233
-
238
+ public static bool isInitted => _status >= Status.Initialize;
239
+
240
+ public static LogLevel logLevel
241
+ {
242
+ get => Config.common.logLevel;
243
+ set => Config.common.logLevel = value;
244
+ }
245
+
234
246
  public static void Init(Action onReady = null)
235
247
  {
236
248
  if (isReady)
@@ -257,8 +269,28 @@ namespace Amanotes.Core
257
269
  var sdk = new GameObject("AmaGDK");
258
270
  _instance = sdk.AddComponent<AmaGDK>();
259
271
  }
260
-
261
- public static void SetOnReadyCallback(Action onReady)
272
+
273
+ /// <summary>
274
+ /// Will be triggered right after all the cached data being loaded
275
+ /// And before any Adapter has been called to Init
276
+ /// </summary>
277
+ /// <param name="onInit"></param>
278
+ public static void SetCallback_OnGDKInit(Action onInit)
279
+ {
280
+ if (isInitted)
281
+ {
282
+ onInit.Invoke();
283
+ return;
284
+ }
285
+
286
+ dispatcher.AddListener(Event.GDK_INIT, onInit, true);
287
+ }
288
+
289
+ /// <summary>
290
+ /// Will be trigger after all adapters have been ready
291
+ /// </summary>
292
+ /// <param name="onReady"></param>
293
+ public static void SetCallback_OnGDKReady(Action onReady)
262
294
  {
263
295
  if (isReady)
264
296
  {
@@ -1,6 +1,7 @@
1
1
  using System;
2
2
  using System.Collections.Generic;
3
3
  using System.Text.RegularExpressions;
4
+ using UnityEngine;
4
5
  using UnityEngine.Profiling;
5
6
  using static Amanotes.Core.Internal.Logging;
6
7
 
@@ -9,7 +10,7 @@ namespace Amanotes.Core.Internal
9
10
  public struct SemVer : IComparable<SemVer>, IComparer<SemVer>
10
11
  {
11
12
  public static readonly SemVer ZERO = new SemVer(0, 0, 0);
12
- private static readonly Regex VERSION_PATTERN = new Regex(@"^(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?$");
13
+ private static readonly Regex VERSION_PATTERN = new Regex(@"^(\d+)\.(\d+)(?:\.(\d+))?(?:\.(\d+))?$");
13
14
 
14
15
  public int major;
15
16
  public int minor;
@@ -45,13 +46,21 @@ namespace Amanotes.Core.Internal
45
46
  }
46
47
  major = int.Parse(match.Groups[1].Value);
47
48
  minor = int.Parse(match.Groups[2].Value);
48
- patch = int.Parse(match.Groups[3].Value);
49
+ if (match.Groups.Count > 2)
50
+ {
51
+ if (!int.TryParse(match.Groups[3].Value, out patch))
52
+ {
53
+ patch = 0;
54
+ }
55
+ }
49
56
  if (match.Groups.Count > 3)
50
57
  {
51
58
  if (!int.TryParse(match.Groups[4].Value, out extra))
59
+ {
52
60
  extra = -1;
53
61
  }
54
62
  }
63
+ }
55
64
  Profiler.EndSample();
56
65
  }
57
66
 
@@ -66,6 +75,21 @@ namespace Amanotes.Core.Internal
66
75
 
67
76
  public int CompareTo(SemVer other)
68
77
  {
78
+ if (!isValid)
79
+ {
80
+ if (!other.isValid)
81
+ {
82
+ return 0;
83
+ }
84
+ return -1;
85
+ }
86
+
87
+ if (!other.isValid)
88
+ {
89
+ return 1;
90
+ }
91
+
92
+
69
93
  if (major != other.major) return major.CompareTo(other.major);
70
94
  if (minor != other.minor) return minor.CompareTo(other.minor);
71
95
  if (patch != other.patch) return patch.CompareTo(other.patch);
@@ -22,7 +22,7 @@ namespace Amanotes.Core.Internal
22
22
 
23
23
  public static class Messsage
24
24
  {
25
- public const string READY = "Init success";
25
+ public const string READY = "Ready";
26
26
  public const string SDK_INIT_CALLED = "init has been called!";
27
27
  public const string MULTIPLE_INSTANCE = "multiple instance found!";
28
28
  public const string CONFIG_NOT_FOUND = "AmaGDKConfig not found in Resources!";
@@ -132,7 +132,7 @@ namespace Amanotes.Core.Internal
132
132
  }
133
133
 
134
134
  AmaGDK[] result = Resources.FindObjectsOfTypeAll<AmaGDK>();
135
- for (var i = 0; i < result.Length; i++)
135
+ for (int i = 0; i < result.Length; i++)
136
136
  {
137
137
  if (result[i] == null) continue;
138
138
 
@@ -175,7 +175,7 @@ namespace Amanotes.Core.Internal
175
175
  analyticsData.cachedEventDetails.Clear();
176
176
  analyticsData.migrationLog = new MigrationLog();
177
177
  analyticsData.SaveIfDirty();
178
- sessionStat.Clear();
178
+ sessionStat?.Clear();
179
179
  #if UNITY_2021_3_OR_NEWER
180
180
  eventQueue.Clear();
181
181
  #else
@@ -189,8 +189,33 @@ namespace Amanotes.Core.Internal
189
189
  public interface IOnApplicationFocus { void OnApplicationFocus(bool hasFocus); }
190
190
  public interface IOnFrameUpdate { void OnFrameUpdate(); }
191
191
 
192
- public static class Utils
192
+ public static class Utils // Hidden Utils
193
193
  {
194
+ private static readonly Dictionary<string, float> LastFireInSessions = new Dictionary<string, float>();
195
+
196
+ public static int GetTimeDiffLastFire(string eventName)
197
+ {
198
+ if (!LastFireInSessions.TryGetValue(eventName, out float lastFire))
199
+ {
200
+ LastFireInSessions[eventName] = Time.realtimeSinceStartup;
201
+ return 0;
202
+ }
203
+
204
+ float current = Time.realtimeSinceStartup;
205
+ int diff = Mathf.RoundToInt(current - lastFire);
206
+ LastFireInSessions[eventName] = current;
207
+ return diff;
208
+ }
209
+
210
+ public static void ThrowExceptionIfEditor(string message)
211
+ {
212
+ #if UNITY_EDITOR
213
+ throw new GDKException(message);
214
+ #else
215
+ Logging.LogError(message);
216
+ #endif
217
+ }
218
+
194
219
  /// <summary>
195
220
  /// Registers the list of server time providers.
196
221
  /// </summary>
@@ -16,4 +16,5 @@ namespace Amanotes.Core
16
16
  return AmaGDK.Analytics.GetAccumulatedCount(attr.name) + 1;
17
17
  }
18
18
  }
19
+ public class LifetimeCountAttribute : AccumulatedCountAttribute { }
19
20
  }
@@ -6,22 +6,10 @@ namespace Amanotes.Core
6
6
  {
7
7
  public class TimeDiffLastFireAttribute : ConverterLogEventAttribute
8
8
  {
9
- static readonly Dictionary<string, float> lastFireInSessions = new Dictionary<string, float>();
10
-
11
9
  public override object Convert(object parent, FieldInfo fieldInfo, object param)
12
10
  {
13
- // return AmaGDK.Ads.InterstitialShowCalledInSession;
14
11
  string name = parent.GetType().FullName;
15
- if (!lastFireInSessions.TryGetValue(name, out var lastFire))
16
- {
17
- lastFireInSessions[name] = Time.realtimeSinceStartup;
18
- return 0;
19
- }
20
-
21
- var current = Time.realtimeSinceStartup;
22
- var diff = Mathf.RoundToInt(current - lastFire);
23
- lastFireInSessions[name] = current;
24
- return diff;
12
+ return Internal.Utils.GetTimeDiffLastFire(name);
25
13
  }
26
14
  }
27
15
 
@@ -35,7 +35,7 @@ namespace Amanotes.Core
35
35
 
36
36
  if (AmaGDK.Config.analytics.immediatelyLoggedEvents.Contains(eventName))
37
37
  {
38
- AmaGDK.Analytics.LogEventImmediately(eventName, @params);
38
+ AmaGDK.Analytics.LogEvent(eventName, @params).LogImmediately();
39
39
  }
40
40
  else
41
41
  {
@@ -115,5 +115,17 @@ namespace Amanotes.Core
115
115
  additionalParameters[kvp.Key] = kvp.Value;
116
116
  }
117
117
  }
118
+
119
+ /// <summary>
120
+ /// AttachContainerParameters method attaches container parameters to the event.
121
+ /// </summary>
122
+ /// <param name="parameters">The container parameters to attach.</param>
123
+ public void AttachContainerParameters(params (string, object)[] parameters)
124
+ {
125
+ foreach ((string key, object value) in parameters)
126
+ {
127
+ additionalParameters[key] = value;
128
+ }
129
+ }
118
130
  }
119
131
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.amanotes.gdk",
3
- "version": "0.2.61",
3
+ "version": "0.2.63",
4
4
  "displayName": "AmaGDK",
5
5
  "description": "Amanotes Game Development Kit",
6
6
  "unity": "2019.4",