/// <summary> /// APPENDS found crcInfo's to the specified list. /// </summary> public static void ParseCRCInformation(string fileContents, List <AssetBundleCRCInfo> infos) { Debug.Log("ParseCRCInformation:\n" + fileContents); string[] assetBundleLines = fileContents.Split('\n'); foreach (string assetBundle in assetBundleLines) { string[] infoParts = assetBundle.Split('|'); if (infoParts.Length == 3) { AssetBundleCRCInfo newAssetBundleCRCInfo = new AssetBundleCRCInfo(); newAssetBundleCRCInfo.m_name = infoParts[0]; newAssetBundleCRCInfo.m_CRC = UInt32.Parse(infoParts[1]); newAssetBundleCRCInfo.m_fileSizeBytes = Int32.Parse(infoParts[2]); int index = infos.FindIndex(x => x.m_name == infoParts[0]); if (index >= 0) { infos[index] = newAssetBundleCRCInfo; } else { infos.Add(newAssetBundleCRCInfo); } } // Else file is done. } }
public void TryGetBundleCRCInformationFromLocalFiles() { Debug.Log("AssetBundleInformationManager: GetBundleCRCInformationFromLocalFiles"); string crcFile = AssetBundleManager.Instance.CurrentVersionDownloadLocation + "/assetbundles.crc"; string tmpCrcFile = AssetBundleManager.Instance.CurrentVersionDownloadLocation + "/assetbundles.crc_tmp"; bool shouldLoad = false; if (File.Exists(crcFile)) { //cool, we have prior knowledge of assetbundles. //we need to check all files vs the crcs and filelengths shouldLoad = true; } else if (File.Exists(tmpCrcFile)) { try { File.Move(tmpCrcFile, crcFile); shouldLoad = true; } catch (Exception e) { Debug.LogException(e); Debug.LogError("Exception while moving tmpCrcFile to crc file location. We assume no CRC info. " + e); } } if (shouldLoad) { Debug.Log("AssetBundleInformationManager: Loading local CRC Info"); string assetBundleCRCContents = File.ReadAllText(crcFile); try { ParseCRCInformation(assetBundleCRCContents, m_localAssetBundleCRCInformation); } catch (Exception e) { Debug.LogError("Failed to parse assetbundle local CRCInfo: " + e.ToString()); } } else { Debug.Log("AssetBundleInformationManager: No Local CRC Info"); } HasLoadedLocalCRCInfo = true; // Even if we don't have a local file by this point, we might have the includedInBuild one. // So lets initialize bundles anyway. // We know for sure we don't have server info here, so null is passed. for (int i = 0; i < m_localAssetBundleCRCInformation.Count; i++) { AssetBundleCRCInfo localCrc = m_localAssetBundleCRCInformation[i]; CheckLocalAssetBundle(localCrc, i, null); } }
public void CheckLocalAssetBundle(string assetBundleName) { var serverCrc = TryGetCrcInfo(assetBundleName, m_serverAssetBundleCRCInformation); for (int i = 0; i < m_localAssetBundleCRCInformation.Count; i++) { AssetBundleCRCInfo localCrc = m_localAssetBundleCRCInformation[i]; if (localCrc.m_name == assetBundleName) { CheckLocalAssetBundle(localCrc, i, serverCrc); break; } } }
public void CheckLocalAssetBundle(AssetBundleCRCInfo localCrc, int localCrcIndex, AssetBundleCRCInfo?serverCrc) { bool isInGame = AssetBundleManager.Instance.IsInGame; string fullFileName = AssetBundleManager.Instance.CurrentVersionDownloadLocation + "/" + localCrc.m_name; string tempFileName = fullFileName + ".incomplete"; FileInfo fullAssetFileInfo = new FileInfo(fullFileName); if (fullAssetFileInfo.Exists) { //check filesize first if (fullAssetFileInfo.Length == localCrc.m_fileSizeBytes) { if (isInGame) { //the file is the correct size, but CRC is slow, so we'll delay the CRC //don't do this now! return; } Debug.Log("AssetBundleInformationManager::CheckLocalAssetBundle : Completed file: " + localCrc.m_name); //sweet, same length, it's complete, now to check CRC uint crc = AssetBundleUtils.GenerateCRC32FromFile(fullFileName); if (crc == localCrc.m_CRC) { //it's the right file, untampered. //it's loadable. Debug.Log("AssetBundleInformationManager::CheckLocalAssetBundle : Local Asset Bundle " + localCrc.m_name + " is Loadable. SUCCESS"); AssetBundleLocalFileChecked.Invoke(this, new AssetBundleLocalFileCheckedEventArgs(localCrc.m_name, true, localCrc.m_fileSizeBytes, localCrc.m_fileSizeBytes)); AssetBundleStateChanged.Invoke(this, new AssetBundleStateChangedEventArgs(localCrc.m_name, AssetBundleDownloadState.Loadable, null)); AssetBundleRevokePermision.Invoke(this, new AssetBundleEventArgs(localCrc.m_name)); } else { //tampered? or damaged? Delete it. Debug.LogError("AssetBundleInformationManager::CheckLocalAssetBundle : Local Asset Bundle " + localCrc.m_name + " failed the CRC check. Deleting."); AssetBundleDownloadCorruptedOrBroken.Invoke(this, new AssetBundleDeleteAssetBundleFileEventArgs(localCrc.m_name, "FAILED_LOCAL_CRC_CHECK")); } } else { //it's not an incomplete dl, and it's either too big or too small, not sure how that could happen, wipe it and force a redownload //no point crcing as the bytes are definitely different. Debug.LogError("AssetBundleInformationManager: Local Asset Bundle " + localCrc.m_name + " failed the LENGTH check. How!? Deleting."); AssetBundleDownloadCorruptedOrBroken.Invoke(this, new AssetBundleDeleteAssetBundleFileEventArgs(localCrc.m_name, "FAILED_LOCAL_LENGTH_CHECK")); } } FileInfo tempAssetFileInfo = new FileInfo(tempFileName); if (tempAssetFileInfo.Exists) { Debug.Log("AssetBundleInformationManager::CheckLocalAssetBundle : Temporary File: " + localCrc.m_name); if (isInGame) { if (serverCrc.HasValue && tempAssetFileInfo.Length < serverCrc.Value.m_fileSizeBytes) { // We don't know what this file is, but we'll assume it's a partially downloaded NEW asset bundle and put it back in the queue Debug.Log("AssetBundleInformationManager::CheckLocalAssetBundle : Temporary Asset Bundle " + localCrc.m_name + " failed CRC. It's small enough to feasibly be a partially-downloaded new asset bundle. Download continuing."); AssetBundleLocalFileChecked.Invoke(this, new AssetBundleLocalFileCheckedEventArgs(serverCrc.Value.m_name, false, tempAssetFileInfo.Length, serverCrc.Value.m_fileSizeBytes)); AssetBundleStateChanged.Invoke(this, new AssetBundleStateChangedEventArgs(serverCrc.Value.m_name, AssetBundleDownloadState.Queued, null)); } return; } else { uint crc = AssetBundleUtils.GenerateCRC32FromFile(tempFileName); bool crcMatchesLocal = localCrc.m_CRC == crc; bool crcMatchesServer = serverCrc.HasValue && serverCrc.Value.m_CRC == crc; if (crcMatchesLocal || crcMatchesServer) { // Crc matches either! if (!crcMatchesLocal) { // The recently completed ".incomplete" file will now be moved to the final destination (oooh). // Thus, the local CRC info needs to match the new crc. m_localAssetBundleCRCInformation[localCrcIndex] = serverCrc.Value; } // The file is loadable, so move it to the right file name. Yay! Debug.Log("AssetBundleInformationManager::CheckLocalAssetBundle : Temporary Asset Bundle " + localCrc.m_name + " matched a CRC check and is now loadable. SUCCESS." + "\nServer: " + crcMatchesServer + ", Local: " + crcMatchesLocal); AssetBundleFinishedAndRequiresMoving.Invoke(this, new AssetBundleEventArgs(localCrc.m_name)); } else if (serverCrc.HasValue && tempAssetFileInfo.Length < serverCrc.Value.m_fileSizeBytes) { // We don't know what this file is, but we'll assume it's a partially downloaded NEW asset bundle. Debug.Log("AssetBundleInformationManager::CheckLocalAssetBundle : Temporary Asset Bundle " + localCrc.m_name + " failed CRC. It's small enough to feasibly be a partially-downloaded new asset bundle. Download continuing."); AssetBundleLocalFileChecked.Invoke(this, new AssetBundleLocalFileCheckedEventArgs(serverCrc.Value.m_name, false, tempAssetFileInfo.Length, serverCrc.Value.m_fileSizeBytes)); AssetBundleStateChanged.Invoke(this, new AssetBundleStateChangedEventArgs(serverCrc.Value.m_name, AssetBundleDownloadState.Queued, null)); } else if (HasLoadedServerCRCInfo) { // It failed all CRC AND we have got all server CRC's. Thus, this file must be corrupted. Debug.LogError("AssetBundleInformationManager::CheckLocalAssetBundle : Local Asset Bundle " + localCrc.m_name + " does not match any CRC, and we have all server CRC's. Assumed corrupted."); AssetBundleDownloadCorruptedOrBroken.Invoke(this, new AssetBundleDeleteAssetBundleFileEventArgs(localCrc.m_name, "FAILED_SERVER_CRC_CHECK")); } else { // We don't know if this is a new version, so no checks are worth doing on this until we have server info Debug.Log("AssetBundleInformationManager::CheckLocalAssetBundle : Local Asset Bundle " + localCrc.m_name + " does not match local CRC and we do not currently have the server CRC's. " + "It's probably a new bundle in a server CRC that we haven't downloaded for this play session yet. We'll queue it for download, pending the server CRC's."); AssetBundleLocalFileChecked.Invoke(this, new AssetBundleLocalFileCheckedEventArgs(localCrc.m_name, false, tempAssetFileInfo.Length, localCrc.m_fileSizeBytes)); AssetBundleStateChanged.Invoke(this, new AssetBundleStateChangedEventArgs(localCrc.m_name, AssetBundleDownloadState.WaitingManualPermission, null)); } } } // CRC checking complete. Phew. tempAssetFileInfo.Refresh(); fullAssetFileInfo.Refresh(); if (!tempAssetFileInfo.Exists && !fullAssetFileInfo.Exists) { // No file left after CRC checks, so the only thing to do is begin downloading afresh. AssetBundleLocalFileChecked.Invoke(this, new AssetBundleLocalFileCheckedEventArgs(localCrc.m_name, false, 0, localCrc.m_fileSizeBytes)); AssetBundleStateChanged.Invoke(this, new AssetBundleStateChangedEventArgs(localCrc.m_name, AssetBundleDownloadState.WaitingManualPermission, null)); } }