com.amanotes.gdk 0.2.57 → 0.2.58

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,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.58 - 2024-04-09]
4
+ - [DEV] combine code coverage report
5
+ - [Dev] Improve GDK Utils
6
+ - [Dev] Add hints to AdCallback APIs
7
+ - [Fix] timeDiffLastFire always returns 0 in adShowCalled callbacks
8
+ - [Fix] Various warnings fixes due to invalid examples
9
+ - [Fix] Warning on AdContext destroyed caused by invalid editor ad callback
10
+
11
+
3
12
  ## [0.2.57 - 2024-04-08]
4
13
  - [Dev] Fix bug in value conversion within KlavarEvent
5
14
  - [Dev] Auto get change log
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -11,6 +11,9 @@ namespace Amanotes.Core
11
11
  {
12
12
  public static class AdExtension
13
13
  {
14
+ /// <summary>
15
+ /// Invoke when ad view has opened
16
+ /// </summary>
14
17
  public static IAdCallback OnAdOpened(this IAdCallback ad, Action callback)
15
18
  {
16
19
  if (!MakeSureAdNotNull(ad)) return null;
@@ -19,6 +22,9 @@ namespace Amanotes.Core
19
22
  return ad;
20
23
  }
21
24
 
25
+ /// <summary>
26
+ /// The user finished watching the video, and should be rewarded.
27
+ /// </summary>
22
28
  public static IAdCallback OnRewardReceived(this IAdCallback ad, Action callback)
23
29
  {
24
30
  if (!MakeSureAdNotNull(ad)) return null;
@@ -27,6 +33,9 @@ namespace Amanotes.Core
27
33
  return ad;
28
34
  }
29
35
 
36
+ /// <summary>
37
+ /// Invoked when the video ad was clicked.
38
+ /// </summary>
30
39
  public static IAdCallback OnAdClicked(this IAdCallback ad, Action callback)
31
40
  {
32
41
  if (!MakeSureAdNotNull(ad)) return null;
@@ -35,6 +44,9 @@ namespace Amanotes.Core
35
44
  return ad;
36
45
  }
37
46
 
47
+ /// <summary>
48
+ /// Callback when the rewarded video ad was failed to show
49
+ /// </summary>
38
50
  public static IAdCallback OnAdShowFailed(this IAdCallback ad, Action callback)
39
51
  {
40
52
  if (!MakeSureAdNotNull(ad)) return null;
@@ -43,6 +55,9 @@ namespace Amanotes.Core
43
55
  return ad;
44
56
  }
45
57
 
58
+ /// <summary>
59
+ /// Invoked before OnAdOpened but is not reliable (not supported by all adNetworks)
60
+ /// </summary>
46
61
  public static IAdCallback OnAdShowSuccess(this IAdCallback ad, Action callback)
47
62
  {
48
63
  if (!MakeSureAdNotNull(ad)) return null;
@@ -51,6 +66,9 @@ namespace Amanotes.Core
51
66
  return ad;
52
67
  }
53
68
 
69
+ /// <summary>
70
+ /// Invoke when ad view is about to be closed
71
+ /// </summary>
54
72
  public static IAdCallback OnAdClosed(this IAdCallback ad, Action callback)
55
73
  {
56
74
  if (!MakeSureAdNotNull(ad)) return null;
@@ -59,6 +77,11 @@ namespace Amanotes.Core
59
77
  return ad;
60
78
  }
61
79
 
80
+ /// <summary>
81
+ /// This callback may invokes several times according to the AdShowReadyStatus
82
+ /// - When there is no ad cached (wifi disabled / no internet / wait4Ad / timeout)
83
+ /// - When the ad is cached & ready to show
84
+ /// </summary>
62
85
  public static IAdCallback OnAdShowReadyStatus(this IAdCallback ad, Action<AdShowReadyStatus> callback)
63
86
  {
64
87
  if (!MakeSureAdNotNull(ad)) return null;
@@ -67,6 +90,10 @@ namespace Amanotes.Core
67
90
  return ad;
68
91
  }
69
92
 
93
+ /// <summary>
94
+ /// The finalize callback that will always trigger to mark an end for the AdShowRoutine
95
+ ///
96
+ /// </summary>
70
97
  public static IAdCallback OnAdResult(this IAdCallback ad, Action<bool> callback)
71
98
  {
72
99
  if (!MakeSureAdNotNull(ad)) return null;
@@ -77,7 +104,7 @@ namespace Amanotes.Core
77
104
 
78
105
  /// <summary>
79
106
  /// Call right before the ad actually open (that means Ad has already been cached & available to show).
80
- /// This callback will not be triggered in case Ad is not available or no internet
107
+ /// This callback will not be triggered in case Ad is not available or no internet (in those case use OnAdShowReadyStatus callback)
81
108
  /// </summary>
82
109
  public static IAdCallback OnBeforeAdOpen(this IAdCallback ad, Action callback)
83
110
  {
@@ -124,7 +151,8 @@ namespace Amanotes.Core
124
151
  internal class AdStat
125
152
  {
126
153
  // per session
127
- internal float lastCallTime;
154
+ internal float prevCallTime;
155
+ internal float currentCallTime;
128
156
  internal int callCount;
129
157
 
130
158
  internal float lastSuccessTime;
@@ -154,7 +182,18 @@ namespace Amanotes.Core
154
182
 
155
183
  internal int TimeSinceLastShowCalled(AdType adType)
156
184
  {
157
- return (int)(Time.realtimeSinceStartup - GetStat(adType).lastCallTime);
185
+ AdStat stat = GetStat(adType);
186
+ AdShowContext context = Ads.context;
187
+
188
+ // Right inside XXX_ShowCalled() callbacks
189
+ if (context != null && context.adType == adType)
190
+ {
191
+ if (stat.callCount == 1) return 0; // first call
192
+ return (int)(stat.currentCallTime - stat.prevCallTime);
193
+ }
194
+
195
+ if (stat.callCount == 0) return 0; // not yet called
196
+ return (int)(Time.realtimeSinceStartup - stat.prevCallTime);
158
197
  }
159
198
 
160
199
  internal int TimeSinceLastShowSuccess(AdType adType)
@@ -626,7 +665,9 @@ namespace Amanotes.Core.Internal
626
665
 
627
666
  AdStat stat = Ads.localData.GetStat(adType);
628
667
  stat.callCount++;
629
- stat.lastCallTime = Time.realtimeSinceStartup;
668
+ stat.prevCallTime = stat.currentCallTime;
669
+ stat.currentCallTime = Time.realtimeSinceStartup;
670
+
630
671
  dispatcher.Dispatch(
631
672
  _isInterstitial ? AmaGDK.Event.INTER_SHOW_CALLED : AmaGDK.Event.REWARD_VIDEO_SHOW_CALLED
632
673
  );
@@ -120,7 +120,17 @@ namespace Amanotes.Core
120
120
  {
121
121
  get => _session;
122
122
  }
123
-
123
+
124
+ public string Country
125
+ {
126
+ get => _country;
127
+ set
128
+ {
129
+ _country = ValidateId(value, COUNTRY_CODE_PATTERN);
130
+ SaveIfDirty();
131
+ }
132
+ }
133
+
124
134
  public void UpdateUserId()
125
135
  {
126
136
  #if UNITY_ANDROID
@@ -199,12 +209,15 @@ namespace Amanotes.Core
199
209
  private string _appsFlyerId;
200
210
  [SerializeField]
201
211
  private string _installationId;
202
- [SerializeField]
212
+ [SerializeField]
203
213
  private int _session;
214
+ [SerializeField]
215
+ private string _country;
204
216
 
205
217
  private const string ALPHANUMERIC_HYPHEN_PATTERN = @"^(?=.*\d)(?=.*[a-zA-Z])(?=.*-).+$";
206
218
  private const string ALPHANUMERIC_PATTERN = @"^(?=.*\d)(?=.*[a-zA-Z])[a-zA-Z\d]+$";
207
219
  private const string NUMERIC_HYPHEN_PATTERN = @"^(?=.*\d)(?=.*-)[\d-]+$";
220
+ private const string COUNTRY_CODE_PATTERN = @"^[A-Z]{2}$";
208
221
 
209
222
  private const string AMA_DEVICE_ID_KEY = "ama_device_id";
210
223
 
package/Runtime/AmaGDK.cs CHANGED
@@ -17,13 +17,14 @@ namespace Amanotes.Core
17
17
  {
18
18
  public partial class AmaGDK : MonoBehaviour
19
19
  {
20
- public const string VERSION = "0.2.57";
20
+ public const string VERSION = "0.2.58";
21
21
 
22
22
  internal static AmaGDK _instance;
23
23
  internal static Status _status = Status.None;
24
24
  internal static bool _allowInit = false;
25
25
  public bool autoInit = true;
26
-
26
+ internal static readonly GDKGeoLocation GeoLocation = new GDKGeoLocation();
27
+ internal static readonly GDKServerTime ServerTime = new GDKServerTime();
27
28
  private static ConfigAsset _config = null;
28
29
 
29
30
  public static partial class Event
@@ -173,7 +174,6 @@ namespace Amanotes.Core
173
174
  }
174
175
  }
175
176
 
176
-
177
177
  IEnumerator InitRoutine()
178
178
  {
179
179
  if (Config == null)
@@ -192,12 +192,39 @@ namespace Amanotes.Core
192
192
  yield return InitAdapters(sb);
193
193
 
194
194
  StartModules();
195
+
196
+ ConfigGeoLocation();
197
+ if (Config.enableServerTime)
198
+ {
199
+ ServerTime.UpdateTime();
200
+ }
201
+
195
202
  dispatcher.Dispatch(Event.GDK_INIT_END);
196
203
 
197
204
  _status = Status.Ready;
198
205
  dispatcher.Dispatch(Event.GDK_READY);
199
206
  Debug.Log($"AmaGDK v{VERSION} | {READY} in {Time.realtimeSinceStartup - startTime:#0.00}s\n\n{sb}");
200
207
  }
208
+
209
+ private void ConfigGeoLocation()
210
+ {
211
+ if (Config.enableGeoLocation)
212
+ {
213
+ var countryCode = User.Country;
214
+ if (string.IsNullOrWhiteSpace(countryCode))
215
+ {
216
+ GeoLocation.GetCountryCode(remoteCountryCode =>
217
+ {
218
+ User.Country = remoteCountryCode;
219
+ GeoLocation.SetCountryCode(remoteCountryCode);
220
+ });
221
+ }
222
+ else
223
+ {
224
+ GeoLocation.SetCountryCode(countryCode);
225
+ }
226
+ }
227
+ }
201
228
  }
202
229
 
203
230
  public partial class AmaGDK // PUBLIC APIS
@@ -461,4 +488,10 @@ namespace Amanotes.Core
461
488
  }
462
489
  }
463
490
  }
491
+
492
+ public class GDKException : Exception
493
+ {
494
+ public GDKException() { }
495
+ public GDKException(string message) : base(message) { }
496
+ }
464
497
  }
@@ -182,4 +182,33 @@ namespace Amanotes.Core.Internal
182
182
  public interface IOnApplicationQuit { void OnApplicationQuit(); }
183
183
  public interface IOnApplicationFocus { void OnApplicationFocus(bool hasFocus); }
184
184
  public interface IOnFrameUpdate { void OnFrameUpdate(); }
185
+
186
+ public static class Utils
187
+ {
188
+ /// <summary>
189
+ /// Registers the list of server time providers.
190
+ /// </summary>
191
+ /// <param name="providers">List of server time providers implementing IServerTimeProvider interface or extending BaseServerTimeProvider.</param>
192
+ /// <remarks>
193
+ /// It is mandatory to call RegisterServerTimeProvider before initializing AmaGDK by calling AmaGDK.Init().
194
+ /// </remarks>
195
+ public static void RegisterServerTimeProvider(List<IServerTimeProvider> providers)
196
+ {
197
+ GDKUtils.ThrowIf(AmaGDK._status != Status.None, "Please call RegisterServerTimeProvider() before initializing AmaGDK by calling AmaGDK.Init()");
198
+ ServerTime.SetTimeProviders(providers);
199
+ }
200
+
201
+ /// <summary>
202
+ /// Set the GeoLocation Provider.
203
+ /// </summary>
204
+ /// <param name="provider">provider implementing IGeoLocationProvider interface.</param>
205
+ /// <remarks>
206
+ /// It is mandatory to call SetGeoLocationProvider before initializing AmaGDK by calling AmaGDK.Init().
207
+ /// </remarks>
208
+ public static void SetGeoLocationProvider(IGeoLocationProvider provider)
209
+ {
210
+ GDKUtils.ThrowIf(AmaGDK._status != Status.None, "Please call SetGeoLocationProvider() before initializing AmaGDK by calling AmaGDK.Init()");
211
+ GeoLocation.SetGeoLocationProvider(provider);
212
+ }
213
+ }
185
214
  }
