com.amanotes.gdk 0.2.47 → 0.2.49

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.
Files changed (67) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/Editor/AmaGDKEditor.cs +133 -65
  3. package/Editor/AmaGDKExtra.cs +31 -0
  4. package/Editor/AmaGDKExtra.cs.meta +11 -0
  5. package/Editor/Utils/AmaGDKEditor.ExtractVersion.cs +1 -1
  6. package/Extra/AmaGDKInstaller.unitypackage +0 -0
  7. package/Extra/AmaGDKProject.unitypackage +0 -0
  8. package/Extra/SDKVersionTracking.unitypackage +0 -0
  9. package/Extra/SDKVersionTracking.unitypackage.meta +7 -0
  10. package/Packages/AmaGDKConfig.unitypackage +0 -0
  11. package/Packages/AmaGDKExample.unitypackage +0 -0
  12. package/Packages/AmaGDKTest.unitypackage +0 -0
  13. package/Packages/AppsFlyerAdapter.unitypackage +0 -0
  14. package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
  15. package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
  16. package/Packages/IronSourceAdapter.unitypackage +0 -0
  17. package/Packages/RevenueCatAdapter.unitypackage +0 -0
  18. package/Runtime/AmaGDK.Adapters.cs +0 -4
  19. package/Runtime/AmaGDK.Ads.cs +89 -29
  20. package/Runtime/AmaGDK.Analytics.cs +97 -64
  21. package/Runtime/AmaGDK.IAP.cs +39 -45
  22. package/Runtime/AmaGDK.RemoteConfig.cs +76 -52
  23. package/Runtime/AmaGDK.UserProfile.cs +106 -124
  24. package/Runtime/AmaGDK.cs +46 -35
  25. package/Runtime/Internal/AmaGDK.Event.cs +185 -0
  26. package/Runtime/Internal/AmaGDK.Event.cs.meta +3 -0
  27. package/Runtime/Internal/AmaGDK.Internal.cs +3 -0
  28. package/Runtime/Internal/AmaGDK.Utils.cs +85 -24
  29. package/Runtime/Klavar/Attributes/AccumulatedCountAttribute.cs +19 -0
  30. package/Runtime/Klavar/Attributes/AccumulatedCountAttribute.cs.meta +11 -0
  31. package/Runtime/Klavar/Attributes/ConnectionAttribute.cs +18 -0
  32. package/Runtime/Klavar/Attributes/ConnectionAttribute.cs.meta +11 -0
  33. package/Runtime/Klavar/Attributes/CountInSessionAttribute.cs +27 -0
  34. package/Runtime/Klavar/Attributes/CountInSessionAttribute.cs.meta +11 -0
  35. package/Runtime/Klavar/Attributes/DescriptionAttribute.cs +7 -0
  36. package/Runtime/Klavar/Attributes/DescriptionAttribute.cs.meta +11 -0
  37. package/Runtime/Klavar/Attributes/DynamicValidateAttribute.cs +30 -0
  38. package/Runtime/Klavar/Attributes/DynamicValidateAttribute.cs.meta +11 -0
  39. package/Runtime/Klavar/Attributes/IgnoreAttribute.cs +16 -0
  40. package/Runtime/Klavar/Attributes/IgnoreAttribute.cs.meta +11 -0
  41. package/Runtime/Klavar/Attributes/MinMaxAttribute.cs +130 -0
  42. package/Runtime/Klavar/Attributes/MinMaxAttribute.cs.meta +11 -0
  43. package/Runtime/Klavar/Attributes/MinMaxLengthAttribute.cs +88 -0
  44. package/Runtime/Klavar/Attributes/MinMaxLengthAttribute.cs.meta +11 -0
  45. package/Runtime/Klavar/Attributes/NameAttribute.cs +35 -0
  46. package/Runtime/Klavar/Attributes/NameAttribute.cs.meta +11 -0
  47. package/Runtime/Klavar/Attributes/NotNullAttribute.cs +16 -0
  48. package/Runtime/Klavar/Attributes/NotNullAttribute.cs.meta +11 -0
  49. package/Runtime/Klavar/Attributes/RegexPatternAttribute.cs +58 -0
  50. package/Runtime/Klavar/Attributes/RegexPatternAttribute.cs.meta +11 -0
  51. package/Runtime/Klavar/Attributes/TimeDiffLastFireAttribute.cs +28 -0
  52. package/Runtime/Klavar/Attributes/TimeDiffLastFireAttribute.cs.meta +11 -0
  53. package/Runtime/Klavar/Attributes/ToStringAttribute.cs +97 -0
  54. package/Runtime/Klavar/Attributes/ToStringAttribute.cs.meta +11 -0
  55. package/Runtime/Klavar/Attributes/ValueAttribute.cs +30 -0
  56. package/Runtime/Klavar/Attributes/ValueAttribute.cs.meta +11 -0
  57. package/Runtime/Klavar/Attributes.meta +8 -0
  58. package/Runtime/Klavar/KlavarEvent.cs +91 -0
  59. package/Runtime/Klavar/KlavarEvent.cs.meta +11 -0
  60. package/Runtime/Klavar/KlavarEventAttribute.cs +39 -0
  61. package/Runtime/Klavar/KlavarEventAttribute.cs.meta +11 -0
  62. package/Runtime/Klavar/KlavarEventTools.cs +92 -0
  63. package/Runtime/Klavar/KlavarEventTools.cs.meta +11 -0
  64. package/Runtime/Klavar/KlavarEventUtils.cs +58 -0
  65. package/Runtime/Klavar/KlavarEventUtils.cs.meta +11 -0
  66. package/Runtime/{Core.meta → Klavar.meta} +1 -1
  67. package/package.json +1 -1
