From 3f518ec3214ab5963072b194facc45ce51272fd6 Mon Sep 17 00:00:00 2001
From: hevinci <hevinci@hotmail.com>
Date: Tue, 6 Sep 2022 18:19:50 +0800
Subject: [PATCH] Update PatchSystem
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

增加清理缓存资源的异步操作类
---
 .../OperationSystem/OperationSystem.cs        |  13 +-
 .../ClearUnusedCacheFilesOperation.cs         | 111 ++++++++++++++++++
 .../ClearUnusedCacheFilesOperation.cs.meta    |  11 ++
 .../PatchSystem/PlayMode/HostPlayModeImpl.cs  |  16 +--
 Assets/YooAsset/Runtime/YooAssets.cs          |  29 ++++-
 5 files changed, 167 insertions(+), 13 deletions(-)
 create mode 100644 Assets/YooAsset/Runtime/PatchSystem/Operations/ClearUnusedCacheFilesOperation.cs
 create mode 100644 Assets/YooAsset/Runtime/PatchSystem/Operations/ClearUnusedCacheFilesOperation.cs.meta

diff --git a/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs b/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs
index cf05a69a..ac39ec5c 100644
--- a/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs
+++ b/Assets/YooAsset/Runtime/OperationSystem/OperationSystem.cs
@@ -13,6 +13,17 @@ namespace YooAsset
 		private static long _maxTimeSlice;
 		private static long _frameTime;
 
+		/// <summary>
+		/// 处理器是否繁忙
+		/// </summary>
+		public static bool IsBusy
+		{
+			get
+			{
+				return _watch.ElapsedMilliseconds - _frameTime >= _maxTimeSlice;
+			}
+		}
+
 
 		/// <summary>
 		/// 初始化异步操作系统
