com.amanotes.gdk 0.2.86 → 0.2.87
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 +22 -0
- package/Editor/Extra/GDKCIBuildCommand.cs +19 -2
- package/Editor/Extra/GDKLocalBuild.cs +25 -1
- package/Editor/Utils/AmaGDKEditor.ExtractVersion.Max.cs +7 -0
- package/Extra/AmaGDKInstaller.unitypackage +0 -0
- package/Extra/AutoEventQC.unitypackage +0 -0
- package/Extra/CheckDiskSpace.unitypackage +0 -0
- package/Extra/Consent.unitypackage +0 -0
- package/Extra/CrashlyticHook.unitypackage +0 -0
- package/Extra/ForceUpdate.unitypackage +0 -0
- package/Extra/LegacyGDKUpdateHelper.unitypackage +0 -0
- package/Extra/PostProcessor.unitypackage +0 -0
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/AmaGDKExample.unitypackage +0 -0
- package/Packages/AmaGDKTest.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.unitypackage +0 -0
- package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
- package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
- package/Packages/IronSourceAdapter.AdQuality.unitypackage +0 -0
- package/Packages/IronSourceAdapter.unitypackage +0 -0
- package/Packages/MaxAdNetworkAdapter.unitypackage +0 -0
- package/Packages/RevenueCatAdapter.unitypackage +0 -0
- package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
- package/Runtime/Ad/AdLogic.cs +222 -147
- package/Runtime/AmaGDK.Analytics.cs +105 -65
- package/Runtime/AmaGDK.RemoteConfig.cs +50 -40
- package/Runtime/AmaGDK.cs +1 -1
- package/Runtime/AnalyticQualityAsset.cs +69 -38
- package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs +31 -17
- package/Runtime/Core/GDKSemVer.cs +23 -26
- package/Runtime/Fps/AmaFPSVisualizer.cs +48 -26
- package/Runtime/Internal/AmaGDK.Utils.cs +90 -46
- package/Runtime/Internal/ForceQuitMonitor.cs +43 -31
- package/Runtime/Klavar/Attributes/MinMaxAttribute.cs +12 -3
- package/Runtime/UI/ScrollView/GDKScrollView.cs +83 -48
- package/Runtime/Utils/GDKFileUtils.cs +2 -7
- package/Runtime/Utils/GDKUtils.cs +20 -8
- package/package.json +1 -1
|
@@ -458,42 +458,51 @@ namespace Amanotes.Core
|
|
|
458
458
|
if (config.normalizeEventName) NormalizeEventName(ref eventNameToSend);
|
|
459
459
|
config.quality.CheckEventQuality(eventParams.eventName, eventParams.parameters);
|
|
460
460
|
|
|
461
|
-
|
|
461
|
+
List<string> inUseAdapterIDs = config.enableEventStat ? new List<string>(listAdapters.Count) : null;
|
|
462
|
+
bool effective = ProcessAdapters(eventParams, eventNameToSend, inUseAdapterIDs);
|
|
463
|
+
HandleEventResult(effective, config, eventNameToSend, countInSession, totalCount, eventParams, inUseAdapterIDs);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
private static bool ProcessAdapters(EventParams eventParams, string eventNameToSend, List<string> inUseAdapterIDs)
|
|
467
|
+
{
|
|
462
468
|
var effective = false;
|
|
463
469
|
foreach (AnalyticsAdapter m in listAdapters)
|
|
464
470
|
{
|
|
465
|
-
if (eventParams
|
|
466
|
-
{
|
|
467
|
-
// IMPORTANT NOTE:
|
|
468
|
-
//
|
|
469
|
-
// Once set overrideConfig, we should skip the adapter config completely!!!
|
|
470
|
-
//
|
|
471
|
-
if (eventParams.IsAdapterForbidden(m.adapterId)) continue;
|
|
472
|
-
}
|
|
473
|
-
else // Do not remove else
|
|
474
|
-
{
|
|
475
|
-
if (m.IsForbidden(eventParams.eventName)) continue;
|
|
476
|
-
}
|
|
471
|
+
if (ShouldSkipAdapter(eventParams, m)) continue;
|
|
477
472
|
|
|
478
473
|
effective = true;
|
|
479
474
|
m.LogEvent(eventNameToSend, eventParams.parameters);
|
|
480
475
|
inUseAdapterIDs?.Add(m.adapterId);
|
|
481
476
|
}
|
|
477
|
+
return effective;
|
|
478
|
+
}
|
|
482
479
|
|
|
480
|
+
private static bool ShouldSkipAdapter(EventParams eventParams, AnalyticsAdapter adapter)
|
|
481
|
+
{
|
|
482
|
+
// IMPORTANT NOTE:
|
|
483
|
+
//
|
|
484
|
+
// Once set overrideConfig, we should skip the adapter config completely!!!
|
|
485
|
+
//
|
|
486
|
+
return eventParams.overrideConfig
|
|
487
|
+
? eventParams.IsAdapterForbidden(adapter.adapterId)
|
|
488
|
+
: adapter.IsForbidden(eventParams.eventName);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
private static void HandleEventResult(bool effective, AnalyticsConfig config, string eventNameToSend, int countInSession, int totalCount, EventParams eventParams, List<string> inUseAdapterIDs)
|
|
492
|
+
{
|
|
483
493
|
if (effective)
|
|
484
494
|
{
|
|
485
495
|
if (config.showAnalyticsLog)
|
|
486
496
|
{
|
|
487
497
|
ForceLog($"[Analytics] Event <{eventNameToSend}> (in session: {countInSession}, total: {totalCount})\n{JsonUtils.DictionaryToJson(eventParams.parameters, true)}");
|
|
488
498
|
}
|
|
499
|
+
GDKUtils.SafeInvoke(OnEventSent, eventNameToSend, eventParams.parameters);
|
|
500
|
+
sessionStat?.OnEventSent(eventNameToSend, eventParams.parameters, inUseAdapterIDs);
|
|
489
501
|
}
|
|
490
502
|
else
|
|
491
503
|
{
|
|
492
504
|
LogError($"Event <{eventParams}> has been skipped (no matching Adapter)\n{JsonUtility.ToJson(eventParams)}");
|
|
493
505
|
}
|
|
494
|
-
|
|
495
|
-
GDKUtils.SafeInvoke(OnEventSent, eventNameToSend, eventParams.parameters);
|
|
496
|
-
sessionStat?.OnEventSent(eventNameToSend, eventParams.parameters, inUseAdapterIDs);
|
|
497
506
|
}
|
|
498
507
|
|
|
499
508
|
internal static void LogEventImmediately(EventParams eventParams)
|
|
@@ -568,63 +577,89 @@ namespace Amanotes.Core
|
|
|
568
577
|
var hasChanged = false;
|
|
569
578
|
var trimKey = key.Trim();
|
|
570
579
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
if (c == '_' || isLetter || isNumber)
|
|
577
|
-
{
|
|
578
|
-
tempKey.Append(c);
|
|
579
|
-
continue;
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
hasChanged = true;
|
|
583
|
-
if (c == ' ' || c == '-')
|
|
584
|
-
{
|
|
585
|
-
tempKey.Append('_');
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
if (hasChanged && willLog)
|
|
590
|
-
{
|
|
591
|
-
tempLog.Append(" - Name may only contain alphanumeric characters and underscores");
|
|
592
|
-
}
|
|
580
|
+
hasChanged = ProcessCharacters(trimKey, tempKey, tempLog, willLog, hasChanged);
|
|
581
|
+
hasChanged = EnsureValidStart(tempKey, tempLog, willLog, hasChanged, key);
|
|
582
|
+
hasChanged = HandleReservedPrefixes(tempKey, tempLog, willLog, hasChanged, key);
|
|
583
|
+
hasChanged = ValidateLength(trimKey, tempKey, tempLog, willLog, hasChanged, key);
|
|
593
584
|
|
|
594
|
-
|
|
595
|
-
{
|
|
596
|
-
hasChanged = true;
|
|
597
|
-
tempKey.Insert(0, 'E');
|
|
598
|
-
if (willLog) tempLog.Append($" - Name must start with a letter: <{key}>");
|
|
599
|
-
}
|
|
585
|
+
ApplyChanges(dryRun, warningLog, tempLog, hasChanged, ref key, tempKey);
|
|
600
586
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
tempKey.Insert(0, prefix.Value);
|
|
607
|
-
if (willLog) tempLog.AppendLine($" - <{key}> starts with reserved prefix <{prefix}>");
|
|
608
|
-
}
|
|
587
|
+
GDKPool.Return(tempLog);
|
|
588
|
+
GDKPool.Return(tempKey);
|
|
589
|
+
}
|
|
590
|
+
Profiler.EndSample();
|
|
591
|
+
}
|
|
609
592
|
|
|
610
|
-
|
|
593
|
+
private static bool ProcessCharacters(string trimKey, StringBuilder tempKey, StringBuilder tempLog, bool willLog, bool hasChanged)
|
|
594
|
+
{
|
|
595
|
+
foreach (var c in trimKey)
|
|
596
|
+
{
|
|
597
|
+
var isLetter = IsAlphabet(c);
|
|
598
|
+
var isNumber = char.IsDigit(c);
|
|
599
|
+
|
|
600
|
+
if (c == '_' || isLetter || isNumber)
|
|
611
601
|
{
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
tempKey.Length = 40;
|
|
602
|
+
tempKey.Append(c);
|
|
603
|
+
continue;
|
|
615
604
|
}
|
|
616
605
|
|
|
617
|
-
|
|
606
|
+
hasChanged = true;
|
|
607
|
+
if (c == ' ' || c == '-')
|
|
618
608
|
{
|
|
619
|
-
|
|
620
|
-
} else {
|
|
621
|
-
if (hasChanged) key = tempKey.ToString();
|
|
609
|
+
tempKey.Append('_');
|
|
622
610
|
}
|
|
623
|
-
|
|
624
|
-
GDKPool.Return(tempLog);
|
|
625
|
-
GDKPool.Return(tempKey);
|
|
626
611
|
}
|
|
627
|
-
|
|
612
|
+
|
|
613
|
+
if (hasChanged && willLog)
|
|
614
|
+
{
|
|
615
|
+
tempLog.Append(" - Name may only contain alphanumeric characters and underscores");
|
|
616
|
+
}
|
|
617
|
+
return hasChanged;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
private static bool EnsureValidStart(StringBuilder tempKey, StringBuilder tempLog, bool willLog, bool hasChanged, string key)
|
|
621
|
+
{
|
|
622
|
+
if (tempKey.Length > 0 && !IsAlphabet(tempKey[0]))
|
|
623
|
+
{
|
|
624
|
+
hasChanged = true;
|
|
625
|
+
tempKey.Insert(0, 'E');
|
|
626
|
+
if (willLog) tempLog.Append($" - Name must start with a letter: <{key}>");
|
|
627
|
+
}
|
|
628
|
+
return hasChanged;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
private static bool HandleReservedPrefixes(StringBuilder tempKey, StringBuilder tempLog, bool willLog, bool hasChanged, string key)
|
|
632
|
+
{
|
|
633
|
+
foreach (var prefix in reservedPrefixes)
|
|
634
|
+
{
|
|
635
|
+
if (tempKey.Length < prefix.Key.Length || !StringStartsWith(tempKey, prefix.Key)) continue;
|
|
636
|
+
hasChanged = true;
|
|
637
|
+
tempKey.Remove(0, prefix.Key.Length);
|
|
638
|
+
tempKey.Insert(0, prefix.Value);
|
|
639
|
+
if (willLog) tempLog.AppendLine($" - <{key}> starts with reserved prefix <{prefix}>");
|
|
640
|
+
}
|
|
641
|
+
return hasChanged;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
private static bool ValidateLength(string trimKey, StringBuilder tempKey, StringBuilder tempLog, bool willLog, bool hasChanged, string key)
|
|
645
|
+
{
|
|
646
|
+
if (trimKey.Length > 40)
|
|
647
|
+
{
|
|
648
|
+
hasChanged = true;
|
|
649
|
+
if (willLog) tempLog.AppendLine($" - Name is too long ({key.Length} > 40): <{key}> ");
|
|
650
|
+
tempKey.Length = 40;
|
|
651
|
+
}
|
|
652
|
+
return hasChanged;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
private static void ApplyChanges(bool dryRun, StringBuilder warningLog, StringBuilder tempLog, bool hasChanged, ref string key, StringBuilder tempKey)
|
|
656
|
+
{
|
|
657
|
+
if (dryRun)
|
|
658
|
+
{
|
|
659
|
+
warningLog.Append(tempLog);
|
|
660
|
+
} else {
|
|
661
|
+
if (hasChanged) key = tempKey.ToString();
|
|
662
|
+
}
|
|
628
663
|
}
|
|
629
664
|
|
|
630
665
|
private static bool StringStartsWith(StringBuilder stringBuilder, string prefix)
|
|
@@ -1069,11 +1104,16 @@ namespace Amanotes.Core
|
|
|
1069
1104
|
h.Add(mId);
|
|
1070
1105
|
}
|
|
1071
1106
|
|
|
1107
|
+
eventData.overrideConfig = true;
|
|
1072
1108
|
if (h.Count > 0)
|
|
1073
1109
|
{
|
|
1074
|
-
eventData.overrideConfig = true;
|
|
1075
1110
|
eventData.allowAdapterIds ??= h;
|
|
1076
1111
|
}
|
|
1112
|
+
else
|
|
1113
|
+
{
|
|
1114
|
+
// No valid adapters found, create empty set to ensure event is skipped
|
|
1115
|
+
eventData.allowAdapterIds ??= GDKPool.GetHashSet();
|
|
1116
|
+
}
|
|
1077
1117
|
|
|
1078
1118
|
return ap;
|
|
1079
1119
|
}
|
|
@@ -259,43 +259,9 @@ namespace Amanotes.Core
|
|
|
259
259
|
try
|
|
260
260
|
{
|
|
261
261
|
DictConfig.Clear();
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
string firstLine = sr.ReadLine();
|
|
266
|
-
if (firstLine == null)
|
|
267
|
-
{
|
|
268
|
-
NextState(false);
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
if (ShouldClearCache(firstLine))
|
|
272
|
-
{
|
|
273
|
-
GDKFileUtils.Delete(fileName);
|
|
274
|
-
string oldVersion = firstLine.StartsWith(VERSION_PREFIX) ? firstLine : "<none>";
|
|
275
|
-
Log($"[RemoteConfig] Cached remote config cleared due to embed version changed:\n{oldVersion} -> {EmbedVersion}");
|
|
276
|
-
NextState(false);
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
//Read key-value
|
|
281
|
-
string line;
|
|
282
|
-
int lineNo = 1;
|
|
283
|
-
while ((line = sr.ReadLine()) != null)
|
|
284
|
-
{
|
|
285
|
-
lineNo++;
|
|
286
|
-
var idx = line.IndexOf('\t');
|
|
287
|
-
if (idx == -1)
|
|
288
|
-
{
|
|
289
|
-
LogWarning($"[RemoteConfig] Cannot get (key, value) at line {lineNo} of cache. Content:\n<{line}>");
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
string key = line.Substring(0, idx);
|
|
293
|
-
string value = line.Substring(idx + 1);
|
|
294
|
-
DictConfig.Add(key, Decode(value));
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
Source = RemoteConfigSource.LocalCache;
|
|
298
|
-
Log("[RemoteConfig] Load from cache");
|
|
262
|
+
bool success = ReadCacheFile();
|
|
263
|
+
Profiler.EndSample();
|
|
264
|
+
NextState(success);
|
|
299
265
|
}
|
|
300
266
|
catch (Exception ex)
|
|
301
267
|
{
|
|
@@ -303,11 +269,55 @@ namespace Amanotes.Core
|
|
|
303
269
|
_cacheExisted = false;
|
|
304
270
|
Profiler.EndSample();
|
|
305
271
|
NextState(false);
|
|
306
|
-
return;
|
|
307
272
|
}
|
|
273
|
+
}
|
|
308
274
|
|
|
309
|
-
|
|
310
|
-
|
|
275
|
+
static bool ReadCacheFile()
|
|
276
|
+
{
|
|
277
|
+
using (StreamReader sr = new StreamReader(GDKFileUtils.GetPath(fileName)))
|
|
278
|
+
{
|
|
279
|
+
string firstLine = sr.ReadLine();
|
|
280
|
+
if (firstLine == null) return false;
|
|
281
|
+
|
|
282
|
+
if (!ValidateCacheVersion(firstLine)) return false;
|
|
283
|
+
|
|
284
|
+
ReadConfigKeyValues(sr);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
Source = RemoteConfigSource.LocalCache;
|
|
288
|
+
Log("[RemoteConfig] Load from cache");
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
static bool ValidateCacheVersion(string firstLine)
|
|
293
|
+
{
|
|
294
|
+
if (ShouldClearCache(firstLine))
|
|
295
|
+
{
|
|
296
|
+
GDKFileUtils.Delete(fileName);
|
|
297
|
+
string oldVersion = firstLine.StartsWith(VERSION_PREFIX) ? firstLine : "<none>";
|
|
298
|
+
Log($"[RemoteConfig] Cached remote config cleared due to embed version changed:\n{oldVersion} -> {EmbedVersion}");
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
static void ReadConfigKeyValues(StreamReader sr)
|
|
305
|
+
{
|
|
306
|
+
string line;
|
|
307
|
+
int lineNo = 1;
|
|
308
|
+
while ((line = sr.ReadLine()) != null)
|
|
309
|
+
{
|
|
310
|
+
lineNo++;
|
|
311
|
+
var idx = line.IndexOf('\t');
|
|
312
|
+
if (idx == -1)
|
|
313
|
+
{
|
|
314
|
+
LogWarning($"[RemoteConfig] Cannot get (key, value) at line {lineNo} of cache. Content:\n<{line}>");
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
string key = line.Substring(0, idx);
|
|
318
|
+
string value = line.Substring(idx + 1);
|
|
319
|
+
DictConfig.Add(key, Decode(value));
|
|
320
|
+
}
|
|
311
321
|
}
|
|
312
322
|
|
|
313
323
|
static void LoadEmbedConfig()
|
package/Runtime/AmaGDK.cs
CHANGED
|
@@ -27,7 +27,7 @@ namespace Amanotes.Core
|
|
|
27
27
|
{
|
|
28
28
|
public partial class AmaGDK : MonoBehaviour
|
|
29
29
|
{
|
|
30
|
-
public const string VERSION = "0.2.
|
|
30
|
+
public const string VERSION = "0.2.87";
|
|
31
31
|
|
|
32
32
|
internal static Status _status = Status.None;
|
|
33
33
|
internal static ConfigAsset _config = null;
|
|
@@ -54,31 +54,27 @@ namespace Amanotes.Core
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
private static readonly HashSet<Type> NumericTypes = new HashSet<Type>
|
|
58
|
+
{
|
|
59
|
+
typeof(int), typeof(long), typeof(short), typeof(byte),
|
|
60
|
+
typeof(double), typeof(float), typeof(decimal),
|
|
61
|
+
typeof(uint), typeof(ulong), typeof(ushort), typeof(sbyte)
|
|
62
|
+
};
|
|
63
|
+
|
|
57
64
|
private bool IsNumericType(Type type)
|
|
58
65
|
{
|
|
59
|
-
return type
|
|
60
|
-
type == typeof(long) ||
|
|
61
|
-
type == typeof(short) ||
|
|
62
|
-
type == typeof(byte) ||
|
|
63
|
-
type == typeof(double) ||
|
|
64
|
-
type == typeof(float) ||
|
|
65
|
-
type == typeof(decimal) ||
|
|
66
|
-
type == typeof(uint) ||
|
|
67
|
-
type == typeof(ulong) ||
|
|
68
|
-
type == typeof(ushort) ||
|
|
69
|
-
type == typeof(sbyte);
|
|
66
|
+
return NumericTypes.Contains(type);
|
|
70
67
|
}
|
|
71
68
|
|
|
69
|
+
private static readonly HashSet<Type> IntegerTypes = new HashSet<Type>
|
|
70
|
+
{
|
|
71
|
+
typeof(sbyte), typeof(byte), typeof(short), typeof(ushort),
|
|
72
|
+
typeof(int), typeof(uint), typeof(long), typeof(ulong)
|
|
73
|
+
};
|
|
74
|
+
|
|
72
75
|
private bool IsIntegerType(Type type)
|
|
73
76
|
{
|
|
74
|
-
return type
|
|
75
|
-
type == typeof(byte) ||
|
|
76
|
-
type == typeof(short) ||
|
|
77
|
-
type == typeof(ushort) ||
|
|
78
|
-
type == typeof(int) ||
|
|
79
|
-
type == typeof(uint) ||
|
|
80
|
-
type == typeof(long) ||
|
|
81
|
-
type == typeof(ulong);
|
|
77
|
+
return IntegerTypes.Contains(type);
|
|
82
78
|
}
|
|
83
79
|
|
|
84
80
|
internal void ValidateParams(string eventName, Dictionary<string, object> eventParams)
|
|
@@ -89,6 +85,19 @@ namespace Amanotes.Core
|
|
|
89
85
|
var isValid = true;
|
|
90
86
|
HashSet<string> checkedParameters = GDKPool.GetHashSet();
|
|
91
87
|
|
|
88
|
+
isValid &= ValidateRequiredParams(eventParams, logBuilder, checkedParameters);
|
|
89
|
+
isValid &= ValidateExtraParams(eventParams, logBuilder, checkedParameters);
|
|
90
|
+
|
|
91
|
+
if (!isValid) LogWarningOnce(logBuilder.ToString());
|
|
92
|
+
|
|
93
|
+
GDKPool.Return(logBuilder);
|
|
94
|
+
GDKPool.Return(checkedParameters);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private bool ValidateRequiredParams(Dictionary<string, object> eventParams, StringBuilder logBuilder, HashSet<string> checkedParameters)
|
|
98
|
+
{
|
|
99
|
+
bool isValid = true;
|
|
100
|
+
|
|
92
101
|
foreach (var kvp in DicParam)
|
|
93
102
|
{
|
|
94
103
|
if (!eventParams.TryGetValue(kvp.Key, out object paramValue))
|
|
@@ -109,7 +118,14 @@ namespace Amanotes.Core
|
|
|
109
118
|
|
|
110
119
|
checkedParameters.Add(kvp.Key);
|
|
111
120
|
}
|
|
121
|
+
|
|
122
|
+
return isValid;
|
|
123
|
+
}
|
|
112
124
|
|
|
125
|
+
private bool ValidateExtraParams(Dictionary<string, object> eventParams, StringBuilder logBuilder, HashSet<string> checkedParameters)
|
|
126
|
+
{
|
|
127
|
+
bool isValid = true;
|
|
128
|
+
|
|
113
129
|
foreach (var parameter in eventParams)
|
|
114
130
|
{
|
|
115
131
|
if (checkedParameters.Contains(parameter.Key)) continue;
|
|
@@ -118,10 +134,7 @@ namespace Amanotes.Core
|
|
|
118
134
|
logBuilder.AppendLine($"[+] {parameter.Key}");
|
|
119
135
|
}
|
|
120
136
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
GDKPool.Return(logBuilder);
|
|
124
|
-
GDKPool.Return(checkedParameters);
|
|
137
|
+
return isValid;
|
|
125
138
|
}
|
|
126
139
|
|
|
127
140
|
private bool ValidateParamType(object paramValue, ParamType paramType)
|
|
@@ -188,26 +201,44 @@ namespace Amanotes.Core
|
|
|
188
201
|
|
|
189
202
|
foreach (EventQuality eventQuality in lstEvent)
|
|
190
203
|
{
|
|
191
|
-
|
|
204
|
+
ValidateEventName(eventQuality.eventName, eventNames);
|
|
205
|
+
ValidateEventParameters(eventQuality);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
GDKPool.Return(eventNames);
|
|
209
|
+
EditorUtility.SetDirty(this);
|
|
210
|
+
}
|
|
192
211
|
|
|
193
|
-
|
|
212
|
+
private void ValidateEventName(string eventName, HashSet<string> eventNames)
|
|
213
|
+
{
|
|
214
|
+
if (string.IsNullOrWhiteSpace(eventName))
|
|
215
|
+
Debug.LogWarning("Event name cannot be empty or whitespace.");
|
|
194
216
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
foreach (var param in eventQuality.lstParam)
|
|
200
|
-
{
|
|
201
|
-
if (string.IsNullOrWhiteSpace(param.paramName)) Debug.LogWarning("Event parameter name cannot be empty or whitespace.");
|
|
217
|
+
if (!eventNames.Add(eventName))
|
|
218
|
+
Debug.LogWarning($"Duplicate event name found: {eventName}. Event names must be unique.");
|
|
219
|
+
}
|
|
202
220
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
221
|
+
private void ValidateEventParameters(EventQuality eventQuality)
|
|
222
|
+
{
|
|
223
|
+
HashSet<string> paramNames = GDKPool.GetHashSet();
|
|
224
|
+
|
|
225
|
+
eventQuality.lstParam = eventQuality.lstParam.OrderBy(param => param.paramName).ToList();
|
|
226
|
+
|
|
227
|
+
foreach (var param in eventQuality.lstParam)
|
|
228
|
+
{
|
|
229
|
+
ValidateParameterName(param.paramName, eventQuality.eventName, paramNames);
|
|
207
230
|
}
|
|
208
231
|
|
|
209
|
-
GDKPool.Return(
|
|
210
|
-
|
|
232
|
+
GDKPool.Return(paramNames);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private void ValidateParameterName(string paramName, string eventName, HashSet<string> paramNames)
|
|
236
|
+
{
|
|
237
|
+
if (string.IsNullOrWhiteSpace(paramName))
|
|
238
|
+
Debug.LogWarning("Event parameter name cannot be empty or whitespace.");
|
|
239
|
+
|
|
240
|
+
if (!paramNames.Add(paramName))
|
|
241
|
+
Debug.LogWarning($"Duplicate parameter name found in event {eventName}: {paramName}. Parameter names must be unique within an event.");
|
|
211
242
|
}
|
|
212
243
|
#endif
|
|
213
244
|
|
|
@@ -162,10 +162,7 @@ namespace Amanotes.Core
|
|
|
162
162
|
|
|
163
163
|
private static string RemoveSurrogatePairs(string str, string replacementCharacter = "?")
|
|
164
164
|
{
|
|
165
|
-
if (str == null)
|
|
166
|
-
{
|
|
167
|
-
return null;
|
|
168
|
-
}
|
|
165
|
+
if (str == null) return null;
|
|
169
166
|
|
|
170
167
|
StringBuilder sb = null;
|
|
171
168
|
for (var i = 0; i < str.Length; i++)
|
|
@@ -174,19 +171,8 @@ namespace Amanotes.Core
|
|
|
174
171
|
|
|
175
172
|
if (char.IsSurrogate(ch))
|
|
176
173
|
{
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
sb = GDKPool.GetStringBuilder();
|
|
180
|
-
sb.Append(str, 0, i);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
sb.Append(replacementCharacter);
|
|
184
|
-
|
|
185
|
-
// If there is a high+low surrogate, skip the low surrogate
|
|
186
|
-
if (i + 1 < str.Length && char.IsHighSurrogate(ch) && char.IsLowSurrogate(str[i + 1]))
|
|
187
|
-
{
|
|
188
|
-
i++;
|
|
189
|
-
}
|
|
174
|
+
sb = HandleSurrogateCharacter(str, i, sb, replacementCharacter, out int skipCount);
|
|
175
|
+
i += skipCount;
|
|
190
176
|
}
|
|
191
177
|
else
|
|
192
178
|
{
|
|
@@ -196,6 +182,34 @@ namespace Amanotes.Core
|
|
|
196
182
|
|
|
197
183
|
return sb == null ? str : GDKPool.ReturnString(sb);
|
|
198
184
|
}
|
|
185
|
+
|
|
186
|
+
private static StringBuilder HandleSurrogateCharacter(string str, int index, StringBuilder sb, string replacementCharacter, out int skipCount)
|
|
187
|
+
{
|
|
188
|
+
skipCount = 0;
|
|
189
|
+
|
|
190
|
+
if (sb == null)
|
|
191
|
+
{
|
|
192
|
+
sb = GDKPool.GetStringBuilder();
|
|
193
|
+
sb.Append(str, 0, index);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
sb.Append(replacementCharacter);
|
|
197
|
+
|
|
198
|
+
// If there is a high+low surrogate, skip the low surrogate
|
|
199
|
+
if (ShouldSkipLowSurrogate(str, index))
|
|
200
|
+
{
|
|
201
|
+
skipCount = 1;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return sb;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private static bool ShouldSkipLowSurrogate(string str, int index)
|
|
208
|
+
{
|
|
209
|
+
return index + 1 < str.Length &&
|
|
210
|
+
char.IsHighSurrogate(str[index]) &&
|
|
211
|
+
char.IsLowSurrogate(str[index + 1]);
|
|
212
|
+
}
|
|
199
213
|
}
|
|
200
214
|
|
|
201
215
|
internal enum AudioDeviceType
|
|
@@ -32,38 +32,35 @@ namespace Amanotes.Core.Internal
|
|
|
32
32
|
// Constructor for string-based version initialization
|
|
33
33
|
public GDKSemVer(string version)
|
|
34
34
|
{
|
|
35
|
-
|
|
36
|
-
major =
|
|
37
|
-
minor =
|
|
38
|
-
patch =
|
|
39
|
-
extra =
|
|
35
|
+
var parsed = ParseVersionString(version);
|
|
36
|
+
major = parsed.major;
|
|
37
|
+
minor = parsed.minor;
|
|
38
|
+
patch = parsed.patch;
|
|
39
|
+
extra = parsed.extra;
|
|
40
|
+
}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
private static (int major, int minor, int patch, int extra) ParseVersionString(string version)
|
|
43
|
+
{
|
|
44
|
+
if (string.IsNullOrEmpty(version)) return (0, 0, 0, -1);
|
|
42
45
|
|
|
43
46
|
Profiler.BeginSample("GDKSemVer()");
|
|
47
|
+
version = version.Trim();
|
|
48
|
+
Match match = VERSION_PATTERN.Match(version);
|
|
49
|
+
|
|
50
|
+
if (!match.Success)
|
|
44
51
|
{
|
|
45
|
-
version
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
LogWarning($"[GDKSemVer] Invalid version string: [{version}]");
|
|
50
|
-
Profiler.EndSample();
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Parse the version components using TryParse for safety
|
|
55
|
-
major = int.TryParse(match.Groups[1].Value, out int parsedMajor) ? parsedMajor : 0;
|
|
56
|
-
minor = int.TryParse(match.Groups[2].Value, out int parsedMinor) ? parsedMinor : 0;
|
|
57
|
-
if (match.Groups.Count > 3 && !int.TryParse(match.Groups[3].Value, out patch))
|
|
58
|
-
{
|
|
59
|
-
patch = 0;
|
|
60
|
-
}
|
|
61
|
-
if (match.Groups.Count > 4 && !int.TryParse(match.Groups[4].Value, out extra))
|
|
62
|
-
{
|
|
63
|
-
extra = -1;
|
|
64
|
-
}
|
|
52
|
+
LogWarning($"[GDKSemVer] Invalid version string: [{version}]");
|
|
53
|
+
Profiler.EndSample();
|
|
54
|
+
return (0, 0, 0, -1);
|
|
65
55
|
}
|
|
56
|
+
|
|
57
|
+
var major = int.TryParse(match.Groups[1].Value, out int parsedMajor) ? parsedMajor : 0;
|
|
58
|
+
var minor = int.TryParse(match.Groups[2].Value, out int parsedMinor) ? parsedMinor : 0;
|
|
59
|
+
var patch = match.Groups.Count > 3 && int.TryParse(match.Groups[3].Value, out int parsedPatch) ? parsedPatch : 0;
|
|
60
|
+
var extra = match.Groups.Count > 4 && int.TryParse(match.Groups[4].Value, out int parsedExtra) ? parsedExtra : -1;
|
|
61
|
+
|
|
66
62
|
Profiler.EndSample();
|
|
63
|
+
return (major, minor, patch, extra);
|
|
67
64
|
}
|
|
68
65
|
|
|
69
66
|
// Property to check if the version is valid
|