init commit
						commit
						bb1a4b8cce
					
				|  | @ -0,0 +1 @@ | ||||||
|  | *.DS_Store | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 9bb2904375c2a46eb90e2a3cace489a0 | ||||||
|  | timeCreated: 1702610996 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: df5ee84bbb0c0495eb6f89444802ffd9 | ||||||
|  | timeCreated: 1703231056 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 44aa37ed74dd4407a9d04a07ccf97247 | ||||||
|  | timeCreated: 1702611095 | ||||||
|  | @ -0,0 +1,93 @@ | ||||||
|  | using UnityEngine; | ||||||
|  | using Guru; | ||||||
|  | using NUnit.Framework; | ||||||
|  | 
 | ||||||
|  | namespace Guru.Editor | ||||||
|  | { | ||||||
|  |     using System.IO; | ||||||
|  |     using UnityEditor; | ||||||
|  |     using Guru.LitJson; | ||||||
|  |      | ||||||
|  |     public class EditorGuruServiceIO | ||||||
|  |     { | ||||||
|  |         private static readonly string DefaultFileName = "guru-service"; | ||||||
|  | 
 | ||||||
|  |         private static string DefaultFilePath = | ||||||
|  |             Path.GetFullPath(Path.Combine(Application.dataPath, $"{DefaultFileName}.json")); | ||||||
|  | 
 | ||||||
|  |         private static string _selectedFilePath = ""; | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 加载配置 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public static GuruServiceConfig LoadConfig() | ||||||
|  |         { | ||||||
|  |             var a = AssetDatabase.FindAssets($"*{DefaultFileName}* t:TextAsset"); | ||||||
|  |             if (a == null || a.Length == 0) | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"<color=orange>--- Can't ind guru-services file</color>"); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 var p = AssetDatabase.GUIDToAssetPath(a[0]); | ||||||
|  |                 var fp = Path.GetFullPath(p); | ||||||
|  |                 if (File.Exists(fp)) _selectedFilePath = fp; | ||||||
|  |                 var t = AssetDatabase.LoadAssetAtPath<TextAsset>(p); | ||||||
|  |                 // Debug.Log($"<color=#88ff00>--- find services file:{p} \n{t.text}</color>"); | ||||||
|  |                 return JsonMapper.ToObject<GuruServiceConfig>(t.text); | ||||||
|  |             } | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 保存配置 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="config"></param> | ||||||
|  |         internal static void SaveConfig(GuruServiceConfig config = null) | ||||||
|  |         { | ||||||
|  |             if (config == null) | ||||||
|  |             { | ||||||
|  |                 config = new GuruServiceConfig();     | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             var jw = new JsonWriter() | ||||||
|  |             { | ||||||
|  |                 PrettyPrint = true, | ||||||
|  |             }; | ||||||
|  |             JsonMapper.ToJson(config, jw); | ||||||
|  | 
 | ||||||
|  |             var json = jw.ToString(); | ||||||
|  | 
 | ||||||
|  |             if (string.IsNullOrEmpty(_selectedFilePath)) _selectedFilePath = DefaultFilePath; | ||||||
|  |             File.WriteAllText(_selectedFilePath, json); | ||||||
|  |             Debug.Log($"Save config to {_selectedFilePath}"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 创建空配置 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         internal static GuruServiceConfig CreateEmpty() | ||||||
|  |         { | ||||||
|  |             var cfg = new GuruServiceConfig(); | ||||||
|  |             cfg.version = GuruSDK.Version; | ||||||
|  |             cfg.app_settings = new GuruAppSettings(); | ||||||
|  |             cfg.ad_settings = new GuruAdSettings(); | ||||||
|  |             cfg.adjust_settings = new GuruAdjustSettings(); | ||||||
|  |             cfg.fb_settings = new GuruFbSettings(); | ||||||
|  |             return cfg; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         [Test] | ||||||
|  |         public static void Test_SaveConfig() | ||||||
|  |         { | ||||||
|  |             var cfg = CreateEmpty();  | ||||||
|  |             SaveConfig(cfg); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 043619bc8571240f6b8926c2ccffbd29 | ||||||
|  | timeCreated: 1702877769 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: eec1c72fa3d0c493b9b30091a81043ee | ||||||
|  | timeCreated: 1703413024 | ||||||
|  | @ -0,0 +1,40 @@ | ||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="ball.sort.puzzle.color.game.bubble.sorting.free" android:versionCode="1" android:versionName="1.0"> | ||||||
|  |   <application android:label="@string/app_name" android:icon="@drawable/app_icon"> | ||||||
|  |     <!-- The MessagingUnityPlayerActivity is a class that extends | ||||||
|  |          UnityPlayerActivity to work around a known issue when receiving | ||||||
|  |          notification data payloads in the background. --> | ||||||
|  |     <activity android:name="com.google.firebase.MessagingUnityPlayerActivity"  | ||||||
|  |               android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"> | ||||||
|  |       <intent-filter> | ||||||
|  |         <action android:name="android.intent.action.MAIN" /> | ||||||
|  |         <category android:name="android.intent.category.LAUNCHER" /> | ||||||
|  |       </intent-filter> | ||||||
|  |       <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> | ||||||
|  |     </activity> | ||||||
|  |     <service android:name="com.google.firebase.messaging.MessageForwardingService" android:permission="android.permission.BIND_JOB_SERVICE" android:exported="false"> | ||||||
|  |     </service> | ||||||
|  |     <receiver android:name="com.adjust.sdk.AdjustReferrerReceiver" android:permission="android.permission.INSTALL_PACKAGES" android:exported="true"> | ||||||
|  |       <intent-filter> | ||||||
|  |         <action android:name="com.android.vending.INSTALL_REFERRER" /> | ||||||
|  |       </intent-filter> | ||||||
|  |     </receiver> | ||||||
|  |     <activity android:name="com.facebook.unity.FBUnityLoginActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" /> | ||||||
|  |     <activity android:name="com.facebook.unity.FBUnityDialogsActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" /> | ||||||
|  |     <activity android:name="com.facebook.unity.FBUnityGamingServicesFriendFinderActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" /> | ||||||
|  |     <activity android:name="com.facebook.unity.FBUnityAppLinkActivity" android:exported="true" /> | ||||||
|  |     <activity android:name="com.facebook.unity.FBUnityDeepLinkingActivity" android:exported="true" /> | ||||||
|  |     <activity android:name="com.facebook.unity.FBUnityGameRequestActivity" /> | ||||||
|  |     <activity android:name="com.facebook.unity.FBUnityCreateGameGroupActivity" /> | ||||||
|  |     <activity android:name="com.facebook.unity.FBUnityJoinGameGroupActivity" /> | ||||||
|  |     <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="fb111111111111111" /> | ||||||
|  |     <meta-data android:name="com.facebook.sdk.AutoLogAppEventsEnabled" android:value="false" /> | ||||||
|  |     <meta-data android:name="com.facebook.sdk.AdvertiserIDCollectionEnabled" android:value="true" /> | ||||||
|  |     <provider android:name="com.facebook.FacebookContentProvider" android:authorities="com.facebook.app.FacebookContentProvider.000" android:exported="true" /> | ||||||
|  |     <meta-data name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION" value="true" /> | ||||||
|  |     <meta-data name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING" value="true" /> | ||||||
|  |   </application> | ||||||
|  |   <uses-permission android:name="android.permission.INTERNET" /> | ||||||
|  |   <uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" /> | ||||||
|  |   <uses-permission android:name="com.google.android.gms.permission.AD_ID" /> | ||||||
|  | </manifest> | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: ad463c22214a24eecba0c3d3428cd2bc | ||||||
|  | timeCreated: 1703413179 | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M | ||||||
|  | org.gradle.parallel=true | ||||||
|  | android.enableR8=**MINIFY_WITH_R_EIGHT** | ||||||
|  | unityStreamingAssets=**STREAMING_ASSETS** | ||||||
|  | # Android Resolver Properties Start | ||||||
|  | android.useAndroidX=true | ||||||
|  | android.enableJetifier=true | ||||||
|  | # Android Resolver Properties End | ||||||
|  | **ADDITIONAL_PROPERTIES** | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 91158a71185444f2798701c44312902f | ||||||
|  | timeCreated: 1703468454 | ||||||
|  | @ -0,0 +1,66 @@ | ||||||
|  | apply plugin: 'com.android.application' | ||||||
|  | 
 | ||||||
|  | dependencies { | ||||||
|  |     implementation project(':unityLibrary') | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | android { | ||||||
|  |     compileSdkVersion **APIVERSION** | ||||||
|  |     buildToolsVersion '**BUILDTOOLS**' | ||||||
|  | 
 | ||||||
|  |     compileOptions { | ||||||
|  |         sourceCompatibility JavaVersion.VERSION_1_8 | ||||||
|  |         targetCompatibility JavaVersion.VERSION_1_8 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     defaultConfig { | ||||||
|  |         minSdkVersion **MINSDKVERSION** | ||||||
|  |         targetSdkVersion **TARGETSDKVERSION** | ||||||
|  |         applicationId '**APPLICATIONID**' | ||||||
|  |         ndk { | ||||||
|  |             abiFilters **ABIFILTERS** | ||||||
|  |         } | ||||||
|  |         versionCode **VERSIONCODE** | ||||||
|  |         versionName '**VERSIONNAME**' | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     aaptOptions { | ||||||
|  |         noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ') | ||||||
|  |         ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~" | ||||||
|  |     }**SIGN** | ||||||
|  | 
 | ||||||
|  |     lintOptions { | ||||||
|  |         abortOnError false | ||||||
|  |         checkReleaseBuilds false | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     buildTypes { | ||||||
|  |         debug { | ||||||
|  |             minifyEnabled **MINIFY_DEBUG** | ||||||
|  |             proguardFiles getDefaultProguardFile('proguard-android.txt')**SIGNCONFIG** | ||||||
|  |             jniDebuggable true | ||||||
|  |         } | ||||||
|  |         release { | ||||||
|  |             minifyEnabled **MINIFY_RELEASE** | ||||||
|  |             proguardFiles getDefaultProguardFile('proguard-android.txt')**SIGNCONFIG** | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     packagingOptions { | ||||||
|  |         exclude("META-INF/*.kotlin_module") | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     **PLAY_ASSET_PACKS****SPLITS** | ||||||
|  | **BUILT_APK_LOCATION** | ||||||
|  |     bundle { | ||||||
|  |         language { | ||||||
|  |             enableSplit = false | ||||||
|  |         } | ||||||
|  |         density { | ||||||
|  |             enableSplit = false | ||||||
|  |         } | ||||||
|  |         abi { | ||||||
|  |             enableSplit = true | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }**SPLITS_VERSION_CODE****LAUNCHER_SOURCE_BUILD_SETUP** | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 5ca7eb01ab20749d7b9254c3a4825e31 | ||||||
|  | TextScriptImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 6cf3317fddf61454181264b523a2804e | ||||||
|  | TextScriptImporter: | ||||||
|  |   externalObjects: {} | ||||||
|  |   userData:  | ||||||
|  |   assetBundleName:  | ||||||
|  |   assetBundleVariant:  | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: f9253ec9aa37d4fd28af570d9427c00b | ||||||
|  | timeCreated: 1702629767 | ||||||
|  | @ -0,0 +1,113 @@ | ||||||
|  | using System.Collections; | ||||||
|  | using Unity.EditorCoroutines.Editor; | ||||||
|  | 
 | ||||||
|  | namespace Guru.Editor | ||||||
|  | { | ||||||
|  |     using NUnit.Framework; | ||||||
|  |     using UnityEditor; | ||||||
|  |     using UnityEngine; | ||||||
|  |     using System; | ||||||
|  |     using System.IO; | ||||||
|  |     using System.Xml; | ||||||
|  |      | ||||||
|  |     public static class AndroidManifestMod | ||||||
|  |     { | ||||||
|  |         private const string TargetPath = "Plugins/Android/AndroidManifest.xml"; | ||||||
|  |         private const string ValOptimizeInitialization = "com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"; | ||||||
|  |         private const string ValOptimizeAdLoading = "com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"; | ||||||
|  | 
 | ||||||
|  |         private static string TargetFullPath = Path.Combine(Application.dataPath, TargetPath); | ||||||
|  |          | ||||||
|  |         public static bool IsManifestExist() => File.Exists(TargetFullPath); | ||||||
|  | 
 | ||||||
|  |         public static void Apply() | ||||||
|  |         { | ||||||
|  |             if (!IsManifestExist()) | ||||||
|  |             { | ||||||
|  |                 CopyManifest(); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             var doc = new XmlDocument(); | ||||||
|  |             doc.Load(TargetFullPath); | ||||||
|  | 
 | ||||||
|  |             var rootNode = doc.SelectSingleNode("manifest/application"); | ||||||
|  |             int item1 = 0; | ||||||
|  |             int item2 = 0; | ||||||
|  |              | ||||||
|  |             XmlNodeList metadatas = rootNode.SelectNodes("meta-data"); | ||||||
|  |             if (metadatas != null && metadatas.Count > 0) | ||||||
|  |             { | ||||||
|  |                 bool isDirty = false; | ||||||
|  |        | ||||||
|  |                 foreach (XmlElement e in metadatas) | ||||||
|  |                 { | ||||||
|  |                     if (e != null) | ||||||
|  |                     { | ||||||
|  |                         if (e.HasAttribute("android:name")) | ||||||
|  |                         { | ||||||
|  |                             if (e.Attributes["android:name"].Value == ValOptimizeInitialization) item1 = 1; | ||||||
|  |                             if (e.Attributes["android:name"].Value == ValOptimizeAdLoading) item2 = 1; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             string androidSP = "http://schemas.android.com/apk/res/android"; | ||||||
|  |              | ||||||
|  |             if (item1 == 0) | ||||||
|  |             { | ||||||
|  |                var e =  doc.CreateElement("meta-data"); | ||||||
|  |                e.SetAttribute("name",androidSP, ValOptimizeInitialization); | ||||||
|  |                e.SetAttribute("value",androidSP, "true"); | ||||||
|  |                rootNode.AppendChild(e); | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             if (item2 == 0) | ||||||
|  |             { | ||||||
|  |                 var e =  doc.CreateElement("meta-data"); | ||||||
|  |                 e.SetAttribute("name",androidSP,ValOptimizeAdLoading); | ||||||
|  |                 e.SetAttribute("value",androidSP, "true"); | ||||||
|  |                 rootNode.AppendChild(e); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             var rootE = doc.SelectSingleNode("manifest") as XmlElement; | ||||||
|  |             if (rootE != null) | ||||||
|  |             { | ||||||
|  |                 rootE.Attributes["package"].Value = PlayerSettings.applicationIdentifier; // 写入包名 | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             doc.Save(TargetFullPath); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static void CopyManifest() | ||||||
|  |         { | ||||||
|  |             if (File.Exists(TargetFullPath)) return; | ||||||
|  |              | ||||||
|  |             var path = GuruEditorHelper.GetFilePath($"{nameof(AndroidManifestMod)}.cs t:Script"); | ||||||
|  |             if (!string.IsNullOrEmpty(path)) | ||||||
|  |             { | ||||||
|  |                 var files = Path.GetFullPath($"{path}/../Files"); | ||||||
|  |                 var from = $"{files}/AndroidManifest.txt"; | ||||||
|  |                 if (File.Exists(from)) | ||||||
|  |                 { | ||||||
|  |                     File.Copy(from, TargetFullPath); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #region Testing | ||||||
|  | 
 | ||||||
|  |         [Test] | ||||||
|  |         public static void Test_Injection() | ||||||
|  |         { | ||||||
|  |             Apply(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  |          | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 9ce9c7008577c4c04b10eb96a3244867 | ||||||
|  | timeCreated: 1703409620 | ||||||
|  | @ -0,0 +1,117 @@ | ||||||
|  | using System.Linq; | ||||||
|  | 
 | ||||||
|  | namespace Guru.Editor | ||||||
|  | { | ||||||
|  |     using UnityEditor; | ||||||
|  |     using UnityEngine; | ||||||
|  |     using System; | ||||||
|  |     using System.IO; | ||||||
|  |     public class AndroidProjectMod | ||||||
|  |     { | ||||||
|  |         private static readonly int TargetSDKVersion = 33; | ||||||
|  |          | ||||||
|  |         private static readonly string LauncherName = "launcherTemplate"; | ||||||
|  |         private static string LauncherFullPath = Path.Combine(Application.dataPath, $"Plugins/Android/{LauncherName}.gradle"); | ||||||
|  |          | ||||||
|  |         private static readonly string MainName = "mainTemplate"; | ||||||
|  |         private static string MainFullPath = Path.Combine(Application.dataPath,  $"Plugins/Android/{MainName}.gradle"); | ||||||
|  |          | ||||||
|  |         private static readonly string PropertiesName = "gradleTemplate"; | ||||||
|  |         private static string PropertiesFullPath = Path.Combine(Application.dataPath,  $"Plugins/Android/{PropertiesName}.properties"); | ||||||
|  |          | ||||||
|  |         public static void Apply() | ||||||
|  |         { | ||||||
|  |             FixLauncher(); | ||||||
|  |             FixMain(); | ||||||
|  |             FixProperties(); | ||||||
|  |             CheckTargetSDKVersion(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         private static void FixLauncher() | ||||||
|  |         { | ||||||
|  |             if (!File.Exists(LauncherFullPath)) | ||||||
|  |             { | ||||||
|  |                 CopyFile($"{LauncherName}.txt", LauncherFullPath); | ||||||
|  |                 Debug.Log($"[MOD] --- Copy file to: {LauncherFullPath}"); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             var ptn1 = "**PACKAGING_OPTIONS**"; | ||||||
|  |             var ptn2 = "abortOnError false"; | ||||||
|  |             var lines = File.ReadAllLines(LauncherFullPath); | ||||||
|  | 
 | ||||||
|  |             string line = ""; | ||||||
|  |             for (int i = 0; i < lines.Length; i++) | ||||||
|  |             { | ||||||
|  |                 line = lines[i]; | ||||||
|  |                 if (line.Contains(ptn1)) | ||||||
|  |                 { | ||||||
|  |                     lines[i] = line.Replace(ptn1, "\n\n\tpackagingOptions {\n\t\texclude(\"META-INF/*.kotlin_module\")\n\t}\n\n"); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if (line.Contains(ptn2)) | ||||||
|  |                 { | ||||||
|  |                     if (lines[i + 1].Contains("}")) | ||||||
|  |                     { | ||||||
|  |                         lines[i + 1] = lines[i + 1].Replace("}", "\tcheckReleaseBuilds false\n\t}"); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             Debug.Log($"[MOD] --- Fix file at: {LauncherFullPath}"); | ||||||
|  |             File.WriteAllLines(LauncherFullPath, lines); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |         private static void FixMain() | ||||||
|  |         { | ||||||
|  |             if (!File.Exists(MainFullPath)) | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"[MOD] --- Copy file to: {MainFullPath}"); | ||||||
|  |                 CopyFile($"{MainName}.txt", MainFullPath); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         private static void FixProperties() | ||||||
|  |         { | ||||||
|  |             if (!File.Exists(PropertiesFullPath)) | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"[MOD] --- Copy file to: {PropertiesFullPath}"); | ||||||
|  |                 CopyFile($"{PropertiesName}.txt", PropertiesFullPath); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static void CheckTargetSDKVersion() | ||||||
|  |         { | ||||||
|  |             var ver = (int) PlayerSettings.Android.targetSdkVersion; | ||||||
|  |             if (ver < TargetSDKVersion) | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"[MOD] --- Fix target sdk version -> {TargetSDKVersion}"); | ||||||
|  |                 PlayerSettings.Android.targetSdkVersion = (AndroidSdkVersions)TargetSDKVersion; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #region File IO | ||||||
|  | 
 | ||||||
|  |         private static string GetMoveFilePath(string fileName) | ||||||
|  |         { | ||||||
|  |             var path = GuruEditorHelper.GetFilePath($"{nameof(AndroidProjectMod)}.cs t:Script"); | ||||||
|  |             var files = Path.GetFullPath($"{path}/../Files"); | ||||||
|  |             return $"{files}/{fileName}"; | ||||||
|  |         } | ||||||
|  |         private static void CopyFile(string fileName, string toPath) | ||||||
|  |         { | ||||||
|  |             var from = GetMoveFilePath(fileName); | ||||||
|  |             if (!string.IsNullOrEmpty(from)) | ||||||
|  |             { | ||||||
|  |                 if (File.Exists(from)) | ||||||
|  |                 { | ||||||
|  |                     File.Copy(from, toPath); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 3e096221d72bd44baa543f1629092c4a | ||||||
|  | timeCreated: 1703412483 | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | namespace Guru.Editor | ||||||
|  | { | ||||||
|  |     using UnityEditor; | ||||||
|  |     public class GuruEditorHelper | ||||||
|  |     { | ||||||
|  |         public static string GetFilePath(string filter) | ||||||
|  |         { | ||||||
|  |             var guids = AssetDatabase.FindAssets(filter); | ||||||
|  |             if (guids != null && guids.Length > 0) | ||||||
|  |             { | ||||||
|  |                 var path = AssetDatabase.GUIDToAssetPath(guids[0]); | ||||||
|  |                 return path; | ||||||
|  |             } | ||||||
|  |             return ""; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: d05ef4ba47b6e4cb7bf95cb073af4915 | ||||||
|  | timeCreated: 1703413245 | ||||||
|  | @ -0,0 +1,69 @@ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | namespace Guru.Editor | ||||||
|  | { | ||||||
|  |     using UnityEditor; | ||||||
|  |     using System.IO; | ||||||
|  |     using UnityEngine; | ||||||
|  |     using System.Collections; | ||||||
|  |     using Guru.Editor; | ||||||
|  |     using Unity.EditorCoroutines.Editor; | ||||||
|  |      | ||||||
|  |     public class GuruSDKBooster | ||||||
|  |     { | ||||||
|  |          | ||||||
|  |         // [MenuItem("Test/API/Test CR")] | ||||||
|  |         static void TestCR() | ||||||
|  |         { | ||||||
|  |            // EditorHelper.StartCoroutine(OnTestRun()); | ||||||
|  |            EditorCoroutineUtility.StartCoroutineOwnerless(OnTestRun()); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         static IEnumerator OnTestRun() | ||||||
|  |         { | ||||||
|  |             int i = 0; | ||||||
|  |             while (i < 5) | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"--- ticket: {i}"); | ||||||
|  |                 i++; | ||||||
|  |                 yield return new EditorWaitForSeconds(1); | ||||||
|  |             } | ||||||
|  |             Debug.Log($"------- runner end -------"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |     // [InitializeOnLoad] | ||||||
|  |     internal class BoostOnLoad | ||||||
|  |     { | ||||||
|  |         static BoostOnLoad() | ||||||
|  |         { | ||||||
|  |             var config = EditorGuruServiceIO.LoadConfig(); | ||||||
|  |             if (null != config) | ||||||
|  |             { | ||||||
|  |                 Debug.Log("<color=#88ff00>found guru-services file on disk</color>"); | ||||||
|  |                 // TODO: | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 Debug.Log("<color=yellow>Can't find guru-services.json on load...</color>"); | ||||||
|  |                 // GuruSDKManager.Open(); | ||||||
|  |                 EditorGuruServiceIO.LoadConfig(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |      | ||||||
|  |      | ||||||
|  |      | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 4012c7bdb57bc4bfbb3b313a86ea3901 | ||||||
|  | timeCreated: 1702627784 | ||||||
|  | @ -0,0 +1,16 @@ | ||||||
|  | using Guru.Editor; | ||||||
|  | using UnityEditor; | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     public class GuruSDKMenuItems | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         [MenuItem("Guru/Guru SDK")] | ||||||
|  |         private static void ShowGuruManager() | ||||||
|  |         { | ||||||
|  |             GuruSDKManager.Open(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 7e6a90bd7ba03491d87943c2c1fcf17e | ||||||
|  | timeCreated: 1702861089 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 627835e82d65043cf8996da4a8377fa7 | ||||||
|  | timeCreated: 1703231041 | ||||||
|  | @ -0,0 +1,887 @@ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.IO; | ||||||
|  | using Facebook.Unity.Settings; | ||||||
|  | using UnityEditor.Compilation; | ||||||
|  | 
 | ||||||
|  | namespace Guru.Editor | ||||||
|  | { | ||||||
|  |     using System; | ||||||
|  |     using UnityEditor; | ||||||
|  |     using UnityEngine; | ||||||
|  |     using Guru; | ||||||
|  |     using AppLovinMax.Scripts.IntegrationManager.Editor; | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     public class GuruSDKManager: EditorWindow | ||||||
|  |     { | ||||||
|  |         private const string GURU_SETTINGS_PATH = "Assets/Guru/Resources/GuruSettings.asset"; | ||||||
|  |         private const string APPLOVIN_SETTINGS_PATH = "Assets/Guru/Resources/AppLovinSettings.asset"; | ||||||
|  |         private const string FACEBOOK_SETTINGS_PATH = "Assets/FacebookSDK/SDK/Resources/FacebookSettings.asset"; | ||||||
|  |         private const string ANDROID_KEYSTORE_PATH = "Packages/com.guru.unity.sdk.core/Keystore/guru.jks"; | ||||||
|  |         private const string KeyMaxAutoUpdateEnabled = "com.applovin.auto_update_enabled"; | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         private static GuruSDKManager _instance; | ||||||
|  |         public static GuruSDKManager Instance { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (_instance == null) | ||||||
|  |                 { | ||||||
|  |                     _instance = GetWindow<GuruSDKManager>(); | ||||||
|  |                 } | ||||||
|  |                 return _instance; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private GuruServiceConfig _serviceConfig; | ||||||
|  |         private static GUIStyle _itemTitleStyle; | ||||||
|  |         private static GUIStyle StyleItemTitle | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (_itemTitleStyle == null) | ||||||
|  |                 { | ||||||
|  |                     _itemTitleStyle = new GUIStyle("BOX") | ||||||
|  |                     { | ||||||
|  |                         fontSize = 12, | ||||||
|  |                         fontStyle = FontStyle.Bold, | ||||||
|  |                         stretchWidth = true, | ||||||
|  |                         alignment = TextAnchor.MiddleLeft, | ||||||
|  |                         padding = new RectOffset(4, 4, 4, 4), | ||||||
|  |                     }; | ||||||
|  |                 } | ||||||
|  |                 return _itemTitleStyle; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private bool _hasCheckingCompleted = false; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         public GuruSDKManager() | ||||||
|  |         { | ||||||
|  |             this.minSize = new Vector2(480, 640); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         public static void Open() | ||||||
|  |         { | ||||||
|  |             Instance.Show(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         private void OnEnable() | ||||||
|  |         { | ||||||
|  |             titleContent = new GUIContent("Guru SDK Manager"); | ||||||
|  |             _serviceConfig = EditorGuruServiceIO.LoadConfig(); | ||||||
|  |             if (_serviceConfig != null) | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"<color=#88ff00>[Guru] Load <guru-services> success.</color>"); | ||||||
|  |                 CheckServicesCompletion(); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"<color=red>[Guru] <guru-services> file not found...</color>"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #region Service Checker | ||||||
|  | 
 | ||||||
|  |         private const string MARK_FAIL = "#FAIL"; | ||||||
|  |         private const string MARK_INDENT = "    "; | ||||||
|  |         private List<string> _completionCheckResult; | ||||||
|  |         private int _serviceCriticalFail = 0; | ||||||
|  |         private int _serviceNormalFail = 0; | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 检查服务文件的配置完整性 | ||||||
|  |         /// </summary> | ||||||
|  |         private void CheckServicesCompletion() | ||||||
|  |         { | ||||||
|  |             _serviceCriticalFail = 0; | ||||||
|  |             _serviceNormalFail = 0; | ||||||
|  |              | ||||||
|  |             _completionCheckResult = new List<string>(40); | ||||||
|  |             string mk_yes = " ( \u2714 ) "; | ||||||
|  |             string mk_no = " ( \u2718 ) "; | ||||||
|  |             string mk_star = " ( \u2605 ) "; | ||||||
|  |             string check_passed = $"{MARK_INDENT}{mk_yes} All items passed!"; | ||||||
|  |             if (_serviceConfig == null) | ||||||
|  |             { | ||||||
|  |                 AddResultLine($"{mk_yes} guru-services is missing", false); | ||||||
|  |                 AddResultLine($"Please contact Guru tech support to get help.", false); | ||||||
|  |                 _serviceCriticalFail++; | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 bool passed = true; | ||||||
|  |                 AddResultLine($"{mk_star} <guru-services> exists!"); | ||||||
|  |                 AddResultLine($"--------------------------------"); | ||||||
|  |                  | ||||||
|  |                 //-------- APP Settings -------- | ||||||
|  |                 passed = true; | ||||||
|  |                 AddResultLine($"[ App ]"); | ||||||
|  |                 if (_serviceConfig.app_settings == null) | ||||||
|  |                 { | ||||||
|  |                     passed = false; | ||||||
|  |                     AddResultLine($"{MARK_INDENT}{mk_no} settings is missing!", false); | ||||||
|  |                     _serviceCriticalFail++; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     if (_serviceConfig.app_settings.app_id.IsNullOrEmpty()) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} AppID is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (_serviceConfig.app_settings.bundle_id.IsNullOrEmpty()) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} BundleID is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (_serviceConfig.app_settings.product_name.IsNullOrEmpty()) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Product Name is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (_serviceConfig.app_settings.support_email.IsNullOrEmpty()) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Support Email is missing!", false); | ||||||
|  |                         _serviceNormalFail++; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 if (passed) AddResultLine(check_passed); | ||||||
|  |                  | ||||||
|  |                 //-------- ADS Settings -------- | ||||||
|  |                 passed = true; | ||||||
|  |                 AddResultLine($"[ Ads ]"); | ||||||
|  |                 if (_serviceConfig.ad_settings == null) | ||||||
|  |                 { | ||||||
|  |                     passed = false; | ||||||
|  |                     AddResultLine($"{MARK_INDENT}{mk_no} settings is missing!", false); | ||||||
|  |                     _serviceCriticalFail++; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     if (_serviceConfig.ad_settings.sdk_key.IsNullOrEmpty()) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} SDK Key is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.ad_settings.admob_app_id)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Admob ID is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.ad_settings.max_ids_android)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} AppLovin Android IDs is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.ad_settings.max_ids_ios)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} AppLovin iOS IDs is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.ad_settings.amazon_ids_android)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Amazon Android IDs is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.ad_settings.amazon_ids_ios)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Amazon iOS IDs is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.ad_settings.pubmatic_ids_android)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Pubmatic Android IDs is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.ad_settings.pubmatic_ids_ios)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Pubmatic iOS IDs is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.ad_settings.moloco_ids_android)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Moloco Android Test IDs is missing!", false); | ||||||
|  |                         _serviceNormalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.ad_settings.moloco_ids_ios)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Moloco iOS Test IDs is missing!", false); | ||||||
|  |                         _serviceNormalFail++; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 if (passed) AddResultLine(check_passed); | ||||||
|  |                  | ||||||
|  |                 //-------- Channels Settings -------- | ||||||
|  |                 passed = true; | ||||||
|  |                 AddResultLine($"[ Channels ]"); | ||||||
|  |                 if (_serviceConfig.fb_settings == null) | ||||||
|  |                 { | ||||||
|  |                     passed = false; | ||||||
|  |                     AddResultLine($"{MARK_INDENT}{mk_no} Facebook settings is missing!", false); | ||||||
|  |                     _serviceCriticalFail++; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     if (_serviceConfig.fb_settings.app_id.IsNullOrEmpty()) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Facebook AppID is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                     if (_serviceConfig.fb_settings.client_token.IsNullOrEmpty()) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Facebook Client Token is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 if (_serviceConfig.adjust_settings == null) | ||||||
|  |                 { | ||||||
|  |                     passed = false; | ||||||
|  |                     AddResultLine($"{MARK_INDENT}{mk_no} Adjust settings is missing!", false); | ||||||
|  |                     _serviceCriticalFail++; | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     if(!IsArrayNotEmpty(_serviceConfig.adjust_settings.app_token)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Adjust AppToken is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     if (!IsArrayNotEmpty(_serviceConfig.adjust_settings.events)) | ||||||
|  |                     { | ||||||
|  |                         passed = false; | ||||||
|  |                         AddResultLine($"{MARK_INDENT}{mk_no} Adjust Events is missing!", false); | ||||||
|  |                         _serviceCriticalFail++; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 if (passed) AddResultLine(check_passed); | ||||||
|  |                  | ||||||
|  |                 //-------- IAP -------- | ||||||
|  |                 passed = true; | ||||||
|  |                 AddResultLine($"[ IAP ]"); | ||||||
|  |                 if (!IsArrayNotEmpty(_serviceConfig.products)) | ||||||
|  |                 { | ||||||
|  |                     passed = false; | ||||||
|  |                     AddResultLine($"{MARK_INDENT}{mk_no} Product list is missing!", false); | ||||||
|  |                     _serviceNormalFail++; | ||||||
|  |                 } | ||||||
|  |                 if (passed) AddResultLine(check_passed); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void AddResultLine(string msg, bool passed = true) | ||||||
|  |         { | ||||||
|  |             if (_completionCheckResult == null) | ||||||
|  |             { | ||||||
|  |                 _completionCheckResult = new List<string>(40); | ||||||
|  |             } | ||||||
|  |             string mk = passed? "" : MARK_FAIL; | ||||||
|  |             _completionCheckResult.Add($"{msg}{mk}"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void GUI_ServiceCheckResult() | ||||||
|  |         { | ||||||
|  |             if (_completionCheckResult != null) | ||||||
|  |             { | ||||||
|  |                 Color green = new Color(0.7f, 1, 0); | ||||||
|  |                 Color red = new Color(1, 0.2f, 0); | ||||||
|  |                 Color c; | ||||||
|  |                 string line = ""; | ||||||
|  |                 for (int i = 0; i < _completionCheckResult.Count; i++) | ||||||
|  |                 { | ||||||
|  |                     c = green; | ||||||
|  |                     line = _completionCheckResult[i]; | ||||||
|  |                     if (line.EndsWith(MARK_FAIL)) | ||||||
|  |                     { | ||||||
|  |                         line = line.Replace(MARK_FAIL, ""); | ||||||
|  |                         c = red; | ||||||
|  |                     } | ||||||
|  |                     GUI_Color(c, () => | ||||||
|  |                     { | ||||||
|  |                         EditorGUILayout.LabelField(line); | ||||||
|  |                         GUILayout.Space(2); | ||||||
|  |                     }); | ||||||
|  |                      | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  |         #region GUI | ||||||
|  | 
 | ||||||
|  |         void OnGUI() | ||||||
|  |         { | ||||||
|  |             // TITLE | ||||||
|  |             GUI_WindowTitle(); | ||||||
|  |              | ||||||
|  |             // CONTENT | ||||||
|  |             if (_serviceConfig == null) | ||||||
|  |             { | ||||||
|  |                 GUI_OnConfigDisabled(); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 GUI_OnConfigEnabled(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void GUI_WindowTitle() | ||||||
|  |         { | ||||||
|  |             GUILayout.Space(4); | ||||||
|  |              | ||||||
|  |             var s = new GUIStyle("BOX") | ||||||
|  |             { | ||||||
|  |                 fontSize = 36, | ||||||
|  |                 fontStyle = FontStyle.Bold, | ||||||
|  |                 alignment = TextAnchor.MiddleCenter, | ||||||
|  |                 stretchWidth = true, | ||||||
|  |                 stretchHeight = true, | ||||||
|  |                 fixedHeight = 60, | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             EditorGUILayout.LabelField("Guru SDK",s); | ||||||
|  |             s.fontSize = 13; | ||||||
|  |             s.fixedHeight = 20; | ||||||
|  |             EditorGUILayout.LabelField($"Version {GuruSDK.Version}", s); | ||||||
|  |              | ||||||
|  |             GUILayout.Space(4); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 配置不可用 | ||||||
|  |         /// </summary> | ||||||
|  |         private void GUI_OnConfigDisabled() | ||||||
|  |         { | ||||||
|  |             GUI_Color(new Color(1,0.2f, 0), () => | ||||||
|  |             { | ||||||
|  |                 EditorGUILayout.LabelField("<>", StyleItemTitle); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 配置可用 | ||||||
|  |         /// </summary> | ||||||
|  |         private void GUI_OnConfigEnabled() | ||||||
|  |         { | ||||||
|  |             var box = new GUIStyle("BOX"); | ||||||
|  |             float btnH = 40; | ||||||
|  |              | ||||||
|  |             //------------ check allsettings ------------- | ||||||
|  |             EditorGUILayout.LabelField("[ Guru Service ]", StyleItemTitle); | ||||||
|  |             GUILayout.Space(2); | ||||||
|  |             GUI_ServiceCheckResult(); | ||||||
|  |             GUILayout.Space(16); | ||||||
|  | 
 | ||||||
|  |             if (_serviceCriticalFail > 0) | ||||||
|  |             { | ||||||
|  |                 // 严重错误过多 | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 GUI_Button("IMPORT ALL SETTINGS", () => | ||||||
|  |                 { | ||||||
|  |                     CheckAllComponents(); | ||||||
|  |                 }, null, GUILayout.Height(btnH)); | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             GUILayout.Space(4); | ||||||
|  |           | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #region Check Components | ||||||
|  | 
 | ||||||
|  |         private string logBuffer; | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         private void CheckAllComponents() | ||||||
|  |         { | ||||||
|  |             string barTitle = "Setup All Components"; | ||||||
|  |             EditorUtility.DisplayCancelableProgressBar(barTitle, "Start collect all components", 0); | ||||||
|  |             Debug.Log("--- Setup All Components ---"); | ||||||
|  |             ImportGuruSettings(); | ||||||
|  |             EditorUtility.DisplayCancelableProgressBar(barTitle, "GuruSettings is done", 0.2f); | ||||||
|  |             ImportAppLovinSettings(); | ||||||
|  |             EditorUtility.DisplayCancelableProgressBar(barTitle, "AppLovinSettings is done", 0.4f); | ||||||
|  |             ImportFacebookSettings(); | ||||||
|  |             EditorUtility.DisplayCancelableProgressBar(barTitle, "FacebookSettings is done", 0.6f); | ||||||
|  |             ApplyMods(); | ||||||
|  |             EditorUtility.DisplayCancelableProgressBar(barTitle, "All Mods is done", 0.8f);   | ||||||
|  |              | ||||||
|  |             AssetDatabase.SaveAssets(); | ||||||
|  |              | ||||||
|  |             CompilationPipeline.RequestScriptCompilation(); | ||||||
|  |             CompilationPipeline.compilationFinished += o => | ||||||
|  |             { | ||||||
|  |                 EditorUtility.ClearProgressBar(); | ||||||
|  |                 AssetDatabase.Refresh(); | ||||||
|  | 
 | ||||||
|  |                 EditorUtility.DisplayDialog("Importing Guru Services", "All the settings importing success!", "OK"); | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //------------------------- GuruSettings -------------------------------- | ||||||
|  |         private void ImportGuruSettings() | ||||||
|  |         { | ||||||
|  |             GuruSettings settings = null; | ||||||
|  |             if (IsAssetExists(nameof(GuruSettings), GURU_SETTINGS_PATH)) | ||||||
|  |             { | ||||||
|  |                 settings = AssetDatabase.LoadAssetAtPath<GuruSettings>(GURU_SETTINGS_PATH); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 settings = CreateInstance<GuruSettings>(); | ||||||
|  |                 AssetDatabase.CreateAsset(settings, GURU_SETTINGS_PATH); | ||||||
|  |             } | ||||||
|  |             settings.CompanyName = "Guru"; | ||||||
|  |             settings.ProductName = _serviceConfig.app_settings.product_name; | ||||||
|  |             settings.GameIdentifier = _serviceConfig.app_settings.bundle_id; | ||||||
|  |             settings.PriacyUrl = _serviceConfig.app_settings.privacy_url; | ||||||
|  |             settings.TermsUrl = _serviceConfig.app_settings.terms_url; | ||||||
|  |             settings.SupportEmail = _serviceConfig.app_settings.support_email; | ||||||
|  |             settings.AndroidStoreUrl = _serviceConfig.app_settings.android_store; | ||||||
|  |             settings.IOSStoreUrl = _serviceConfig.app_settings.ios_store; | ||||||
|  |              | ||||||
|  |             SerializedObject so = new SerializedObject(settings); | ||||||
|  |             SerializedProperty n; | ||||||
|  |             SerializedObject nn; | ||||||
|  |             SerializedProperty p; | ||||||
|  |             string[] arr; | ||||||
|  |              | ||||||
|  |             n = so.FindProperty("IPMSetting"); | ||||||
|  |             if (null != n) | ||||||
|  |             { | ||||||
|  |                 p = n.serializedObject.FindProperty("IPMSetting.appID"); | ||||||
|  |                 p.stringValue = _serviceConfig.app_settings.app_id; | ||||||
|  |                  | ||||||
|  |                 p = n.serializedObject.FindProperty("IPMSetting.tokenValidTime"); | ||||||
|  |                 p.intValue = _serviceConfig.app_settings.token_vaild_time; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //---------- AMAZON ----------------------- | ||||||
|  |             n = so.FindProperty("AmazonSetting"); | ||||||
|  |             if (null != n) | ||||||
|  |             { | ||||||
|  |                 p = n.serializedObject.FindProperty("AmazonSetting.Enable"); | ||||||
|  |                 p.boolValue = true; | ||||||
|  |                  | ||||||
|  |                 arr = _serviceConfig.ad_settings.amazon_ids_android; | ||||||
|  |                 if (IsArrayHasLength(arr, 4)) | ||||||
|  |                 { | ||||||
|  |                     p = n.serializedObject.FindProperty("AmazonSetting.Android.appID"); | ||||||
|  |                     p.stringValue = arr[0]; | ||||||
|  |                     p = n.serializedObject.FindProperty("AmazonSetting.Android.bannerSlotID"); | ||||||
|  |                     p.stringValue = arr[1]; | ||||||
|  |                     p = n.serializedObject.FindProperty("AmazonSetting.Android.interSlotID"); | ||||||
|  |                     p.stringValue = arr[2]; | ||||||
|  |                     p = n.serializedObject.FindProperty("AmazonSetting.Android.rewardSlotID"); | ||||||
|  |                     p.stringValue = arr[3]; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 arr = _serviceConfig.ad_settings.amazon_ids_ios; | ||||||
|  |                 if (IsArrayHasLength(arr, 4)) | ||||||
|  |                 { | ||||||
|  |                     p = n.serializedObject.FindProperty("AmazonSetting.iOS.appID"); | ||||||
|  |                     p.stringValue = arr[0]; | ||||||
|  |                     p = n.serializedObject.FindProperty("AmazonSetting.iOS.bannerSlotID"); | ||||||
|  |                     p.stringValue = arr[1]; | ||||||
|  |                     p = n.serializedObject.FindProperty("AmazonSetting.iOS.interSlotID"); | ||||||
|  |                     p.stringValue = arr[2]; | ||||||
|  |                     p = n.serializedObject.FindProperty("AmazonSetting.iOS.rewardSlotID"); | ||||||
|  |                     p.stringValue = arr[3]; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             //---------- PUBMATIC ----------------------- | ||||||
|  |             n = so.FindProperty("PubmaticSetting"); | ||||||
|  |             if (null != n) | ||||||
|  |             { | ||||||
|  |                 p = n.serializedObject.FindProperty("PubmaticSetting.Enable"); | ||||||
|  |                 p.boolValue = true; | ||||||
|  |                  | ||||||
|  |                 arr = _serviceConfig.ad_settings.pubmatic_ids_android; | ||||||
|  |                 if (IsArrayHasLength(arr, 4)) | ||||||
|  |                 { | ||||||
|  |                     p = n.serializedObject.FindProperty("PubmaticSetting.Android.storeUrl"); | ||||||
|  |                     p.stringValue = arr[0]; | ||||||
|  |                     p = n.serializedObject.FindProperty("PubmaticSetting.Android.bannerUnitID"); | ||||||
|  |                     p.stringValue = arr[1]; | ||||||
|  |                     p = n.serializedObject.FindProperty("PubmaticSetting.Android.interUnitID"); | ||||||
|  |                     p.stringValue = arr[2]; | ||||||
|  |                     p = n.serializedObject.FindProperty("PubmaticSetting.Android.rewardUnitID"); | ||||||
|  |                     p.stringValue = arr[3]; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 arr = _serviceConfig.ad_settings.pubmatic_ids_ios; | ||||||
|  |                 if (IsArrayHasLength(arr, 4)) | ||||||
|  |                 { | ||||||
|  |                     p = n.serializedObject.FindProperty("PubmaticSetting.iOS.storeUrl"); | ||||||
|  |                     p.stringValue = arr[0]; | ||||||
|  |                     p = n.serializedObject.FindProperty("PubmaticSetting.iOS.bannerUnitID"); | ||||||
|  |                     p.stringValue = arr[1]; | ||||||
|  |                     p = n.serializedObject.FindProperty("PubmaticSetting.iOS.interUnitID"); | ||||||
|  |                     p.stringValue = arr[2]; | ||||||
|  |                     p = n.serializedObject.FindProperty("PubmaticSetting.iOS.rewardUnitID"); | ||||||
|  |                     p.stringValue = arr[3]; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //---------- MOLOCO ----------------------- | ||||||
|  |             n = so.FindProperty("MolocoSetting"); | ||||||
|  |             if (null != n) | ||||||
|  |             { | ||||||
|  |                 p = n.serializedObject.FindProperty("MolocoSetting.Enable"); | ||||||
|  |                 p.boolValue = true; | ||||||
|  |                  | ||||||
|  |                 arr = _serviceConfig.ad_settings.moloco_ids_android; | ||||||
|  |                 if (IsArrayHasLength(arr, 3)) | ||||||
|  |                 { | ||||||
|  |                     p = n.serializedObject.FindProperty("MolocoSetting.Android.bannerTestUnitID"); | ||||||
|  |                     p.stringValue = arr[0]; | ||||||
|  |                     p = n.serializedObject.FindProperty("MolocoSetting.Android.interTestUnitID"); | ||||||
|  |                     p.stringValue = arr[1]; | ||||||
|  |                     p = n.serializedObject.FindProperty("MolocoSetting.Android.rewardTestUnitID"); | ||||||
|  |                     p.stringValue = arr[2]; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 arr = _serviceConfig.ad_settings.moloco_ids_ios; | ||||||
|  |                 if (IsArrayHasLength(arr, 3)) | ||||||
|  |                 { | ||||||
|  |                     p = n.serializedObject.FindProperty("MolocoSetting.iOS.bannerTestUnitID"); | ||||||
|  |                     p.stringValue = arr[0]; | ||||||
|  |                     p = n.serializedObject.FindProperty("MolocoSetting.iOS.interTestUnitID"); | ||||||
|  |                     p.stringValue = arr[1]; | ||||||
|  |                     p = n.serializedObject.FindProperty("MolocoSetting.iOS.rewardTestUnitID"); | ||||||
|  |                     p.stringValue = arr[2]; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             //----------- ADSettings ------------------- | ||||||
|  |             n = so.FindProperty("ADSetting"); | ||||||
|  |             if (null != n) | ||||||
|  |             { | ||||||
|  |                 p = n.serializedObject.FindProperty("ADSetting.SDK_KEY"); | ||||||
|  |                 p.stringValue = _serviceConfig.ad_settings.sdk_key; | ||||||
|  |                  | ||||||
|  |                 arr = _serviceConfig.ad_settings.max_ids_android; | ||||||
|  |                 if(IsArrayHasLength(arr, 3)) | ||||||
|  |                 { | ||||||
|  |                     p = n.serializedObject.FindProperty("ADSetting.Android_Banner_ID"); | ||||||
|  |                     p.stringValue = arr[0]; | ||||||
|  |                     p = n.serializedObject.FindProperty("ADSetting.Android_Interstitial_ID"); | ||||||
|  |                     p.stringValue = arr[1]; | ||||||
|  |                     p = n.serializedObject.FindProperty("ADSetting.Android_Rewarded_ID"); | ||||||
|  |                     p.stringValue = arr[2]; | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 arr = _serviceConfig.ad_settings.max_ids_ios; | ||||||
|  |                 if (IsArrayHasLength(arr, 3)) | ||||||
|  |                 { | ||||||
|  |                     p = n.serializedObject.FindProperty("ADSetting.IOS_Banner_ID"); | ||||||
|  |                     p.stringValue = arr[0]; | ||||||
|  |                     p = n.serializedObject.FindProperty("ADSetting.IOS_Interstitial_ID"); | ||||||
|  |                     p.stringValue = arr[1]; | ||||||
|  |                     p = n.serializedObject.FindProperty("ADSetting.IOS_Rewarded_ID"); | ||||||
|  |                     p.stringValue = arr[2]; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             //----------- AdjustSetting ------------------- | ||||||
|  |             n = so.FindProperty("AdjustSetting"); | ||||||
|  |             if (null != n  | ||||||
|  |                 && IsArrayHasLength(_serviceConfig.adjust_settings.app_token, 2)) | ||||||
|  |             { | ||||||
|  |                 p = n.serializedObject.FindProperty("AdjustSetting.androidAppToken"); | ||||||
|  |                 p.stringValue = _serviceConfig.adjust_settings.app_token[0]; | ||||||
|  |                  | ||||||
|  |                 p = n.serializedObject.FindProperty("AdjustSetting.iOSAppToken"); | ||||||
|  |                 p.stringValue = _serviceConfig.adjust_settings.app_token[1]; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //----------- AnalyticsSetting ------------------- | ||||||
|  |             n = so.FindProperty("AnalyticsSetting"); | ||||||
|  |             if (null != n) | ||||||
|  |             { | ||||||
|  |                 p = n.serializedObject.FindProperty("AnalyticsSetting.levelEndSuccessNum"); | ||||||
|  |                 p.intValue = _serviceConfig.app_settings.level_end_success_num; | ||||||
|  |                 p = n.serializedObject.FindProperty("AnalyticsSetting.enalbeFirebaseAnalytics"); | ||||||
|  |                 p.boolValue = _serviceConfig.app_settings.enable_firebase; | ||||||
|  |                 p = n.serializedObject.FindProperty("AnalyticsSetting.enalbeFacebookAnalytics"); | ||||||
|  |                 p.boolValue = _serviceConfig.app_settings.enable_facebook; | ||||||
|  |                 p = n.serializedObject.FindProperty("AnalyticsSetting.enalbeAdjustAnalytics"); | ||||||
|  |                 p.boolValue = _serviceConfig.app_settings.enable_adjust; | ||||||
|  |                 p = n.serializedObject.FindProperty("AnalyticsSetting.adjustEventList"); | ||||||
|  |                 if (null != p && IsArrayNotEmpty(_serviceConfig.adjust_settings.events)) | ||||||
|  |                 { | ||||||
|  |                     p.ClearArray(); | ||||||
|  |                     for (int i = 0; i < _serviceConfig.adjust_settings.events.Length; i++) | ||||||
|  |                     { | ||||||
|  |                         arr = _serviceConfig.adjust_settings.events[i].Split(","); | ||||||
|  |                         if (IsArrayHasLength(arr, 3)) | ||||||
|  |                         { | ||||||
|  |                             p.InsertArrayElementAtIndex(i); | ||||||
|  |                             nn = p.GetArrayElementAtIndex(i).serializedObject; | ||||||
|  |                             nn.FindProperty($"AnalyticsSetting.adjustEventList.Array.data[{i}].EventName").stringValue = arr[0]; | ||||||
|  |                             nn.FindProperty($"AnalyticsSetting.adjustEventList.Array.data[{i}].AndroidToken").stringValue = arr[1]; | ||||||
|  |                             nn.FindProperty($"AnalyticsSetting.adjustEventList.Array.data[{i}].IOSToken").stringValue = arr[2]; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             //---------------- Productions ------------------------ | ||||||
|  |             n = so.FindProperty("Products"); | ||||||
|  |             if (n != null && IsArrayNotEmpty(_serviceConfig.products)) | ||||||
|  |             { | ||||||
|  |                 n.ClearArray(); | ||||||
|  |                 for (int i = 0; i < _serviceConfig.products.Length; i++) | ||||||
|  |                 { | ||||||
|  |                     arr = _serviceConfig.products[i].Split(","); | ||||||
|  |                     if (IsArrayHasLength(arr, 5)) | ||||||
|  |                     { | ||||||
|  |                         n.InsertArrayElementAtIndex(i); | ||||||
|  |                         nn = n.GetArrayElementAtIndex(i).serializedObject; | ||||||
|  |                         nn.FindProperty($"Products.Array.data[{i}].ProductName").stringValue = arr[0]; | ||||||
|  |                         nn.FindProperty($"Products.Array.data[{i}].GooglePlayProductId").stringValue = arr[1]; | ||||||
|  |                         nn.FindProperty($"Products.Array.data[{i}].AppStoreProductId").stringValue = arr[2]; | ||||||
|  |                         nn.FindProperty($"Products.Array.data[{i}].Price").doubleValue = double.Parse(arr[3]); | ||||||
|  |                         nn.FindProperty($"Products.Array.data[{i}].Type").enumValueIndex = int.Parse(arr[4]); | ||||||
|  |                         nn.FindProperty($"Products.Array.data[{i}].IsFree").boolValue = false; | ||||||
|  |                         nn.FindProperty($"Products.Array.data[{i}].Category").stringValue = "Store"; | ||||||
|  |                     }  | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //------- Save SO ---------- | ||||||
|  |             so.ApplyModifiedProperties(); | ||||||
|  |             EditorUtility.SetDirty(settings); | ||||||
|  |             AssetDatabase.SaveAssetIfDirty(settings); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //------------------------- AppLovinSettings -------------------------------- | ||||||
|  |         private void ImportAppLovinSettings() | ||||||
|  |         { | ||||||
|  |             EditorPrefs.SetBool(KeyMaxAutoUpdateEnabled, false); // 关闭Max自动升级功能 | ||||||
|  |              | ||||||
|  |             AppLovinSettings settings = null; | ||||||
|  |             if (IsAssetExists(nameof(AppLovinSettings), APPLOVIN_SETTINGS_PATH)) | ||||||
|  |             { | ||||||
|  |                 settings = AssetDatabase.LoadAssetAtPath<AppLovinSettings>(APPLOVIN_SETTINGS_PATH); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 settings = CreateInstance<AppLovinSettings>(); | ||||||
|  |                 AssetDatabase.CreateAsset(settings, APPLOVIN_SETTINGS_PATH); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             settings.SetAttributionReportEndpoint = true; | ||||||
|  |             settings.QualityServiceEnabled = true; | ||||||
|  |             settings.SdkKey = _serviceConfig.ad_settings.sdk_key; | ||||||
|  |             if (IsArrayHasLength(_serviceConfig.ad_settings.admob_app_id, 2)) | ||||||
|  |             { | ||||||
|  |                 settings.AdMobAndroidAppId = _serviceConfig.ad_settings.admob_app_id[0]; | ||||||
|  |                 settings.AdMobIosAppId = _serviceConfig.ad_settings.admob_app_id[1]; | ||||||
|  |             } | ||||||
|  |             settings.ConsentFlowEnabled = false; | ||||||
|  |             EditorUtility.SetDirty(settings); | ||||||
|  |             AssetDatabase.SaveAssetIfDirty(settings); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //------------------------- FacebookSettings -------------------------------- | ||||||
|  |         private void ImportFacebookSettings() | ||||||
|  |         { | ||||||
|  |             FacebookSettings settings = null; | ||||||
|  |             if (IsAssetExists(nameof(FacebookSettings), FACEBOOK_SETTINGS_PATH)) | ||||||
|  |             { | ||||||
|  |                 settings = AssetDatabase.LoadAssetAtPath<FacebookSettings>(FACEBOOK_SETTINGS_PATH); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 settings = CreateInstance<FacebookSettings>(); | ||||||
|  |                 AssetDatabase.CreateAsset(settings, FACEBOOK_SETTINGS_PATH); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             var so = new SerializedObject(settings); | ||||||
|  |             SerializedProperty n; | ||||||
|  |              | ||||||
|  |             n = so.FindProperty("appLabels"); | ||||||
|  |             if (n != null) | ||||||
|  |             { | ||||||
|  |                 n.ClearArray(); | ||||||
|  |                 n.InsertArrayElementAtIndex(0); | ||||||
|  |                 n.GetArrayElementAtIndex(0).stringValue = _serviceConfig.app_settings.product_name; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             n = so.FindProperty("appIds"); | ||||||
|  |             if (n != null) | ||||||
|  |             { | ||||||
|  |                 n.ClearArray(); | ||||||
|  |                 n.InsertArrayElementAtIndex(0); | ||||||
|  |                 n.GetArrayElementAtIndex(0).stringValue = _serviceConfig.fb_settings.app_id; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             n = so.FindProperty("clientTokens"); | ||||||
|  |             if (n != null) | ||||||
|  |             { | ||||||
|  |                 n.ClearArray(); | ||||||
|  |                 n.InsertArrayElementAtIndex(0); | ||||||
|  |                 n.GetArrayElementAtIndex(0).stringValue = _serviceConfig.fb_settings.client_token; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             n = so.FindProperty("androidKeystorePath"); | ||||||
|  |             n.stringValue = ANDROID_KEYSTORE_PATH; | ||||||
|  |              | ||||||
|  |             so.ApplyModifiedProperties(); | ||||||
|  |             EditorUtility.SetDirty(settings); | ||||||
|  |             AssetDatabase.SaveAssetIfDirty(settings); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void ApplyMods() | ||||||
|  |         { | ||||||
|  |             PlayerSettings.applicationIdentifier = _serviceConfig.app_settings.bundle_id; // 设置包名 | ||||||
|  | 
 | ||||||
|  | #if UNITY_ANDROID | ||||||
|  |             AndroidManifestMod.Apply(); | ||||||
|  |             AndroidProjectMod.Apply(); | ||||||
|  | #endif | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region GUI Utils | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         private void GUI_Color(Color color, Action content) | ||||||
|  |         { | ||||||
|  |             var c = GUI.color; | ||||||
|  |             GUI.color = color; | ||||||
|  |             content?.Invoke(); | ||||||
|  |             GUI.color = c; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         private void GUI_Button(string label, Action content, Color color, GUIStyle style = null, params GUILayoutOption[] options) | ||||||
|  |         { | ||||||
|  |             GUI_Color(color, ()=> GUI_Button(label, content, style, options)); | ||||||
|  |         } | ||||||
|  |         private void GUI_Button(string label, Action content, GUIStyle style = null, params GUILayoutOption[] options) | ||||||
|  |         { | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             if (style != null) | ||||||
|  |             { | ||||||
|  |                 if (GUILayout.Button(label,style, options)) | ||||||
|  |                 { | ||||||
|  |                     content?.Invoke(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 if (GUILayout.Button(label, options)) | ||||||
|  |                 { | ||||||
|  |                     content?.Invoke(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |              | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region Utils | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 获取Assets路径 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="filter"></param> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         private static bool IsAssetExists(string typeName, string defaultPath) | ||||||
|  |         { | ||||||
|  |             bool result = false; | ||||||
|  |             var guids = AssetDatabase.FindAssets($"t:{typeName}"); | ||||||
|  |             string p = ""; | ||||||
|  |             if (guids != null && guids.Length > 0) | ||||||
|  |             { | ||||||
|  |                 for (int i = 0; i < guids.Length; i++) | ||||||
|  |                 { | ||||||
|  |                     p = AssetDatabase.GUIDToAssetPath(guids[i]); | ||||||
|  |                     if (File.Exists(p)) | ||||||
|  |                     { | ||||||
|  |                         if (p == defaultPath) | ||||||
|  |                         { | ||||||
|  |                             result = true; | ||||||
|  |                         } | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             File.Delete(p); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return result; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static bool IsArrayNotEmpty(Array array) | ||||||
|  |         { | ||||||
|  |             if (array == null) return false; | ||||||
|  |             if (array.Length == 0) return false; | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static bool IsArrayHasLength(Array array, int length) | ||||||
|  |         { | ||||||
|  |             if(!IsArrayNotEmpty(array)) return false; | ||||||
|  |             return array.Length >= length; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  |          | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 0a6aed96e95b747cdbb3c19c8d01b5f1 | ||||||
|  | timeCreated: 1702786341 | ||||||
|  | @ -0,0 +1,22 @@ | ||||||
|  | { | ||||||
|  |     "name": "GuruSDK.Editor", | ||||||
|  |     "rootNamespace": "Guru.Editor", | ||||||
|  |     "references": [ | ||||||
|  |         "Unity.EditorCoroutines.Editor", | ||||||
|  |         "GuruSDK", | ||||||
|  |         "Guru.LitJson", | ||||||
|  |         "Guru.Runtime", | ||||||
|  |         "MaxSdk.Scripts.IntegrationManager.Editor" | ||||||
|  |     ], | ||||||
|  |     "includePlatforms": [ | ||||||
|  |         "Editor" | ||||||
|  |     ], | ||||||
|  |     "excludePlatforms": [], | ||||||
|  |     "allowUnsafeCode": false, | ||||||
|  |     "overrideReferences": false, | ||||||
|  |     "precompiledReferences": [], | ||||||
|  |     "autoReferenced": true, | ||||||
|  |     "defineConstraints": [], | ||||||
|  |     "versionDefines": [], | ||||||
|  |     "noEngineReferences": false | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 65cafb0a78f2a474eb82c73f624745d8 | ||||||
|  | timeCreated: 1702611049 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: c0ee5782432f84c0a8d70e660102aabe | ||||||
|  | timeCreated: 1702610991 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 8e84534c908cf44e3bb7d315216557da | ||||||
|  | timeCreated: 1702611028 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: e8c2747c350c2451089422bf119c2094 | ||||||
|  | timeCreated: 1703505490 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 99b9bdd32c352412598d6d22bf5438b6 | ||||||
|  | timeCreated: 1702628339 | ||||||
|  | @ -0,0 +1,223 @@ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     using UnityEngine; | ||||||
|  |     using System; | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     public partial class GuruSDK | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 启动广告服务 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void StartAds() | ||||||
|  |         { | ||||||
|  |             if (InitConfig.UseCustomConsent) | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"{Tag} --- Call <color=orange>StartAdsWithCustomConsent</color> when you use custom consent, and pass the result (boolean) to the method."); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 // 默认的启动顺序是先启动Consent后, 根据用户回调的结果来启动广告 | ||||||
|  |                 Instance.StartConsentFlow(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 使用自定义的Consent, 获取用户授权后, 调用此方法 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="userAllow"></param> | ||||||
|  |         public static void StartAdsWithCustomConsent(bool userAllow = true) | ||||||
|  |         { | ||||||
|  |             if (userAllow) | ||||||
|  |             { | ||||||
|  |                 StartAdService(); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 Debug.Log($"{Tag} --- User refuse to provide ads Id, Ads Service will be cancelled"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #region Guru Consent | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 启动Consent流程 | ||||||
|  |         /// </summary> | ||||||
|  |         private void StartConsentFlow() | ||||||
|  |         { | ||||||
|  |             LogI($"StartConsentFlow"); | ||||||
|  |             GuruConsent.StartConsent(OnConsentOver); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void OnConsentOver(int code) | ||||||
|  |         { | ||||||
|  |             Callbacks.ConsentFlow._onConsentResult?.Invoke(code); | ||||||
|  |             switch(code) | ||||||
|  |             { | ||||||
|  |                 case GuruConsent.StatusCode.OBTAINED: | ||||||
|  |                 case GuruConsent.StatusCode.NOT_AVAILABLE: | ||||||
|  |                     // 已获取授权, 或者地区不可用 | ||||||
|  | #if UNITY_IOS | ||||||
|  |                     CheckATTStatus(); | ||||||
|  | #else | ||||||
|  |                     StartAdService(); | ||||||
|  | #endif | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | #if UNITY_IOS | ||||||
|  |          /// <summary> | ||||||
|  |         /// iOS 平台检查 ATT 状态 | ||||||
|  |         /// </summary> | ||||||
|  |         private void CheckATTStatus() | ||||||
|  |         { | ||||||
|  |             AttManager.Instance.CheckATTStatus(OnATTStatus); | ||||||
|  |         } | ||||||
|  | #endif | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region Ad Services | ||||||
|  | 
 | ||||||
|  |         private static bool _initAdsCompleted = false; | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 启动广告服务 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void StartAdService() | ||||||
|  |         { | ||||||
|  |             LogI($"StartAdService"); | ||||||
|  |             ADService.Instance.StartService(OnAdsInitComplete,  | ||||||
|  |                 InitConfig.AutoLoadWhenAdsReady, IsDebugMode); | ||||||
|  |              | ||||||
|  |             //--------- Callbacks ----------- | ||||||
|  |             ADService.OnInterstitialLoaded = OnInterstitialLoaded; | ||||||
|  |             ADService.OnInterstitialFailed = OnInterstitialFailed; | ||||||
|  |             ADService.OnRewardLoaded = OnRewardLoaded; | ||||||
|  |             ADService.OnRewardFailed = OnRewardFailed; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static void OnInterstitialLoaded()  | ||||||
|  |             => Callbacks.Ads._onInterstitialADLoaded?.Invoke(); | ||||||
|  |         private static void OnInterstitialFailed() | ||||||
|  |             => Callbacks.Ads._onInterstitialADFailed?.Invoke(); | ||||||
|  |         private static void OnRewardLoaded() | ||||||
|  |             => Callbacks.Ads._onRewardedADLoaded?.Invoke();  | ||||||
|  |         private static void OnRewardFailed() | ||||||
|  |             => Callbacks.Ads._onRewardADFailed?.Invoke(); | ||||||
|  | 
 | ||||||
|  |         private static void OnAdsInitComplete() | ||||||
|  |         { | ||||||
|  |             _initAdsCompleted = true; | ||||||
|  |             Callbacks.Ads._onAdsInitComplete?.Invoke(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static bool CheckAdsReady() | ||||||
|  |         { | ||||||
|  |             if (!_initAdsCompleted) | ||||||
|  |             { | ||||||
|  |                 LogE("Ads is not ready. Call <GuruSDk.StartAdService> first."); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 显示Banner广告 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="placement"></param> | ||||||
|  |         public static void ShowBanner(string placement = "") | ||||||
|  |         { | ||||||
|  |             if (!CheckAdsReady()) return; | ||||||
|  |             ADService.Instance.ShowBanner(placement); | ||||||
|  |         } | ||||||
|  |         /// <summary> | ||||||
|  |         /// 隐藏Banner广告 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void HideBanner() | ||||||
|  |         { | ||||||
|  |             if (!CheckAdsReady()) return; | ||||||
|  |             ADService.Instance.HideBanner(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void LoadInterstitialAd() | ||||||
|  |         { | ||||||
|  |             if (!CheckAdsReady()) return; | ||||||
|  |             ADService.Instance.RequestInterstitialAD(); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 显示插屏广告 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="placement"></param> | ||||||
|  |         /// <param name="onDismissed"></param> | ||||||
|  |         public static void ShowInterstitialAd(string placement = "", Action onDismissed = null) | ||||||
|  |         { | ||||||
|  |             if (!CheckAdsReady()) return; | ||||||
|  |             if (!ADService.Instance.IsInterstitialADReady()) | ||||||
|  |             { | ||||||
|  |                 LogE("Interstitial is not ready. Call <GuruSDk.ShowInterstitialAd> again."); | ||||||
|  |                 LoadInterstitialAd(); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             ADService.Instance.ShowInterstitialAD(placement, onDismissed); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void LoadRewardAd() | ||||||
|  |         { | ||||||
|  |             if (!CheckAdsReady()) return; | ||||||
|  |             ADService.Instance.RequestRewardedAD(); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 显示激励视频广告 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="placement"></param> | ||||||
|  |         /// <param name="onRewarded"></param> | ||||||
|  |         /// <param name="onFailed"></param> | ||||||
|  |         public static void ShowRewardAd(string placement = "", Action onRewarded = null, Action<string> onFailed = null) | ||||||
|  |         { | ||||||
|  |             if (!CheckAdsReady()) return; | ||||||
|  |             if (!ADService.Instance.IsRewardedADReady()) | ||||||
|  |             { | ||||||
|  |                 LogE("RewardAd is not ready. Call <GuruSDk.LoadRewardAd> again."); | ||||||
|  |                 LoadRewardAd(); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             ADService.Instance.ShowRewardedAD(placement, onRewarded, onFailed); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region MaxServices | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 显示Max调试菜单 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void ShowMaxDebugPanel() | ||||||
|  |         { | ||||||
|  | #if UNITY_EDITOR | ||||||
|  | 
 | ||||||
|  |             LogI($"Can not show Max Debug Panel in Editor, skipped."); | ||||||
|  |             return; | ||||||
|  | #endif | ||||||
|  |             if (!ADService.Instance.IsInitialized) | ||||||
|  |             { | ||||||
|  |                 LogI($"ADService is not initialized, call <GuruSDK.StartAds> first."); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             ADService.Instance.ShowMaxDebugPanel(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: d1320ee3985cd4265906c63a00fd12d4 | ||||||
|  | timeCreated: 1702628352 | ||||||
|  | @ -0,0 +1,216 @@ | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     using System.Collections.Generic; | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     /// <summary> | ||||||
|  |     /// 打点管理 | ||||||
|  |     /// </summary> | ||||||
|  |     public partial class GuruSDK | ||||||
|  |     { | ||||||
|  |         //----------------- 关卡开始类型 --------------------- | ||||||
|  |         public const string EventLevelStartModePlay = "play"; | ||||||
|  |         public const string EventLevelStartModeReplay = "replay"; | ||||||
|  |         public const string EventLevelStartModeContinue= "continue"; | ||||||
|  |          | ||||||
|  |         //----------------- 关卡结束类型 --------------------- | ||||||
|  |         public const string EventLevelEndSuccess = "success"; | ||||||
|  |         public const string EventLevelEndFail = "fail"; | ||||||
|  |         public const string EventLevelEndExit = "exit"; | ||||||
|  |         public const string EventLevelEndTimeout = "timeout"; | ||||||
|  | 
 | ||||||
|  |         #region 通用接口 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 自定义事件打点 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="eventName"></param> | ||||||
|  |         /// <param name="data"></param> | ||||||
|  |         public static void LogEvent(string eventName, Dictionary<string, dynamic> data = null) | ||||||
|  |             => Analytics.Track(eventName, data); | ||||||
|  | 
 | ||||||
|  |         public static void SetScreen(string screen, string extra = "")  | ||||||
|  |             => Analytics.SetCurrentScreen(screen, extra); | ||||||
|  |          | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         #endregion | ||||||
|  |          | ||||||
|  |         #region 游戏打点 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 游戏启动打点 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="level"></param> | ||||||
|  |         /// <param name="levelName"></param> | ||||||
|  |         /// <param name="levelCategory"></param> | ||||||
|  |         /// <param name="levelID"></param> | ||||||
|  |         /// <param name="startType"></param> | ||||||
|  |         /// <param name="isReplay"></param> | ||||||
|  |         public static void LogLevelStart(int level, string startType = EventLevelStartModePlay,  | ||||||
|  |             string levelCategory = "main", string levelName = "", string levelID = "", | ||||||
|  |             bool isReplay = false) | ||||||
|  |         { | ||||||
|  |             Analytics.LogLevelStart(level, levelName, levelCategory, levelID, startType, isReplay); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 游戏点击 Continue 重开始游戏 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="level"></param> | ||||||
|  |         /// <param name="levelCategory"></param> | ||||||
|  |         /// <param name="levelName"></param> | ||||||
|  |         /// <param name="levelID"></param> | ||||||
|  |         public static void LogLevelContinue(int level, string levelCategory = "main", | ||||||
|  |             string levelName = "", string levelID = "") | ||||||
|  |         { | ||||||
|  |             LogLevelStart(level, EventLevelStartModeContinue, levelCategory, levelName, levelID,  true); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 游戏点击 Continue 重开始游戏 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="level"></param> | ||||||
|  |         /// <param name="levelCategory"></param> | ||||||
|  |         /// <param name="levelName"></param> | ||||||
|  |         /// <param name="levelID"></param> | ||||||
|  |         public static void LogLevelReplay(int level, string levelCategory = "main", | ||||||
|  |             string levelName = "", string levelID = "") | ||||||
|  |         { | ||||||
|  |             LogLevelStart(level, EventLevelStartModeReplay,levelCategory, levelName, levelID,  true); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 游戏胜利打点 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void LogLevelEnd(int level,  string result = EventLevelEndSuccess, | ||||||
|  |             string levelCategory = "main", string levelName = "", string levelID = "", | ||||||
|  |             int? duration = null, int? step = null, int? score = null ) | ||||||
|  |         { | ||||||
|  |             if (InitConfig.AutoRecordFinishedLevels) | ||||||
|  |             { | ||||||
|  |                 if(result == EventLevelEndSuccess) Model.SuccessLevelCount++; // 自动记录关卡完成次数 | ||||||
|  |                 Model.TotalPlayedCount++; // 自动记录关卡总次数 | ||||||
|  | 
 | ||||||
|  |                 Analytics.BLevel = Model.SuccessLevelCount; // 记录 BLevel | ||||||
|  |                 Analytics.BPlay = Model.TotalPlayedCount; // 记录 BPlay | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             Analytics.LogLevelEnd(level, result,  | ||||||
|  |                 levelName, levelCategory, levelCategory, | ||||||
|  |                 duration, step, score); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 游戏失败打点 | ||||||
|  |         /// 需要为游戏记录详细的失败原因 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void LogLevelFail(int level, | ||||||
|  |             string levelCategory = "main",string levelName = "", string levelID = "", | ||||||
|  |             int? duration = null, int? step = null, int? score = null ) | ||||||
|  |         { | ||||||
|  |             LogLevelEnd(level, EventLevelEndFail, levelCategory, levelName, levelID, duration, step, score); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 因退出关卡导致游戏失败 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void LogLevelFailExit(int level, | ||||||
|  |             string levelCategory = "main", string levelName = "", string levelID = "", | ||||||
|  |             int? duration = null, int? step = null, int? score = null) | ||||||
|  |         { | ||||||
|  |             LogLevelEnd(level, EventLevelEndExit, levelCategory, levelName, levelID, duration, step, score); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 因关卡超时导致游戏失败 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void LogLevelFailTimeout(int level, | ||||||
|  |             string levelCategory = "main", string levelName = "", string levelID = "", | ||||||
|  |             int? duration = null, int? step = null, int? score = null) | ||||||
|  |         { | ||||||
|  |             LogLevelEnd(level, EventLevelEndTimeout, levelCategory, levelName, levelID, duration, step, score); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 玩家(角色)升级事件 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="playerLevel"></param> | ||||||
|  |         /// <param name="playerName"></param> | ||||||
|  |         public static void LogLevelUp(int playerLevel, string playerName) | ||||||
|  |         { | ||||||
|  |             Analytics.LevelUp(playerLevel, playerName); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 玩家解锁成就 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="achievementName"></param> | ||||||
|  |         public static void LogAchievement(string achievementName) | ||||||
|  |         { | ||||||
|  |             Analytics.UnlockAchievement(achievementName); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region 用户属性 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 设置用户属性 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="key"></param> | ||||||
|  |         /// <param name="value"></param> | ||||||
|  |         public static void SetUserProperty(string key, string value) | ||||||
|  |             => Analytics.SetUserProperty(key, value); | ||||||
|  | 
 | ||||||
|  |         public static void SetUID(string uid) | ||||||
|  |         { | ||||||
|  |             SetUserProperty(Analytics.PropertyUserID, uid); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void SetUserBLevel(int blevel) | ||||||
|  |         { | ||||||
|  |             SetUserProperty(Analytics.PropertyLevel, $"{blevel}"); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public static void SetUserBPlay(int bplay) | ||||||
|  |         { | ||||||
|  |             SetUserProperty(Analytics.PropertyPlay, $"{bplay}"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void SetUserTotalCoins(int totalCoins) | ||||||
|  |         { | ||||||
|  |             SetUserProperty(Analytics.PropertyCoin, $"{totalCoins}");         | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public static void SetUserCoins(int coins) | ||||||
|  |         { | ||||||
|  |             SetUserProperty(Analytics.PropertyNonIAPCoin, $"{coins}");         | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public static void SetUserPaidCoins(int paidCoins) | ||||||
|  |         { | ||||||
|  |             SetUserProperty(Analytics.PropertyIAPCoin, $"{paidCoins}");         | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public static void SetUserExp(int exp) | ||||||
|  |         { | ||||||
|  |             SetUserProperty(Analytics.PropertyExp, $"{exp}");         | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public static void SetUserHp(int hp) | ||||||
|  |         { | ||||||
|  |             SetUserProperty(Analytics.PropertyHp, $"{hp}");         | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static void SetUserGrade(int grade) | ||||||
|  |         { | ||||||
|  |             SetUserProperty(Analytics.PropertyGrade, $"{grade}");         | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         #endregion | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: b2b75eb78fc3c4f148365eb7e3d89bd7 | ||||||
|  | timeCreated: 1703308617 | ||||||
|  | @ -0,0 +1,119 @@ | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     using System; | ||||||
|  |     using UnityEngine; | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     public partial class GuruSDK | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 回调参数类 | ||||||
|  |         /// </summary> | ||||||
|  |         public class Callbacks | ||||||
|  |         { | ||||||
|  |              | ||||||
|  | 
 | ||||||
|  |             /// <summary> | ||||||
|  |             /// GDPR Consent | ||||||
|  |             /// </summary> | ||||||
|  |             public static class ConsentFlow | ||||||
|  |             { | ||||||
|  |                 /// <summary> | ||||||
|  |                 /// 当Consent启动结束后返回状态码 | ||||||
|  |                 /// </summary> | ||||||
|  |                 public static event Action<int> OnConsentResult | ||||||
|  |                 { | ||||||
|  |                     add => _onConsentResult += value; | ||||||
|  |                     remove => _onConsentResult -= value; | ||||||
|  |                 } | ||||||
|  |                 internal static Action<int> _onConsentResult; | ||||||
|  | 
 | ||||||
|  |                 /// <summary> | ||||||
|  |                 /// ATT 状态返回 | ||||||
|  |                 /// </summary> | ||||||
|  |                 public static event Action<int> OnAttResult | ||||||
|  |                 { | ||||||
|  |                     add => _onAttResult += value; | ||||||
|  |                     remove => _onAttResult -= value; | ||||||
|  |                 } | ||||||
|  |                 internal static Action<int> _onAttResult; | ||||||
|  | 
 | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             /// <summary> | ||||||
|  |             /// 广告回调 | ||||||
|  |             /// </summary> | ||||||
|  |             public static class Ads | ||||||
|  |             { | ||||||
|  |                 internal static Action _onAdsInitComplete; | ||||||
|  |                 public static event Action OnAdsInitComplete | ||||||
|  |                 { | ||||||
|  |                     add => _onAdsInitComplete += value; | ||||||
|  |                     remove => _onAdsInitComplete -= value; | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 internal static Action _onInterstitialADLoaded; | ||||||
|  |                 public static event Action OnInterstitialADLoaded | ||||||
|  |                 { | ||||||
|  |                     add => _onInterstitialADLoaded += value; | ||||||
|  |                     remove => _onInterstitialADLoaded -= value; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 internal static Action _onInterstitialADFailed; | ||||||
|  |                 public static event Action OnInterstitialADFailed | ||||||
|  |                 { | ||||||
|  |                     add => _onInterstitialADFailed += value; | ||||||
|  |                     remove => _onInterstitialADFailed -= value; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 internal static Action _onRewardedADLoaded; | ||||||
|  |                 public static event Action OnRewardedADLoaded | ||||||
|  |                 { | ||||||
|  |                     add => _onRewardedADLoaded += value; | ||||||
|  |                     remove => _onRewardedADLoaded -= value; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 internal static Action _onRewardADFailed; | ||||||
|  |                 public static event Action OnRewardADFailed | ||||||
|  |                 { | ||||||
|  |                     add => _onRewardADFailed += value; | ||||||
|  |                     remove => _onRewardADFailed -= value; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             public static class Remote | ||||||
|  |             { | ||||||
|  |                 internal static Action _onRemoteInitComplete; | ||||||
|  |                 public static event Action OnRemoteInitComplete; | ||||||
|  |                  | ||||||
|  |                 internal static Action _onRemoteFetchComplete; | ||||||
|  |                 public static event Action OnRemoteFetchComplete; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             public static class IAP | ||||||
|  |             { | ||||||
|  |                 internal static Action<bool> _onIAPInitComplete; | ||||||
|  |                 public static event Action<bool> OnIAPInitComplete | ||||||
|  |                 { | ||||||
|  |                     add => _onIAPInitComplete += value; | ||||||
|  |                     remove => _onIAPInitComplete -= value; | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 internal static Action<string> _onPurchaseStart; | ||||||
|  |                 public static event Action<string> OnPurchaseStart | ||||||
|  |                 { | ||||||
|  |                     add => _onPurchaseStart += value; | ||||||
|  |                     remove => _onPurchaseStart -= value; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 971089341f7a64ee38f8d3f82e40f59c | ||||||
|  | timeCreated: 1703307770 | ||||||
|  | @ -0,0 +1,136 @@ | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     using UnityEngine; | ||||||
|  |     using System; | ||||||
|  |     using System.Linq; | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     public partial class GuruSDK | ||||||
|  |     { | ||||||
|  |         public static bool IsIAPReady = false; | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 初始化IAP 功能 | ||||||
|  |         /// </summary> | ||||||
|  |         public static void InitIAP(byte[] googleKey, byte[] appleRootCerts) | ||||||
|  |         { | ||||||
|  |             GuruIAP.Instance.OnInitResult += OnIAPInitResult; | ||||||
|  |             GuruIAP.Instance.OnRestored += OnRestored; | ||||||
|  |             GuruIAP.Instance.OnBuyStart += OnBuyStart; | ||||||
|  |             GuruIAP.Instance.OnBuyEnd += OnBuyEnd; | ||||||
|  |              | ||||||
|  |             GuruIAP.Instance.InitWithKeys(googleKey, appleRootCerts, IsDebugMode); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 初始化结果 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="success"></param> | ||||||
|  |         private static void OnIAPInitResult(bool success) | ||||||
|  |         { | ||||||
|  |             LogI($"IAP init result: {success}"); | ||||||
|  |              | ||||||
|  |             IsIAPReady = success; | ||||||
|  |             Callbacks.IAP._onIAPInitComplete?.Invoke(success); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private static bool CheckIAPReady() | ||||||
|  |         { | ||||||
|  |             if (!IsIAPReady) | ||||||
|  |             { | ||||||
|  |                 LogE("IAP is not ready, call <GuruSDK.InitIAP> first."); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #region Purchase | ||||||
|  | 
 | ||||||
|  |         public static ProductSetting GetProductSettingById(string productId) | ||||||
|  |         { | ||||||
|  |             var products = GuruSettings.Instance.Products; | ||||||
|  |             if (products != null && products.Length > 0) | ||||||
|  |             { | ||||||
|  |                 return products.FirstOrDefault(p => p.ProductId == productId);    | ||||||
|  |             } | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         private static Action<string, bool> _onPurchaseCallback; | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 购买商品, 通过商品Name | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="productId"></param> | ||||||
|  |         /// <param name="purchaseCallback"></param> | ||||||
|  |         public static void Purchase(string productName, Action<string, bool> purchaseCallback = null) | ||||||
|  |         { | ||||||
|  |             if (CheckIAPReady()) | ||||||
|  |             { | ||||||
|  |                 _onPurchaseCallback = purchaseCallback; | ||||||
|  |                 GuruIAP.Instance.Buy(productName); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 购买商品, 通过商品ID | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="productId"></param> | ||||||
|  |         /// <param name="purchaseCallback"></param> | ||||||
|  |         public static bool PurchaseById(string productId, Action<string, bool> purchaseCallback = null) | ||||||
|  |         { | ||||||
|  |             var productName = GetProductSettingById(productId)?.ProductName ?? ""; | ||||||
|  |              | ||||||
|  |             if (CheckIAPReady() && !string.IsNullOrEmpty(productName)) | ||||||
|  |             { | ||||||
|  |                 Purchase(productName, purchaseCallback); | ||||||
|  |                 return true; | ||||||
|  |             } | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 支付回调 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="productId"></param> | ||||||
|  |         /// <param name="success"></param> | ||||||
|  |         private static void OnBuyEnd(string productId, bool success) | ||||||
|  |         { | ||||||
|  |             _onPurchaseCallback?.Invoke(productId, success); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         private static void OnBuyStart(string productId) | ||||||
|  |         { | ||||||
|  |             Callbacks.IAP._onPurchaseStart?.Invoke(productId); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  |          | ||||||
|  |         #region Restore Purchase | ||||||
|  | 
 | ||||||
|  |         private static Action<bool> _onRestored; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 恢复购买 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="restoreCallback"></param> | ||||||
|  |         public static void Restore(Action<bool> restoreCallback) | ||||||
|  |         { | ||||||
|  |             if (CheckIAPReady()) | ||||||
|  |             { | ||||||
|  |                 _onRestored = restoreCallback; | ||||||
|  |                 GuruIAP.Instance.Restore(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         private static void OnRestored(bool success) | ||||||
|  |         { | ||||||
|  |             _onRestored?.Invoke(success); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 2613bac8a776048ac9fd924c6dc7244f | ||||||
|  | timeCreated: 1703320826 | ||||||
|  | @ -0,0 +1,175 @@ | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     using UnityEngine; | ||||||
|  |     using System; | ||||||
|  |      | ||||||
|  |     public partial class GuruSDK: MonoBehaviour | ||||||
|  |     { | ||||||
|  |         public const string Version = "0.1.0"; | ||||||
|  |         public static readonly string Tag = "[Guru]"; | ||||||
|  |          | ||||||
|  |         private static GuruSDK _instance; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 单利引用 | ||||||
|  |         /// </summary> | ||||||
|  |         public static GuruSDK Instance | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if(null == _instance) | ||||||
|  |                 { | ||||||
|  |                     _instance = CreateInstance(); | ||||||
|  |                 } | ||||||
|  |                 return _instance; | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private GuruSDKInitConfig _initConfig; | ||||||
|  |         private Action<bool> _onCompleteCallback; | ||||||
|  | 
 | ||||||
|  |         private static GuruSDKModel _model; | ||||||
|  | 
 | ||||||
|  |         internal static GuruSDKInitConfig InitConfig => Instance._initConfig; | ||||||
|  |         internal static GuruSDKModel Model => GuruSDKModel.Instance; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// Debug Mode | ||||||
|  |         /// </summary> | ||||||
|  |         public static bool IsDebugMode | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  | #if UNITY_EDITOR || DEBUG | ||||||
|  |                 return true; | ||||||
|  | #endif | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         #region 初始化 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         private static GuruSDK CreateInstance() | ||||||
|  |         { | ||||||
|  |             var go = new GameObject(nameof(GuruSDK)); | ||||||
|  |             DontDestroyOnLoad(go); | ||||||
|  |             _instance = go.AddComponent<GuruSDK>(); | ||||||
|  |             return _instance; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         public static void Init(Action<bool> onComplete) | ||||||
|  |         { | ||||||
|  |             Init(GuruSDKInitConfig.Build(), onComplete); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public static void Init(GuruSDKInitConfig config, Action<bool> onComplete) | ||||||
|  |         { | ||||||
|  |             LogI($"---- Guru SDK init ----"); | ||||||
|  |             LogI(config.ToString()); | ||||||
|  |             Instance.StartWithConfig(config, onComplete); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 启动SDK | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="config"></param> | ||||||
|  |         /// <param name="onComplete"></param> | ||||||
|  |         private void StartWithConfig(GuruSDKInitConfig config, Action<bool> onComplete) | ||||||
|  |         { | ||||||
|  |             Model.PropBLevel.OnValueChanged += OnBLevelChanged; | ||||||
|  |             Model.PropBPlay.OnValueChanged += OnBPlayChanged; | ||||||
|  |              | ||||||
|  |             _initConfig = config; | ||||||
|  |             _onCompleteCallback = onComplete; | ||||||
|  |              | ||||||
|  |             //---------- Start Firebase ------------ | ||||||
|  |             FirebaseUtil.InitFirebase(OnFirebaseReady); | ||||||
|  |             FirebaseUtil.OnFetchRemoteSuccess += OnFetchRemoteSuccess; | ||||||
|  |             //---------- Start Facebook ------------ | ||||||
|  |             FBService.Instance.StartService(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void OnFetchRemoteSuccess() | ||||||
|  |         { | ||||||
|  |             Callbacks.Remote._onRemoteFetchComplete?.Invoke(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         /// <summary> | ||||||
|  |         /// 开始各种组件初始化 | ||||||
|  |         /// </summary> | ||||||
|  |         private void OnFirebaseReady() | ||||||
|  |         { | ||||||
|  |             LogI($"--- #1 SDK Init complete ---"); | ||||||
|  |             if (InitConfig.IAPEnabled) | ||||||
|  |             { | ||||||
|  |                 LogI($"--- #2 Init IAP ---"); | ||||||
|  |                 InitIAP(_initConfig.GoogleKeys, _initConfig.AppleRootCerts); // 初始化IAP | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (!InitConfig.UseCustomConsent) | ||||||
|  |             { | ||||||
|  |                 LogI($"--- #3 Start Consent Flow ---"); | ||||||
|  |                 StartConsentFlow(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //TODO: 开始Remote初始化  | ||||||
|  |              | ||||||
|  |             if(!string.IsNullOrEmpty(IPMConfig.IPM_UID)) SetUID(IPMConfig.IPM_UID); | ||||||
|  |              | ||||||
|  |             _onCompleteCallback?.Invoke(true); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void OnBLevelChanged(int blevel) | ||||||
|  |         { | ||||||
|  |             SetUserBLevel(blevel); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void OnBPlayChanged(int bplay) | ||||||
|  |         { | ||||||
|  |             SetUserBPlay(bplay); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region Misc | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 打开页面 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="url"></param> | ||||||
|  |         public static void OpenURL(string url) | ||||||
|  |         { | ||||||
|  |             GuruWebview.OpenPage(url); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region Logging | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         public static void LogI(object message) | ||||||
|  |         { | ||||||
|  |             Debug.Log($"{Tag} {message}"); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public static void LogW(object message) | ||||||
|  |         { | ||||||
|  |             Debug.LogWarning($"{Tag} {message}"); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public static void LogE(object message) | ||||||
|  |         { | ||||||
|  |             Debug.LogError($"{Tag} {message}"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  |          | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 62635518506334610aeaf54c9c29fe75 | ||||||
|  | timeCreated: 1703035168 | ||||||
|  | @ -0,0 +1,97 @@ | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     using System.Collections.Generic; | ||||||
|  |     using System.Text; | ||||||
|  |     /// <summary> | ||||||
|  |     /// 启动参数配置 | ||||||
|  |     /// </summary> | ||||||
|  |     public partial class GuruSDKInitConfig | ||||||
|  |     { | ||||||
|  |         /// <summary> | ||||||
|  |         /// 使用自定义的ConsentFlow启动流程 | ||||||
|  |         /// </summary> | ||||||
|  |         public bool UseCustomConsent = false; | ||||||
|  |         /// <summary> | ||||||
|  |         /// SDK初始化完成后自动加载广告 | ||||||
|  |         /// </summary> | ||||||
|  |         public bool AutoLoadWhenAdsReady = true; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 使用IAP支付插件功能 | ||||||
|  |         /// </summary> | ||||||
|  |         public bool IAPEnabled = true; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 自动记录完成的关卡 | ||||||
|  |         /// </summary> | ||||||
|  |         public bool AutoRecordFinishedLevels = true; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 显示Debug日志 | ||||||
|  |         /// </summary> | ||||||
|  |         public bool ShowDebugLog = false; | ||||||
|  |         /// <summary> | ||||||
|  |         /// 运控参数的默认配置 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public Dictionary<string, object> DefaultRemoteData = new Dictionary<string, object>(); | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 支付初始化Keys | ||||||
|  |         /// </summary> | ||||||
|  |         public byte[] GoogleKeys; | ||||||
|  |         public byte[] AppleRootCerts; | ||||||
|  |          | ||||||
|  |         #region Initialization | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 构建启动配置 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         public static GuruSDKInitConfig Build( | ||||||
|  |             bool useCustomConsent = false,  | ||||||
|  |             bool autoLoadAds = true,  | ||||||
|  |             bool iapEnabled = true,  | ||||||
|  |             bool autoRecordFinishedLevels = true,  | ||||||
|  |             bool showDebugLog = false, | ||||||
|  |             Dictionary<string, object> defaultRemoteData = null, | ||||||
|  |             byte[] googleKeys = null, | ||||||
|  |             byte[] appleRootCerts = null) | ||||||
|  |         { | ||||||
|  |             // 创建启动用参数 | ||||||
|  |             GuruSDKInitConfig config = new GuruSDKInitConfig() | ||||||
|  |             { | ||||||
|  |                 UseCustomConsent = useCustomConsent, | ||||||
|  |                 AutoLoadWhenAdsReady = autoLoadAds, | ||||||
|  |                 IAPEnabled = iapEnabled, | ||||||
|  |                 AutoRecordFinishedLevels = autoRecordFinishedLevels, | ||||||
|  |                 ShowDebugLog = showDebugLog, | ||||||
|  |                 GoogleKeys = googleKeys, | ||||||
|  |                 AppleRootCerts = appleRootCerts, | ||||||
|  |                 DefaultRemoteData = defaultRemoteData ?? new Dictionary<string, object>(), | ||||||
|  |             }; | ||||||
|  | #if UNITY_EDITOR | ||||||
|  |             config.ShowDebugLog = true; | ||||||
|  | #endif | ||||||
|  |             return config; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region Print | ||||||
|  | 
 | ||||||
|  |         public override string ToString() | ||||||
|  |         { | ||||||
|  |             StringBuilder sb = new StringBuilder(); | ||||||
|  |             sb.AppendLine($"------- Custom init Config -------"); | ||||||
|  |             sb.AppendLine($"\tUseCustomConsent: {UseCustomConsent}"); | ||||||
|  |             sb.AppendLine($"\tAutoLoadWhenAdsReady: {AutoLoadWhenAdsReady}"); | ||||||
|  |             sb.AppendLine($"\tIAPEnabled: {IAPEnabled}"); | ||||||
|  |             sb.AppendLine($"\tShowDebugLog: {ShowDebugLog}"); | ||||||
|  |             sb.AppendLine($"------- Custom init Config -------"); | ||||||
|  |             return sb.ToString(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: e6c57dd4792204f5f9b778eb7e7cb920 | ||||||
|  | timeCreated: 1703039335 | ||||||
|  | @ -0,0 +1,94 @@ | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using UnityEngine.Serialization; | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |      | ||||||
|  |     [Serializable] | ||||||
|  |     public class GuruServiceConfig | ||||||
|  |     { | ||||||
|  |         public string version; | ||||||
|  |         public GuruAppSettings app_settings; | ||||||
|  |         public GuruAdjustSettings adjust_settings; | ||||||
|  |         public GuruFbSettings fb_settings; | ||||||
|  |         public GuruAdSettings ad_settings; | ||||||
|  |         public string[] products; | ||||||
|  |          | ||||||
|  |         //-------------------------------- 配置检测 -------------------------------- | ||||||
|  |         public bool IsIAPEnabled() => products != null && products.Length > 0; | ||||||
|  | 
 | ||||||
|  |         public bool IsAmazonAndroidEnabled() => ad_settings != null &&  | ||||||
|  |                                                 ad_settings.amazon_ids_android != null && | ||||||
|  |                                                 ad_settings.amazon_ids_android.Length > 0; | ||||||
|  |         public bool IsAmazonIOSEnabled() => ad_settings != null &&  | ||||||
|  |                                                 ad_settings.amazon_ids_ios != null && | ||||||
|  |                                                 ad_settings.amazon_ids_ios.Length > 0; | ||||||
|  |         public bool IsPubmaticAndroidEnabled() => ad_settings != null &&  | ||||||
|  |                                             ad_settings.pubmatic_ids_android != null && | ||||||
|  |                                             ad_settings.pubmatic_ids_android.Length > 0; | ||||||
|  |         public bool IsPubmaticIOSEnabled() => ad_settings != null &&  | ||||||
|  |                                                   ad_settings.pubmatic_ids_ios != null && | ||||||
|  |                                                   ad_settings.pubmatic_ids_ios.Length > 0; | ||||||
|  |         public bool IsMolocoAndroidEnabled() => ad_settings != null &&  | ||||||
|  |                                                   ad_settings.moloco_ids_android != null && | ||||||
|  |                                                   ad_settings.moloco_ids_android.Length > 0; | ||||||
|  |         public bool IsMolocoIOSEnabled() => ad_settings != null &&  | ||||||
|  |                                                 ad_settings.moloco_ids_ios != null && | ||||||
|  |                                                 ad_settings.moloco_ids_ios.Length > 0; | ||||||
|  |         //-------------------------------- 配置检测 -------------------------------- | ||||||
|  |          | ||||||
|  |          | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     [Serializable]     | ||||||
|  |     public class GuruAppSettings | ||||||
|  |     { | ||||||
|  |         public string app_id; | ||||||
|  |         public string product_name; | ||||||
|  |         public string bundle_id; | ||||||
|  |         public string support_email; | ||||||
|  |         public string privacy_url; | ||||||
|  |         public string terms_url; | ||||||
|  |         public string android_store; | ||||||
|  |         public string ios_store; | ||||||
|  |         public int token_vaild_time = 604800; | ||||||
|  |         public int level_end_success_num = 50; | ||||||
|  |         public bool enable_firebase = true; | ||||||
|  |         public bool enable_facebook = true; | ||||||
|  |         public bool enable_adjust = true; | ||||||
|  |         public bool enable_iap = false; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     [Serializable] | ||||||
|  |     public class GuruAdjustSettings | ||||||
|  |     { | ||||||
|  |         public string[] app_token; | ||||||
|  |         public string[] events; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     [Serializable] | ||||||
|  |     public class GuruFbSettings | ||||||
|  |     { | ||||||
|  |         public string app_id; | ||||||
|  |         public string client_token; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     [Serializable] | ||||||
|  |     public class GuruAdSettings | ||||||
|  |     { | ||||||
|  |         public string sdk_key; | ||||||
|  |         public string[] admob_app_id; | ||||||
|  |         public string[] max_ids_android; | ||||||
|  |         public string[] max_ids_ios; | ||||||
|  |         public string[] amazon_ids_android; | ||||||
|  |         public string[] amazon_ids_ios; | ||||||
|  |         public string[] pubmatic_ids_android; | ||||||
|  |         public string[] pubmatic_ids_ios; | ||||||
|  |         public string[] moloco_ids_android; | ||||||
|  |         public string[] moloco_ids_ios; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  |      | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 5c9728047bb1049639340975b4e8d7ee | ||||||
|  | timeCreated: 1702861449 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 2b0ce7d06a8234e3f9a0eb466c38f041 | ||||||
|  | timeCreated: 1702627775 | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     internal class GuruIAP: IAPServiceBase<GuruIAP> | ||||||
|  |     { | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 获取BLevel | ||||||
|  |         /// </summary> | ||||||
|  |         /// <returns></returns> | ||||||
|  |         protected override int GetBLevel() => GuruSDKModel.Instance.SuccessLevelCount; // BLevel | ||||||
|  | 
 | ||||||
|  |         protected override void OnPurchaseOver(bool success, string productName) | ||||||
|  |         { | ||||||
|  |             if (success) | ||||||
|  |             { | ||||||
|  |                 GuruSDKModel.Instance.PurchasedCount++; // 记录成功购买次数 | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: f22899a5bf889441fba95e634696a74b | ||||||
|  | timeCreated: 1703320926 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 2093caa07830a41d5958de2faf589f13 | ||||||
|  | timeCreated: 1703321414 | ||||||
|  | @ -0,0 +1,38 @@ | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     using UnityEngine; | ||||||
|  |     using System; | ||||||
|  |      | ||||||
|  |     internal class BindableProperty<T> | ||||||
|  |     { | ||||||
|  |         private T _value; | ||||||
|  | 
 | ||||||
|  |         public T Value | ||||||
|  |         { | ||||||
|  |             get => _value; | ||||||
|  |             set | ||||||
|  |             { | ||||||
|  |                 _value = value; | ||||||
|  |                 OnValueChanged?.Invoke(value); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         public event Action<T> OnValueChanged; | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         public BindableProperty()  | ||||||
|  |         { | ||||||
|  |              | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public BindableProperty(Action<T> onChanged) | ||||||
|  |         { | ||||||
|  |             OnValueChanged = onChanged; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         public BindableProperty(T initValue, Action<T> onChanged) | ||||||
|  |         { | ||||||
|  |             _value = initValue; | ||||||
|  |             OnValueChanged = onChanged; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: cc7bbb7d0d6ed42d7985198f9cfc3cb0 | ||||||
|  | timeCreated: 1703323782 | ||||||
|  | @ -0,0 +1,171 @@ | ||||||
|  | using System; | ||||||
|  | using UnityEngine; | ||||||
|  | using UnityEngine.Serialization; | ||||||
|  | 
 | ||||||
|  | namespace Guru | ||||||
|  | { | ||||||
|  |     [Serializable] | ||||||
|  |     internal class GuruSDKModel | ||||||
|  |     { | ||||||
|  |         private static GuruSDKModel _instance; | ||||||
|  |         public static GuruSDKModel Instance | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if (null == _instance) _instance = Load(); | ||||||
|  |                 return _instance; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         //-------------- data --------------- | ||||||
|  |         public int b_level = 0; | ||||||
|  |         public int b_play = 0; | ||||||
|  |         public int buy_count = 0; | ||||||
|  |         //-------------- data --------------- | ||||||
|  | 
 | ||||||
|  |         private float _lastSavedTime = 0; | ||||||
|  |          | ||||||
|  |         public int SuccessLevelCount | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if(_successLevel == null) InitProperties(); | ||||||
|  |                 return _successLevel.Value; | ||||||
|  |             } | ||||||
|  |             set => _successLevel.Value = value; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public int TotalPlayedCount | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if(_totalPlayed == null) InitProperties(); | ||||||
|  |                 return _totalPlayed.Value; | ||||||
|  |             } | ||||||
|  |             set => _totalPlayed.Value = value; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public int PurchasedCount | ||||||
|  |         { | ||||||
|  |             get | ||||||
|  |             { | ||||||
|  |                 if(_purchasedCount == null) InitProperties(); | ||||||
|  |                 return _purchasedCount.Value; | ||||||
|  |             } | ||||||
|  |             set => _purchasedCount.Value = value; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public bool IsIAPUser => PurchasedCount > 0; | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  |         private BindableProperty<int> _successLevel; | ||||||
|  |         private BindableProperty<int> _totalPlayed; | ||||||
|  |         private BindableProperty<int> _purchasedCount; | ||||||
|  |          | ||||||
|  |         public BindableProperty<int> PropBLevel => _successLevel; | ||||||
|  |         public BindableProperty<int> PropBPlay => _totalPlayed; | ||||||
|  |         public BindableProperty<int> PropBuyCount => _purchasedCount; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #region 初始化 | ||||||
|  | 
 | ||||||
|  |         private const float SaveInterval = 3; | ||||||
|  |         private const string SaveKey = "com.guru.sdk.model.save"; | ||||||
|  |         public static GuruSDKModel Load() | ||||||
|  |         { | ||||||
|  |             GuruSDKModel model = null; | ||||||
|  |             if (PlayerPrefs.HasKey(SaveKey)) | ||||||
|  |             { | ||||||
|  |                 var json = PlayerPrefs.GetString(SaveKey, ""); | ||||||
|  |                 if (!string.IsNullOrEmpty(json)) | ||||||
|  |                 { | ||||||
|  |                     try | ||||||
|  |                     { | ||||||
|  |                         model =  JsonUtility.FromJson<GuruSDKModel>(json); | ||||||
|  |                     } | ||||||
|  |                     catch (Exception e) | ||||||
|  |                     { | ||||||
|  |                         Debug.LogError(e); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if(model == null) model = new GuruSDKModel(); | ||||||
|  |             model.InitProperties(); | ||||||
|  |             return model; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 保存至数据 | ||||||
|  |         /// </summary> | ||||||
|  |         private void SaveToPlayerPrefs() | ||||||
|  |         { | ||||||
|  |             var json = JsonUtility.ToJson(this); | ||||||
|  |             PlayerPrefs.SetString(SaveKey, json); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void InitProperties() | ||||||
|  |         { | ||||||
|  |             _successLevel = new BindableProperty<int>(b_level, OnLevelChanged); | ||||||
|  |             _totalPlayed = new BindableProperty<int>(b_play, OnPlayedChanged); | ||||||
|  |             _purchasedCount = new BindableProperty<int>(buy_count, OnPurchasedNumChanged); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         /// 保存数据 | ||||||
|  |         /// </summary> | ||||||
|  |         /// <param name="force"></param> | ||||||
|  |         public void Save(bool force = false) | ||||||
|  |         { | ||||||
|  |             bool save = force || (Time.realtimeSinceStartup - _lastSavedTime>= SaveInterval); | ||||||
|  |             if (save) | ||||||
|  |             { | ||||||
|  |                 _lastSavedTime = Time.realtimeSinceStartup; | ||||||
|  |                 SaveToPlayerPrefs(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  |         #region 数据绑定变化 | ||||||
|  |         private void OnLevelChanged(int value) | ||||||
|  |         { | ||||||
|  |             b_level = value; | ||||||
|  |             Save(); | ||||||
|  |         } | ||||||
|  |         private void OnPlayedChanged(int value) | ||||||
|  |         { | ||||||
|  |             b_play = value; | ||||||
|  |             Save(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private void OnPurchasedNumChanged(int value) | ||||||
|  |         { | ||||||
|  |             buy_count = value; | ||||||
|  |             Save(); | ||||||
|  |         } | ||||||
|  |         #endregion | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 9d518492c434042c6aeb20ce679df8ab | ||||||
|  | timeCreated: 1703321428 | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | { | ||||||
|  |     "name": "GuruSDK", | ||||||
|  |     "rootNamespace": "Guru", | ||||||
|  |     "references": [ | ||||||
|  |         "Guru.Runtime", | ||||||
|  |         "UnityEngine.Purchasing.Security", | ||||||
|  |         "UnityEngine.Purchasing.SecurityStub", | ||||||
|  |         "UnityEngine.Purchasing.SecurityCore" | ||||||
|  |     ], | ||||||
|  |     "includePlatforms": [], | ||||||
|  |     "excludePlatforms": [], | ||||||
|  |     "allowUnsafeCode": false, | ||||||
|  |     "overrideReferences": false, | ||||||
|  |     "precompiledReferences": [], | ||||||
|  |     "autoReferenced": true, | ||||||
|  |     "defineConstraints": [], | ||||||
|  |     "versionDefines": [], | ||||||
|  |     "noEngineReferences": false | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 85fac0454e8c64a0da25f1f632acaa75 | ||||||
|  | timeCreated: 1702611014 | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: fc679813f31644f20b79c6f24939c6a9 | ||||||
|  | timeCreated: 1702611035 | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | <linker> | ||||||
|  |     <assembly fullname="GuruSDK"> | ||||||
|  |         <namespace fullname="Guru" preserve="all"/> | ||||||
|  |     </assembly> | ||||||
|  | </linker> | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 33d446758bba24852bac2e3d9c6bf6fc | ||||||
|  | timeCreated: 1703388178 | ||||||
|  | @ -0,0 +1,15 @@ | ||||||
|  | { | ||||||
|  |   "name": "com.guru.unity.sdk", | ||||||
|  |   "displayName": "Guru SDK", | ||||||
|  |   "version": "0.0.1", | ||||||
|  |   "description": "Guru SDK for unity project", | ||||||
|  |   "unity": "2020.3", | ||||||
|  |   "author":{ | ||||||
|  |     "name": "Guru Fungames Studio" | ||||||
|  |   }, | ||||||
|  |   "license": "MIT", | ||||||
|  |   "category": "Game,Tool,Development", | ||||||
|  |   "dependencies": { | ||||||
|  |     "com.guru.unity.sdk.core": "git@github.com:castbox/upm-guru-sdk-core-proto.git" | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | fileFormatVersion: 2 | ||||||
|  | guid: 2e68608e12de34fa69d2e96e7dcb8892 | ||||||
|  | timeCreated: 1702610734 | ||||||
		Loading…
	
		Reference in New Issue