Unreal 技术笔记

unreal editor 下如何 mount 加密过的 pak

2023-08-12  本文已影响0人  子夜书案

问题:editor 下如何调试 pak 的 mount 流程?

FPakPlatformFile*  PakPlatform = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(FPakPlatformFile::GetTypeName()));
if (PakPlatform)
{
    PakPlatform->Mount(*pakPath, PakOrder)
}
FPakPlatformFile* HotPatchServer::CheckAndInitPakPlatform()
{
    FPakPlatformFile*  HandlePakPlatform = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(FPakPlatformFile::GetTypeName()));
    if (!HandlePakPlatform)
    {
        UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform FPakPlatformFile == NULL")); 
// 方便 Editor 调试 mount 流程
#if WITH_EDITOR
        if (EnabledEditorHotPatch)
        {
            IPlatformFileModule* PlatformFileModule = FModuleManager::LoadModulePtr<IPlatformFileModule>(FPakPlatformFile::GetTypeName());
            if (PlatformFileModule != NULL)
            {
                HandlePakPlatform = (FPakPlatformFile*)(PlatformFileModule->GetPlatformFile());

                IPlatformFile& TopmostPlatformFile = FPlatformFileManager::Get().GetPlatformFile();
                const TCHAR* Name = TEXT("");
                for (IPlatformFile* ChainElement = &TopmostPlatformFile; ChainElement; ChainElement = ChainElement->GetLowerLevel())
                {
                    UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform 寻找合适插入位置 Name = %s"), ChainElement->GetName());
                    if (ChainElement->GetLowerLevel() == NULL)
                    {
                        HandlePakPlatform->Initialize(ChainElement, TEXT(""));
                        HandlePakPlatform->InitializeAfterSetActive();
                        Name = ChainElement->GetName();
                        break;
                    }
                }
                for (IPlatformFile* ChainElement = &TopmostPlatformFile; ChainElement; ChainElement = ChainElement->GetLowerLevel())
                {
                    UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform 寻找被插队的节点 Name = %s"), ChainElement->GetName());
                    if (ChainElement->GetLowerLevel() != NULL && FCString::Stricmp(ChainElement->GetLowerLevel()->GetName(), Name) == 0 && FCString::Stricmp(FPakPlatformFile::GetTypeName(), Name) != 0)
                    {
                        UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform 寻找到了需要插入的节点 Name = %s OldGetLowerLevel = %s NewLowerLevel = %s"), ChainElement->GetName(), ChainElement->GetName(), HandlePakPlatform->GetName());
                        ChainElement->SetLowerLevel(HandlePakPlatform);
                        break;
                    }
                }
                if (TopmostPlatformFile.GetLowerLevel() == NULL)
                {
                    UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform 没寻找到被插队的节点 HandlePakPlatform 被放在最上层!"));
                    FPlatformFileManager::Get().SetPlatformFile(*HandlePakPlatform);
                }
            }
        }
#endif
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform FPakPlatformFile is OK"));
    }
    return HandlePakPlatform;
}

问题:editor 挂载(mount)加密后的 pak 报错?

一般正式上线时,为了资源不被轻松破解,一般都会选择将 pak 加密。

如下图所示:


加密设置

一开始我也很疑惑,经过多次查找下来,在 Engine/Source/Programs/UnrealBuildTool/Configuration/TargetRules.cs 中发现了如下代码:


定义

具体模版内容为:


模版内容

以上可以总结为:在打包时(编译项目时),会根据项目的设置,自动生成对应的解密代码。

其实也比较简单,就像上面的代码一样,加一个解密的 callback 就可以了,具体的代码如下:

bool bEncryptPakIndex;
bool bEncryptPakIniFiles;
bool bEncryptUAssetFiles;
bool bEncryptAllAssetFiles;
FString GSetting = FString::Printf(TEXT("%sDefaultCrypto.ini"), *FPaths::SourceConfigDir());
GConfig->GetBool(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("bEncryptPakIndex"), bEncryptPakIndex, GSetting);
GConfig->GetBool(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("bEncryptPakIniFiles"), bEncryptPakIniFiles, GSetting);
GConfig->GetBool(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("bEncryptUAssetFiles"), bEncryptUAssetFiles, GSetting);
GConfig->GetBool(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("bEncryptAllAssetFiles"), bEncryptAllAssetFiles, GSetting);
if (bEncryptPakIndex || bEncryptPakIniFiles || bEncryptUAssetFiles || bEncryptAllAssetFiles) {
    FString EncryptionKey;
    GConfig->GetString(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("EncryptionKey"), EncryptionKey, GSetting);
    UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform EncryptionKey = %s"), &EncryptionKey);
    FCoreDelegates::GetPakEncryptionKeyDelegate().BindLambda([EncryptionKey](uint8* key) {
        TArray<uint8> KeyBase64Array;
        FBase64::Decode(EncryptionKey, KeyBase64Array);
        FMemory::Memcpy(key, KeyBase64Array.GetData(), FAES::FAESKey::KeySize);
     });
}