@@ -1,36 +1,40 @@
1
1
  using System;
2
- using System.Collections;
3
2
  using System.Text.RegularExpressions;
4
3
  using Amanotes.Core.Internal;
4
+ using System.Collections.Generic;
5
5
  using UnityEngine;
6
+
6
7
  namespace Amanotes.Core
7
8
  {
8
9
  public partial class AmaGDK //User profile
9
10
  {
10
11
  public static readonly UserProfile User = new UserProfile();
11
- public static event Action<string> OnUserIdChanged;
12
12
 
13
13
  [Serializable]
14
14
  public partial class UserProfile : IJsonFile
15
15
  {
16
- private const string FILE_NAME = nameof(UserProfile);
17
- [NonSerialized] internal bool _dirty;
18
-
19
16
  private void Save()
20
17
  {
21
- GDKFileUtils.Save(FILE_NAME, JsonUtility.ToJson(this));
22
- }
23
-
24
- internal void SaveIfDirty()
25
- {
26
- if (!_dirty) return;
27
- _dirty = false;
28
18
  this.SaveJsonToFile();
29
19
  }
30
20
  }
31
21
 
32
22
  public partial class UserProfile //PUBLIC
33
23
  {
24
+ public Dictionary<string, object> CollectAllUserIds()
25
+ {
26
+ var dic = new Dictionary<string, object>();
27
+ if (!string.IsNullOrWhiteSpace(IDFA)) dic["idfa"] = IDFA;
28
+ if (!string.IsNullOrWhiteSpace(IDFV)) dic["idfv"] = IDFV;
29
+ if (!string.IsNullOrWhiteSpace(GAId)) dic["gaid"] = GAId;
30
+ if (!string.IsNullOrWhiteSpace(AndroidId)) dic["android_id"] = AndroidId;
31
+ if (!string.IsNullOrWhiteSpace(PseudoId)) dic["pseudo_id"] = PseudoId;
32
+ if (!string.IsNullOrWhiteSpace(AmaDeviceId)) dic["ama_device_id"] = AmaDeviceId;
33
+ if (!string.IsNullOrWhiteSpace(AppsFlyerId)) dic["appsflyer_id"] = AppsFlyerId;
34
+ if (!string.IsNullOrWhiteSpace(InstallationId)) dic["installation_id"] = InstallationId;
35
+ return dic;
36
+ }
37
+
34
38
  public string UserId
35
39
  {
36
40
  get
@@ -40,9 +44,8 @@ namespace Amanotes.Core
40
44
  }
41
45
  private set
42
46
  {
43
- if (_userId == value) return;
47
+ if (_userId == value) return;
44
48
  _userId = value;
45
- OnUserIdChanged?.Invoke(_userId);
46
49
  Save();
47
50
  }
48
51
  }
@@ -102,65 +105,8 @@ namespace Amanotes.Core
102
105
  get => _installationId;
103
106
  set => _installationId = ValidateId(value, ALPHANUMERIC_PATTERN);
104
107
  }
105
- }
106
-
107
- public partial class UserProfile //INTERNAL
108
- {
109
- [SerializeField]
110
- private string _userId;
111
- [SerializeField]
112
- private string _gaid;
113
- [SerializeField]
114
- private string _idfa;
115
- [SerializeField]
116
- private string _idfv;
117
- [SerializeField]
118
- private string _androidId;
119
- [SerializeField]
120
- private string _pseudoId;
121
- [SerializeField]
122
- private string _amaDeviceId;
123
- [SerializeField]
124
- private string _appsFlyerId;
125
- [SerializeField]
126
- private string _installationId;
127
-
128
- private const string ALPHANUMERIC_HYPHEN_PATTERN = @"^(?=.*\d)(?=.*[a-zA-Z])(?=.*-).+$";
129
- private const string ALPHANUMERIC_PATTERN = @"^(?=.*\d)(?=.*[a-zA-Z])[a-zA-Z\d]+$";
130
- private const string NUMERIC_HYPHEN_PATTERN = @"^(?=.*\d)(?=.*-)[\d-]+$";
131
-
132
- private const string AMA_DEVICE_ID_KEY = "ama_device_id";
133
- private const float TIME_OUT = 5f;
134
- private const float WAIT_TIME = 0.5f;
135
- private WaitForSecondsRealtime waitForDuration = new WaitForSecondsRealtime(WAIT_TIME);
136
-
137
- internal void InitModule()
138
- {
139
- User.LoadJsonFromFile();
140
-
141
- // Always get the latest advertising id
142
- GetAdvertisingId();
143
- }
144
-
145
- internal void StartModule()
146
- {
147
- UpdateUserId();
148
- }
149
108
 
150
- // internal IEnumerator Init()
151
- // {
152
- // float time = 0;
153
- // while (!User.IsAmaDeviceIdExist())
154
- // {
155
- // yield return waitForDuration;
156
- // time += WAIT_TIME;
157
- // if (time <= TIME_OUT) continue;
158
- // Logging.LogWarning($"| UserProfile <init> timeout: {TIME_OUT} (ama_device_id not exist)");
159
- // break;
160
- // }
161
- // }
162
-
163
- internal void UpdateUserId()
109
+ public void UpdateUserId()
164
110
  {
165
111
  #if UNITY_ANDROID
166
112
  if (!string.IsNullOrWhiteSpace(_gaid))
@@ -168,33 +114,35 @@ namespace Amanotes.Core
168
114
  UserId = $"GAID-{_gaid}";
169
115
  return;
170
116
  }
171
-
172
- if (!string.IsNullOrWhiteSpace(_androidId))
173
- {
174
- UserId = $"ADR-{_androidId}";
175
- return;
176
- }
177
117
  #endif
178
-
179
118
  #if UNITY_IOS
180
119
  if (!string.IsNullOrWhiteSpace(_idfa))
181
120
  {
182
121
  UserId = $"IDFA-{_idfa}";
183
122
  return;
184
123
  }
124
+ #endif
185
125
 
186
- if (!string.IsNullOrWhiteSpace(_idfv))
126
+ if (!string.IsNullOrWhiteSpace(_pseudoId))
187
127
  {
188
- UserId = $"IDFV-{_idfv}";
128
+ UserId = $"FRB-{_pseudoId}";
189
129
  return;
190
130
  }
191
- #endif
192
131
 
193
- if (!string.IsNullOrWhiteSpace(_pseudoId))
132
+ #if UNITY_ANDROID
133
+ if (!string.IsNullOrWhiteSpace(_androidId))
194
134
  {
195
- UserId = $"FRB-{_pseudoId}";
135
+ UserId = $"ADR-{_androidId}";
196
136
  return;
197
137
  }
138
+ #endif
139
+ #if UNITY_IOS
140
+ if (!string.IsNullOrWhiteSpace(_idfv))
141
+ {
142
+ UserId = $"IDFV-{_idfv}";
143
+ return;
144
+ }
145
+ #endif
198
146
 
199
147
  if (!string.IsNullOrWhiteSpace(_amaDeviceId))
200
148
  {
@@ -214,71 +162,105 @@ namespace Amanotes.Core
214
162
  return;
215
163
  }
216
164
  }
