/// <summary>
        /// 序列化可更新模式版本资源列表(版本 0)回调函数。
        /// </summary>
        /// <param name="stream">目标流。</param>
        /// <param name="versionList">要序列化的可更新模式版本资源列表(版本 0)。</param>
        /// <returns>是否序列化可更新模式版本资源列表(版本 0)成功。</returns>
        public static bool UpdatableVersionListSerializeCallback_V0(Stream stream, UpdatableVersionList versionList)
        {
            if (!versionList.IsValid)
            {
                return(false);
            }

            Utility.Random.GetRandomBytes(s_CachedHashBytes);
            using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8))
            {
                binaryWriter.Write(s_CachedHashBytes);
                binaryWriter.WriteEncryptedString(versionList.ApplicableGameVersion, s_CachedHashBytes);
                binaryWriter.Write(versionList.InternalResourceVersion);
                UpdatableVersionList.Asset[] assets = versionList.GetAssets();
                binaryWriter.Write(assets.Length);
                UpdatableVersionList.Resource[] resources = versionList.GetResources();
                binaryWriter.Write(resources.Length);
                foreach (UpdatableVersionList.Resource resource in resources)
                {
                    binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes);
                    binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes);
                    binaryWriter.Write(resource.LoadType);
                    binaryWriter.Write(resource.Length);
                    binaryWriter.Write(resource.HashCode);
                    binaryWriter.Write(resource.ZipLength);
                    binaryWriter.Write(resource.ZipHashCode);
                    int[] assetIndexes = resource.GetAssetIndexes();
                    binaryWriter.Write(assetIndexes.Length);
                    byte[] hashBytes = new byte[CachedHashBytesLength];
                    foreach (int assetIndex in assetIndexes)
                    {
                        Utility.Converter.GetBytes(resource.HashCode, hashBytes);
                        UpdatableVersionList.Asset asset = assets[assetIndex];
                        binaryWriter.WriteEncryptedString(asset.Name, hashBytes);
                        int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes();
                        binaryWriter.Write(dependencyAssetIndexes.Length);
                        foreach (int dependencyAssetIndex in dependencyAssetIndexes)
                        {
                            binaryWriter.WriteEncryptedString(assets[dependencyAssetIndex].Name, hashBytes);
                        }
                    }
                }

                UpdatableVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups();
                binaryWriter.Write(resourceGroups.Length);
                foreach (UpdatableVersionList.ResourceGroup resourceGroup in resourceGroups)
                {
                    binaryWriter.WriteEncryptedString(resourceGroup.Name, s_CachedHashBytes);
                    int[] resourceIndexes = resourceGroup.GetResourceIndexes();
                    binaryWriter.Write(resourceIndexes.Length);
                    foreach (ushort resourceIndex in resourceIndexes)
                    {
                        binaryWriter.Write(resourceIndex);
                    }
                }
            }

            Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength);
            return(true);
        }
        public bool BuildResourcePack(string sourceVersion, string targetVersion)
        {
            if (!Directory.Exists(OutputPath))
            {
                Directory.CreateDirectory(OutputPath);
            }

            string defaultResourcePackName = Path.Combine(OutputPath, Utility.Text.Format("{0}.{1}", DefaultResourcePackName, DefaultExtension));

            if (File.Exists(defaultResourcePackName))
            {
                File.Delete(defaultResourcePackName);
            }

            UpdatableVersionList sourceUpdatableVersionList = default(UpdatableVersionList);

            if (sourceVersion != null)
            {
                DirectoryInfo sourceDirectoryInfo    = new DirectoryInfo(Path.Combine(Path.Combine(SourcePath, sourceVersion), Platform.ToString()));
                FileInfo[]    sourceVersionListFiles = sourceDirectoryInfo.GetFiles("GameFrameworkVersion.*.dat", SearchOption.TopDirectoryOnly);
                byte[]        sourceVersionListBytes = File.ReadAllBytes(sourceVersionListFiles[0].FullName);
                sourceVersionListBytes = Utility.Zip.Decompress(sourceVersionListBytes);
                using (Stream stream = new MemoryStream(sourceVersionListBytes))
                {
                    sourceUpdatableVersionList = m_UpdatableVersionListSerializer.Deserialize(stream);
                }
            }

            UpdatableVersionList targetUpdatableVersionList = default(UpdatableVersionList);
            DirectoryInfo        targetDirectoryInfo        = new DirectoryInfo(Path.Combine(Path.Combine(SourcePath, targetVersion), Platform.ToString()));

            FileInfo[] targetVersionListFiles = targetDirectoryInfo.GetFiles("GameFrameworkVersion.*.dat", SearchOption.TopDirectoryOnly);
            byte[]     targetVersionListBytes = File.ReadAllBytes(targetVersionListFiles[0].FullName);
            targetVersionListBytes = Utility.Zip.Decompress(targetVersionListBytes);
            using (Stream stream = new MemoryStream(targetVersionListBytes))
            {
                targetUpdatableVersionList = m_UpdatableVersionListSerializer.Deserialize(stream);
            }

            List <ResourcePackVersionList.Resource> resources = new List <ResourcePackVersionList.Resource>();

            UpdatableVersionList.Resource[] sourceResources = sourceUpdatableVersionList.IsValid ? sourceUpdatableVersionList.GetResources() : EmptyResourceArray;
            UpdatableVersionList.Resource[] targetResources = targetUpdatableVersionList.GetResources();
            long offset = 0L;

            foreach (UpdatableVersionList.Resource targetResource in targetResources)
            {
                bool ready = false;
                foreach (UpdatableVersionList.Resource sourceResource in sourceResources)
                {
                    if (sourceResource.Name != targetResource.Name || sourceResource.Variant != targetResource.Variant || sourceResource.Extension != targetResource.Extension)
                    {
                        continue;
                    }

                    if (sourceResource.LoadType == targetResource.LoadType && sourceResource.Length == targetResource.Length && sourceResource.HashCode == targetResource.HashCode)
                    {
                        ready = true;
                    }

                    break;
                }

                if (!ready)
                {
                    resources.Add(new ResourcePackVersionList.Resource(targetResource.Name, targetResource.Variant, targetResource.Extension, targetResource.LoadType, offset, targetResource.Length, targetResource.HashCode, targetResource.ZipLength, targetResource.ZipHashCode));
                    offset += targetResource.ZipLength;
                }
            }

            ResourcePackVersionList.Resource[] resourceArray = resources.ToArray();
            using (FileStream fileStream = new FileStream(defaultResourcePackName, FileMode.Create, FileAccess.Write))
            {
                if (!m_ResourcePackVersionListSerializer.Serialize(fileStream, new ResourcePackVersionList(0, 0L, 0, resourceArray)))
                {
                    return(false);
                }
            }

            int    position            = 0;
            int    hashCode            = 0;
            string targetDirectoryPath = targetDirectoryInfo.FullName;

            using (FileStream fileStream = new FileStream(defaultResourcePackName, FileMode.Open, FileAccess.ReadWrite))
            {
                position            = (int)fileStream.Length;
                fileStream.Position = position;
                foreach (ResourcePackVersionList.Resource resource in resourceArray)
                {
                    string resourcePath = Path.Combine(targetDirectoryPath, GetResourceFullName(resource.Name, resource.Variant, resource.HashCode));
                    if (!File.Exists(resourcePath))
                    {
                        return(false);
                    }

                    byte[] resourceBytes = File.ReadAllBytes(resourcePath);
                    fileStream.Write(resourceBytes, 0, resourceBytes.Length);
                }

                if (fileStream.Position - position != offset)
                {
                    return(false);
                }

                fileStream.Position = position;
                hashCode            = Utility.Verifier.GetCrc32(fileStream);

                fileStream.Position = 0L;
                if (!m_ResourcePackVersionListSerializer.Serialize(fileStream, new ResourcePackVersionList(position, offset, hashCode, resourceArray)))
                {
                    return(false);
                }
            }

            string targetResourcePackName = Path.Combine(OutputPath, Utility.Text.Format("{0}-{1}-{2}.{3:x8}.{4}", DefaultResourcePackName, sourceVersion ?? GetNoneVersion(targetVersion), targetVersion, hashCode, DefaultExtension));

            if (File.Exists(targetResourcePackName))
            {
                File.Delete(targetResourcePackName);
            }

            File.Move(defaultResourcePackName, targetResourcePackName);
            return(true);
        }
        /// <summary>
        /// 序列化可更新模式版本资源列表(版本 1)回调函数。
        /// </summary>
        /// <param name="binaryWriter">目标流。</param>
        /// <param name="versionList">要序列化的可更新模式版本资源列表(版本 1)。</param>
        /// <returns>序列化可更新模式版本资源列表(版本 1)是否成功。</returns>
        public static bool SerializeUpdatableVersionListCallback_V1(BinaryWriter binaryWriter, UpdatableVersionList versionList)
        {
            if (!versionList.IsValid)
            {
                return(false);
            }

            Utility.Random.GetRandomBytes(s_CachedHashBytes);
            binaryWriter.Write(s_CachedHashBytes);
            binaryWriter.WriteEncryptedString(versionList.ApplicableGameVersion, s_CachedHashBytes);
            binaryWriter.Write7BitEncodedInt32(versionList.InternalResourceVersion);
            UpdatableVersionList.Asset[] assets = versionList.GetAssets();
            binaryWriter.Write7BitEncodedInt32(assets.Length);
            foreach (UpdatableVersionList.Asset asset in assets)
            {
                binaryWriter.WriteEncryptedString(asset.Name, s_CachedHashBytes);
                int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes();
                binaryWriter.Write7BitEncodedInt32(dependencyAssetIndexes.Length);
                foreach (int dependencyAssetIndex in dependencyAssetIndexes)
                {
                    binaryWriter.Write7BitEncodedInt32(dependencyAssetIndex);
                }
            }

            UpdatableVersionList.Resource[] resources = versionList.GetResources();
            binaryWriter.Write7BitEncodedInt32(resources.Length);
            foreach (UpdatableVersionList.Resource resource in resources)
            {
                binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes);
                binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes);
                binaryWriter.WriteEncryptedString(resource.Extension != DefaultExtension ? resource.Extension : null, s_CachedHashBytes);
                binaryWriter.Write(resource.LoadType);
                binaryWriter.Write7BitEncodedInt32(resource.Length);
                binaryWriter.Write(resource.HashCode);
                binaryWriter.Write7BitEncodedInt32(resource.ZipLength);
                binaryWriter.Write(resource.ZipHashCode);
                int[] assetIndexes = resource.GetAssetIndexes();
                binaryWriter.Write7BitEncodedInt32(assetIndexes.Length);
                foreach (int assetIndex in assetIndexes)
                {
                    binaryWriter.Write7BitEncodedInt32(assetIndex);
                }
            }

            UpdatableVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups();
            binaryWriter.Write7BitEncodedInt32(resourceGroups.Length);
            foreach (UpdatableVersionList.ResourceGroup resourceGroup in resourceGroups)
            {
                binaryWriter.WriteEncryptedString(resourceGroup.Name, s_CachedHashBytes);
                int[] resourceIndexes = resourceGroup.GetResourceIndexes();
                binaryWriter.Write7BitEncodedInt32(resourceIndexes.Length);
                foreach (int resourceIndex in resourceIndexes)
                {
                    binaryWriter.Write7BitEncodedInt32(resourceIndex);
                }
            }

            Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength);
            return(true);
        }