/// <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); }
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); }