165
+ }
166
+
167
+ public partial class UserProfile //INTERNAL
168
+ {
169
+ [SerializeField]
170
+ private string _userId;
171
+ [SerializeField]
172
+ private string _gaid;
173
+ [SerializeField]
174
+ private string _idfa;
175
+ [SerializeField]
176
+ private string _idfv;
177
+ [SerializeField]
178
+ private string _androidId;
179
+ [SerializeField]
180
+ private string _pseudoId;
181
+ [SerializeField]
182
+ private string _amaDeviceId;
183
+ [SerializeField]
184
+ private string _appsFlyerId;
185
+ [SerializeField]
186
+ private string _installationId;
187
+
188
+ private const string ALPHANUMERIC_HYPHEN_PATTERN = @"^(?=.*\d)(?=.*[a-zA-Z])(?=.*-).+$";
189
+ private const string ALPHANUMERIC_PATTERN = @"^(?=.*\d)(?=.*[a-zA-Z])[a-zA-Z\d]+$";
190
+ private const string NUMERIC_HYPHEN_PATTERN = @"^(?=.*\d)(?=.*-)[\d-]+$";
217
191
 
218
- private bool IsAmaDeviceIdExist()
192
+ private const string AMA_DEVICE_ID_KEY = "ama_device_id";
193
+
194
+ internal void InitModule()
219
195
  {
220
- if (!string.IsNullOrEmpty(_amaDeviceId))
221
- {
222
- Logging.Log($"AmaDeviceId is already existed: {_amaDeviceId}");
223
- return true;
224
- }
225
- return false;
196
+ User.LoadJsonFromFile();
197
+
198
+ #if UNITY_ANDROID
199
+ AndroidId = SystemInfo.deviceUniqueIdentifier;
200
+ #elif UNITY_IOS
201
+ IDFV = SystemInfo.deviceUniqueIdentifier;
202
+ #endif
203
+
204
+ // Always get the latest advertising id
205
+ GetAdvertisingId();
226
206
  }
227
207
 
208
+ internal void StartModule()
209
+ {
210
+ UpdateUserId();
211
+ Logging.Log($"[UserProfile] user_id: {_userId}");
212
+ }
213
+
228
214
  private void SetAdvertisingID(string id)
229
215
  {
230
216
  switch (Application.platform)
231
217
  {
232
218
  case RuntimePlatform.IPhonePlayer:
233
219
  IDFA = id;
234
- IDFV = SystemInfo.deviceUniqueIdentifier;
235
220
  break;
236
221
  case RuntimePlatform.Android:
237
222
  GAId = id;
238
- AndroidId = SystemInfo.deviceUniqueIdentifier;
239
- break;
240
- default:
241
- // Logging.Log($"[UserProfile] There is no advertising ID on {Application.platform}");
242
223
  break;
243
224
  }
244
225
  }
245
226
 
246
227
  private void GetAdvertisingId()
247
228
  {
248
- float time = Time.realtimeSinceStartup;
249
-
250
229
  AdvertisingIdFetcher.RequestAdvertisingId(advertisingId =>
251
230
  {
252
- SetAdvertisingID(advertisingId);
253
- switch (Application.platform)
231
+ GDKUtils.DelayCall(0, () =>
254
232
  {
255
- case RuntimePlatform.IPhonePlayer:
256
- string v = KeyChain.GetKeyChain(AMA_DEVICE_ID_KEY);
257
- if (string.IsNullOrEmpty(v))
258
- {
259
- v = Guid.NewGuid().ToString();
260
- KeyChain.SetKeyChain(AMA_DEVICE_ID_KEY, v);
261
- }
262
- AmaDeviceId = v;
263
- break;
233
+ SetAdvertisingID(advertisingId);
234
+ switch (Application.platform)
235
+ {
236
+ case RuntimePlatform.IPhonePlayer:
237
+ string v = KeyChain.GetKeyChain(AMA_DEVICE_ID_KEY);
238
+ if (string.IsNullOrEmpty(v))
239
+ {
240
+ v = Guid.NewGuid().ToString();
241
+ KeyChain.SetKeyChain(AMA_DEVICE_ID_KEY, v);
242
+ }
243
+ AmaDeviceId = v;
244
+ break;
264
245
 
265
- case RuntimePlatform.Android:
266
- string cachedAmaDeviceId = PlayerPrefs.GetString(AMA_DEVICE_ID_KEY);
267
- if (string.IsNullOrEmpty(cachedAmaDeviceId))
268
- {
269
- cachedAmaDeviceId = SystemInfo.deviceUniqueIdentifier;
270
- PlayerPrefs.SetString(AMA_DEVICE_ID_KEY, cachedAmaDeviceId);
271
- }
272
- AmaDeviceId = cachedAmaDeviceId;
273
- break;
246
+ case RuntimePlatform.Android:
247
+ string cachedAmaDeviceId = PlayerPrefs.GetString(AMA_DEVICE_ID_KEY);
248
+ if (string.IsNullOrEmpty(cachedAmaDeviceId))
249
+ {
250
+ cachedAmaDeviceId = SystemInfo.deviceUniqueIdentifier;
251
+ PlayerPrefs.SetString(AMA_DEVICE_ID_KEY, cachedAmaDeviceId);
252
+ }
253
+ AmaDeviceId = cachedAmaDeviceId;
254
+ break;
274
255
 
275
- default:
276
- AmaDeviceId = SystemInfo.deviceUniqueIdentifier;
277
- break;
278
- }
256
+ default:
257
+ AmaDeviceId = SystemInfo.deviceUniqueIdentifier;
258
+ break;
259
+ }
279
260
 
280
- Logging.Log($"Generate AmaDeviceId completed: {_amaDeviceId}");
281
- User.Save();
261
+ Logging.Log($"[UserProfile] ama_device_id: {_amaDeviceId}");
262
+ Save();
263
+ });
282
264
  });
283
265
  }
