/// <summary>
        /// 从文件系统中加载二进制资源。
        /// </summary>
        /// <param name="binaryAssetName">要加载二进制资源的名称。</param>
        /// <returns>存储加载二进制资源的二进制流。</returns>
        public byte[] LoadBinaryFromFileSystem(string binaryAssetName)
        {
            ResourceInfo resourceInfo = GetResourceInfo(binaryAssetName, AssetCategory.Binary);

            if (resourceInfo == null)
            {
                throw new Exception(Utility.Text.Format("Can not load binary '{0}' from file system which is not exist.", binaryAssetName));
            }

            if (!resourceInfo.Ready)
            {
                throw new Exception(Utility.Text.Format("Can not load binary '{0}' from file system which is not ready.", binaryAssetName));
            }

            if (!resourceInfo.IsLoadFromBinary)
            {
                throw new Exception(Utility.Text.Format("Can not load binary '{0}' from file system which is not a binary asset.", binaryAssetName));
            }

            if (!resourceInfo.UseFileSystem)
            {
                throw new Exception(Utility.Text.Format("Can not load binary '{0}' from file system which is not use file system.", binaryAssetName));
            }

            IFileSystem fileSystem = m_ResourceComponent.GetFileSystem(resourceInfo.FileSystemName, resourceInfo.StorageInReadOnly);

            byte[] bytes = fileSystem.ReadFile(resourceInfo.ResourceName.FullName);
            if (bytes == null)
            {
                return(null);
            }

            if (resourceInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || resourceInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt)
            {
                DecryptResourceCallback decryptResourceCallback = m_ResourceComponent.DecryptResourceCallback ?? DefaultDecryptResourceCallback;
                decryptResourceCallback(bytes, 0, bytes.Length, resourceInfo.ResourceName.Name, resourceInfo.ResourceName.Variant, resourceInfo.ResourceName.Extension, resourceInfo.StorageInReadOnly, resourceInfo.FileSystemName, (byte)resourceInfo.LoadType, resourceInfo.Length, resourceInfo.HashCode);
            }

            return(bytes);
        }