@@ -77,6 +77,42 @@ namespace Amanotes.Core.Internal
77
77
  // Check if each segment exists in the output string in the correct order
78
78
  return AreSegmentsPresentInOrder(segments, formattedString);
79
79
  }
80
+
81
+ /// <summary>
82
+ /// Retrieves the current server time adjusted to the user's timezone.
83
+ /// </summary>
84
+ /// <returns>The current server time adjusted to the user's timezone if available; otherwise, null.</returns>
85
+ public static DateTime? GetServerTime()
86
+ {
87
+ return AmaGDK.ServerTime.GetTime();
88
+ }
89
+
90
+ /// <summary>
91
+ /// Asynchronously retrieves the current server time with a callback function, adjusted to the user's timezone.
92
+ /// </summary>
93
+ /// <param name="result">Callback function invoked with the server time adjusted to the user's timezone if available; otherwise, null is passed in case of network or server errors.</param>
94
+ public static void GetServerTime(Action<DateTime?> result)
95
+ {
96
+ AmaGDK.ServerTime.GetTime(result);
97
+ }
98
+
99
+ /// <summary>
100
+ /// Gets the country code.
101
+ /// </summary>
102
+ /// <returns>The country code if available; otherwise, null.</returns>
103
+ public static string GetCountryCode()
104
+ {
105
+ return AmaGDK.GeoLocation.GetCountryCode();
106
+ }
107
+
108
+ /// <summary>
109
+ /// Gets the country code asynchronously with a callback function.
110
+ /// </summary>
111
+ /// <param name="result">Callback function to be invoked with the country code if available; otherwise, null will be passed in case of network or server errors.</param>
112
+ public static void GetCountryCode(Action<string> result)
113
+ {
114
+ AmaGDK.GeoLocation.GetCountryCode(result);
115
+ }
80
116
 