284
266
 
package/Runtime/AmaGDK.cs CHANGED
@@ -17,18 +17,27 @@ namespace Amanotes.Core
17
17
  {
18
18
  public partial class AmaGDK : MonoBehaviour
19
19
  {
20
- public const string VERSION = "0.2.47";
20
+ public const string VERSION = "0.2.49";
21
21
 
22
22
  internal static AmaGDK _instance;
23
23
  internal static Status _status = Status.None;
24
- internal static Action _onReadyCallback;
25
- internal static Action<string> _onAdapterReadyCallback;
26
24
  internal static bool _allowInit = false;
27
25
  public bool autoInit = true;
28
26
 
29
27
  private static ConfigAsset _config = null;
30
- // private static readonly Dictionary<string, AdapterInfo> _adapters = new Dictionary<string, AdapterInfo>();
31
-
28
+
29
+ public static partial class Event
30
+ {
31
+ public const string GDK_HOOK_START = nameof(GDK_HOOK_START);
32
+ public const string GDK_HOOK_END = nameof(GDK_HOOK_END);
33
+
34
+ public const string GDK_INIT_START = nameof(GDK_INIT_START);
35
+ public const string GDK_INIT_END = nameof(GDK_INIT_END);
36
+
37
+ public const string GDK_READY = nameof(GDK_READY);
38
+ public const string ADAPTER_READY = nameof(ADAPTER_READY);
39
+ }
40
+
32
41
  public static ConfigAsset Config
33
42
  {
34
43
  get
@@ -42,15 +51,17 @@ namespace Amanotes.Core
42
51
 
43
52
  private void Awake()
44
53
  {
45
- if (_instance != null && _instance != this)
54
+ if (_instance != null)
46
55
  {
47
- LogWarning(MULTIPLE_INSTANCE);
48
- Destroy(this);
56
+ if (_instance != this)
57
+ {
58
+ LogWarning(MULTIPLE_INSTANCE);
59
+ Destroy(this);
60
+ }
61
+ LogWarning("Should never be here!");
49
62
  return;
50
63
  }
51
-
52
- if (_instance != null) LogWarning("Should never be here!");
53
-
64
+
54
65
  _instance = this;
55
66
  DontDestroyOnLoad(this);
56
67
 
@@ -60,10 +71,12 @@ namespace Amanotes.Core
60
71
 
61
72
  IEnumerator InitHook()
62
73
  {
74
+ dispatcher.Dispatch(Event.GDK_HOOK_START);
63
75
  int nHooks = Hook.hooks.Count;
64
76
  if (nHooks == 0)
65
77
  {
66
78
  Log($"[Hook] No hook registered!");
79
+ dispatcher.Dispatch(Event.GDK_HOOK_END);
67
80
  yield break;
68
81
  }
69
82
 
@@ -71,7 +84,6 @@ namespace Amanotes.Core
71
84
  var hookCompleted = false;
72
85
 
73
86
  float stTime = Time.realtimeSinceStartup;
74
-
75
87
  Hook.TriggerHooks(() =>
76
88
  {
77
89
  hookCompleted = true;
@@ -79,6 +91,7 @@ namespace Amanotes.Core
79
91
  yield return new WaitUntil(() => hookCompleted);
80
92
  float elapsed = Time.realtimeSinceStartup - stTime;
81
93
  Log($"[Hook] {nHooks} hooks complete after " + elapsed);
94
+ dispatcher.Dispatch(Event.GDK_HOOK_END);
82
95
  }
83
96
 
84
97
  IEnumerator WaitForManualInit()
@@ -106,7 +119,8 @@ namespace Amanotes.Core
106
119
  User.InitModule();
107
120
  Analytics.InitModule();
108
121
  Ads.InitModule();
109
- IAP.InitModule();
122
+ IAP.InitModule();
123
+ RemoteConfig.InitModule();
110
124
  }
111
125
  Profiler.EndSample();
112
126
  }
@@ -119,6 +133,7 @@ namespace Amanotes.Core
119
133
  Analytics.StartModule();
120
134
  Ads.StartModule();
121
135
  IAP.StartModule();
136
+ RemoteConfig.StartModule();
122
137
  }
123
138
  Profiler.EndSample();
124
139
  }
@@ -137,9 +152,9 @@ namespace Amanotes.Core
137
152
  {
138
153
  // Log($"Initiating {adapter.adapterId} --> initOrder: {adapter.initOrder} | {adapter.status}");
139
154
  float startTime = Time.realtimeSinceStartup;
140
- Profiler.BeginSample("AmaGDK.adapter.InitSDK()");
155
+ Profiler.BeginSample($"AmaGDK.adapter.InitSDK-{adapter.adapterId}");
141
156
  {
142
- adapter.InitSDK();
157
+ adapter.InitSDK();
143
158
  }
144
159
  Profiler.EndSample();
145
160
 
@@ -150,13 +165,12 @@ namespace Amanotes.Core
150
165
  LogWarning($"{adapter.adapterId} init time out: {TIMEOUT}");
151
166
  }
152
167
 
153
- _onAdapterReadyCallback?.Invoke(adapter.adapterId);
168
+ dispatcher.Dispatch(Event.ADAPTER_READY, adapter.adapterId);
154
169
  sb.AppendLine($"[{(adapter.IsReady ? " OK " : "FAIL")}] {adapter.adapterId} (~ {Time.realtimeSinceStartup - startTime:#0.00}s)");
155
170
 
156
171
  // Wait for postprocessing of each adapter
157
172
  yield return null;
158
173
  }
159
- _onAdapterReadyCallback = null;
160
174
  }