结合上面的代码:

FPakPlatformFile* HotPatchServer::CheckAndInitPakPlatform()
{
    FPakPlatformFile*  HandlePakPlatform = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(FPakPlatformFile::GetTypeName()));
    if (!HandlePakPlatform)
    {
        UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform FPakPlatformFile == NULL")); 
// 方便 Editor 调试 mount 流程
#if WITH_EDITOR
        if (EnabledEditorHotPatch)
        {
            bool bEncryptPakIndex;
            bool bEncryptPakIniFiles;
            bool bEncryptUAssetFiles;
            bool bEncryptAllAssetFiles;
            FString GSetting = FString::Printf(TEXT("%sDefaultCrypto.ini"), *FPaths::SourceConfigDir());
            GConfig->GetBool(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("bEncryptPakIndex"), bEncryptPakIndex, GSetting);
            GConfig->GetBool(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("bEncryptPakIniFiles"), bEncryptPakIniFiles, GSetting);
            GConfig->GetBool(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("bEncryptUAssetFiles"), bEncryptUAssetFiles, GSetting);
            GConfig->GetBool(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("bEncryptAllAssetFiles"), bEncryptAllAssetFiles, GSetting);
            if (bEncryptPakIndex || bEncryptPakIniFiles || bEncryptUAssetFiles || bEncryptAllAssetFiles) {
                FString EncryptionKey;
                GConfig->GetString(TEXT("/Script/CryptoKeys.CryptoKeysSettings"), TEXT("EncryptionKey"), EncryptionKey, GSetting);
                UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform EncryptionKey = %s"), &EncryptionKey);
                FCoreDelegates::GetPakEncryptionKeyDelegate().BindLambda([EncryptionKey](uint8* key) {
                    TArray<uint8> KeyBase64Array;
                    FBase64::Decode(EncryptionKey, KeyBase64Array);
                    FMemory::Memcpy(key, KeyBase64Array.GetData(), FAES::FAESKey::KeySize);
                 });
            }
            
            IPlatformFileModule* PlatformFileModule = FModuleManager::LoadModulePtr<IPlatformFileModule>(FPakPlatformFile::GetTypeName());
            if (PlatformFileModule != NULL)
            {
                HandlePakPlatform = (FPakPlatformFile*)(PlatformFileModule->GetPlatformFile());

                IPlatformFile& TopmostPlatformFile = FPlatformFileManager::Get().GetPlatformFile();
                const TCHAR* Name = TEXT("");
                for (IPlatformFile* ChainElement = &TopmostPlatformFile; ChainElement; ChainElement = ChainElement->GetLowerLevel())
                {
                    UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform 寻找合适插入位置 Name = %s"), ChainElement->GetName());
                    if (ChainElement->GetLowerLevel() == NULL)
                    {
                        HandlePakPlatform->Initialize(ChainElement, TEXT(""));
                        HandlePakPlatform->InitializeAfterSetActive();
                        Name = ChainElement->GetName();
                        break;
                    }
                }
                for (IPlatformFile* ChainElement = &TopmostPlatformFile; ChainElement; ChainElement = ChainElement->GetLowerLevel())
                {
                    UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform 寻找被插队的节点 Name = %s"), ChainElement->GetName());
                    if (ChainElement->GetLowerLevel() != NULL && FCString::Stricmp(ChainElement->GetLowerLevel()->GetName(), Name) == 0 && FCString::Stricmp(FPakPlatformFile::GetTypeName(), Name) != 0)
                    {
                        UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform 寻找到了需要插入的节点 Name = %s OldGetLowerLevel = %s NewLowerLevel = %s"), ChainElement->GetName(), ChainElement->GetName(), HandlePakPlatform->GetName());
                        ChainElement->SetLowerLevel(HandlePakPlatform);
                        break;
                    }
                }
                if (TopmostPlatformFile.GetLowerLevel() == NULL)
                {
                    UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform 没寻找到被插队的节点 HandlePakPlatform 被放在最上层!"));
                    FPlatformFileManager::Get().SetPlatformFile(*HandlePakPlatform);
                }
            }
        }
#endif
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("CheckAndInitPakPlatform FPakPlatformFile is OK"));
    }
    return HandlePakPlatform;
}

上一篇 下一篇

猜你喜欢

热点阅读