81
117
  static bool AreSegmentsPresentInOrder(string[] segments, string outputString)
82
118
  {
@@ -117,6 +153,12 @@ namespace Amanotes.Core.Internal
117
153
  segments[matches.Count] = template.Substring(lastIndex);
118
154
  return segments;
119
155
  }
156
+
157
+ internal static void ThrowIf(bool condition, string message)
158
+ {
159
+ if (condition)
160
+ throw new GDKException(message);
161
+ }
120
162
  }
121
163
 
122
164
  public static class GDKReflection
@@ -0,0 +1,119 @@
1
+ using System;
2
+ using System.Collections;
3
+ using UnityEngine;
4
+ using UnityEngine.Networking;
5
+
6
+ namespace Amanotes.Core.Internal
7
+ {
8
+ public partial class ConfigAsset
9
+ {
10
+ [SerializeField] public bool enableGeoLocation = true;
11
+ }
12
+
13
+ internal class GDKGeoLocation
14
+ {
15
+ private IGeoLocationProvider provider = new CountryIS_GeoLocationProvider();
16
+ private string localCountryCode;
17
+
18
+ public void SetGeoLocationProvider(IGeoLocationProvider provider)
19
+ {
20
+ this.provider = provider;
21
+ }
22
+ public string GetCountryCode()
23
+ {
24
+ GDKUtils.ThrowIf(!AmaGDK.Config.enableGeoLocation, "GeoLocation is disabled, Please enable it in the AmaGDKConfig");
25
+ return localCountryCode;
26
+ }
27
+
28
+ public void GetCountryCode(Action<string> result)
29
+ {
30
+ GDKUtils.ThrowIf(!AmaGDK.Config.enableGeoLocation, "GeoLocation is disabled, Please enable it in the AmaGDKConfig");
31
+ if (!string.IsNullOrWhiteSpace(localCountryCode))
32
+ {
33
+ result?.Invoke(localCountryCode);
34
+ return;
35
+ }
36
+ provider.FetchGeoLocation(data =>
37
+ {
38
+ result?.Invoke(data.countryCode?.ToUpper());
39
+ if (data.errorMessage != null)
40
+ Logging.Log(data.errorMessage);
41
+ });
42
+ }
43
+
44
+ internal void SetCountryCode(string countryCode)
45
+ {
46
+ localCountryCode = countryCode;
47
+ }
48
+ }
49
+ }
50
+
51
+ namespace Amanotes.Core
52
+ {
53
+ public class GeoLocationData
54
+ {
55
+ public string countryCode;
56
+ public string errorMessage;
57
+
58
+ public GeoLocationData(string countryCode, string errorMessage = null)
59
+ {
60
+ this.countryCode = countryCode;
61
+ this.errorMessage = errorMessage;
62
+ }
63
+
64
+ public static GeoLocationData WithErrorMessage(string message)
65
+ {
66
+ return new GeoLocationData(null, message);
67
+ }
68
+ }
69
+
70
+ public interface IGeoLocationProvider
71
+ {
72
+ public void FetchGeoLocation(Action<GeoLocationData> result);
73
+ }
74
+
75
+ public class CountryIS_GeoLocationProvider: IGeoLocationProvider
76
+ {
77
+ public const string URL = "https://api.country.is/";
78
+ [Serializable]
79
+ private class LocationData
80
+ {
81
+ public string country;
82
+ }
83
+
84
+ void IGeoLocationProvider.FetchGeoLocation(Action<GeoLocationData> result)
85
+ {
86
+ AmaGDK._instance.StartCoroutine(FetchGeoLocationRoutine(result));
87
+ }
88
+
89
+ private IEnumerator FetchGeoLocationRoutine(Action<GeoLocationData> result)
90
+ {
91
+ using (var request = UnityWebRequest.Get(URL))
92
+ {
93
+ yield return request.SendWebRequest();
94
+
95
+ if (request.result != UnityWebRequest.Result.Success)
96
+ {
97
+ result?.Invoke(GeoLocationData.WithErrorMessage($"Error fetching location: {request.error}"));
98
+ yield break;
99
+ }
100
+
101
+ try
102
+ {
103
+ var data = ParseResponse(request.downloadHandler.text);
104
+ result?.Invoke(data);
105
+ }
106
+ catch (Exception e)
107
+ {
108
+ result?.Invoke(GeoLocationData.WithErrorMessage($"Error parsing location data: {e.Message}"));
109
+ }
110
+ }
111
+ }
112
+
113
+ private GeoLocationData ParseResponse(string response)
114
+ {
115
+ var locationData = JsonUtility.FromJson<LocationData>(response);
116
+ return new GeoLocationData(locationData.country);
117
+ }
118
+ }
119
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: aaf2bb28b9484523af7d43aa2f6fb36e
3
+ timeCreated: 1711956851
@@ -0,0 +1,211 @@
1
+ using System;
2
+ using System.Collections;
3
+ using System.Collections.Generic;
4
+ using UnityEngine;
5
+ using UnityEngine.Networking;
6
+
7
+ namespace Amanotes.Core
8
+ {
9
+ public class ServerTimeData
10
+ {
11
+ public DateTime? time;
12
+ public string errorMessage;
13
+
14
+ public ServerTimeData(DateTime time)
15
+ {
16
+ this.time = time;
17
+ errorMessage = null;
18
+ }
19
+
20
+ public ServerTimeData(string errorMessage)
21
+ {
22
+ time = null;
23
+ this.errorMessage = errorMessage;
24
+ }
25
+ }
26
+
27
+ public interface IServerTimeProvider
28
+ {
29
+ public void FetchServerTime(Action<ServerTimeData> result);
30
+ }
31
+
32
+ public abstract class BaseServerTimeProvider : IServerTimeProvider
33
+ {
34
+ public abstract string GetURL();
35
+ public abstract ServerTimeData ParseResponse(string response);
36
+
37
+ public void FetchServerTime(Action<ServerTimeData> result)
38
+ {
39
+ AmaGDK._instance.StartCoroutine(FetchTimeRoutine(result));
40
+ }
41
+
42
+ private IEnumerator FetchTimeRoutine(Action<ServerTimeData> result)
43
+ {
44
+ using (var request = UnityWebRequest.Get(GetURL()))
45
+ {
46
+ yield return request.SendWebRequest();
47
+
48
+ if (request.result != UnityWebRequest.Result.Success)
49
+ {
50
+ result?.Invoke(new ServerTimeData($"Error fetching time: {request.error}"));
51
+ yield break;
52
+ }
53
+
54
+ result?.Invoke(ParseResponse(request.downloadHandler.text));
55
+ }
56
+ }
57
+ }
58
+
59
+ internal class WorldTimeServer_TimeProvider : BaseServerTimeProvider
60
+ {
61
+ private const string URL = "https://www.worldtimeserver.com/current_time_in_LA.aspx";
62
+
63
+ public override ServerTimeData ParseResponse(string response)
64
+ {
65
+ string startStr = "id=\"serverTimeStamp\" value=\"";
66
+ int startIndex = response.IndexOf(startStr) + startStr.Length;
67
+ string unixTimeStr = string.Empty;
68
+ char currentChar = char.MinValue;
69
+ for (int i = startIndex, n = response.Length; i < n; i++)
70
+ {
71
+ currentChar = response[i];
72
+ if (currentChar == '.' || currentChar == '\"') break;
73
+ unixTimeStr += currentChar;
74
+ }
75
+ if (long.TryParse(unixTimeStr, out long unixTime))
76
+ {
77
+ DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(unixTime);
78
+ return new ServerTimeData(dateTimeOffset.DateTime);
79
+ }
80
+ else
81
+ {
82
+ return new ServerTimeData("Error parsing WorldTimeServer data");
83
+ }
84
+ }
85
+ public override string GetURL()
86
+ {
87
+ return URL;
88
+ }
89
+ }
90
+
91
+ internal class WorldTimeAPI_TimeProvider : BaseServerTimeProvider
92
+ {
93
+ private const string URL = "https://worldtimeapi.org/api/ip";
94
+
95
+ [Serializable]
96
+ private class TimeData
97
+ {
98
+ public string datetime;
99
+ }
100
+
101
+ public override string GetURL()
102
+ {
103
+ return URL;
104
+ }
105
+
106
+ public override ServerTimeData ParseResponse(string response)
107
+ {
108
+ try
109
+ {
110
+ var data = JsonUtility.FromJson<TimeData>(response);
111
+ DateTime utcTime = DateTime.ParseExact(data.datetime, "yyyy-MM-dd'T'HH:mm:ss.ffffffzzz", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.AdjustToUniversal);
112
+ return new ServerTimeData(utcTime);
113
+ }
114
+ catch (Exception e)
115
+ {
116
+ return new ServerTimeData($"Error parsing time data: {e.Message}");
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ namespace Amanotes.Core.Internal
123
+ {
124
+ public partial class ConfigAsset
125
+ {
126
+ [SerializeField] public bool enableServerTime = true;
127
+ }
128
+
129
+ internal class GDKServerTime
130
+ {
131
+ private const float MAX_WAIT_TIME = 60;
132
+ private List<IServerTimeProvider> providers = new List<IServerTimeProvider>() { new WorldTimeAPI_TimeProvider(), new WorldTimeServer_TimeProvider() };
133
+ private int currentIndex = 0;
134
+ private IServerTimeProvider provider
135
+ {
136
+ get { return providers[currentIndex]; }
137
+ }
138
+
139
+ private DateTime? serverTime;
140
+ private float timeSinceFetchServerTime;
141
+ private int retryCount = 0;
142
+
143
+ internal GDKServerTime()
144
+ {
145
+ }
146
+
147
+ public void SetTimeProviders(List<IServerTimeProvider> providers)
148
+ {
149
+ GDKUtils.ThrowIf(providers == null || providers.Count == 0, "Server time providers list cannot be null or empty.");
150
+ this.providers = providers;
151
+ currentIndex = 0;
152
+ }
153
+
154
+ public DateTime? GetTime()
155
+ {
156
+ GDKUtils.ThrowIf(!AmaGDK.Config.enableServerTime, "ServerTime is disabled, Please enable it in the AmaGDKConfig");
157
+ if (serverTime == null)
158
+ return null;
159
+ float duration = Time.realtimeSinceStartup - timeSinceFetchServerTime;
160
+ return ((DateTime)serverTime).AddSeconds(duration);
161
+ }
162
+
163
+ public void GetTime(Action<DateTime?> result)
164
+ {
165
+ GDKUtils.ThrowIf(!AmaGDK.Config.enableServerTime, "ServerTime is disabled, Please enable it in the AmaGDKConfig");
166
+ if (serverTime == null)
167
+ {
168
+ UpdateTime(result);
169
+ }
170
+ else
171
+ {
172
+ result(GetTime());
173
+ }
174
+ }
175
+
176
+ public void UpdateTime(Action<DateTime?> result = null)
177
+ {
178
+ provider.FetchServerTime(data =>
179
+ {
180
+ if (data.time != null)
181
+ {
182
+ serverTime = data.time;
183
+ timeSinceFetchServerTime = Time.realtimeSinceStartup;
184
+ result?.Invoke(data.time);
185
+ }
186
+ else
187
+ {
188
+ result?.Invoke(null);
189
+ Logging.Log(data.errorMessage);
190
+ FetchTimeWithOtherProvider();
191
+ }
192
+ });
193
+ }
194
+
195
+ private void FetchTimeWithOtherProvider()
196
+ {
197
+ retryCount++;
198
+ currentIndex = (currentIndex + 1) % providers.Count;
199
+ if (retryCount < providers.Count)
200
+ {
201
+ UpdateTime();
202
+ return;
203
+ }
204
+ float waitTime = Mathf.Min(MAX_WAIT_TIME, Mathf.Pow(2, retryCount - providers.Count + 1));
205
+ GDKUtils.DelayCall(waitTime, () =>
206
+ {
207
+ UpdateTime();
208
+ });
209
+ }
210
+ }
211
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 04a5b0922db443b39ec9a3edeb2e3337
3
+ timeCreated: 1711943237
@@ -11,9 +11,10 @@ namespace Amanotes.Core
11
11
  public string lastEventName;
12
12
 
13
13
  public static void LogEventError(string message)
14
- {
15
- if (!Application.isBatchMode)
16
- Logging.LogError(message);
14
+ {
15
+ #if !AMAGDK_DEV
16
+ Logging.LogError(message);
17
+ #endif
17
18
  throw new KlavarException(message);
18
19
  }
19
20
  }
@@ -39,14 +39,14 @@ namespace Amanotes.Core
39
39
  public static string ToCamelCase(string text)
40
40
  {
41
41
  var tokens = ToTokens(text);
42
- return string.Join("", tokens.Select(t => Char.ToUpper(t[0]) + t.Substring(1).ToLower()));
42
+ return string.Join("", tokens.Select((t, i) =>
43
+ (i == 0 ? Char.ToLower(t[0]) : Char.ToUpper(t[0])) + t.Substring(1).ToLower()));
43
44
  }
44
45
 
45
46
  public static string ToPascalCase(string text)
46
47
  {
47
48
  var tokens = ToTokens(text);
48
- return string.Join("", tokens.Select((t, i) =>
49
- (i == 0 ? Char.ToLower(t[0]) : Char.ToUpper(t[0])) + t.Substring(1).ToLower()));
49
+ return string.Join("", tokens.Select(t => Char.ToUpper(t[0]) + t.Substring(1).ToLower()));
50
50
  }
51
51
 
52
52
  public static string ToKebabCase(string text)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.amanotes.gdk",
3
- "version": "0.2.57",
3
+ "version": "0.2.58",
4
4
  "displayName": "AmaGDK",
5
5
  "description": "Amanotes Game Development Kit",
6
6
  "unity": "2019.4",