161
175
 
162
176
 
@@ -170,6 +184,7 @@ namespace Amanotes.Core
170
184
  float startTime = Time.realtimeSinceStartup;
171
185
  yield return InitHook();
172
186
 
187
+ dispatcher.Dispatch(Event.GDK_INIT_START);
173
188
  var sb = new StringBuilder();
174
189
  InitModules();
175
190
 
@@ -177,10 +192,10 @@ namespace Amanotes.Core
177
192
  yield return InitAdapters(sb);
178
193
 
179
194
  StartModules();
195
+ dispatcher.Dispatch(Event.GDK_INIT_END);
180
196
 
181
197
  _status = Status.Ready;
182
- _onReadyCallback?.Invoke();
183
- _onReadyCallback = null;
198
+ dispatcher.Dispatch(Event.GDK_READY);
184
199
  Debug.Log($"AmaGDK v{VERSION} | {READY} in {Time.realtimeSinceStartup - startTime:#0.00}s\n\n{sb}");
185
200
  }
186
201
  }
@@ -200,8 +215,7 @@ namespace Amanotes.Core
200
215
 
201
216
  if (onReady != null)
202
217
  {
203
- _onReadyCallback -= onReady;
204
- _onReadyCallback += onReady;
218
+ dispatcher.AddListener(Event.GDK_READY, onReady, true);
205
219
  }
