diff --git a/UnityProject/Assets/TEngine/Editor/Inspector/ResourceModuleDriverInspector.cs b/UnityProject/Assets/TEngine/Editor/Inspector/ResourceModuleDriverInspector.cs index 9f5b93e9..0d524d5c 100644 --- a/UnityProject/Assets/TEngine/Editor/Inspector/ResourceModuleDriverInspector.cs +++ b/UnityProject/Assets/TEngine/Editor/Inspector/ResourceModuleDriverInspector.cs @@ -17,6 +17,7 @@ namespace TEngine.Editor.Inspector }; private SerializedProperty _playMode = null; + private SerializedProperty _encryptionType = null; private SerializedProperty _updatableWhilePlaying = null; private SerializedProperty _milliseconds = null; private SerializedProperty _minUnloadUnusedAssetsInterval = null; @@ -56,6 +57,8 @@ namespace TEngine.Editor.Inspector _playMode.enumValueIndex = selectedIndex; } } + + EditorGUILayout.PropertyField(_encryptionType); } EditorGUILayout.PropertyField(_updatableWhilePlaying); @@ -220,6 +223,7 @@ namespace TEngine.Editor.Inspector private void OnEnable() { _playMode = serializedObject.FindProperty("playMode"); + _encryptionType = serializedObject.FindProperty("encryptionType"); _updatableWhilePlaying = serializedObject.FindProperty("updatableWhilePlaying"); _milliseconds = serializedObject.FindProperty("milliseconds"); _minUnloadUnusedAssetsInterval = serializedObject.FindProperty("minUnloadUnusedAssetsInterval"); diff --git a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/EncryptionType.cs b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/EncryptionType.cs new file mode 100644 index 00000000..1bef99ca --- /dev/null +++ b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/EncryptionType.cs @@ -0,0 +1,27 @@ +namespace TEngine +{ + /// + /// 资源模块的加密类型枚举。 + /// 用于定义资源加载时的不同加密方式。 + /// + public enum EncryptionType + { + /// + /// 无加密。 + /// 资源将以原始形式加载,不进行任何加密处理。 + /// + None, + + /// + /// 文件偏移加密。 + /// 通过在文件开头添加偏移量来隐藏真实文件内容的加密方式。 + /// + FileOffSet, + + /// + /// 文件流加密。 + /// 使用加密流对文件内容进行加密处理的加密方式。 + /// + FileStream, + } +} \ No newline at end of file diff --git a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/EncryptionType.cs.meta b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/EncryptionType.cs.meta new file mode 100644 index 00000000..23f5acfc --- /dev/null +++ b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/EncryptionType.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 18468bde9ea948729cd7eab8a2d6e598 +timeCreated: 1742356779 \ No newline at end of file diff --git a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/IResourceModule.cs b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/IResourceModule.cs index b1bfefb5..13139a41 100644 --- a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/IResourceModule.cs +++ b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/IResourceModule.cs @@ -25,6 +25,11 @@ namespace TEngine /// 获取或设置运行模式。 /// EPlayMode PlayMode { get; set; } + + /// + /// 资源加密方式。 + /// + EncryptionType EncryptionType { get; set; } /// /// 是否边玩边下载。 diff --git a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModule.Services.cs b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModule.Services.cs index 63342075..2b9aea16 100644 --- a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModule.Services.cs +++ b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModule.Services.cs @@ -179,6 +179,55 @@ namespace TEngine return 32; } } + + + #region WebDecryptionServices + /// + /// 资源文件偏移加载解密类 + /// + public class FileOffsetWebDecryption : IWebDecryptionServices + { + public WebDecryptResult LoadAssetBundle(WebDecryptFileInfo fileInfo) + { + int offset = GetFileOffset(); + byte[] decryptedData = new byte[fileInfo.FileData.Length - offset]; + Buffer.BlockCopy(fileInfo.FileData, offset, decryptedData, 0, decryptedData.Length); + // 从内存中加载AssetBundle + WebDecryptResult decryptResult = new WebDecryptResult(); + decryptResult.Result = AssetBundle.LoadFromMemory(decryptedData); + return decryptResult; + } + + private static int GetFileOffset() + { + return 32; + } + } + + public class FileStreamWebDecryption : IWebDecryptionServices + { + public WebDecryptResult LoadAssetBundle(WebDecryptFileInfo fileInfo) + { + // 优化:使用Buffer批量操作替代逐字节异或 + byte[] decryptedData = new byte[fileInfo.FileData.Length]; + Buffer.BlockCopy(fileInfo.FileData, 0, decryptedData, 0, fileInfo.FileData.Length); + + // 批量异或解密(性能优化) + int batchSize = sizeof(ulong); + int length = decryptedData.Length / batchSize * batchSize; + for (int i = 0; i < length; i += batchSize) + { + ulong value = BitConverter.ToUInt64(decryptedData, i); + value ^= BundleStream.KEY; + Buffer.BlockCopy(BitConverter.GetBytes(value), 0, decryptedData, i, batchSize); + } + + WebDecryptResult decryptResult = new WebDecryptResult(); + decryptResult.Result = AssetBundle.LoadFromMemory(decryptedData); + return decryptResult; + } + } + #endregion } /// @@ -200,9 +249,14 @@ public class BundleStream : FileStream public override int Read(byte[] array, int offset, int count) { var index = base.Read(array, offset, count); - for (int i = 0; i < array.Length; i++) + // 批量异或解密(性能优化) + int batchSize = sizeof(ulong); + int length = array.Length / batchSize * batchSize; + for (int i = 0; i < length; i += batchSize) { - array[i] ^= KEY; + ulong value = BitConverter.ToUInt64(array, i); + value ^= BundleStream.KEY; + Buffer.BlockCopy(BitConverter.GetBytes(value), 0, array, i, batchSize); } return index; diff --git a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModule.cs b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModule.cs index 41fa6d5c..bc0bd3e4 100644 --- a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModule.cs +++ b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModule.cs @@ -5,6 +5,9 @@ using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; using YooAsset; +#if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR +using WeChatWASM; +#endif namespace TEngine { @@ -22,6 +25,8 @@ namespace TEngine /// 资源系统运行模式。 /// public EPlayMode PlayMode { get; set; } = EPlayMode.OfflinePlayMode; + + public EncryptionType EncryptionType { get; set; } = EncryptionType.None; /// /// 设置异步系统参数,每帧执行消耗的最大时间切片(单位:毫秒) @@ -164,12 +169,14 @@ namespace TEngine createParameters.EditorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(packageRoot); initializationOperation = package.InitializeAsync(createParameters); } - + + IDecryptionServices decryptionServices = CreateDecryptionServices(); + // 单机运行模式 if (playMode == EPlayMode.OfflinePlayMode) { var createParameters = new OfflinePlayModeParameters(); - createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(); + createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(decryptionServices); initializationOperation = package.InitializeAsync(createParameters); } @@ -180,8 +187,8 @@ namespace TEngine string fallbackHostServer = FallbackHostServerURL; IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer); var createParameters = new HostPlayModeParameters(); - createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(); - createParameters.CacheFileSystemParameters = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices); + createParameters.BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(decryptionServices); + createParameters.CacheFileSystemParameters = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices, decryptionServices); initializationOperation = package.InitializeAsync(createParameters); } @@ -190,10 +197,14 @@ namespace TEngine { var createParameters = new WebPlayModeParameters(); #if UNITY_WEBGL && WEIXINMINIGAME && !UNITY_EDITOR + IWebDecryptionServices webDecryptionServices = CreateWebDecryptionServices(); + + // 注意:如果有子目录,请修改此处! + string packageRoot = $"{WeChatWASM.WX.env.USER_DATA_PATH}/__GAME_FILE_CACHE"; string defaultHostServer = HostServerURL; string fallbackHostServer = FallbackHostServerURL; IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer); - createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateWechatFileSystemParameters(remoteServices); + createParameters.WebServerFileSystemParameters = WechatFileSystemCreater.CreateFileSystemParameters(packageRoot, remoteServices, webDecryptionServices); #else createParameters.WebServerFileSystemParameters = FileSystemParameters.CreateDefaultWebServerFileSystemParameters(); #endif @@ -207,6 +218,32 @@ namespace TEngine return initializationOperation; } + /// + /// 创建解密服务。 + /// + private IDecryptionServices CreateDecryptionServices() + { + return EncryptionType switch + { + EncryptionType.FileOffSet => new FileOffsetDecryption(), + EncryptionType.FileStream => new FileStreamDecryption(), + _ => null + }; + } + + /// + /// 创建Web解密服务。 + /// + private IWebDecryptionServices CreateWebDecryptionServices() + { + return EncryptionType switch + { + EncryptionType.FileOffSet => new FileOffsetWebDecryption(), + EncryptionType.FileStream => new FileStreamWebDecryption(), + _ => null + }; + } + /// /// 获取当前资源包版本。 /// diff --git a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModuleDriver.cs b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModuleDriver.cs index 1b9cd83b..edc7b789 100644 --- a/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModuleDriver.cs +++ b/UnityProject/Assets/TEngine/Runtime/Module/ResourceModule/ResourceModuleDriver.cs @@ -89,6 +89,14 @@ namespace TEngine #endif } } + + [SerializeField] + private EncryptionType encryptionType = EncryptionType.None; + + /// + /// 资源模块的加密类型。 + /// + public EncryptionType EncryptionType => encryptionType; /// /// 是否支持边玩边下载。 @@ -238,6 +246,7 @@ namespace TEngine _resourceModule.DefaultPackageName = PackageName; _resourceModule.PlayMode = PlayMode; + _resourceModule.EncryptionType = encryptionType; _resourceModule.Milliseconds = milliseconds; _resourceModule.HostServerURL = Settings.UpdateSetting.GetResDownLoadPath(); _resourceModule.FallbackHostServerURL = Settings.UpdateSetting.GetFallbackResDownLoadPath(); diff --git a/UnityProject/Assets/TEngine/Runtime/TEngine.Runtime.asmdef b/UnityProject/Assets/TEngine/Runtime/TEngine.Runtime.asmdef index a8a92395..69d2ab01 100644 --- a/UnityProject/Assets/TEngine/Runtime/TEngine.Runtime.asmdef +++ b/UnityProject/Assets/TEngine/Runtime/TEngine.Runtime.asmdef @@ -4,7 +4,8 @@ "references": [ "GUID:e34a5702dd353724aa315fb8011f08c3", "GUID:f51ebe6a0ceec4240a699833d6309b23", - "GUID:6055be8ebefd69e48b49212b09b47b2f" + "GUID:6055be8ebefd69e48b49212b09b47b2f", + "GUID:5efd170ecd8084500bed5692932fe14e" ], "includePlatforms": [], "excludePlatforms": [],