| using System.Collections;  | 
| using System.Collections.Generic;  | 
| using UnityEngine;  | 
| using System;  | 
| using UnityEditor;  | 
| using System.IO;  | 
| using System.Text.RegularExpressions;  | 
| using System.Text;  | 
|   | 
| using Beebyte.Obfuscator;  | 
| using static UnityEditor.UIElements.ToolbarMenu;  | 
|   | 
| public class ClientPackage  | 
| {  | 
|     public static readonly string versionsFilePath = Application.dataPath + Path.DirectorySeparatorChar + "Editor/VersionConfigs/Versions.txt";  | 
|     public static readonly string[] baseLevels = new string[] { "Assets/Resources/Scenes/Launch.unity", "Assets/Resources/Scenes/Empty.unity" };  | 
|   | 
|     public static string auditOutTime = string.Empty;  | 
|   | 
|     public static string SDK_PLUGIN_PROJECT {  | 
|         get { return LocalSave.GetString("SDK_PROJECT_PATH"); }  | 
|         set { LocalSave.SetString("SDK_PROJECT_PATH", value); }  | 
|     }  | 
|   | 
|     public static bool obfuscatorEnabled {  | 
|         get { return LocalSave.GetBool("obfuscatorEnabled", false); }  | 
|         set { LocalSave.SetBool("obfuscatorEnabled", value); }  | 
|     }  | 
|     public static bool includeConfig {  | 
|         get { return LocalSave.GetBool("client_pg_includeConfig", false); }  | 
|         set { LocalSave.SetBool("client_pg_includeConfig", value); }  | 
|     }  | 
|   | 
|     public static bool includeUI {  | 
|         get { return LocalSave.GetBool("client_pg_includeUI", false); }  | 
|         set { LocalSave.SetBool("client_pg_includeUI", value); }  | 
|     }  | 
|   | 
|     public static int AssetPrior {  | 
|         get { return LocalSave.GetInt("HalfAssetPrior", 1); }  | 
|         set { LocalSave.SetInt("HalfAssetPrior", value); }  | 
|     }  | 
|   | 
|     static string THE_2TH_WORLD_SDK_PATH = Application.dataPath + "/Plugins/Android/bin";  | 
|     static string MANIFEST_PATH = Application.dataPath + "/Plugins/Android/AndroidManifest.xml";  | 
|     static string iOS_PLUGIN_PATH = Application.dataPath + "/Plugins/iOS/Channel";  | 
|   | 
|     static string File_baseProjectTemplate = Application.dataPath + "/Plugins/Android/baseProjectTemplate.gradle";  | 
|     static string File_google_services = Application.dataPath + "/Plugins/Android/google-services.json";  | 
|     static string File_gradleTemplate = Application.dataPath + "/Plugins/Android/gradleTemplate.properties";  | 
|     static string File_LauncherManifest = Application.dataPath + "/Plugins/Android/LauncherManifest.xml";  | 
|     static string File_launcherTemplate = Application.dataPath + "/Plugins/Android/launcherTemplate.gradle";  | 
|     static string File_mainTemplate = Application.dataPath + "/Plugins/Android/mainTemplate.gradle";  | 
|     static string File_deps = Application.dataPath + "/Plugins/Android/deps.gradle";  | 
|   | 
|     /// <summary>  | 
|     /// 打包  | 
|     /// </summary>  | 
|     /// <param name="_sdkPath">整合sdk路径</param>  | 
|     /// <param name="_assetBundlePath">_assetBundle的资源路径,默认在项目目录下的 AssetBundles/android</param>  | 
|     /// <param name="_output">打包完成后的输出路径</param>  | 
|     /// <param name="_publisherString">渠道id,可打多个包,用|分割</param>  | 
|     /// <param name="_buildIndex">打包序序号,用于标识名称</param>  | 
|     /// <param name="_development">是否为开发版</param>  | 
|     /// <param name="_replace">ios打包导出xcode工程模式,Append和Replace</param>  | 
|     public static void BuildPublishers(string _sdkPath, string _assetBundlePath, string _output, string _publisherString, int _buildIndex, bool _development, bool _replace)  | 
|     {  | 
|   | 
|         var publisherIds = new List<string>();  | 
|         var tempStrings = _publisherString.Split(StringUtility.splitSeparator, StringSplitOptions.RemoveEmptyEntries);  | 
|   | 
|         for (int i = 0; i < tempStrings.Length; i++)  | 
|         {  | 
|             var temp = tempStrings[i];  | 
|             var matches = Regex.Matches(temp, "\\d+");  | 
|             switch (matches.Count)  | 
|             {  | 
|                 case 1:  | 
|                     var id = int.Parse(matches[0].Value);  | 
|                     publisherIds.Add(id.ToString());  | 
|                     break;  | 
|                 case 2:  | 
|                     var min = int.Parse(matches[0].Value);  | 
|                     var max = int.Parse(matches[1].Value);  | 
|                     for (int j = min; j <= max; j++)  | 
|                     {  | 
|                         publisherIds.Add(j.ToString());  | 
|                     }  | 
|                     break;  | 
|             }  | 
|         }  | 
|   | 
|         var smallPackages = new List<string>();  | 
|         var halfPackages = new List<string>();  | 
|         var bigPackages = new List<string>();  | 
|   | 
|         for (int i = 0; i < publisherIds.Count; i++)  | 
|         {  | 
|             try  | 
|             {  | 
|                 var publisher = publisherIds[i];  | 
|                 var versionName = string.Empty;  | 
|                 var versionConfig = GetVersionConfig(publisher, out versionName);  | 
|                 switch (versionConfig.assetAccess)  | 
|                 {  | 
|                     case InstalledAsset.NullAsset:  | 
|                         smallPackages.Add(publisher);  | 
|                         break;  | 
|                     case InstalledAsset.HalfAsset:  | 
|                         halfPackages.Add(publisher);  | 
|                         break;  | 
|                     case InstalledAsset.FullAsset:  | 
|                     case InstalledAsset.IngoreDownLoad:  | 
|                         bigPackages.Add(publisher);  | 
|                         break;  | 
|   | 
|                 }  | 
|             }  | 
|             catch (Exception ex)  | 
|             {  | 
|                 Debug.Log(ex);  | 
|             }  | 
|         }  | 
|   | 
|         if (Directory.Exists(ResourcesPath.Instance.StreamingAssetPath))  | 
|         {  | 
|             Directory.Delete(ResourcesPath.Instance.StreamingAssetPath, true);  | 
|         }  | 
|   | 
|         if (smallPackages.Count > 0)  | 
|         {  | 
|             var files = new List<FileInfo>();  | 
|             var builtInFiles = new List<FileInfo>();  | 
|   | 
|             FileExtersion.GetAllDirectoryFileInfos(_assetBundlePath, files);  | 
|             foreach (var file in files)  | 
|             {  | 
|                 var fileName = Path.GetFileName(file.FullName);  | 
|   | 
|                 if (file.FullName.Contains("builtin"))  | 
|                 {  | 
|                     builtInFiles.Add(file);  | 
|                     continue;  | 
|                 }  | 
|   | 
|                 if (ConfigInitiator.builtinConfig.Contains(fileName))  | 
|                 {  | 
|                     builtInFiles.Add(file);  | 
|                     continue;  | 
|                 }  | 
|   | 
|                 // File.Delete(file.FullName);  | 
|             }  | 
|   | 
|             var totalCount = builtInFiles.Count;  | 
|             var completeCount = 0;  | 
|             foreach (var item in builtInFiles)  | 
|             {  | 
|                 var extension = Path.GetExtension(item.FullName);  | 
|                 if (extension == ".meta")  | 
|                 {  | 
|                     continue;  | 
|                 }  | 
|   | 
|                 var relativePath = FileExtersion.GetFileRelativePath(_assetBundlePath, item.FullName);  | 
|                 var to = StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, relativePath);  | 
|                 var directory = Path.GetDirectoryName(to);  | 
|                 if (!Directory.Exists(directory))  | 
|                 {  | 
|                     Directory.CreateDirectory(directory);  | 
|                 }  | 
|   | 
|                 File.Copy(item.FullName, to, true);  | 
|                 completeCount++;  | 
|             }  | 
|   | 
|             EditorUtility.ClearProgressBar();  | 
|   | 
|             for (int i = 0; i < smallPackages.Count; i++)  | 
|             {  | 
| #if UNITY_ANDROID  | 
|                 BuildApk(_sdkPath, _output, smallPackages[i], _buildIndex, _development);  | 
| #elif UNITY_IOS  | 
|                 BuildIpa(_sdkPath, smallPackages[i], _buildIndex, _replace);  | 
| #endif  | 
|             }  | 
|         }  | 
|   | 
|         if (halfPackages.Count > 0)  | 
|         {  | 
|             PriorBundleConfig.Init(true);  | 
|   | 
|             var fromFiles = new List<FileInfo>();  | 
|             FileExtersion.GetAllDirectoryFileInfos(_assetBundlePath, fromFiles);  | 
|   | 
|             var excludeFileFullNames = new List<string>();  | 
|             var tempFiles = new List<FileInfo>();  | 
|             FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(_assetBundlePath, "/gmodels"), tempFiles);  | 
|             foreach (var file in tempFiles)  | 
|             {  | 
|                 var extersion = Path.GetExtension(file.FullName);  | 
|                 var fileName = Path.GetFileNameWithoutExtension(file.FullName);  | 
|                 var prior = PriorBundleConfig.GetAssetPrior(AssetVersion.AssetCategory.Mob, fileName);  | 
|                 if (prior > AssetPrior)  | 
|                 {  | 
|                     excludeFileFullNames.Add(file.FullName);  | 
|                 }  | 
|             }  | 
|   | 
|             tempFiles.Clear();  | 
|             FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(_assetBundlePath, "/maps"), tempFiles);  | 
|             foreach (var file in tempFiles)  | 
|             {  | 
|                 var extersion = Path.GetExtension(file.FullName);  | 
|                 var fileName = Path.GetFileNameWithoutExtension(file.FullName);  | 
|                 var prior = PriorBundleConfig.GetAssetPrior(AssetVersion.AssetCategory.Scene, fileName);  | 
|                 if (prior > AssetPrior)  | 
|                 {  | 
|                     excludeFileFullNames.Add(file.FullName);  | 
|                 }  | 
|             }  | 
|   | 
|             tempFiles.Clear();  | 
|             FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(_assetBundlePath, "/audio"), tempFiles);  | 
|             foreach (var file in tempFiles)  | 
|             {  | 
|                 var extersion = Path.GetExtension(file.FullName);  | 
|                 var fileName = Path.GetFileNameWithoutExtension(file.FullName);  | 
|                 var prior = PriorBundleConfig.GetAssetPrior(AssetVersion.AssetCategory.Audio, fileName);  | 
|                 if (prior > AssetPrior)  | 
|                 {  | 
|                     excludeFileFullNames.Add(file.FullName);  | 
|                 }  | 
|             }  | 
|   | 
|             tempFiles.Clear();  | 
|             FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(_assetBundlePath, "/effect"), tempFiles);  | 
|             foreach (var file in tempFiles)  | 
|             {  | 
|                 var extersion = Path.GetExtension(file.FullName);  | 
|                 var fileName = Path.GetFileNameWithoutExtension(file.FullName);  | 
|                 var prior = PriorBundleConfig.GetAssetPrior(AssetVersion.AssetCategory.Effect, fileName);  | 
|                 if (prior > AssetPrior)  | 
|                 {  | 
|                     excludeFileFullNames.Add(file.FullName);  | 
|                 }  | 
|             }  | 
|   | 
|             //剔除视频资源  | 
|             tempFiles.Clear();  | 
|             var videoPath = StringUtility.Contact(_assetBundlePath, "/video");  | 
|             if (File.Exists(videoPath))  | 
|             {  | 
|                 FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(_assetBundlePath, "/video"), tempFiles);  | 
|                 foreach (var file in tempFiles)  | 
|                 {  | 
|                     var extersion = Path.GetExtension(file.FullName);  | 
|                     var fileName = Path.GetFileNameWithoutExtension(file.FullName);  | 
|                     var prior = PriorBundleConfig.GetAssetPrior(AssetVersion.AssetCategory.Video, fileName);  | 
|                     if (prior > AssetPrior)  | 
|                     {  | 
|                         excludeFileFullNames.Add(file.FullName);  | 
|                     }  | 
|                 }  | 
|             }  | 
|   | 
|             //剔除表资源  | 
|             if (!includeConfig)  | 
|             {  | 
|                 tempFiles.Clear();  | 
|                 FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(_assetBundlePath, "/config"), tempFiles);  | 
|                 foreach (var file in tempFiles)  | 
|                 {  | 
|                     if (!ConfigInitiator.builtinConfig.Contains(file.Name))  | 
|                         excludeFileFullNames.Add(file.FullName);  | 
|                 }  | 
|             }  | 
|   | 
|             //剔除UI资源  | 
|             tempFiles.Clear();  | 
|             FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(_assetBundlePath, "/ui/sprite"), tempFiles);  | 
|             foreach (var file in tempFiles)  | 
|             {  | 
|                 var fileName = Path.GetFileName(file.FullName);  | 
|                 if (fileName == "loadingbg")  | 
|                 {  | 
|                     excludeFileFullNames.Add(file.FullName);  | 
|                 }  | 
|             }  | 
|             if (!includeUI)  | 
|             {  | 
|                 tempFiles.Clear();  | 
|                 FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(_assetBundlePath, "/ui"), tempFiles);  | 
|                 foreach (var file in tempFiles)  | 
|                 {  | 
|                     excludeFileFullNames.Add(file.FullName);  | 
|                 }  | 
|             }  | 
|   | 
|             for (int i = fromFiles.Count - 1; i >= 0; i--)  | 
|             {  | 
|                 var item = fromFiles[i];  | 
|                 if (excludeFileFullNames.Contains(item.FullName))  | 
|                 {  | 
|                     fromFiles.RemoveAt(i);  | 
|                 }  | 
|             }  | 
|   | 
|             var totalCount = fromFiles.Count;  | 
|             var completeCount = 0;  | 
|             foreach (var item in fromFiles)  | 
|             {  | 
|                 var relativePath = FileExtersion.GetFileRelativePath(_assetBundlePath, item.FullName);  | 
|                 var to = StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, relativePath);  | 
|                 if (relativePath.StartsWith("patch"))//不包含meta文件和补丁  | 
|                     continue;  | 
|   | 
|                 var directory = Path.GetDirectoryName(to);  | 
|                 if (!Directory.Exists(directory))  | 
|                     Directory.CreateDirectory(directory);  | 
|   | 
|                 var extension = Path.GetExtension(item.FullName);  | 
|                 if (extension == ".meta")  | 
|                     continue;  | 
|   | 
|                 File.Copy(item.FullName, to, true);  | 
|                 completeCount++;  | 
|             }  | 
|   | 
|             EditorUtility.ClearProgressBar();  | 
|             for (int i = 0; i < halfPackages.Count; i++)  | 
|             {  | 
| #if UNITY_ANDROID  | 
|                 BuildApk(_sdkPath, _output, halfPackages[i], _buildIndex, _development);  | 
| #elif UNITY_IOS  | 
|                 BuildIpa(_sdkPath, halfPackages[i], _buildIndex, _replace);  | 
| #endif  | 
|             }  | 
|         }  | 
|   | 
|         if (bigPackages.Count > 0)  | 
|         {  | 
|             var fromFiles = new List<FileInfo>();  | 
|             FileExtersion.GetAllDirectoryFileInfos(_assetBundlePath, fromFiles);  | 
|   | 
|             var totalCount = fromFiles.Count;  | 
|             var completeCount = 0;  | 
|             foreach (var item in fromFiles)  | 
|             {  | 
|                 var relativePath = FileExtersion.GetFileRelativePath(_assetBundlePath, item.FullName);  | 
|                 var to = StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, relativePath);  | 
|                 if (relativePath.StartsWith("patch"))//不包含meta文件和补丁  | 
|                     continue;  | 
|   | 
|                 var directory = Path.GetDirectoryName(to);  | 
|                 if (!Directory.Exists(directory))  | 
|                     Directory.CreateDirectory(directory);  | 
|   | 
|                 var extension = Path.GetExtension(item.FullName);  | 
|                 if (extension == ".meta")  | 
|                     continue;  | 
|   | 
|                 File.Copy(item.FullName, to, true);  | 
|                 completeCount++;  | 
|             }  | 
|   | 
|             for (int i = 0; i < bigPackages.Count; i++)  | 
|             {  | 
| #if UNITY_ANDROID  | 
|                 BuildApk(_sdkPath, _output, bigPackages[i], _buildIndex, _development);  | 
| #elif UNITY_IOS  | 
|                 BuildIpa(_sdkPath, bigPackages[i], _buildIndex, _replace);  | 
| #endif  | 
|             }  | 
|         }  | 
|   | 
|     }  | 
|   | 
|     public static void BuildApk(string _sdkPath, string _output, string _publisher, int _buildIndex, bool _development)  | 
|     {  | 
|         PreBuild(_publisher, _buildIndex);  | 
|         var auditTimeFile = StringUtility.Contact(Application.dataPath, Path.DirectorySeparatorChar, "Resources/Config/AuditTime.txt");  | 
|         if (File.Exists(auditTimeFile))  | 
|         {  | 
|             File.Delete(auditTimeFile);  | 
|         }  | 
|   | 
|         var versionName = string.Empty;  | 
|         var versionConfig = GetVersionConfig(_publisher, out versionName);  | 
|         var versionConfigCSpath = Application.dataPath + "/Scripts/System/ClientVersion/VersionConfig.cs";  | 
|         var text = File.ReadAllText(versionConfigCSpath);  | 
|   | 
|         if (text.Contains("VERSION_ALTERNATIVE"))  | 
|         {  | 
|             var pattern = "VERSION_ALTERNATIVE = \".*\"";  | 
|             text = Regex.Replace(text, pattern, StringUtility.Contact("VERSION_ALTERNATIVE = ", "\"", versionConfig.m_Version, "\""));  | 
|   | 
|             bool encoderShouldEmitUTF8Identifier = true;  | 
|             bool throwOnInvalidBytes = false;  | 
|             UTF8Encoding encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier, throwOnInvalidBytes);  | 
|             bool append = false;  | 
|             StreamWriter streamWriter = new StreamWriter(versionConfigCSpath, append, encoding);  | 
|             streamWriter.Write(text);  | 
|             streamWriter.Close();  | 
|             AssetDatabase.ImportAsset(versionConfigCSpath);  | 
|         }  | 
|   | 
|         // 针对某一些打包的特殊性, 这里特指依赖的第三方库含有资源的问题  | 
|         // 这里对有这种特型的渠道的sdk在打包的时候差异化gradle文件  | 
|         // 更名原有文件  | 
|         // string _gradleTemplateUrl = EditorApplication.applicationContentsPath + "/PlaybackEngines/AndroidPlayer/Tools/GradleTemplates/";  | 
|         // string _gradleFileUrl = _gradleTemplateUrl + "mainTemplate.gradle";  | 
|         // string _diffGradleFileUrl = StringUtility.Contact(_sdkPath, "/GradleDiff/", versionConfig.appId, "/mainTemplate.gradle");  | 
|         // FileInfo _fileInfo = new FileInfo(_diffGradleFileUrl);  | 
|   | 
|         // if (!_fileInfo.Exists)  | 
|         // {  | 
|         //     EditorUtility.DisplayDialog("警告", "Gradle模式需要配置差异文件,但是没有找到该文件: " + _diffGradleFileUrl, "@Hale");  | 
|         //     return;  | 
|         // }  | 
|   | 
|         // _fileInfo.CopyTo(_gradleFileUrl, true);  | 
|   | 
|         // 移动配置文件至打包工作目录中  | 
|         var keystorePath = Application.dataPath + "/Editor/Keystore/" + versionConfig.keystoreFileName + ".keystore";  | 
|         if (!File.Exists(keystorePath))  | 
|         {  | 
|             Debug.LogError("签名文件不存在");  | 
|             return;  | 
|         }  | 
|         PlayerSettings.Android.keystoreName = keystorePath;  | 
|         PlayerSettings.Android.keystorePass = versionConfig.keystorePassword;  | 
|         PlayerSettings.Android.keyaliasName = versionConfig.keystoreAlias;  | 
|         PlayerSettings.Android.keyaliasPass = versionConfig.keystoreAliasPassword;  | 
|         // PlayerSettings.Android.targetSdkVersion = AndroidSdkVersions.AndroidApiLevel22;  | 
|         PlayerSettings.Android.bundleVersionCode = VersionConfig.GetVersionNumber(versionConfig.version);  | 
|   | 
|         PlayerSettings.enableInternalProfiler = _development;  | 
|   | 
|         //删除原sdk文件  | 
|         if (Directory.Exists(THE_2TH_WORLD_SDK_PATH))  | 
|             Directory.Delete(THE_2TH_WORLD_SDK_PATH, true);  | 
|         if (File.Exists(MANIFEST_PATH))  | 
|             File.Delete(MANIFEST_PATH);  | 
|         if (File.Exists(File_baseProjectTemplate))  | 
|             File.Delete(File_baseProjectTemplate);  | 
|         if (File.Exists(File_google_services))  | 
|             File.Delete(File_google_services);  | 
|         if (File.Exists(File_gradleTemplate))  | 
|             File.Delete(File_gradleTemplate);  | 
|         if (File.Exists(File_LauncherManifest))  | 
|             File.Delete(File_LauncherManifest);  | 
|         if (File.Exists(File_launcherTemplate))  | 
|             File.Delete(File_launcherTemplate);  | 
|         if (File.Exists(File_mainTemplate))  | 
|             File.Delete(File_mainTemplate);  | 
|         if (File.Exists(File_deps))  | 
|             File.Delete(File_deps);  | 
|         var variant = _development ? "debug" : "release";  | 
|   | 
|         string channelSdkPath;  | 
|         string copySdkFile;  | 
|   | 
|         channelSdkPath = StringUtility.Contact(_sdkPath, "/Channel/Android/", versionConfig.appId, "/", variant);  | 
|         copySdkFile = StringUtility.Contact(_sdkPath, "/Channel/Android/", versionConfig.appId, "/AndroidManifest.xml");  | 
|         File.Copy(copySdkFile, MANIFEST_PATH);  | 
|         copySdkFile = StringUtility.Contact(_sdkPath, "/Channel/Android/", versionConfig.appId, "/baseProjectTemplate.gradle");  | 
|         File.Copy(copySdkFile, File_baseProjectTemplate);  | 
|         copySdkFile = StringUtility.Contact(_sdkPath, "/Channel/Android/", versionConfig.appId, "/deps.gradle");  | 
|         File.Copy(copySdkFile, File_deps);  | 
|         copySdkFile = StringUtility.Contact(_sdkPath, "/Channel/Android/", versionConfig.appId, "/google-services.json");  | 
|         File.Copy(copySdkFile, File_google_services);  | 
|         copySdkFile = StringUtility.Contact(_sdkPath, "/Channel/Android/", versionConfig.appId, "/gradleTemplate.properties");  | 
|         File.Copy(copySdkFile, File_gradleTemplate);  | 
|         //copySdkFile = StringUtility.Contact(_sdkPath, "/Channel/Android/", versionConfig.appId, "/LauncherManifest.xml");  | 
|         //File.Copy(copySdkFile, File_LauncherManifest);  | 
|         copySdkFile = StringUtility.Contact(_sdkPath, "/Channel/Android/", versionConfig.appId, "/launcherTemplate.gradle");  | 
|         File.Copy(copySdkFile, File_launcherTemplate);  | 
|         copySdkFile = StringUtility.Contact(_sdkPath, "/Channel/Android/", versionConfig.appId, "/mainTemplate.gradle");  | 
|         File.Copy(copySdkFile, File_mainTemplate);  | 
|         DebugEx.LogFormat("Android 清单等文件拷贝成功");  | 
|           | 
|   | 
|   | 
|         if (Directory.Exists(channelSdkPath))  | 
|         {  | 
|             FileExtersion.DirectoryCopy(channelSdkPath, THE_2TH_WORLD_SDK_PATH);  | 
|             DebugEx.LogFormat("执行Android 渠道SDK 文件拷贝,from:{0};to:{1}", channelSdkPath, THE_2TH_WORLD_SDK_PATH);  | 
|         }  | 
|         else  | 
|         {  | 
|             DebugEx.LogFormat("Android 渠道SDK文件不存在,{0}", channelSdkPath);  | 
|             return;  | 
|         }  | 
|   | 
|         var option = AssetDatabase.LoadAssetAtPath<Options>("Assets/Editor/Beebyte/Obfuscator/ObfuscatorOptions.asset");  | 
|         if (option != null)  | 
|         {  | 
|             option.enabled = obfuscatorEnabled;  | 
|             EditorUtility.SetDirty(option);  | 
|         }  | 
|   | 
|         AssetDatabase.SaveAssets();  | 
|         AssetDatabase.Refresh();  | 
|   | 
|         IFix.Editor.IFixEditor.InjectAllAssemblys();//对injectAssemblys里的程序集进行注入,然后备份  | 
|   | 
|         if (_development)  | 
|         {  | 
|             var apkName = StringUtility.Contact(_output, "/", versionName, "_", versionConfig.clientPackageFlag, "_v", versionConfig.m_Version, "_", _buildIndex, "_development.apk");  | 
|             BuildPipeline.BuildPlayer(baseLevels, apkName, BuildTarget.Android, BuildOptions.Development | BuildOptions.ConnectWithProfiler | BuildOptions.AllowDebugging);  | 
|         }  | 
|         else  | 
|         {  | 
|             var apkName = StringUtility.Contact(_output, "/", versionName, "_", versionConfig.clientPackageFlag, "_v", versionConfig.m_Version, "_", _buildIndex, ".apk");  | 
|             BuildPipeline.BuildPlayer(baseLevels, apkName, BuildTarget.Android, BuildOptions.None);  | 
|         }  | 
|     }  | 
|   | 
|     public static VersionConfig versionConfig1 = null;  | 
|     public static void BuildIpa(string _sdkPath, string _publisher, int _buildIndex, bool _replace)  | 
|     {  | 
|         PreBuild(_publisher, _buildIndex);  | 
|   | 
|         var versionName = string.Empty;  | 
|         versionConfig1 = GetVersionConfig(_publisher, out versionName);  | 
|   | 
|         if (Directory.Exists(iOS_PLUGIN_PATH))  | 
|         {  | 
|             Directory.Delete(iOS_PLUGIN_PATH, true);  | 
|         }  | 
|   | 
|         if (versionConfig1.sdkFileName.Trim().Length != 0)  | 
|         {  | 
|             FileExtersion.DirectoryCopy(StringUtility.Contact(_sdkPath, "/Channel/iOS/", versionConfig1.sdkFileName, "/Plugins"), iOS_PLUGIN_PATH);  | 
|         }  | 
|         else  | 
|         {  | 
|             FileExtersion.DirectoryCopy(StringUtility.Contact(_sdkPath, "/Channel/iOS/", versionConfig1.appId, "/Plugins"), iOS_PLUGIN_PATH);  | 
|         }  | 
|   | 
|         DateTime outTime;  | 
|         var correct = DateTime.TryParse(auditOutTime, out outTime);  | 
|         var directory = Application.dataPath + Path.DirectorySeparatorChar + "Resources/Config";  | 
|         if (!Directory.Exists(directory))  | 
|         {  | 
|             Directory.CreateDirectory(directory);  | 
|         }  | 
|         File.WriteAllText(Application.dataPath + Path.DirectorySeparatorChar + "Resources/Config/AuditTime.txt", correct ? auditOutTime : "");  | 
|   | 
|         var option = AssetDatabase.LoadAssetAtPath<Options>("Assets/Editor/Beebyte/Obfuscator/ObfuscatorOptions.asset");  | 
|         if (option != null)  | 
|         {  | 
|             option.enabled = obfuscatorEnabled;  | 
|             EditorUtility.SetDirty(option);  | 
|         }  | 
|   | 
|         AssetDatabase.SaveAssets();  | 
|         AssetDatabase.Refresh();  | 
|         PlayerSettings.iOS.buildNumber = VersionConfig.Get().buildIndex.ToString();  | 
|         PlayerSettings.iOS.appleDeveloperTeamID = VersionConfig.Get().appleDeveloperTeamID;  | 
|   | 
|         IFix.Editor.IFixEditor.InjectAllAssemblys();//对injectAssemblys里的程序集进行注入,然后备份  | 
| #if UNITY_IOS  | 
|         if (_replace)  | 
|         {  | 
|             XCodeProjectMod.BuildIOSProject_Replace();  | 
|         }  | 
|         else  | 
|         {  | 
|             XCodeProjectMod.BuildIOSProject_Append();  | 
|         }  | 
| #endif  | 
|     }  | 
|   | 
|     private static void PreBuild(string _publisher, int _buildIndex)  | 
|     {  | 
|         var newVersionConfigPath = StringUtility.Contact("Assets/Resources/VersionConfig", ".asset");  | 
|         var versionName = string.Empty;  | 
|         var fromVersionConfig = GetVersionConfig(_publisher, out versionName);  | 
|         var newVersionConfig = ScriptableObject.CreateInstance<VersionConfig>();  | 
|         if (File.Exists(newVersionConfigPath))  | 
|         {  | 
|             AssetDatabase.DeleteAsset(newVersionConfigPath);  | 
|         }  | 
|   | 
|         VersionConfig.Copy(fromVersionConfig, newVersionConfig);  | 
|         newVersionConfig.buildTime = DateTime.Now.ToString("yy/MM/dd--HH:mm");  | 
|         newVersionConfig.buildIndex = _buildIndex;  | 
|   | 
|         if (File.Exists(Application.dataPath + "/Resources/Game.txt"))  | 
|         {  | 
|             File.Delete(Application.dataPath + "/Resources/Game.txt");  | 
|         }  | 
|   | 
|         File.WriteAllText(Application.dataPath + "/Resources/Game.txt", GetGameId(_publisher));  | 
|   | 
|         AssetDatabase.CreateAsset(newVersionConfig, newVersionConfigPath);  | 
|         EditorUtility.SetDirty(newVersionConfig);  | 
|   | 
|         SetIconAndSplashImage(versionName);  | 
|         //SetCreateRoleAnimation();  | 
|   | 
|         PlayerSettings.companyName = "TheSecondWorld";  | 
|         PlayerSettings.productName = newVersionConfig.productName;  | 
|         PlayerSettings.applicationIdentifier = newVersionConfig.bundleIdentifier;  | 
|         PlayerSettings.defaultInterfaceOrientation = UIOrientation.AutoRotation;  | 
|         PlayerSettings.allowedAutorotateToLandscapeLeft = true;  | 
|         PlayerSettings.allowedAutorotateToLandscapeRight = true;  | 
|         PlayerSettings.allowedAutorotateToPortrait = false;  | 
|         PlayerSettings.allowedAutorotateToPortraitUpsideDown = false;  | 
|         PlayerSettings.bundleVersion = VersionConfig.GetVersionNumber(newVersionConfig.version).ToString();  | 
|   | 
|         //生成ILruntiemd CLR 绑定代码  | 
|         ILRuntimeCLRBinding.GenerateCLRBinding();  | 
|   | 
|         AssetDatabase.SaveAssets();  | 
|         AssetDatabase.Refresh();  | 
|     }  | 
|   | 
|     static VersionConfig GetVersionConfig(string _publisher, out string _versionName)  | 
|     {  | 
|         var lines = File.ReadAllLines(versionsFilePath);  | 
|   | 
|         for (int i = 2; i < lines.Length; i++)  | 
|         {  | 
|             var line = lines[i];  | 
|             var lineStrings = line.Split('\t');  | 
|             if (lineStrings[0] == _publisher)  | 
|             {  | 
|                 var config = new VersionConfig();  | 
|                 config.Read(line);  | 
|                 _versionName = lineStrings[1];  | 
|                 if (!string.IsNullOrEmpty(lineStrings[24]))  | 
|                     _versionName = lineStrings[24];  | 
|                 return config;  | 
|             }  | 
|         }  | 
|   | 
|         _versionName = string.Empty;  | 
|         return null;  | 
|     }  | 
|   | 
|     static string GetGameId(string _publisher)  | 
|     {  | 
|         var lines = File.ReadAllLines(versionsFilePath);  | 
|         for (int i = 2; i < lines.Length; i++)  | 
|         {  | 
|             var line = lines[i];  | 
|             var lineStrings = line.Split('\t');  | 
|             if (lineStrings[0] == _publisher)  | 
|             {  | 
|                 return lineStrings[7];  | 
|             }  | 
|         }  | 
|   | 
|         return "xbqy";  | 
|     }  | 
|   | 
|     static void SetIconAndSplashImage(string _versionName)  | 
|     {  | 
|         var buildTarget = GetBuildTarget();  | 
|         var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(StringUtility.Contact("Assets/Editor/Logo/", _versionName, "/Icon.png"));  | 
|         var iconSizes = PlayerSettings.GetIconSizesForTargetGroup(buildTarget);  | 
|         var icons = new Texture2D[iconSizes.Length];  | 
|         for (int i = 0; i < iconSizes.Length; i++)  | 
|         {  | 
|             icons[i] = texture;  | 
|         }  | 
|   | 
|         PlayerSettings.SetIconsForTargetGroup(buildTarget, icons);  | 
|   | 
|         PlayerSettings.SplashScreen.show = false;  | 
|         PlayerSettings.SplashScreen.showUnityLogo = false;  | 
|         PlayerSettings.SplashScreen.unityLogoStyle = PlayerSettings.SplashScreen.UnityLogoStyle.LightOnDark;  | 
|   | 
|         var splashImage = AssetDatabase.LoadAssetAtPath<Sprite>(StringUtility.Contact("Assets/Editor/Logo/", _versionName, "/SplashImage.png"));  | 
|         var splashScreenLogo = PlayerSettings.SplashScreenLogo.Create(3, splashImage);  | 
|         PlayerSettings.SplashScreen.logos = new PlayerSettings.SplashScreenLogo[] { splashScreenLogo };  | 
|   | 
|         if (buildTarget == BuildTargetGroup.Android)  | 
|         {  | 
|             var projectSettings = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/ProjectSettings.asset")[0]);  | 
|             var splashImageSetting = projectSettings.FindProperty("androidSplashScreen");  | 
|             splashImageSetting.objectReferenceValue = splashImage.texture;  | 
|             projectSettings.ApplyModifiedProperties();  | 
|   | 
|             PlayerSettings.Android.splashScreenScale = AndroidSplashScreenScale.ScaleToFill;  | 
|         }  | 
|     }  | 
|   | 
|     public static void SetCreateRoleAnimation()  | 
|     {  | 
|         var from = "Assets/Editor/Video/CreateRoleMovie.mp4";  | 
|         var to = "Assets/StreamingAssets/CreateRoleMovie.mp4";  | 
|   | 
|         if (!Directory.Exists(Application.dataPath + "StreamingAssets"))  | 
|         {  | 
|             Directory.CreateDirectory(Application.dataPath + "StreamingAssets");  | 
|         }  | 
|   | 
|         if (AssetDatabase.LoadAssetAtPath<UnityEngine.Video.VideoClip>(to) == null)  | 
|         {  | 
|             AssetDatabase.CopyAsset(from, to);  | 
|         }  | 
|     }  | 
|   | 
|     static BuildTargetGroup GetBuildTarget()  | 
|     {  | 
| #if UNITY_ANDROID  | 
|         return BuildTargetGroup.Android;  | 
| #elif UNITY_IOS  | 
|         return BuildTargetGroup.iOS;  | 
| #else  | 
|         return BuildTargetGroup.Standalone;  | 
| #endif  | 
|     }  | 
|   | 
| }  |