//生成资源描述文件 public static void GenResDescFile(List <ResouceElement> resList, string patchPath, string resDescFileName, out uint resDescFileCrc) { string tmpFileListPath = patchPath + "/" + resDescFileName; FileStream fs = new FileStream(tmpFileListPath, FileMode.Create, FileAccess.Write); MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); bw.Write(resList.Count);//写入数量 for (int i = 0; i < resList.Count; i++) { ResouceElement resElement = resList[i]; bw.Write(resElement.keyHash); //写入文件KeyHash bw.Write(resElement.fileHash); //写入文件FileHash bw.Write((byte)resElement.resType); bw.Write(resElement.fileSize); } bw.Flush(); ms.WriteTo(fs); bw.Close(); ms.Close(); fs.Close(); resDescFileCrc = Crc.Crc32(resDescFileName + ComputeMD5(tmpFileListPath)); File.Move(tmpFileListPath, $"{patchPath}/{resDescFileCrc}"); }
//生成帮助文件 public static void GenAssistDescFile(List <ResouceElement> resList, string patchPath, string versionStr, string versionFileName, string resListDescFileName) { string describeFileName = Path.GetFileName(patchPath) + ".txt"; string describePath = patchPath + "/../" + describeFileName; if (File.Exists(describePath)) { File.Delete(describePath); } StringBuilder sb = new StringBuilder(); for (int i = 0; i < resList.Count; i++) { ResouceElement resElement = resList[i]; sb.AppendLine("KeyHash:" + resElement.keyHash + "\tFileHash:" + resElement.fileHash + "\tFileSize:" + (int)resElement.fileSize + "\tResType:" + (int)resElement.resType + "\tKey:" + resElement.key); } sb.AppendLine(); sb.AppendLine($"VersionFileCRC: {versionFileName}"); sb.AppendLine($"Version: {versionStr}\tFileListRCR:{resListDescFileName}"); StreamWriter sw = new StreamWriter(describePath); sw.Write(sb.ToString()); sw.Flush(); sw.Close(); }
//拷贝资源 public static void CopyRes2Path(List <ResouceElement> resElemList, string path, string suffix) { for (int i = 0; i < resElemList.Count; i++) { ResouceElement tmpElem = resElemList[i]; string tmpTargetPath = $"{path}/{tmpElem.fileHash}{suffix}"; File.Copy(tmpElem.filePath, tmpTargetPath); } }
//构建资源描述 public static List <ResouceElement> GetResouceElements(string path, ResouceElement.EResType resType, string prefix) { List <ResouceElement> tmpElemList = new List <ResouceElement>(); List <string> tmpFiles = GetFiles(path, "*.*", new string[] { ".manifest" }); for (int i = 0; i < tmpFiles.Count; i++) { ResouceElement tmpElem = new ResouceElement(); tmpElem.filePath = tmpFiles[i].Replace("\\", "/"); tmpElem.key = prefix + tmpElem.filePath.Replace(path, ""); tmpElem.keyHash = Crc.Crc32(tmpElem.key); tmpElem.fileHash = Crc.Crc32(tmpElem.key + ComputeMD5(tmpElem.filePath)); tmpElem.resType = resType; var tmpFileInfo = new FileInfo(tmpFiles[i]); tmpElem.fileSize = (ushort)(tmpFileInfo.Length / 1024f); tmpElem.fileSize = tmpElem.fileSize > 0 ? tmpElem.fileSize : (ushort)1; tmpElemList.Add(tmpElem); } return(tmpElemList); }
void DoPublish() { if (string.IsNullOrEmpty(mLastPatchPath) || !Directory.Exists(mLastPatchPath) || string.IsNullOrEmpty(mCurrPatchPath) || !Directory.Exists(mCurrPatchPath)) { ShowNotification(new GUIContent("错误:路径为空或不存在此路径")); return; } string tmpRuntimeResFullPath = Path.GetFullPath(PathHelper.RUN_TIME_RES_PATH).Replace("\\", "/"); string tmpBundlePath = $"{tmpRuntimeResFullPath}/{string.Format(PathHelper.BUNDLE_FOLDER, mPlatform)}/"; //源资源bundle路径 string tmpTblFolder = PathHelper.GetBytesFileFoldNameByType(PathHelper.EBytesFileType.Table); //源资源tbl文件夹 string tmpSkillActionFolder = PathHelper.GetBytesFileFoldNameByType(PathHelper.EBytesFileType.Action); //源资源SkillAction文件夹 string tmpPatchPath = mCurrPatchPath + mPlatform + "/Patch_" + System.DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss"); //当前补丁存放路径 if (!Directory.Exists(tmpPatchPath)) { Directory.CreateDirectory(tmpPatchPath); } //把bundle文件对应平台文件copy一份到StreamingAssets List <ResouceElement> tmpStreamingAssetsList = PublishUtility.GetResouceElements(tmpBundlePath, ResouceElement.EResType.AssetBundle, string.Empty); //处理tbl List <ResouceElement> tmpTblList = PublishUtility.GetResouceElements($"{tmpRuntimeResFullPath}/{tmpTblFolder}", ResouceElement.EResType.Bytes, tmpTblFolder); //游戏动作 List <ResouceElement> tmpActionList = PublishUtility.GetResouceElements($"{tmpRuntimeResFullPath}/{tmpSkillActionFolder}", ResouceElement.EResType.Bytes, tmpSkillActionFolder); List <ResouceElement> tmpAllResList = new List <ResouceElement>(); tmpAllResList.AddRange(tmpStreamingAssetsList); tmpAllResList.AddRange(tmpTblList); tmpAllResList.AddRange(tmpActionList); uint tmpVersionFileCrc = FileHelper.ResVersionFileCRC; uint tmpResDescFileCrc = 0; PublishUtility.GenResDescAndVersionFile(tmpPatchPath, tmpAllResList, FileHelper.RES_DESC_FILE, out tmpResDescFileCrc, tmpVersionFileCrc, mMajor, mMinor, mSvn); //差异比较 string tmpPath = $"{mLastPatchPath}/{FileHelper.ResVersionFileCRC}"; if (!File.Exists(tmpPath)) { ShowNotification(new GUIContent($"错误:找不到最后一次补丁的版本描述文件 {FileHelper.ResVersionFileCRC}")); return; } byte[] tmpData = FileHelper.ReadFile(tmpPath); VersionData tmpLastVersionData = VersionData.LoadVersionData(tmpData); tmpPath = $"{mLastPatchPath}/{tmpLastVersionData.ResDescCrc}"; if (!File.Exists(tmpPath)) { ShowNotification(new GUIContent($"错误:找不到最后一次补丁的资源描述文件 {tmpLastVersionData.ResDescCrc}")); return; } tmpData = FileHelper.ReadFile(tmpPath); Dictionary <uint, long> tmpLastResDescInfo = ResourcesSystem.LoadResDescInfo(tmpData); List <ResouceElement> tmpDiffList = new List <ResouceElement>(); for (int i = 0, max = tmpAllResList.Count; i < max; ++i) { ResouceElement tmpResElem = tmpAllResList[i]; long tmpResFlag = 0; if (tmpLastResDescInfo.TryGetValue(tmpResElem.keyHash, out tmpResFlag)) { var tmpResInfo = ResourcesSystem.ResFlag2Info(tmpResFlag); if (tmpResElem.fileHash == tmpResInfo.FileHash) { continue; } } tmpDiffList.Add(tmpResElem); } PublishUtility.GenAssistDescFile(tmpDiffList, tmpPatchPath, $"{mMajor}.{mMinor}.{mSvn}", tmpVersionFileCrc.ToString(), tmpResDescFileCrc.ToString()); PublishUtility.CopyRes2Path(tmpDiffList, tmpPatchPath, string.Empty); ShowNotification(new GUIContent($"打包补丁成功 差异化文件 {tmpDiffList.Count} 个")); }