@@ -32,7 +43,7 @@ namespace YooAsset
 
 			for (int i = _operations.Count - 1; i >= 0; i--)
 			{
-				if (_watch.ElapsedMilliseconds - _frameTime >= _maxTimeSlice)
+				if (IsBusy)
 					return;
 
 				var operation = _operations[i];
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Operations/ClearUnusedCacheFilesOperation.cs b/Assets/YooAsset/Runtime/PatchSystem/Operations/ClearUnusedCacheFilesOperation.cs
new file mode 100644
index 00000000..cebf6a71
--- /dev/null
+++ b/Assets/YooAsset/Runtime/PatchSystem/Operations/ClearUnusedCacheFilesOperation.cs
@@ -0,0 +1,111 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using UnityEngine;
+
+namespace YooAsset
+{
+	/// <summary>
+	/// 清理未使用的缓存资源操作类
+	/// </summary>
+	public abstract class ClearUnusedCacheFilesOperation : AsyncOperationBase
+	{
+	}
+
+	/// <summary>
+	/// 编辑器模式
+	/// </summary>
+	internal sealed class EditorPlayModeClearUnusedCacheFilesOperation : ClearUnusedCacheFilesOperation
+	{
+		internal override void Start()
+		{
+			Status = EOperationStatus.Succeed;
+		}
+		internal override void Update()
+		{
+		}
+	}
+
+	/// <summary>
+	/// 离线模式
+	/// </summary>
+	internal sealed class OfflinePlayModeClearUnusedCacheFilesOperation : ClearUnusedCacheFilesOperation
+	{
+		internal override void Start()
+		{
+			Status = EOperationStatus.Succeed;
+		}
+		internal override void Update()
+		{
+		}
+	}
+
+	/// <summary>
+	/// 联机模式
+	/// </summary>
+	internal sealed class HostPlayModeClearUnusedCacheFilesOperation : ClearUnusedCacheFilesOperation
+	{
+		private enum ESteps
+		{
+			None,
+			GetUnusedCacheFiles,
+			ClearUnusedCacheFiles,
+			Done,
+		}
+
+		private ESteps _steps = ESteps.None;
+		private List<string> _unusedCacheFilePaths;
+		private int _unusedFileTotalCount = 0;
+		private HostPlayModeImpl _impl;
+
+		internal HostPlayModeClearUnusedCacheFilesOperation(HostPlayModeImpl impl)
+		{
+			_impl = impl;
+		}
+		internal override void Start()
+		{
+			_steps = ESteps.GetUnusedCacheFiles;
+		}
+		internal override void Update()
+		{
+			if (_steps == ESteps.None || _steps == ESteps.Done)
+				return;
+
+			if (_steps == ESteps.GetUnusedCacheFiles)
+			{
+				_unusedCacheFilePaths = _impl.ClearUnusedCacheFilePaths();
+				_unusedFileTotalCount = _unusedCacheFilePaths.Count;
+				YooLogger.Log($"Found unused cache file count : {_unusedFileTotalCount}");
+				_steps = ESteps.ClearUnusedCacheFiles;
+			}
+
+			if (_steps == ESteps.ClearUnusedCacheFiles)
+			{
+				for (int i = _unusedCacheFilePaths.Count - 1; i >= 0; i--)
+				{
+					string filePath = _unusedCacheFilePaths[i];
+					if (File.Exists(filePath))
+					{
+						YooLogger.Log($"Delete unused cache file : {filePath}");
+						File.Delete(filePath);
+					}
+					_unusedCacheFilePaths.RemoveAt(i);
+
+					if (OperationSystem.IsBusy)
+						break;
+				}
+
+				if (_unusedFileTotalCount == 0)
+					Progress = 1.0f;
+				else
+					Progress = 1.0f - (_unusedCacheFilePaths.Count / _unusedFileTotalCount);
+
+				if (_unusedCacheFilePaths.Count == 0)
+				{
+					_steps = ESteps.Done;
+					Status = EOperationStatus.Succeed;
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Operations/ClearUnusedCacheFilesOperation.cs.meta b/Assets/YooAsset/Runtime/PatchSystem/Operations/ClearUnusedCacheFilesOperation.cs.meta
new file mode 100644
index 00000000..41bfef3b
--- /dev/null
+++ b/Assets/YooAsset/Runtime/PatchSystem/Operations/ClearUnusedCacheFilesOperation.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 5d188c50fd00bf941b2eeebb374dc0d1
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/YooAsset/Runtime/PatchSystem/PlayMode/HostPlayModeImpl.cs b/Assets/YooAsset/Runtime/PatchSystem/PlayMode/HostPlayModeImpl.cs
index de3e60be..e668cfae 100644
--- a/Assets/YooAsset/Runtime/PatchSystem/PlayMode/HostPlayModeImpl.cs
+++ b/Assets/YooAsset/Runtime/PatchSystem/PlayMode/HostPlayModeImpl.cs
@@ -88,16 +88,18 @@ namespace YooAsset
 		}
 
 		/// <summary>
-		/// 清空未被使用的缓存文件
+		/// 获取未被使用的缓存文件路径集合
 		/// </summary>
-		public void ClearUnusedCacheFiles()
+		public List<string> ClearUnusedCacheFilePaths()
 		{
 			string cacheFolderPath = SandboxHelper.GetCacheFolderPath();
 			if (Directory.Exists(cacheFolderPath) == false)
-				return;
+				return new List<string>();
 
 			DirectoryInfo directoryInfo = new DirectoryInfo(cacheFolderPath);
-			foreach (FileInfo fileInfo in directoryInfo.GetFiles())
+			FileInfo[] fileInfos = directoryInfo.GetFiles();
+			List<string> result = new List<string>(fileInfos.Length);
+			foreach (FileInfo fileInfo in fileInfos)
 			{
 				bool used = false;
 				foreach (var patchBundle in LocalPatchManifest.BundleList)
@@ -109,11 +111,9 @@ namespace YooAsset
 					}
 				}
 				if (used == false)
-				{
-					YooLogger.Log($"Delete unused cache file : {fileInfo.Name}");
-					File.Delete(fileInfo.FullName);
-				}
+					result.Add(fileInfo.FullName);
 			}
+			return result;
 		}
 
 		/// <summary>
diff --git a/Assets/YooAsset/Runtime/YooAssets.cs b/Assets/YooAsset/Runtime/YooAssets.cs
index f28a4d4f..dbb1ed1e 100644
--- a/Assets/YooAsset/Runtime/YooAssets.cs
+++ b/Assets/YooAsset/Runtime/YooAssets.cs
@@ -203,7 +203,7 @@ namespace YooAsset
 			{
 				var hostPlayModeParameters = parameters as HostPlayModeParameters;
 				CacheSystem.Initialize(hostPlayModeParameters.VerifyLevel);
-				DownloadSystem.Initialize(hostPlayModeParameters.BreakpointResumeFileSize);		
+				DownloadSystem.Initialize(hostPlayModeParameters.BreakpointResumeFileSize);
 			}
 			else
 			{
@@ -1040,10 +1040,31 @@ namespace YooAsset
 		/// <summary>
 		/// 清空未被使用的缓存文件
 		/// </summary>
-		public static void ClearUnusedCacheFiles()
+		public static ClearUnusedCacheFilesOperation ClearUnusedCacheFiles()
 		{
-			if (_playMode == EPlayMode.HostPlayMode)
-				_hostPlayModeImpl.ClearUnusedCacheFiles();
+			DebugCheckInitialize();
+			if (_playMode == EPlayMode.EditorSimulateMode)
+			{
+				var operation = new EditorPlayModeClearUnusedCacheFilesOperation();
+				OperationSystem.StartOperation(operation);
+				return operation;
+			}
+			else if (_playMode == EPlayMode.OfflinePlayMode)
+			{
+				var operation = new OfflinePlayModeClearUnusedCacheFilesOperation();
+				OperationSystem.StartOperation(operation);
+				return operation;
+			}
+			else if (_playMode == EPlayMode.HostPlayMode)
+			{
+				var operation = new HostPlayModeClearUnusedCacheFilesOperation(_hostPlayModeImpl);
+				OperationSystem.StartOperation(operation);
+				return operation;
+			}
+			else
+			{
+				throw new NotImplementedException();
+			}
 		}
 		#endregion