206
220
 
207
221
  if (_allowInit)
@@ -211,28 +225,21 @@ namespace Amanotes.Core
211
225
  }
212
226
 
213
227
  _allowInit = true;
214
-
215
228
  if (_instance != null) return;
229
+
216
230
  var sdk = new GameObject("AmaGDK");
217
231
  _instance = sdk.AddComponent<AmaGDK>();
218
232
  }
219
233
 
220
234
  public static void SetOnReadyCallback(Action onReady)
221
235
  {
222
- if (onReady == null)
223
- {
224
- LogWarning("Cannot add a null callback!");
225
- return;
226
- }
227
-
228
236
  if (isReady)
229
237
  {
230
238
  onReady.Invoke();
231
239
  return;
232
240
  }
233
241
 
234
- _onReadyCallback -= onReady;
235
- _onReadyCallback += onReady;
242
+ dispatcher.AddListener(Event.GDK_READY, onReady, true);
236
243
  }
237
244
 
238
245
  public static void SetAdapterReadyCallback(Action<string> onAdapterReady)
@@ -242,11 +249,15 @@ namespace Amanotes.Core
242
249
  LogWarning("Cannot add a null callback!");
243
250
  return;
244
251
  }
252
+
253
+ if (AmaGDK.isReady)
254
+ {
255
+ LogWarning("All adapters has been init / ready!");
256
+ return;
257
+ }
245
258
 
246
- _onAdapterReadyCallback -= onAdapterReady;
247
- _onAdapterReadyCallback += onAdapterReady;
259
+ dispatcher.AddListener(Event.ADAPTER_READY, onAdapterReady, false);
248
260
  }
249
-
250
261
  }
251
262
 
252
263
  public partial class AmaGDK
@@ -316,7 +327,7 @@ namespace Amanotes.Core
316
327
  return;
317
328
  }
318
329
 
319
- int startIndex = zshrcContent.IndexOf($"export {variableName}=");
330
+ int startIndex = zshrcContent.IndexOf($"export {variableName}=", StringComparison.Ordinal);
320
331
  if (startIndex >= 0)
321
332
  {
322
333
  startIndex += $"export {variableName}=".Length;
@@ -366,7 +377,7 @@ namespace Amanotes.Core
366
377
  #endif
367
378
  }
368
379
 
369
- public partial class AmaGDK // Switch dev mode
380
+ public partial class AmaGDK
370
381
  {
371
382
  public static class Hook
372
383
  {