using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using UnityEditor; using System.IO; using System.Text.RegularExpressions; using System.Text; using TableConfig; 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 SDK_PLUGIN_PROJECT { get { return LocalSave.GetString("SDK_PROJECT_PATH"); } set { LocalSave.SetString("SDK_PROJECT_PATH", value); } } static string ANDROID_PLUGIN_PATH = Application.dataPath + "/Plugins/Android"; static int packageIndex { get { return LocalSave.GetInt("ClientPackageIndex", 1); } set { LocalSave.SetInt("ClientPackageIndex", value); } } public static void BuildPublishers(string _sdkPath, string _assetBundlePath, string _output, string _publisherString, bool _development, bool _replace) { var publisherIds = new List(); 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(); var halfPackages = new List(); var bigPackages = new List(); 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) { for (int i = 0; i < smallPackages.Count; i++) { #if UNITY_ANDROID BuildApk(_sdkPath, _output, smallPackages[i], _development); #elif UNITY_IOS BuildIpa(smallPackages[i], _replace); #endif } } if (halfPackages.Count > 0) { ConfigManager.Instance.PreLoadConfigs(); FileExtersion.DirectoryCopy(_assetBundlePath, ResourcesPath.Instance.StreamingAssetPath); var files = new List(); FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "mob"), files); foreach (var file in files) { var extersion = Path.GetExtension(file.FullName); var fileName = Path.GetFileName(file.FullName); if (!string.IsNullOrEmpty(extersion)) { fileName = fileName.Replace(extersion, ""); } if (!PriorBundleConfig.mobs.Contains(fileName)) { File.Delete(file.FullName); } } files.Clear(); FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "maps"), files); foreach (var file in files) { var extersion = Path.GetExtension(file.FullName); var fileName = Path.GetFileName(file.FullName); if (!string.IsNullOrEmpty(extersion)) { fileName = fileName.Replace(extersion, ""); } if (!PriorBundleConfig.scenes.Contains(fileName)) { File.Delete(file.FullName); } } files.Clear(); FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "audio"), files); foreach (var file in files) { var extersion = Path.GetExtension(file.FullName); var fileName = Path.GetFileName(file.FullName); if (!string.IsNullOrEmpty(extersion)) { fileName = fileName.Replace(extersion, ""); } if (!PriorBundleConfig.audios.Contains(fileName)) { File.Delete(file.FullName); } } files.Clear(); FileExtersion.GetAllDirectoryFileInfos(StringUtility.Contact(ResourcesPath.Instance.StreamingAssetPath, "effect"), files); foreach (var file in files) { var extersion = Path.GetExtension(file.FullName); var fileName = Path.GetFileName(file.FullName); if (!string.IsNullOrEmpty(extersion)) { fileName = fileName.Replace(extersion, ""); } if (!PriorBundleConfig.effects.Contains(fileName)) { File.Delete(file.FullName); } } for (int i = 0; i < halfPackages.Count; i++) { #if UNITY_ANDROID BuildApk(_sdkPath, _output, halfPackages[i], _development); #elif UNITY_IOS BuildIpa(halfPackages[i], _replace); #endif } } if (bigPackages.Count > 0) { FileExtersion.DirectoryCopy(_assetBundlePath, ResourcesPath.Instance.StreamingAssetPath); for (int i = 0; i < bigPackages.Count; i++) { #if UNITY_ANDROID BuildApk(_sdkPath, _output, bigPackages[i], _development); #elif UNITY_IOS BuildIpa(bigPackages[i], _replace); #endif } } packageIndex++; } public static void BuildApk(string _sdkPath, string _output, string _publisher, bool _development) { PreBuild(_publisher); 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); } PlayerSettings.Android.keystoreName = Application.dataPath + "/Editor/Keystore/" + versionConfig.keystoreFileName + ".keystore"; PlayerSettings.Android.keystorePass = versionConfig.keystorePassword; PlayerSettings.Android.keyaliasName = versionConfig.keystoreAlias; PlayerSettings.Android.keyaliasPass = versionConfig.keystoreAliasPassword; PlayerSettings.enableInternalProfiler = _development; if (Directory.Exists(ANDROID_PLUGIN_PATH)) { Directory.Delete(ANDROID_PLUGIN_PATH, true); } Debug.LogFormat("执行Android SDK 文件拷贝,from:{0};to:{1}", StringUtility.Contact(_sdkPath, "/Android/", versionConfig.appId), ANDROID_PLUGIN_PATH); FileExtersion.DirectoryCopy(StringUtility.Contact(_sdkPath, "/Android/", versionConfig.appId), ANDROID_PLUGIN_PATH); if (!versionConfig.appId.Equals("test")) { FileExtersion.DirectoryCopy(StringUtility.Contact(_sdkPath, "/渠道差异/", versionConfig.productName), ANDROID_PLUGIN_PATH); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); var index = packageIndex; if (_development) { var apkName = StringUtility.Contact(_output, "/", versionName, "_", versionConfig.clientPackageFlag, "_v", versionConfig.m_Version, "_", index, "_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, "_", index, ".apk"); BuildPipeline.BuildPlayer(baseLevels, apkName, BuildTarget.Android, BuildOptions.None); } } public static void BuildIpa(string _publisher, bool _replace) { PreBuild(_publisher); PlayerSettings.iOS.buildNumber = VersionConfig.Get().buildIndex.ToString(); PlayerSettings.iOS.appleDeveloperTeamID = VersionConfig.Get().appleDeveloperTeamID; if (_replace) { XCodeProjectMod.BuildIOSProject_Replace(); } else { XCodeProjectMod.BuildIOSProject_Append(); } } private static void PreBuild(string _publisher) { try { var newVersionConfigPath = StringUtility.Contact("Assets/Resources/ScriptableObject/Config/VersionConfig", ".asset"); var versionName = string.Empty; var fromVersionConfig = GetVersionConfig(_publisher, out versionName); var newVersionConfig = ScriptableObject.CreateInstance(); if (File.Exists(newVersionConfigPath)) { AssetDatabase.DeleteAsset(newVersionConfigPath); } VersionConfig.Copy(fromVersionConfig, newVersionConfig); newVersionConfig.buildTime = DateTime.Now.ToString("yy/MM/dd--HH:mm"); newVersionConfig.buildIndex = packageIndex; AssetDatabase.CreateAsset(newVersionConfig, newVersionConfigPath); EditorUtility.SetDirty(newVersionConfig); SetIconAndSplashImage(versionName); 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 = newVersionConfig.version; } catch (Exception ex) { Debug.Log(ex); } finally { 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]; return config; } } _versionName = string.Empty; return null; } static void SetIconAndSplashImage(string _versionName) { var buildTarget = GetBuildTarget(); var texture = AssetDatabase.LoadAssetAtPath(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(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) { PlayerSettings.Android.splashScreenScale = AndroidSplashScreenScale.ScaleToFill; } var logoFromPath = "Assets/Editor/Logo/" + _versionName + "/TB_DL_Logo.png"; var logoToPath = "Assets/Resources/UI/Sprites/TB_DL_Logo.png"; AssetDatabase.DeleteAsset(logoToPath); AssetDatabase.CopyAsset(logoFromPath, logoToPath); var importerPath = "Assets/Resources/UI/Sprites/TB_DL_Logo.png"; var importer = AssetImporter.GetAtPath(importerPath); var textureImporter = importer as TextureImporter; if (textureImporter != null) { textureImporter.spritePackingTag = string.Empty; textureImporter.assetBundleName = string.Empty; var platformSetting = new TextureImporterPlatformSettings(); switch (buildTarget) { case BuildTargetGroup.Android: platformSetting.overridden = true; platformSetting.allowsAlphaSplitting = false; platformSetting.name = "Android"; platformSetting.maxTextureSize = 512; platformSetting.format = TextureImporterFormat.ETC2_RGBA8; platformSetting.compressionQuality = 1; textureImporter.SetPlatformTextureSettings(platformSetting); break; case BuildTargetGroup.iOS: platformSetting.overridden = true; platformSetting.allowsAlphaSplitting = false; platformSetting.name = "iOS"; platformSetting.maxTextureSize = 512; platformSetting.format = TextureImporterFormat.PVRTC_RGBA4; platformSetting.compressionQuality = 1; textureImporter.SetPlatformTextureSettings(platformSetting); break; } AssetDatabase.ImportAsset(importerPath); EditorUtility.SetDirty(textureImporter); } } static BuildTargetGroup GetBuildTarget() { #if UNITY_ANDROID return BuildTargetGroup.Android; #elif UNITY_IOS return BuildTargetGroup.iOS; #else return BuildTargetGroup.Standalone; #endif } }