Пример #2
0
        private bool ApplyResource(ApplyInfo applyInfo)
        {
            long position = m_ApplyingResourcePackStream.Position;

            try
            {
                bool zip = applyInfo.Length != applyInfo.ZipLength || applyInfo.HashCode != applyInfo.ZipHashCode;

                int    bytesRead = 0;
                int    bytesLeft = applyInfo.ZipLength;
                string directory = Path.GetDirectoryName(applyInfo.ResourcePath);
                if (!Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }

                m_ApplyingResourcePackStream.Position += applyInfo.Offset;
                using (FileStream fileStream = new FileStream(applyInfo.ResourcePath, FileMode.Create, FileAccess.ReadWrite))
                {
                    while ((bytesRead = m_ApplyingResourcePackStream.Read(m_CachedBytes, 0, bytesLeft < CachedBytesLength ? bytesLeft : CachedBytesLength)) > 0)
                    {
                        bytesLeft -= bytesRead;
                        fileStream.Write(m_CachedBytes, 0, bytesRead);
                    }

                    if (zip)
                    {
                        fileStream.Position = 0L;
                        int hashCode = Utility.Verifier.GetCrc32(fileStream);
                        if (hashCode != applyInfo.ZipHashCode)
                        {
                            string errorMessage = Utility.Text.Format("Resource zip hash code error, need '{0}', applied '{1}'.", applyInfo.ZipHashCode.ToString(), hashCode.ToString());

                            m_ResourceComponent.OnResourceApplyFailure(applyInfo.ResourceName, m_ApplyingResourcePackPath, errorMessage);

                            return(false);
                        }

                        if (m_ResourceComponent.DecompressCachedStream == null)
                        {
                            m_ResourceComponent.DecompressCachedStream = new MemoryStream();
                        }

                        fileStream.Position = 0L;
                        m_ResourceComponent.DecompressCachedStream.Position = 0L;
                        m_ResourceComponent.DecompressCachedStream.SetLength(0L);
                        if (!Utility.Zip.Decompress(fileStream, m_ResourceComponent.DecompressCachedStream))
                        {
                            string errorMessage = Utility.Text.Format("Unable to decompress resource '{0}'.", applyInfo.ResourcePath);
                            m_ResourceComponent.OnResourceApplyFailure(applyInfo.ResourceName, m_ApplyingResourcePackPath, errorMessage);

                            return(false);
                        }

                        fileStream.Position = 0L;
                        fileStream.SetLength(0L);
                        fileStream.Write(m_ResourceComponent.DecompressCachedStream.GetBuffer(), 0, (int)m_ResourceComponent.DecompressCachedStream.Length);
                    }
                    else
                    {
                        int hashCode = 0;
                        fileStream.Position = 0L;
                        if (applyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || applyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt ||
                            applyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || applyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt)
                        {
                            Utility.Converter.GetBytes(applyInfo.HashCode, m_CachedHashBytes);
                            if (applyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || applyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt)
                            {
                                hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, Utility.Encryption.QuickEncryptLength);
                            }
                            else if (applyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt || applyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt)
                            {
                                hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, applyInfo.Length);
                            }

                            Array.Clear(m_CachedHashBytes, 0, CachedHashBytesLength);
                        }
                        else
                        {
                            hashCode = Utility.Verifier.GetCrc32(fileStream);
                        }

                        if (hashCode != applyInfo.HashCode)
                        {
                            string errorMessage = Utility.Text.Format("Resource hash code error, need '{0}', applied '{1}'.", applyInfo.HashCode.ToString(), hashCode.ToString());
                            m_ResourceComponent.OnResourceApplyFailure(applyInfo.ResourceName, m_ApplyingResourcePackPath, errorMessage);

                            return(false);
                        }
                    }
                }

                if (applyInfo.UseFileSystem)
                {
                    IFileSystem fileSystem = m_ResourceComponent.GetFileSystem(applyInfo.FileSystemName, false);
                    bool        retVal     = fileSystem.WriteFile(applyInfo.ResourceName.FullName, applyInfo.ResourcePath);
                    if (File.Exists(applyInfo.ResourcePath))
                    {
                        File.Delete(applyInfo.ResourcePath);
                    }

                    return(retVal);
                }

                m_UpdateCandidateInfo.Remove(applyInfo.ResourceName);
                m_ResourceComponent.ResourceInfoDic[applyInfo.ResourceName.AssetCategory][applyInfo.ResourceName].MarkReady();
                m_ResourceComponent.ReadWriteResourceInfoDic[applyInfo.ResourceName.AssetCategory].Add(applyInfo.ResourceName, new ReadWriteResourceInfo(applyInfo.FileSystemName, applyInfo.LoadType, applyInfo.Length, applyInfo.HashCode));

                m_ResourceComponent.OnResourceApplySuccess(applyInfo.ResourceName, applyInfo.ResourcePath, m_ApplyingResourcePackPath, applyInfo.Length, applyInfo.ZipLength);

                string downloadingResource = Utility.Text.Format("{0}.download", applyInfo.ResourcePath);
                if (File.Exists(downloadingResource))
                {
                    File.Delete(downloadingResource);
                }

                m_CurrentGenerateReadWriteVersionListLength += applyInfo.ZipLength;
                if (m_ApplyWaitingInfo.Count <= 0 || m_CurrentGenerateReadWriteVersionListLength >= m_GenerateReadWriteVersionListLength)
                {
                    m_CurrentGenerateReadWriteVersionListLength = 0;
                    GenerateReadWriteVersionList();
                    return(true);
                }

                return(false);
            }
            catch (Exception exception)
            {
                m_ResourceComponent.OnResourceApplyFailure(applyInfo.ResourceName, m_ApplyingResourcePackPath, exception.ToString());

                return(false);
            }
            finally
            {
                m_ApplyingResourcePackStream.Position = position;
            }
        }
        private void RefreshReadWriteCheckInfoStatus()
        {
            if (!m_UpdatableVersionListReady || !m_ReadWriteVersionListReady)
            {
                return;
            }

            int  movedCount           = 0;
            int  removedCount         = 0;
            int  updateCount          = 0;
            long updateTotalLength    = 0L;
            long updateTotalZipLength = 0L;

            foreach (KeyValuePair <ResourceName, CheckInfo> checkInfo in m_CheckInfos)
            {
                CheckInfo ci = checkInfo.Value;
                ci.RefreshStatus(m_CurrentVariant, m_IgnoreOtherVariant);
                if (ci.Status == CheckStatus.StorageInReadOnly)
                {
                    if (m_ResourceComponent.ResourceInfoDic[ci.ResourceName.AssetCategory].ContainsKey(ci.ResourceName))
                    {
                        m_ResourceComponent.ResourceInfoDic[ci.ResourceName.AssetCategory].Remove(ci.ResourceName);
                    }

                    m_ResourceComponent.ResourceInfoDic[ci.ResourceName.AssetCategory].Add(ci.ResourceName, new ResourceInfo(ci.ResourceName, ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode, true, true));
                }
                else if (ci.Status == CheckStatus.StorageInReadWrite)
                {
                    if (ci.NeedMoveToDisk || ci.NeedMoveToFileSystem)
                    {
                        movedCount++;
                        string resourceFullName = ci.ResourceName.FullName;
                        string resourcePath     = Utility.Path.GetRegularPath(Path.Combine(m_ResourceComponent.ReadWritePath, resourceFullName));
                        if (ci.NeedMoveToDisk)
                        {
                            IFileSystem fileSystem = m_ResourceComponent.GetFileSystem(ci.ReadWriteFileSystemName, false);
                            if (!fileSystem.SaveAsFile(resourceFullName, resourcePath))
                            {
                                throw new Exception(Utility.Text.Format("Save as file '{0}' to '{1}' from file system '{2}' error.", resourceFullName, fileSystem.FullPath));
                            }

                            fileSystem.DeleteFile(resourceFullName);
                        }

                        if (ci.NeedMoveToFileSystem)
                        {
                            IFileSystem fileSystem = m_ResourceComponent.GetFileSystem(ci.FileSystemName, false);
                            if (!fileSystem.WriteFile(resourceFullName, resourcePath))
                            {
                                throw new Exception(Utility.Text.Format("Write resource '{0}' to file system '{1}' error.", resourceFullName, fileSystem.FullPath));
                            }

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

                    if (m_ResourceComponent.ResourceInfoDic[ci.ResourceName.AssetCategory].ContainsKey(ci.ResourceName))
                    {
                        m_ResourceComponent.ResourceInfoDic[ci.ResourceName.AssetCategory].Remove(ci.ResourceName);
                    }
                    m_ResourceComponent.ResourceInfoDic[ci.ResourceName.AssetCategory].Add(ci.ResourceName, new ResourceInfo(ci.ResourceName, ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode, false, true));

                    if (m_ResourceComponent.ReadWriteResourceInfoDic[ci.ResourceName.AssetCategory].ContainsKey(ci.ResourceName))
                    {
                        m_ResourceComponent.ReadWriteResourceInfoDic[ci.ResourceName.AssetCategory].Remove(ci.ResourceName);
                    }

                    m_ResourceComponent.ReadWriteResourceInfoDic[ci.ResourceName.AssetCategory].Add(ci.ResourceName, new ReadWriteResourceInfo(ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode));
                }
                else if (ci.Status == CheckStatus.Update)
                {
                    if (m_ResourceComponent.ResourceInfoDic[ci.ResourceName.AssetCategory].ContainsKey(ci.ResourceName))
                    {
                        m_ResourceComponent.ResourceInfoDic[ci.ResourceName.AssetCategory].Remove(ci.ResourceName);
                    }

                    m_ResourceComponent.ResourceInfoDic[ci.ResourceName.AssetCategory].Add(ci.ResourceName, new ResourceInfo(ci.ResourceName, ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode, false, false));
                    updateCount++;
                    updateTotalLength    += ci.Length;
                    updateTotalZipLength += ci.ZipLength;
                    m_ResourceComponent.OnCheckerResourceNeedUpdate(ci.ResourceName, ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode, ci.ZipLength, ci.ZipHashCode);
                }
                else if (ci.Status == CheckStatus.Unavailable || ci.Status == CheckStatus.Disuse)
                {
                    // Do nothing.
                }
                else
                {
                    throw new Exception(Utility.Text.Format("Check resources '{0}' error with unknown status.", ci.ResourceName.FullName));
                }

                if (ci.NeedRemove)
                {
                    removedCount++;
                    if (ci.ReadWriteUseFileSystem)
                    {
                        IFileSystem fileSystem = m_ResourceComponent.GetFileSystem(ci.ReadWriteFileSystemName, false);
                        fileSystem.DeleteFile(ci.ResourceName.FullName);
                    }
                    else
                    {
                        string resourcePath = Utility.Path.GetRegularPath(Path.Combine(m_ResourceComponent.ReadWritePath, ci.ResourceName.FullName));
                        if (File.Exists(resourcePath))
                        {
                            File.Delete(resourcePath);
                        }
                    }
                }
            }

            if (movedCount > 0 || removedCount > 0)
            {
                RemoveEmptyFileSystems();
                Utility.Path.RemoveEmptyDirectory(m_ResourceComponent.ReadWritePath);
            }

            m_ResourceComponent.OnCheckerReadWriteResourceCheckComplete(movedCount, removedCount, updateCount, updateTotalLength, updateTotalZipLength);
        }