From 2ab59d83f900cf94c96cacc6916a7693970a072d Mon Sep 17 00:00:00 2001 From: hxhb Date: Tue, 16 Nov 2021 12:44:09 +0000 Subject: [PATCH] support package game feature/fix crypto issue,update to v70 --- .../Classes/Commandlets/CommandletHelper.hpp | 64 +++++ .../Commandlets/HotPatcherCommandlet.cpp | 67 +---- .../Commandlets/HotPluginCommandlet.cpp | 77 +++++ .../Classes/Commandlets/HotPluginCommandlet.h | 16 ++ .../Commandlets/HotReleaseCommandlet.cpp | 19 +- .../Commandlets/HotShaderPatchCommandlet.cpp | 4 +- .../HotPatcherEditor.Build.cs | 16 +- .../Private/CreatePatch/PatcherProxy.cpp | 108 ++++--- .../CreatePatch/SProjectCreatePatchPage.cpp | 47 ++- .../Private/FlibHotPatcherEditorHelper.cpp | 225 ++++++++++++++- .../Private/GameFeature/GameFeatureProxy.cpp | 82 ++++++ .../GameFeature/SGameFeaturePackager.cpp | 271 ++++++++++++++++++ .../GameFeature/SGameFeaturePackager.h | 60 ++++ .../Model/FHotPatcherCreatePatchModel.h | 3 +- .../SVersionUpdater/SVersionUpdaterWidget.cpp | 2 +- .../SVersionUpdater/VersionUpdaterStyle.cpp | 8 +- .../SVersionUpdater/VersionUpdaterStyle.h | 6 +- .../CreatePatch/SProjectCreatePatchPage.h | 2 + .../Public/FlibHotPatcherEditorHelper.h | 94 ++++++ .../FGameFeaturePackagerSettings.h | 73 +++++ .../Public/GameFeature/GameFeatureProxy.h | 21 ++ .../HotPatcherRuntime.Build.cs | 1 + .../Private/FlibPakHelper.cpp | 95 +++++- .../Private/FlibPatchParserHelper.cpp | 125 +++++--- .../Public/CreatePatch/FExportPatchSettings.h | 51 ++-- .../CreatePatch/FExportReleaseSettings.h | 5 +- .../CreatePatch/HotPatcherSettingBase.h | 3 - .../HotPatcherRuntime/Public/FlibPakHelper.h | 18 +- .../Public/FlibPatchParserHelper.h | 22 +- 29 files changed, 1355 insertions(+), 230 deletions(-) create mode 100644 HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/CommandletHelper.hpp create mode 100644 HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPluginCommandlet.cpp create mode 100644 HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPluginCommandlet.h create mode 100644 HotPatcher/Source/HotPatcherEditor/Private/GameFeature/GameFeatureProxy.cpp create mode 100644 HotPatcher/Source/HotPatcherEditor/Private/GameFeature/SGameFeaturePackager.cpp create mode 100644 HotPatcher/Source/HotPatcherEditor/Private/GameFeature/SGameFeaturePackager.h create mode 100644 HotPatcher/Source/HotPatcherEditor/Public/GameFeature/FGameFeaturePackagerSettings.h create mode 100644 HotPatcher/Source/HotPatcherEditor/Public/GameFeature/GameFeatureProxy.h diff --git a/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/CommandletHelper.hpp b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/CommandletHelper.hpp new file mode 100644 index 00000000..9516a972 --- /dev/null +++ b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/CommandletHelper.hpp @@ -0,0 +1,64 @@ +#pragma once + + +#include "ETargetPlatform.h" +#include "FlibPatchParserHelper.h" + +#define PATCHER_CONFIG_PARAM_NAME TEXT("-config=") + +namespace CommandletHelper +{ + namespace NSPatch + { + void ReceiveMsg(const FString& InMsgType,const FString& InMsg) + { + UE_LOG(LogHotPatcherCommandlet,Display,TEXT("%s:%s"),*InMsgType,*InMsg); + } + + void ReceiveShowMsg(const FString& InMsg) + { + UE_LOG(LogHotPatcherCommandlet,Display,TEXT("%s"),*InMsg); + } + } + + TArray ParserPatchConfigByCommandline(const FString& Commandline,const FString& Token) + { + TArray result; + TMap KeyValues = UFlibPatchParserHelper::GetCommandLineParamsMap(Commandline); + if(KeyValues.Find(Token)) + { + FString AddPakListInfo = *KeyValues.Find(Token); + AddPakListInfo.ParseIntoArray(result,TEXT(",")); + } + return result; + } + + +#define ADD_PATCH_PLATFORMS TEXT("AddPatchPlatforms") + TArray ParserPatchPlatforms(const FString& Commandline) + { + TArray result; + for(auto& PlatformName:ParserPatchConfigByCommandline(Commandline,ADD_PATCH_PLATFORMS)) + { + ETargetPlatform Platform = ETargetPlatform::None; + UFlibPatchParserHelper::GetEnumValueByName(PlatformName,Platform); + if(Platform != ETargetPlatform::None) + { + result.AddUnique(Platform); + } + } + return result; + } + + TArray ParserPatchFilters(const FString& Commandline,const FString& FilterName) + { + TArray Result; + for(auto& FilterPath:ParserPatchConfigByCommandline(Commandline,FString::Printf(TEXT("Add%s"),*FilterName))) + { + FDirectoryPath Path; + Path.Path = FilterPath; + Result.Add(Path); + } + return Result; + } +} diff --git a/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPatcherCommandlet.cpp b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPatcherCommandlet.cpp index 6bb847b0..c96f3d08 100644 --- a/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPatcherCommandlet.cpp +++ b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPatcherCommandlet.cpp @@ -1,6 +1,7 @@ #include "HotPatcherCommandlet.h" // #include "CreatePatch/FExportPatchSettingsEx.h" #include "CreatePatch/PatcherProxy.h" +#include "CommandletHelper.hpp" // engine header #include "CoreMinimal.h" @@ -10,62 +11,6 @@ DEFINE_LOG_CATEGORY(LogHotPatcherCommandlet); -#define PATCHER_CONFIG_PARAM_NAME TEXT("-config=") - -namespace NSPatch -{ - void ReceiveMsg(const FString& InMsgType,const FString& InMsg) - { - UE_LOG(LogHotPatcherCommandlet,Display,TEXT("%s:%s"),*InMsgType,*InMsg); - } - - void ReceiveShowMsg(const FString& InMsg) - { - UE_LOG(LogHotPatcherCommandlet,Display,TEXT("%s"),*InMsg); - } -} - -TArray ParserPatchConfigByCommandline(const FString& Commandline,const FString& Token) -{ - TArray result; - TMap KeyValues = UFlibPatchParserHelper::GetCommandLineParamsMap(Commandline); - if(KeyValues.Find(Token)) - { - FString AddPakListInfo = *KeyValues.Find(Token); - AddPakListInfo.ParseIntoArray(result,TEXT(",")); - } - return result; -} - - -#define ADD_PATCH_PLATFORMS TEXT("AddPatchPlatforms") -TArray ParserPatchPlatforms(const FString& Commandline) -{ - TArray result; - for(auto& PlatformName:ParserPatchConfigByCommandline(Commandline,ADD_PATCH_PLATFORMS)) - { - ETargetPlatform Platform = ETargetPlatform::None; - UFlibPatchParserHelper::GetEnumValueByName(PlatformName,Platform); - if(Platform != ETargetPlatform::None) - { - result.AddUnique(Platform); - } - } - return result; -} - -TArray ParserPatchFilters(const FString& Commandline,const FString& FilterName) -{ - TArray Result; - for(auto& FilterPath:ParserPatchConfigByCommandline(Commandline,FString::Printf(TEXT("Add%s"),*FilterName))) - { - FDirectoryPath Path; - Path.Path = FilterPath; - Result.Add(Path); - } - return Result; -} - int32 UHotPatcherCommandlet::Main(const FString& Params) { UE_LOG(LogHotPatcherCommandlet, Display, TEXT("UHotPatcherCommandlet::Main")); @@ -100,7 +45,7 @@ int32 UHotPatcherCommandlet::Main(const FString& Params) TMap KeyValues = UFlibPatchParserHelper::GetCommandLineParamsMap(Params); UFlibPatchParserHelper::ReplaceProperty(*ExportPatchSetting, KeyValues); - TArray AddPlatforms = ParserPatchPlatforms(Params); + TArray AddPlatforms = CommandletHelper::ParserPatchPlatforms(Params); if(AddPlatforms.Num()) { @@ -109,8 +54,8 @@ int32 UHotPatcherCommandlet::Main(const FString& Params) ExportPatchSetting->PakTargetPlatforms.AddUnique(Platform); } } - ExportPatchSetting->AssetIncludeFilters.Append(ParserPatchFilters(Params,TEXT("AssetIncludeFilters"))); - ExportPatchSetting->AssetIgnoreFilters.Append(ParserPatchFilters(Params,TEXT("AssetIgnoreFilters"))); + ExportPatchSetting->AssetIncludeFilters.Append(CommandletHelper::ParserPatchFilters(Params,TEXT("AssetIncludeFilters"))); + ExportPatchSetting->AssetIgnoreFilters.Append(CommandletHelper::ParserPatchFilters(Params,TEXT("AssetIgnoreFilters"))); FString FinalConfig; UFlibPatchParserHelper::TSerializeStructAsJsonString(*ExportPatchSetting,FinalConfig); @@ -120,8 +65,8 @@ int32 UHotPatcherCommandlet::Main(const FString& Params) UPatcherProxy* PatcherProxy = NewObject(); PatcherProxy->AddToRoot(); PatcherProxy->SetProxySettings(ExportPatchSetting.Get()); - PatcherProxy->OnPaking.AddStatic(&::NSPatch::ReceiveMsg); - PatcherProxy->OnShowMsg.AddStatic(&::NSPatch::ReceiveShowMsg); + PatcherProxy->OnPaking.AddStatic(&::CommandletHelper::NSPatch::ReceiveMsg); + PatcherProxy->OnShowMsg.AddStatic(&::CommandletHelper::NSPatch::ReceiveShowMsg); bExportStatus = PatcherProxy->DoExport(); UE_LOG(LogHotPatcherCommandlet,Display,TEXT("Export Patch Misstion is %s!"),bExportStatus?TEXT("Successed"):TEXT("Failure")); diff --git a/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPluginCommandlet.cpp b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPluginCommandlet.cpp new file mode 100644 index 00000000..c1940948 --- /dev/null +++ b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPluginCommandlet.cpp @@ -0,0 +1,77 @@ +#include "HotPluginCommandlet.h" +#include "ThreadUtils/FProcWorkerThread.hpp" +#include "GameFeature/FGameFeaturePackagerSettings.h" +#include "FlibPatchParserHelper.h" +#include "HotPatcherEditor.h" +#include "CommandletHelper.hpp" + +// engine header +#include "CoreMinimal.h" +#include "GameFeature/GameFeatureProxy.h" +#include "Misc/FileHelper.h" +#include "Misc/CommandLine.h" +#include "Kismet/KismetSystemLibrary.h" +#include "Misc/Paths.h" + +DEFINE_LOG_CATEGORY(LogHotPluginCommandlet); + +TSharedPtr PluginProc; + +int32 UHotPluginCommandlet::Main(const FString& Params) +{ + UE_LOG(LogHotPluginCommandlet, Display, TEXT("UHotPluginCommandlet::Main")); + + FString config_path; + bool bStatus = FParse::Value(*Params, *FString(PATCHER_CONFIG_PARAM_NAME).ToLower(), config_path); + if (!bStatus) + { + UE_LOG(LogHotPluginCommandlet, Error, TEXT("not -config=xxxx.json params.")); + return -1; + } + + if (!FPaths::FileExists(config_path)) + { + UE_LOG(LogHotPluginCommandlet, Error, TEXT("cofnig file %s not exists."), *config_path); + return -1; + } + + FString JsonContent; + bool bExportStatus = false; + if (FFileHelper::LoadFileToString(JsonContent, *config_path)) + { + + if(IsRunningCommandlet()) + { + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")); + AssetRegistryModule.Get().SearchAllAssets(true); + } + + TSharedPtr PluginPackagerSetting = MakeShareable(new FGameFeaturePackagerSettings); + UFlibPatchParserHelper::TDeserializeJsonStringAsStruct(JsonContent,*PluginPackagerSetting); + + TMap KeyValues = UFlibPatchParserHelper::GetCommandLineParamsMap(Params); + UFlibPatchParserHelper::ReplaceProperty(*PluginPackagerSetting, KeyValues); + TArray AddPlatforms = CommandletHelper::ParserPatchPlatforms(Params); + + FString FinalConfig; + UFlibPatchParserHelper::TSerializeStructAsJsonString(*PluginPackagerSetting,FinalConfig); + UE_LOG(LogHotPluginCommandlet, Display, TEXT("%s"), *FinalConfig); + + + UGameFeatureProxy* GameFeatureProxy = NewObject(); + GameFeatureProxy->AddToRoot(); + GameFeatureProxy->SetProxySettings(PluginPackagerSetting.Get()); + GameFeatureProxy->OnPaking.AddStatic(&::CommandletHelper::NSPatch::ReceiveMsg); + GameFeatureProxy->OnShowMsg.AddStatic(&::CommandletHelper::NSPatch::ReceiveShowMsg); + bExportStatus = GameFeatureProxy->DoExport(); + + UE_LOG(LogHotPluginCommandlet,Display,TEXT("Generate Game Feature Misstion is %s!"),bExportStatus?TEXT("Successed"):TEXT("Failure")); + } + + if(FParse::Param(FCommandLine::Get(), TEXT("wait"))) + { + system("pause"); + } + + return 0; +} diff --git a/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPluginCommandlet.h b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPluginCommandlet.h new file mode 100644 index 00000000..b5d25a01 --- /dev/null +++ b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotPluginCommandlet.h @@ -0,0 +1,16 @@ +#pragma once + +#include "Commandlets/Commandlet.h" +#include "HotPluginCommandlet.generated.h" + +DECLARE_LOG_CATEGORY_EXTERN(LogHotPluginCommandlet, Log, All); + +UCLASS() +class UHotPluginCommandlet :public UCommandlet +{ + GENERATED_BODY() + +public: + + virtual int32 Main(const FString& Params)override; +}; \ No newline at end of file diff --git a/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotReleaseCommandlet.cpp b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotReleaseCommandlet.cpp index d2d42cb6..26696d08 100644 --- a/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotReleaseCommandlet.cpp +++ b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotReleaseCommandlet.cpp @@ -1,6 +1,7 @@ #include "HotReleaseCommandlet.h" #include "CreatePatch/FExportReleaseSettings.h" #include "CreatePatch/ReleaseProxy.h" +#include "CommandletHelper.hpp" // engine header #include "CoreMinimal.h" @@ -10,20 +11,6 @@ DEFINE_LOG_CATEGORY(LogHotReleaseCommandlet); -#define PATCHER_CONFIG_PARAM_NAME TEXT("-config=") - -namespace NSRelease -{ - void ReceiveMsg(const FString& InMsgType,const FString& InMsg) - { - UE_LOG(LogHotReleaseCommandlet,Log,TEXT("%s:%s"),*InMsgType,*InMsg); - } - - void ReceiveShowMsg(const FString& InMsg) - { - UE_LOG(LogHotReleaseCommandlet,Log,TEXT("%s"),*InMsg); - } -} #define ADD_PLATFORM_PAK_LIST TEXT("AddPlatformPakList") TArray ParserPlatformPakList(const FString& Commandline) @@ -119,8 +106,8 @@ int32 UHotReleaseCommandlet::Main(const FString& Params) UReleaseProxy* ReleaseProxy = NewObject(); ReleaseProxy->AddToRoot(); ReleaseProxy->SetProxySettings(ExportReleaseSetting.Get()); - ReleaseProxy->OnPaking.AddStatic(&::NSRelease::ReceiveMsg); - ReleaseProxy->OnShowMsg.AddStatic(&::NSRelease::ReceiveShowMsg); + ReleaseProxy->OnPaking.AddStatic(&::CommandletHelper::NSPatch::ReceiveMsg); + ReleaseProxy->OnShowMsg.AddStatic(&::CommandletHelper::NSPatch::ReceiveShowMsg); bool bExportStatus = ReleaseProxy->DoExport(); UE_LOG(LogHotReleaseCommandlet,Display,TEXT("Export Release Misstion is %s!"),bExportStatus?TEXT("Successed"):TEXT("Failure")); diff --git a/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotShaderPatchCommandlet.cpp b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotShaderPatchCommandlet.cpp index 9bb3ce10..43bc3826 100644 --- a/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotShaderPatchCommandlet.cpp +++ b/HotPatcher/Source/HotPatcherEditor/Classes/Commandlets/HotShaderPatchCommandlet.cpp @@ -1,6 +1,6 @@ #include "HotShaderPatchCommandlet.h" #include "ShaderPatch/FExportShaderPatchSettings.h" - +#include "CommandletHelper.hpp" // engine header #include "CoreMinimal.h" #include "Misc/FileHelper.h" @@ -11,8 +11,6 @@ DEFINE_LOG_CATEGORY(LogHotShaderPatchCommandlet); -#define PATCHER_CONFIG_PARAM_NAME TEXT("-config=") - int32 UHotShaderPatchCommandlet::Main(const FString& Params) { UE_LOG(LogHotShaderPatchCommandlet, Display, TEXT("UHotShaderPatchCommandlet::Main")); diff --git a/HotPatcher/Source/HotPatcherEditor/HotPatcherEditor.Build.cs b/HotPatcher/Source/HotPatcherEditor/HotPatcherEditor.Build.cs index da375de2..cd585985 100644 --- a/HotPatcher/Source/HotPatcherEditor/HotPatcherEditor.Build.cs +++ b/HotPatcher/Source/HotPatcherEditor/HotPatcherEditor.Build.cs @@ -47,7 +47,7 @@ public HotPatcherEditor(ReadOnlyTargetRules Target) : base(Target) "PakFileUtilities", "HotPatcherRuntime", "BinariesPatchFeature" - // ... add other public dependencies that you statically link with here ... + // ... add other public dependencies that you statically link with here ... } ); @@ -143,11 +143,23 @@ public HotPatcherEditor(ReadOnlyTargetRules Target) : base(Target) System.Console.WriteLine("MajorVersion {0} MinorVersion: {1} PatchVersion {2}",Target.Version.MajorVersion,Target.Version.MinorVersion,Target.Version.PatchVersion); bLegacyPublicIncludePaths = false; OptimizeCode = CodeOptimization.InShippingBuildsOnly; + + // Game feature + bool bEnableGameFeature = false; + if (bEnableGameFeature || (Target.Version.MajorVersion > 4 || Target.Version.MinorVersion > 26)) + { + PublicDefinitions.Add("ENGINE_GAME_FEATURE"); + PublicDependencyModuleNames.AddRange(new string[] + { + // "GameFeatures", + // "ModularGameplay", + }); + } PublicDefinitions.AddRange(new string[] { "TOOL_NAME=\"HotPatcher\"", - "CURRENT_VERSION_ID=69", + "CURRENT_VERSION_ID=70", "REMOTE_VERSION_FILE=\"https://imzlp.com/opensource/version.json\"" }); } diff --git a/HotPatcher/Source/HotPatcherEditor/Private/CreatePatch/PatcherProxy.cpp b/HotPatcher/Source/HotPatcherEditor/Private/CreatePatch/PatcherProxy.cpp index f8d682ca..3da22288 100644 --- a/HotPatcher/Source/HotPatcherEditor/Private/CreatePatch/PatcherProxy.cpp +++ b/HotPatcher/Source/HotPatcherEditor/Private/CreatePatch/PatcherProxy.cpp @@ -616,7 +616,10 @@ namespace PatchWorker FExternFileInfo AddShaderLib; AddShaderLib.Type = EPatchAssetType::NEW; AddShaderLib.FilePath.FilePath = FPaths::ConvertRelativePathToFull(FilePath); - AddShaderLib.MountPath = FPaths::Combine(Context.GetSettingObject()->CookShaderOptions.ShderLibMountPoint,FString::Printf(TEXT("%s.%s"),*FileName,*FileExtersion)); + AddShaderLib.MountPath = FPaths::Combine( + UFlibPatchParserHelper::ParserMountPointRegular(Context.GetSettingObject()->CookShaderOptions.GetShaderLibMountPointRegular()), + FString::Printf(TEXT("%s.%s"),*FileName,*FileExtersion) + ); Context.GetPatcherDiffInfoByName(PlatformName)->AddExternalFiles.Add(AddShaderLib); Context.GetPatcherChunkInfoByName(PlatformName,Chunk.ChunkName)->AddExternFileToPak.Add(AddShaderLib); } @@ -664,7 +667,10 @@ namespace PatchWorker FExternFileInfo AssetRegistryFileInfo; AssetRegistryFileInfo.Type = EPatchAssetType::NEW; AssetRegistryFileInfo.FilePath.FilePath = AssetRegistryPath; - AssetRegistryFileInfo.MountPath = FPaths::Combine(Context.GetSettingObject()->GetSerializeAssetRegistryOptions().AssetRegistryMountPoint,ChunkAssetRegistryName); + AssetRegistryFileInfo.MountPath = FPaths::Combine( + UFlibPatchParserHelper::ParserMountPointRegular(Context.GetSettingObject()->GetSerializeAssetRegistryOptions().GetAssetRegistryMountPointRegular()) + ,ChunkAssetRegistryName + ); Context.GetPatcherDiffInfoByName(PlatformName)->AddExternalFiles.Add(AssetRegistryFileInfo); Context.GetPatcherChunkInfoByName(PlatformName,Chunk.ChunkName)->AddExternFileToPak.Add(AssetRegistryFileInfo); } @@ -904,56 +910,70 @@ namespace PatchWorker if(Context.PatchProxy) Context.PatchProxy->OnPakListGenerated.Broadcast(Context,Chunk,Platform,ChunkPakListCommands); - - auto AppendOptionsLambda = [](TArray& OriginCommands,const TArray& Options) + + TArray IgnoreCompressFormats = UFlibHotPatcherEditorHelper::GetExtensionsToNotUsePluginCompressionByGConfig(); + for(auto& PakCommand:ChunkPakListCommands) { - // [Pak] - // +ExtensionsToNotUsePluginCompression=uplugin - // +ExtensionsToNotUsePluginCompression=upluginmanifest - // +ExtensionsToNotUsePluginCompression=uproject - // +ExtensionsToNotUsePluginCompression=ini - // +ExtensionsToNotUsePluginCompression=icu - // +ExtensionsToNotUsePluginCompression=res - TArray IgnoreCompressFormats; - GConfig->GetArray(TEXT("Pak"),TEXT("ExtensionsToNotUsePluginCompression"),IgnoreCompressFormats,GEngineIni); - - auto GetPakCommandFileExtensionLambda = [](const FString& Command)->FString + TArray EmptyArray; + TArray CompressOption{TEXT("-compress")}; + + auto AppendPakCommandOptions = [&Context](FPakCommand& PakCommand, + const TArray& Options, + bool bAppendAllMatch, + const TArray& AppendFileExtersions, + const TArray& IgnoreFormats, // 忽略追加Option的文件格式 + const TArray& InIgnoreFormatsOptions // 给忽略的格式忽略追加哪些option,如-compress不在ini中添加 + ) { - FString result; - int32 DotPos = Command.Find(TEXT("."), ESearchCase::CaseSensitive, ESearchDir::FromEnd); - if (DotPos != INDEX_NONE) - { - result = Command.Mid(DotPos + 1); - if(result.EndsWith(TEXT("\""))) - { - result.RemoveAt(result.Len()-1,1); - } - } - return result; + UFlibHotPatcherEditorHelper::AppendPakCommandOptions( + PakCommand.PakCommands, + Options, + bAppendAllMatch, + AppendFileExtersions, + IgnoreFormats, + InIgnoreFormatsOptions + ); + UFlibHotPatcherEditorHelper::AppendPakCommandOptions( + PakCommand.IoStoreCommands, + Options, + bAppendAllMatch, + AppendFileExtersions, + IgnoreFormats, + InIgnoreFormatsOptions + ); }; + // 给所有的文件添加PakCommand的Option参数,默认只包含-compress,除了ExtensionsToNotUsePluginCompression中配置的文件都会添加 + UFlibHotPatcherEditorHelper::AppendPakCommandOptions(PakCommand.PakCommands,Context.GetSettingObject()->GetUnrealPakSettings().UnrealPakListOptions,true,EmptyArray,IgnoreCompressFormats,CompressOption); + UFlibHotPatcherEditorHelper::AppendPakCommandOptions(PakCommand.PakCommands,Context.GetSettingObject()->GetDefaultPakListOptions(),true,EmptyArray,IgnoreCompressFormats,CompressOption); + UFlibHotPatcherEditorHelper::AppendPakCommandOptions(PakCommand.IoStoreCommands,Context.GetSettingObject()->GetIoStoreSettings().IoStorePakListOptions,true,EmptyArray,IgnoreCompressFormats,CompressOption); + UFlibHotPatcherEditorHelper::AppendPakCommandOptions(PakCommand.IoStoreCommands,Context.GetSettingObject()->GetDefaultPakListOptions(),true,EmptyArray,IgnoreCompressFormats,CompressOption); + + FEncryptSetting EncryptSettings = UFlibHotPatcherEditorHelper::GetCryptoSettingByPakEncryptSettings(Context.GetSettingObject()->GetEncryptSettings()); - for(auto& Command:OriginCommands) + // 加密所有文件 + if(EncryptSettings.bEncryptAllAssetFiles) { - FString PakOptionsStr; - for (const auto& Param : Options) + TArray EncryptOption{TEXT("-encrypt")}; + AppendPakCommandOptions(PakCommand,EncryptOption,true,EmptyArray,EmptyArray,EmptyArray); + } + else + { + // 加密 uasset + if(EncryptSettings.bEncryptUAssetFiles) { - FString FileExtension = GetPakCommandFileExtensionLambda(Command); - if(IgnoreCompressFormats.Contains(FileExtension) && Param.Equals(TEXT("-compress"),ESearchCase::IgnoreCase)) - { - continue; - } - PakOptionsStr += TEXT(" ") + Param; + TArray EncryptOption{TEXT("-encrypt")}; + TArray EncryptFileExtersion{TEXT("uasset")}; + + AppendPakCommandOptions(PakCommand,EncryptOption,false,EncryptFileExtersion,EmptyArray,EmptyArray); + } + // 加密 ini + if(EncryptSettings.bEncryptIniFiles) + { + TArray EncryptOption{TEXT("-encrypt")}; + TArray EncryptFileExtersion{TEXT("ini")}; + AppendPakCommandOptions(PakCommand,EncryptOption,false,EncryptFileExtersion,EmptyArray,EmptyArray); } - Command = FString::Printf(TEXT("%s%s"),*Command,*PakOptionsStr); } - }; - - for(auto& PakCommand:ChunkPakListCommands) - { - AppendOptionsLambda(PakCommand.PakCommands,Context.GetSettingObject()->GetUnrealPakSettings().UnrealPakListOptions); - AppendOptionsLambda(PakCommand.PakCommands,Context.GetSettingObject()->GetDefaultPakListOptions()); - AppendOptionsLambda(PakCommand.IoStoreCommands,Context.GetSettingObject()->GetIoStoreSettings().IoStorePakListOptions); - AppendOptionsLambda(PakCommand.IoStoreCommands,Context.GetSettingObject()->GetDefaultPakListOptions()); } if (!ChunkPakListCommands.Num()) diff --git a/HotPatcher/Source/HotPatcherEditor/Private/CreatePatch/SProjectCreatePatchPage.cpp b/HotPatcher/Source/HotPatcherEditor/Private/CreatePatch/SProjectCreatePatchPage.cpp index 8d829523..c3a71c93 100644 --- a/HotPatcher/Source/HotPatcherEditor/Private/CreatePatch/SProjectCreatePatchPage.cpp +++ b/HotPatcher/Source/HotPatcherEditor/Private/CreatePatch/SProjectCreatePatchPage.cpp @@ -4,6 +4,7 @@ #include "CreatePatch/SHotPatcherExportPatch.h" #include "CreatePatch/SHotPatcherExportRelease.h" #include "ShaderPatch/SHotPatcherExportShaderPatch.h" +#include "GameFeature/SGameFeaturePackager.h" // engine header #include "Framework/Commands/UIAction.h" @@ -33,6 +34,10 @@ void SProjectCreatePatchPage::Construct(const FArguments& InArgs, TSharedPtr SProjectCreatePatchPage::GetActivePatchable()con result = mShaderPatch; break; } + case EHotPatcherActionModes::ByGameFeature: + { + result = mGameFeature; + break; + } } } return result; @@ -232,6 +249,18 @@ EVisibility SProjectCreatePatchPage::HandleExportShaderPatchVisibility() const return EVisibility::Collapsed; } +EVisibility SProjectCreatePatchPage::HandleExportGameFeatureVisibility() const +{ + if (mGameFeature.IsValid()) + { + if (mCreatePatchModel->GetPatcherMode() == EHotPatcherActionModes::ByGameFeature) + { + return EVisibility::Visible; + } + } + return EVisibility::Collapsed; +} + EVisibility SProjectCreatePatchPage::HandleOperatorConfigVisibility()const { return EVisibility::Visible; @@ -276,6 +305,10 @@ FText SProjectCreatePatchPage::HandlePatchModeComboButtonContentText() const { return LOCTEXT("PatcherModeComboButton_ByShaderPatch", "By SahderPatch"); } + if (PatcherMode == EHotPatcherActionModes::ByGameFeature) + { + return LOCTEXT("PatcherModeComboButton_ByGameFeature", "By GameFeature"); + } } return FText(); diff --git a/HotPatcher/Source/HotPatcherEditor/Private/FlibHotPatcherEditorHelper.cpp b/HotPatcher/Source/HotPatcherEditor/Private/FlibHotPatcherEditorHelper.cpp index 3b974416..9c31c954 100644 --- a/HotPatcher/Source/HotPatcherEditor/Private/FlibHotPatcherEditorHelper.cpp +++ b/HotPatcher/Source/HotPatcherEditor/Private/FlibHotPatcherEditorHelper.cpp @@ -842,29 +842,50 @@ TArray UFlibHotPatcherEditorHelper::GetSupportPlatforms() return Result; } +#define ENCRYPT_CRYPTO_NAME TEXT("cryptokeys") -FString UFlibHotPatcherEditorHelper::GetEncryptSettingsCommandlineOptions(const FPakEncryptSettings& EncryptSettings,const FString& PlatformName) +FString UFlibHotPatcherEditorHelper::GetEncryptSettingsCommandlineOptions(const FPakEncryptSettings& PakEncryptSettings,const FString& PlatformName) { FString Result; - if(EncryptSettings.bEncryptAllAssetFiles) + + FString CryptoKey = UFlibPatchParserHelper::ReplaceMarkPath(PakEncryptSettings.CryptoKeys.FilePath); + + auto AppendCommandOptions = [&Result](bool bEncryptIndex,bool bbEncrypt,bool bSign) { - Result += EncryptSettings.bEncryptAllAssetFiles? TEXT("-encrypt "):TEXT(""); - } - if(EncryptSettings.bEncryptIndex) + if(bbEncrypt) + { + Result += TEXT("-encrypt "); + } + if(bEncryptIndex) + { + Result += TEXT("-encryptindex "); + } + if(bSign) + { + Result += TEXT("-sign "); + } + }; + + FEncryptSetting EncryptSettings = UFlibHotPatcherEditorHelper::GetCryptoSettingByPakEncryptSettings(PakEncryptSettings); + if(PakEncryptSettings.bUseDefaultCryptoIni) { - Result += EncryptSettings.bEncryptIndex? TEXT("-encryptindex "):TEXT(""); + FString SaveTo = FPaths::ConvertRelativePathToFull(FPaths::Combine(FPaths::ProjectSavedDir(),TEXT("HotPatcher"),TEXT("Crypto.json"))); + FPakEncryptionKeys PakEncryptionKeys = UFlibHotPatcherEditorHelper::GetCryptoByProjectSettings(); + UFlibHotPatcherEditorHelper::SerializePakEncryptionKeyToFile(PakEncryptionKeys,SaveTo); + CryptoKey = SaveTo; } - FString CryptoKey = UFlibPatchParserHelper::ReplaceMarkPath(EncryptSettings.CryptoKeys.FilePath); + + AppendCommandOptions( + EncryptSettings.bEncryptIndex, + (EncryptSettings.bEncryptIniFiles || EncryptSettings.bEncryptAllAssetFiles || EncryptSettings.bEncryptUAssetFiles), + EncryptSettings.bSign + ); + if(FPaths::FileExists(CryptoKey)) { - Result += FString::Printf(TEXT("-crypto=\"%s\" "),*CryptoKey); + Result += FString::Printf(TEXT("-%s=\"%s\" "),ENCRYPT_CRYPTO_NAME,*CryptoKey); } - if(EncryptSettings.bUseDefaultCryptoIni) - Result += EncryptSettings.bUseDefaultCryptoIni? TEXT("-encryptionini "):TEXT(""); - if(EncryptSettings.bSign) - Result += EncryptSettings.bSign? TEXT("-sign "):TEXT(""); - Result += FString::Printf(TEXT("-projectdir=\"%s\" "),*FPaths::ConvertRelativePathToFull(FPaths::ProjectDir())); Result += FString::Printf(TEXT("-enginedir=\"%s\" "),*FPaths::ConvertRelativePathToFull(FPaths::EngineDir())); Result += FString::Printf(TEXT("-platform=%s"),*PlatformName); @@ -1255,3 +1276,181 @@ FHotPatcherVersion UFlibHotPatcherEditorHelper::MakeNewReleaseByDiff(const FHotP NewRelease.PlatformAssets = BasePlatformAssetsRef; return NewRelease; } + + + +#define ENCRYPT_KEY_NAME TEXT("EncryptionKey") +#define ENCRYPT_PAK_INI_FILES_NAME TEXT("bEncryptPakIniFiles") +#define ENCRYPT_PAK_INDEX_NAME TEXT("bEncryptPakIndex") +#define ENCRYPT_UASSET_FILES_NAME TEXT("bEncryptUAssetFiles") +#define ENCRYPT_ALL_ASSET_FILES_NAME TEXT("bEncryptAllAssetFiles") + +#define SIGNING_PAK_SIGNING_NAME TEXT("bEnablePakSigning") +#define SIGNING_MODULES_NAME TEXT("SigningModulus") +#define SIGNING_PUBLIC_EXPONENT_NAME TEXT("SigningPublicExponent") +#define SIGNING_PRIVATE_EXPONENT_NAME TEXT("SigningPrivateExponent") + +FPakEncryptionKeys UFlibHotPatcherEditorHelper::GetCryptoByProjectSettings() +{ + FPakEncryptionKeys result; + + result.EncryptionKey.Name = TEXT("Embedded"); + result.EncryptionKey.Guid = FGuid::NewGuid().ToString(); + + UClass* Class = FindObject(ANY_PACKAGE, TEXT("/Script/CryptoKeys.CryptoKeysSettings"), true); + if(Class) + { + FString AESKey; + for(TFieldIterator PropertyIter(Class);PropertyIter;++PropertyIter) + { + FProperty* PropertyIns = *PropertyIter; + UE_LOG(LogTemp,Log,TEXT("%s"),*PropertyIns->GetName()); + if(PropertyIns->GetName().Equals(ENCRYPT_KEY_NAME)) + { + result.EncryptionKey.Key = *PropertyIns->ContainerPtrToValuePtr(Class->GetDefaultObject()); + } + if(PropertyIns->GetName().Equals(ENCRYPT_PAK_INI_FILES_NAME)) + { + result.bEnablePakIniEncryption = *PropertyIns->ContainerPtrToValuePtr(Class->GetDefaultObject()); + } + if(PropertyIns->GetName().Equals(ENCRYPT_PAK_INDEX_NAME)) + { + result.bEnablePakIndexEncryption = *PropertyIns->ContainerPtrToValuePtr(Class->GetDefaultObject()); + } + if(PropertyIns->GetName().Equals(ENCRYPT_UASSET_FILES_NAME)) + { + result.bEnablePakUAssetEncryption = *PropertyIns->ContainerPtrToValuePtr(Class->GetDefaultObject()); + } + if(PropertyIns->GetName().Equals(ENCRYPT_ALL_ASSET_FILES_NAME)) + { + result.bEnablePakFullAssetEncryption = *PropertyIns->ContainerPtrToValuePtr(Class->GetDefaultObject()); + } + // SIGN + if(PropertyIns->GetName().Equals(SIGNING_PAK_SIGNING_NAME)) + { + result.bEnablePakSigning = *PropertyIns->ContainerPtrToValuePtr(Class->GetDefaultObject()); + } + if(PropertyIns->GetName().Equals(SIGNING_PUBLIC_EXPONENT_NAME)) + { + result.SigningKey.PublicKey.Exponent = *PropertyIns->ContainerPtrToValuePtr(Class->GetDefaultObject()); + } + if(PropertyIns->GetName().Equals(SIGNING_MODULES_NAME)) + { + result.SigningKey.PublicKey.Modulus = *PropertyIns->ContainerPtrToValuePtr(Class->GetDefaultObject()); + result.SigningKey.PrivateKey.Modulus = result.SigningKey.PublicKey.Modulus; + } + if(PropertyIns->GetName().Equals(SIGNING_PRIVATE_EXPONENT_NAME)) + { + result.SigningKey.PrivateKey.Exponent = *PropertyIns->ContainerPtrToValuePtr(Class->GetDefaultObject()); + } + } + } + return result; +} + +FEncryptSetting UFlibHotPatcherEditorHelper::GetCryptoSettingsByJson(const FString& CryptoJson) +{ + FEncryptSetting result; + FArchive* File = IFileManager::Get().CreateFileReader(*CryptoJson); + TSharedPtr RootObject; + TSharedRef> Reader = TJsonReaderFactory::Create(File); + if (FJsonSerializer::Deserialize(Reader, RootObject)) + { + result.bSign = RootObject->GetBoolField(TEXT("bEnablePakSigning")); + result.bEncryptIndex = RootObject->GetBoolField(TEXT("bEnablePakIndexEncryption")); + result.bEncryptIniFiles = RootObject->GetBoolField(TEXT("bEnablePakIniEncryption")); + result.bEncryptUAssetFiles = RootObject->GetBoolField(TEXT("bEnablePakUAssetEncryption")); + result.bEncryptAllAssetFiles = RootObject->GetBoolField(TEXT("bEnablePakFullAssetEncryption")); + } + return result; +} + +FEncryptSetting UFlibHotPatcherEditorHelper::GetCryptoSettingByPakEncryptSettings(const FPakEncryptSettings& Config) +{ + FEncryptSetting EncryptSettings; + if(Config.bUseDefaultCryptoIni) + { + FPakEncryptionKeys ProjectCrypt = UFlibHotPatcherEditorHelper::GetCryptoByProjectSettings(); + EncryptSettings.bEncryptIniFiles = ProjectCrypt.bEnablePakIniEncryption; + EncryptSettings.bEncryptUAssetFiles = ProjectCrypt.bEnablePakUAssetEncryption; + EncryptSettings.bEncryptAllAssetFiles = ProjectCrypt.bEnablePakFullAssetEncryption; + EncryptSettings.bEncryptIndex = ProjectCrypt.bEnablePakIndexEncryption; + EncryptSettings.bSign = ProjectCrypt.bEnablePakSigning; + } + else + { + FString CryptoKeyFile = FPaths::ConvertRelativePathToFull(Config.CryptoKeys.FilePath); + if(FPaths::FileExists(CryptoKeyFile)) + { + FEncryptSetting CryptoJsonSettings = UFlibHotPatcherEditorHelper::GetCryptoSettingsByJson(CryptoKeyFile); + EncryptSettings.bEncryptIniFiles = CryptoJsonSettings.bEncryptIniFiles; + EncryptSettings.bEncryptUAssetFiles = CryptoJsonSettings.bEncryptUAssetFiles; + EncryptSettings.bEncryptAllAssetFiles = CryptoJsonSettings.bEncryptAllAssetFiles; + EncryptSettings.bSign = CryptoJsonSettings.bSign; + EncryptSettings.bEncryptIndex = CryptoJsonSettings.bEncryptIndex; + } + } + return EncryptSettings; +} + +bool UFlibHotPatcherEditorHelper::SerializePakEncryptionKeyToFile(const FPakEncryptionKeys& PakEncryptionKeys, + const FString& ToFile) +{ + FString KeyInfo; + UFlibPatchParserHelper::TSerializeStructAsJsonString(PakEncryptionKeys,KeyInfo); + return UFLibAssetManageHelperEx::SaveStringToFile(ToFile, KeyInfo); +} + +FString UFlibHotPatcherEditorHelper::GetPakCommandExtersion(const FString& InCommand) +{ + auto GetPakCommandFileExtensionLambda = [](const FString& Command)->FString + { + FString result; + int32 DotPos = Command.Find(TEXT("."), ESearchCase::CaseSensitive, ESearchDir::FromEnd); + if (DotPos != INDEX_NONE) + { + result = Command.Mid(DotPos + 1); + int32 FirstDoubleQuotesPos = -1; + if(result.FindChar('"',FirstDoubleQuotesPos)) + { + result.RemoveAt(FirstDoubleQuotesPos,result.Len()-FirstDoubleQuotesPos); + } + } + return result; + }; + return GetPakCommandFileExtensionLambda(InCommand); +} + +TArray UFlibHotPatcherEditorHelper::GetExtensionsToNotUsePluginCompressionByGConfig() +{ + TArray IgnoreCompressFormats; + GConfig->GetArray(TEXT("Pak"),TEXT("ExtensionsToNotUsePluginCompression"),IgnoreCompressFormats,GEngineIni); + return IgnoreCompressFormats; +} + +void UFlibHotPatcherEditorHelper::AppendPakCommandOptions(TArray& OriginCommands, + const TArray& Options, bool bAppendAllMatch, const TArray& AppendFileExtersions, + const TArray& IgnoreFormats, const TArray& InIgnoreOptions) +{ + for(auto& Command:OriginCommands) + { + FString PakOptionsStr; + for (const auto& Param : Options) + { + FString FileExtension = UFlibHotPatcherEditorHelper::GetPakCommandExtersion(Command); + if(IgnoreFormats.Contains(FileExtension) && InIgnoreOptions.Contains(Param)) + { + continue; + } + + FString AppendOptionStr = TEXT(""); + if(bAppendAllMatch || AppendFileExtersions.Contains(FileExtension)) + { + AppendOptionStr += TEXT(" ") + Param; + } + + PakOptionsStr += AppendOptionStr; + } + Command = FString::Printf(TEXT("%s%s"),*Command,*PakOptionsStr); + } +} diff --git a/HotPatcher/Source/HotPatcherEditor/Private/GameFeature/GameFeatureProxy.cpp b/HotPatcher/Source/HotPatcherEditor/Private/GameFeature/GameFeatureProxy.cpp new file mode 100644 index 00000000..998f389f --- /dev/null +++ b/HotPatcher/Source/HotPatcherEditor/Private/GameFeature/GameFeatureProxy.cpp @@ -0,0 +1,82 @@ +#include "GameFeature/GameFeatureProxy.h" + +#include + +#include "HotPatcherEditor.h" +#include "CreatePatch/PatcherProxy.h" + +bool UGameFeatureProxy::DoExport() +{ + PatchSettings = MakeShareable(new FExportPatchSettings); + FString FeatureName = GetSettingObject()->FeatureName; + // make patch setting + { + PatchSettings->bByBaseVersion = false; + PatchSettings->VersionId = GetSettingObject()->FeatureName; + FDirectoryPath FeaturePluginPath; + FeaturePluginPath.Path = FString::Printf(TEXT("/%s"),*PatchSettings->VersionId); + + PatchSettings->AssetIncludeFilters.Add(FeaturePluginPath); + + FPlatformExternAssets PlatformExternAssets; + { + PlatformExternAssets.TargetPlatform = ETargetPlatform::AllPlatforms; + FExternFileInfo FeaturePlugin; + + if(UFlibPatchParserHelper::GetPluginPakPathByName(PatchSettings->VersionId,FeaturePlugin.FilePath.FilePath,FeaturePlugin.MountPath)) + { + FeaturePlugin.Type = EPatchAssetType::NEW; + PlatformExternAssets.AddExternFileToPak.Add(FeaturePlugin); + + TSharedPtr Plugin = IPluginManager::Get().FindPlugin(FeatureName); + if(Plugin) + { + for(const auto& NonContentDir:GetSettingObject()->NonContentDirs) + { + FString PluginConfigDir = FPaths::ConvertRelativePathToFull(FPaths::Combine(Plugin->GetBaseDir(),NonContentDir)); + if(FPaths::DirectoryExists(PluginConfigDir)) + { + FExternDirectoryInfo ConfigDir; + ConfigDir.DirectoryPath.Path = PluginConfigDir; + ConfigDir.MountPoint = FPaths::Combine(Plugin->GetBaseDir(),NonContentDir); + PlatformExternAssets.AddExternDirectoryToPak.Add(ConfigDir); + } + } + } + } + } + PatchSettings->AddExternAssetsToPlatform.Add(PlatformExternAssets); + PatchSettings->bCookPatchAssets = GetSettingObject()->bCookPatchAssets; + + { + PatchSettings->SerializeAssetRegistryOptions = GetSettingObject()->SerializeAssetRegistryOptions; + PatchSettings->SerializeAssetRegistryOptions.AssetRegistryMountPointRegular = FString::Printf(TEXT("%s[%s]"),AS_PLUGINDIR_MARK,*GetSettingObject()->FeatureName); + PatchSettings->SerializeAssetRegistryOptions.AssetRegistryNameRegular = FString::Printf(TEXT("AssetRegistry.bin")); + } + { + PatchSettings->CookShaderOptions = GetSettingObject()->CookShaderOptions; + PatchSettings->CookShaderOptions.bSharedShaderLibrary = true; + PatchSettings->CookShaderOptions.bNativeShader = true; + PatchSettings->CookShaderOptions.ShderLibMountPointRegular = FString::Printf(TEXT("%s[%s]"),AS_PLUGINDIR_MARK,*GetSettingObject()->FeatureName); + } + PatchSettings->IoStoreSettings = GetSettingObject()->IoStoreSettings; + PatchSettings->EncryptSettings = GetSettingObject()->EncryptSettings; + PatchSettings->PakTargetPlatforms.Append(GetSettingObject()->TargetPlatforms); + PatchSettings->SavePath.Path = GetSettingObject()->GetSaveAbsPath(); + PatchSettings->bStorageNewRelease = false; + PatchSettings->bStorageConfig = true; + } + UPatcherProxy* PatcherProxy = NewObject(); + PatcherProxy->AddToRoot(); + PatcherProxy->SetProxySettings(PatchSettings.Get()); + PatcherProxy->DoExport(); + + if(GetSettingObject()->IsSaveConfig()) + { + FString SaveToFile = FPaths::Combine(GetSettingObject()->GetSaveAbsPath(),FString::Printf(TEXT("%s_GameFeatureConfig.json"),*GetSettingObject()->FeatureName)); + FString SerializedJsonStr; + UFlibPatchParserHelper::TSerializeStructAsJsonString(*GetSettingObject(),SerializedJsonStr); + FFileHelper::SaveStringToFile(SerializedJsonStr, *SaveToFile); + } + return Super::DoExport(); +} diff --git a/HotPatcher/Source/HotPatcherEditor/Private/GameFeature/SGameFeaturePackager.cpp b/HotPatcher/Source/HotPatcherEditor/Private/GameFeature/SGameFeaturePackager.cpp new file mode 100644 index 00000000..2340ae17 --- /dev/null +++ b/HotPatcher/Source/HotPatcherEditor/Private/GameFeature/SGameFeaturePackager.cpp @@ -0,0 +1,271 @@ +#include "SGameFeaturePackager.h" +#include "FlibPatchParserHelper.h" +#include "FlibHotPatcherEditorHelper.h" +#include "HotPatcherEditor.h" +#include "GameFeature/FGameFeaturePackagerSettings.h" +#include "CreatePatch/PatcherProxy.h" +#include "CreatePatch/SHotPatcherExportPatch.h" +#include "GameFeature/GameFeatureProxy.h" +#include "Interfaces/IPluginManager.h" +#include "Kismet/KismetSystemLibrary.h" + +#include "Kismet/KismetTextLibrary.h" + +#define LOCTEXT_NAMESPACE "SHotPatcherGameFeaturePackager" + +void SHotPatcherGameFeaturePackager::Construct(const FArguments& InArgs, + TSharedPtr InCreateModel) +{ + GameFeaturePackagerSettings = MakeShareable(new FGameFeaturePackagerSettings); + CreateExportFilterListView(); + + mCreatePatchModel = InCreateModel; + + ChildSlot + [ + SNew(SVerticalBox) + + SVerticalBox::Slot() + .AutoHeight() + .Padding(FEditorStyle::GetMargin("StandardDialog.ContentPadding")) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .VAlign(VAlign_Center) + [ + SettingsView->GetWidget()->AsShared() + ] + ] + + + SVerticalBox::Slot() + .AutoHeight() + .Padding(0.0, 8.0, 0.0, 0.0) + + SVerticalBox::Slot() + .AutoHeight() + .HAlign(HAlign_Right) + .Padding(4, 4, 10, 4) + [ + SNew(SButton) + .Text(LOCTEXT("GenerateGameFeature", "Generate GameFeature")) + .OnClicked(this,&SHotPatcherGameFeaturePackager::DoGameFeaturePackager) + .IsEnabled(this,&SHotPatcherGameFeaturePackager::CanGameFeaturePackager) + .ToolTipText(this,&SHotPatcherGameFeaturePackager::GetGenerateTooltipText) + ] + ]; +} + +void SHotPatcherGameFeaturePackager::ImportConfig() +{ + UE_LOG(LogHotPatcher, Log, TEXT("Import Game Feature Packager Config")); + TArray Files = this->OpenFileDialog(); + if (!Files.Num()) return; + + FString LoadFile = Files[0]; + + FString JsonContent; + if (UFLibAssetManageHelperEx::LoadFileToString(LoadFile, JsonContent)) + { + // UFlibHotPatcherEditorHelper::DeserializeReleaseConfig(ExportReleaseSettings, JsonContent); + UFlibPatchParserHelper::TDeserializeJsonStringAsStruct(JsonContent,*GameFeaturePackagerSettings); + SettingsView->GetDetailsView()->ForceRefresh(); + } +} + +void SHotPatcherGameFeaturePackager::ExportConfig() const +{ + UE_LOG(LogHotPatcher, Log, TEXT("Export Game Feature Packager Config")); + TArray Files = this->SaveFileDialog(); + + if (!Files.Num()) return; + + FString SaveToFile = Files[0].EndsWith(TEXT(".json")) ? Files[0] : Files[0].Append(TEXT(".json")); + + if (GameFeaturePackagerSettings) + { + FString SerializedJsonStr; + UFlibPatchParserHelper::TSerializeStructAsJsonString(*GameFeaturePackagerSettings,SerializedJsonStr); + if (FFileHelper::SaveStringToFile(SerializedJsonStr, *SaveToFile)) + { + FText Msg = LOCTEXT("SavedGameFeatureConfigMas", "Successd to Export the Game Feature Packager Config."); + UFlibHotPatcherEditorHelper::CreateSaveFileNotify(Msg, SaveToFile); + } + } +} + +void SHotPatcherGameFeaturePackager::ResetConfig() +{ + UE_LOG(LogHotPatcher, Log, TEXT("Reset Game Feature Packager Config")); + FString DefaultSettingJson; + UFlibPatchParserHelper::TSerializeStructAsJsonString(*FGameFeaturePackagerSettings::Get(),DefaultSettingJson); + UFlibPatchParserHelper::TDeserializeJsonStringAsStruct(DefaultSettingJson,*GameFeaturePackagerSettings); + SettingsView->GetDetailsView()->ForceRefresh(); +} + +// #if ENGINE_GAME_FEATURE +// #include "GameFeaturesSubsystem.h" +// #endif +void SHotPatcherGameFeaturePackager::DoGenerate() +{ +#if ENGINE_GAME_FEATURE + if(GetConfigSettings()->bAutoLoadFeaturePlugin) + { + FString FeatureName = GetConfigSettings()->FeatureName; + FString OutPluginURL; + UWorld* World = GEditor->GetEditorWorldContext().World(); + + if(World) + { + auto GameFeatureFounder = [](const FString& FeatureName) + { + bool bFound = false; + FString FeaturePluginDir = FPaths::ConvertRelativePathToFull(FPaths::Combine(FPaths::ProjectPluginsDir(),TEXT("GameFeatures"),FeatureName)); + FString FeatureUPluginPath = FPaths::Combine(FeaturePluginDir,FString::Printf(TEXT("%s.uplugin"),*FeatureName)); + + if(FPaths::DirectoryExists(FeaturePluginDir) && FPaths::FileExists(FeatureUPluginPath)) + { + bFound = true; + } + return bFound; + }; + + if(IPluginManager::Get().FindPlugin(TEXT("GameFeatures")).IsValid() && + IPluginManager::Get().FindPlugin(TEXT("ModularGameplay")).IsValid() + ) + { + if(GameFeatureFounder(FeatureName)) + { + UKismetSystemLibrary::ExecuteConsoleCommand(World,FString::Printf(TEXT("LoadGameFeaturePlugin %s"),*FeatureName)); + UKismetSystemLibrary::ExecuteConsoleCommand(World,FString::Printf(TEXT("DeactivateGameFeaturePlugin %s"),*FeatureName)); + } + } + else + { + UE_LOG(LogHotPatcher,Warning,TEXT("GameFeatures or ModularGameplay is not Enabled!")); + } + + if(IPluginManager::Get().FindPlugin(FeatureName)) + { + FeaturePackager(); + } + else + { + UE_LOG(LogHotPatcher,Error,TEXT("%s load faild, %s"),*GetConfigSettings()->FeatureName); + } + } + // UGameFeaturesSubsystem::Get().GetPluginURLForBuiltInPluginByName(FeatureName,OutPluginURL); + // UGameFeaturesSubsystem::Get().LoadGameFeaturePlugin(OutPluginURL,FGameFeaturePluginDeactivateComplete::CreateLambda([this](const UE::GameFeatures::FResult& InStatus) + // { + // if(InStatus.IsValid() && !InStatus.HasError()) + // { + // FeaturePackager(); + // } + // else + // { + // UE_LOG(LogHotPatcher,Error,TEXT("Package Feature %s faild, %s"),*GetConfigSettings()->FeatureName,**InStatus.TryGetError()); + // } + // })); + } +#endif +} + +void SHotPatcherGameFeaturePackager::FeaturePackager() +{ + if(!GetConfigSettings()->IsStandaloneMode()) + { + UGameFeatureProxy* GameFeatureProxy = NewObject(); + GameFeatureProxy->AddToRoot(); + GameFeatureProxy->SetProxySettings(GetConfigSettings()); + GameFeatureProxy->DoExport(); + } + else + { + FString CurrentConfig; + UFlibPatchParserHelper::TSerializeStructAsJsonString(*GetConfigSettings(),CurrentConfig); + FString SaveConfigTo = FPaths::ConvertRelativePathToFull(FPaths::Combine(FPaths::ProjectSavedDir(),TEXT("HotPatcher"),FString::Printf(TEXT("%s_GameFeatureConfig.json"),*GetConfigSettings()->FeatureName))); + FFileHelper::SaveStringToFile(CurrentConfig,*SaveConfigTo); + FString MissionCommand = FString::Printf(TEXT("\"%s\" -run=HotPlugin -config=\"%s\" %s"),*UFlibPatchParserHelper::GetProjectFilePath(),*SaveConfigTo,*GetConfigSettings()->GetCombinedAdditionalCommandletArgs()); + UE_LOG(LogHotPatcher,Log,TEXT("HotPatcher %s Mission: %s %s"),*GetMissionName(),*UFlibHotPatcherEditorHelper::GetUECmdBinary(),*MissionCommand); + FHotPatcherEditorModule::Get().RunProcMission(UFlibHotPatcherEditorHelper::GetUECmdBinary(),MissionCommand,GetMissionName()); + } +} + +FText SHotPatcherGameFeaturePackager::GetGenerateTooltipText() const +{ + FString FinalString; + struct FStatus + { + FStatus(bool InMatch,const FString& InDisplay):bMatch(InMatch) + { + Display = FString::Printf(TEXT("%s:%s"),*InDisplay,InMatch?TEXT("true"):TEXT("false")); + } + FString GetDisplay()const{return Display;} + bool bMatch; + FString Display; + }; + TArray AllStatus; + AllStatus.Emplace(HasValidConfig(),TEXT("HasValidGameFeatureConfig")); + bool bHasSavePath = GameFeaturePackagerSettings->GetSaveAbsPath().IsEmpty()?false:FPaths::DirectoryExists(GameFeaturePackagerSettings->GetSaveAbsPath()); + AllStatus.Emplace(bHasSavePath,TEXT("HasSavePath")); + + for(const auto& Status:AllStatus) + { + FinalString+=FString::Printf(TEXT("%s\n"),*Status.GetDisplay()); + } + return UKismetTextLibrary::Conv_StringToText(FinalString); +} + +void SHotPatcherGameFeaturePackager::CreateExportFilterListView() +{ + // Create a property view + FPropertyEditorModule& EditModule = FModuleManager::Get().GetModuleChecked("PropertyEditor"); + + FDetailsViewArgs DetailsViewArgs; + { + DetailsViewArgs.bAllowSearch = true; + DetailsViewArgs.bHideSelectionTip = true; + DetailsViewArgs.bLockable = false; + DetailsViewArgs.bSearchInitialKeyFocus = true; + DetailsViewArgs.bUpdatesFromSelection = false; + DetailsViewArgs.NotifyHook = nullptr; + DetailsViewArgs.bShowOptions = true; + DetailsViewArgs.bShowModifiedPropertiesOption = false; + DetailsViewArgs.bShowScrollBar = false; + DetailsViewArgs.bShowOptions = true; + DetailsViewArgs.bUpdatesFromSelection= true; + } + + FStructureDetailsViewArgs StructureViewArgs; + { + StructureViewArgs.bShowObjects = true; + StructureViewArgs.bShowAssets = true; + StructureViewArgs.bShowClasses = true; + StructureViewArgs.bShowInterfaces = true; + } + + SettingsView = EditModule.CreateStructureDetailView(DetailsViewArgs, StructureViewArgs, nullptr); + FStructOnScope* Struct = new FStructOnScope(FGameFeaturePackagerSettings::StaticStruct(), (uint8*)GameFeaturePackagerSettings.Get()); + // SettingsView->GetOnFinishedChangingPropertiesDelegate().AddRaw(ExportReleaseSettings.Get(),&FGameFeaturePackagerSettings::OnFinishedChangingProperties); + // SettingsView->GetDetailsView()->RegisterInstancedCustomPropertyLayout(FGameFeaturePackagerSettings::StaticStruct(),FOnGetDetailCustomizationInstance::CreateStatic(&FReleaseSettingsDetails::MakeInstance)); + SettingsView->SetStructureData(MakeShareable(Struct)); +} + +bool SHotPatcherGameFeaturePackager::CanGameFeaturePackager() const +{ + bool bHasSavePath = GameFeaturePackagerSettings->GetSaveAbsPath().IsEmpty()?false:FPaths::DirectoryExists(GameFeaturePackagerSettings->GetSaveAbsPath()); + return HasValidConfig() && bHasSavePath; +} + +bool SHotPatcherGameFeaturePackager::HasValidConfig() const +{ + bool bHasTarget = !!GetConfigSettings()->TargetPlatforms.Num(); + return bHasTarget; +} + +FReply SHotPatcherGameFeaturePackager::DoGameFeaturePackager() +{ + DoGenerate(); + return FReply::Handled(); +} + + + +#undef LOCTEXT_NAMESPACE diff --git a/HotPatcher/Source/HotPatcherEditor/Private/GameFeature/SGameFeaturePackager.h b/HotPatcher/Source/HotPatcherEditor/Private/GameFeature/SGameFeaturePackager.h new file mode 100644 index 00000000..d75fcf1d --- /dev/null +++ b/HotPatcher/Source/HotPatcherEditor/Private/GameFeature/SGameFeaturePackager.h @@ -0,0 +1,60 @@ +// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "Model/FHotPatcherCreatePatchModel.h" +#include "CreatePatch/SHotPatcherPatchableBase.h" +#include "GameFeature/FGameFeaturePackagerSettings.h" + +// engine header +#include "Templates/SharedPointer.h" +#include "IStructureDetailsView.h" + +/** + * Implements the cooked platforms panel. + */ +class SHotPatcherGameFeaturePackager + : public SHotPatcherPatchableBase +{ +public: + + SLATE_BEGIN_ARGS(SHotPatcherGameFeaturePackager) { } + SLATE_END_ARGS() + +public: + + /** + * Constructs the widget. + * + * @param InArgs The Slate argument list. + */ + void Construct( const FArguments& InArgs,TSharedPtr InCreateModel); + +public: + virtual void ImportConfig(); + virtual void ImportProjectConfig(){}; + virtual void ExportConfig()const; + virtual void ResetConfig(); + virtual void DoGenerate(); + + virtual FGameFeaturePackagerSettings* GetConfigSettings() override{return GameFeaturePackagerSettings.Get();}; + virtual FGameFeaturePackagerSettings* GetConfigSettings()const {return GameFeaturePackagerSettings.Get();}; + + virtual FString GetMissionName() override{return TEXT("Game Feature Packager");} + virtual FText GetGenerateTooltipText() const override; +protected: + void CreateExportFilterListView(); + bool CanGameFeaturePackager()const; + bool HasValidConfig()const; + FReply DoGameFeaturePackager(); + void FeaturePackager(); + +private: + + // TSharedPtr mCreatePatchModel; + TSharedPtr PatchSettings; + /** Settings view ui element ptr */ + TSharedPtr SettingsView; + TSharedPtr GameFeaturePackagerSettings; +}; + diff --git a/HotPatcher/Source/HotPatcherEditor/Private/Model/FHotPatcherCreatePatchModel.h b/HotPatcher/Source/HotPatcherEditor/Private/Model/FHotPatcherCreatePatchModel.h index b3a662ef..89d4cc21 100644 --- a/HotPatcher/Source/HotPatcherEditor/Private/Model/FHotPatcherCreatePatchModel.h +++ b/HotPatcher/Source/HotPatcherEditor/Private/Model/FHotPatcherCreatePatchModel.h @@ -8,7 +8,8 @@ namespace EHotPatcherActionModes { ByPatch, ByRelease, - ByShaderPatch + ByShaderPatch, + ByGameFeature }; } diff --git a/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/SVersionUpdaterWidget.cpp b/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/SVersionUpdaterWidget.cpp index 745be1f0..d202bc42 100644 --- a/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/SVersionUpdaterWidget.cpp +++ b/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/SVersionUpdaterWidget.cpp @@ -21,7 +21,7 @@ void SVersionUpdaterWidget::Construct(const FArguments& InArgs) static bool GBrushInited = false; if(!GBrushInited) { - FVersionUpdaterStyle::Initialize(); + FVersionUpdaterStyle::Initialize(FString::Printf(TEXT("%s_UpdaterStyle"),TOOL_NAME)); FVersionUpdaterStyle::ReloadTextures(); GBrushInited = true; } diff --git a/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/VersionUpdaterStyle.cpp b/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/VersionUpdaterStyle.cpp index 96161302..2da01ab4 100644 --- a/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/VersionUpdaterStyle.cpp +++ b/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/VersionUpdaterStyle.cpp @@ -7,11 +7,11 @@ TSharedPtr< FSlateStyleSet > FVersionUpdaterStyle::StyleInstance = NULL; -void FVersionUpdaterStyle::Initialize() +void FVersionUpdaterStyle::Initialize(const FString& Name) { if (!StyleInstance.IsValid()) { - StyleInstance = Create(); + StyleInstance = Create(Name); FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance); } } @@ -40,9 +40,9 @@ const FVector2D Updater_Icon16x16(16.0f, 16.0f); const FVector2D Updater_Icon20x20(20.0f, 20.0f); const FVector2D Updater_Icon40x40(40.0f, 40.0f); -TSharedRef< FSlateStyleSet > FVersionUpdaterStyle::Create() +TSharedRef< FSlateStyleSet > FVersionUpdaterStyle::Create(const FString& Name) { - TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("VersionUpdaterStyle")); + TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet(*Name)); Style->SetContentRoot( FPaths::EngineContentDir() / TEXT("Editor/Slate") ); Style->SetCoreContentRoot(FPaths::EngineContentDir() / TEXT("Slate")); diff --git a/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/VersionUpdaterStyle.h b/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/VersionUpdaterStyle.h index 047872d7..cd47283c 100644 --- a/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/VersionUpdaterStyle.h +++ b/HotPatcher/Source/HotPatcherEditor/Private/SVersionUpdater/VersionUpdaterStyle.h @@ -3,13 +3,15 @@ #pragma once #include "CoreMinimal.h" +#include "Chaos/AABB.h" +#include "Chaos/AABB.h" #include "Styling/SlateStyle.h" class FVersionUpdaterStyle { public: - static void Initialize(); + static void Initialize(const FString& Name); static void Shutdown(); @@ -24,7 +26,7 @@ class FVersionUpdaterStyle static const FSlateBrush* GetBrush( FName PropertyName, const ANSICHAR* Specifier = NULL ); private: - static TSharedRef< class FSlateStyleSet > Create(); + static TSharedRef< class FSlateStyleSet > Create(const FString& Name); private: diff --git a/HotPatcher/Source/HotPatcherEditor/Public/CreatePatch/SProjectCreatePatchPage.h b/HotPatcher/Source/HotPatcherEditor/Public/CreatePatch/SProjectCreatePatchPage.h index 11b1ff42..fc30c3f1 100644 --- a/HotPatcher/Source/HotPatcherEditor/Public/CreatePatch/SProjectCreatePatchPage.h +++ b/HotPatcher/Source/HotPatcherEditor/Public/CreatePatch/SProjectCreatePatchPage.h @@ -40,6 +40,7 @@ class SProjectCreatePatchPage EVisibility HandleExportPatchVisibility() const; EVisibility HandleExportReleaseVisibility() const; EVisibility HandleExportShaderPatchVisibility() const; + EVisibility HandleExportGameFeatureVisibility() const; EVisibility HandleOperatorConfigVisibility()const; EVisibility HandleImportProjectConfigVisibility()const; @@ -55,4 +56,5 @@ class SProjectCreatePatchPage TSharedPtr mPatch; TSharedPtr mRelease; TSharedPtr mShaderPatch; + TSharedPtr mGameFeature; }; diff --git a/HotPatcher/Source/HotPatcherEditor/Public/FlibHotPatcherEditorHelper.h b/HotPatcher/Source/HotPatcherEditor/Public/FlibHotPatcherEditorHelper.h index e6e8b3fe..0ca75e22 100644 --- a/HotPatcher/Source/HotPatcherEditor/Public/FlibHotPatcherEditorHelper.h +++ b/HotPatcher/Source/HotPatcherEditor/Public/FlibHotPatcherEditorHelper.h @@ -23,6 +23,72 @@ DECLARE_LOG_CATEGORY_EXTERN(LogHotPatcherEditorHelper, Log, All); struct FExportPatchSettings; + + +USTRUCT() +struct FEncryptionKeyEntry +{ + GENERATED_BODY() + UPROPERTY() + FString Name; + UPROPERTY() + FString Guid; + UPROPERTY() + FString Key; +}; + +USTRUCT() +struct FSignKeyItem +{ + GENERATED_BODY() + UPROPERTY() + FString Exponent; + UPROPERTY() + FString Modulus; +}; + +USTRUCT() +struct FSignKeyEntry +{ + GENERATED_BODY() + UPROPERTY() + FSignKeyItem PublicKey; + UPROPERTY() + FSignKeyItem PrivateKey; +}; + +USTRUCT() +struct FPakEncryptionKeys +{ + GENERATED_BODY(); + + UPROPERTY() + FEncryptionKeyEntry EncryptionKey; + UPROPERTY() + TArray SecondaryEncryptionKeys; + + UPROPERTY() + bool bEnablePakIndexEncryption; + UPROPERTY() + bool bEnablePakIniEncryption; + UPROPERTY() + bool bEnablePakUAssetEncryption; + UPROPERTY() + bool bEnablePakFullAssetEncryption; + UPROPERTY() + bool bDataCryptoRequired; + UPROPERTY() + bool PakEncryptionRequired; + UPROPERTY() + bool PakSigningRequired; + + UPROPERTY() + bool bEnablePakSigning; + UPROPERTY() + FSignKeyEntry SigningKey; +}; + + /** * */ @@ -135,5 +201,33 @@ class HOTPATCHEREDITOR_API UFlibHotPatcherEditorHelper : public UBlueprintFuncti static FHotPatcherVersion MakeNewRelease(const FHotPatcherVersion& InBaseVersion, const FHotPatcherVersion& InCurrentVersion, FExportPatchSettings* InPatchSettings); static FHotPatcherVersion MakeNewReleaseByDiff(const FHotPatcherVersion& InBaseVersion, const FPatchVersionDiff& InDiff, FExportPatchSettings* InPatchSettings); +public: + // Encrypt + static FPakEncryptionKeys GetCryptoByProjectSettings(); + static FEncryptSetting GetCryptoSettingsByJson(const FString& CryptoJson); + static FEncryptSetting GetCryptoSettingByPakEncryptSettings(const FPakEncryptSettings& Config); + + static bool SerializePakEncryptionKeyToFile(const FPakEncryptionKeys& PakEncryptionKeys,const FString& ToFile); +public: + // In: "C:\Users\lipengzha\Documents\UnrealProjects\Blank425\Intermediate\Staging\Blank425.upluginmanifest" "../../../Blank425/Plugins/Blank425.upluginmanifest + // To: upluginmanifest + static FString GetPakCommandExtersion(const FString& InCommand); + + // [Pak] + // +ExtensionsToNotUsePluginCompression=uplugin + // +ExtensionsToNotUsePluginCompression=upluginmanifest + // +ExtensionsToNotUsePluginCompression=uproject + // +ExtensionsToNotUsePluginCompression=ini + // +ExtensionsToNotUsePluginCompression=icu + // +ExtensionsToNotUsePluginCompression=res + static TArray GetExtensionsToNotUsePluginCompressionByGConfig(); + + static void AppendPakCommandOptions( + TArray& OriginCommands, + const TArray& Options, + bool bAppendAllMatch, + const TArray& AppendFileExtersions, + const TArray& IgnoreFormats, + const TArray& InIgnoreOptions); }; diff --git a/HotPatcher/Source/HotPatcherEditor/Public/GameFeature/FGameFeaturePackagerSettings.h b/HotPatcher/Source/HotPatcherEditor/Public/GameFeature/FGameFeaturePackagerSettings.h new file mode 100644 index 00000000..10c60a10 --- /dev/null +++ b/HotPatcher/Source/HotPatcherEditor/Public/GameFeature/FGameFeaturePackagerSettings.h @@ -0,0 +1,73 @@ +#pragma once + +#include "HotPatcherLog.h" +#include "CreatePatch/HotPatcherSettingBase.h" +#include "FlibPatchParserHelper.h" +#include "HotPatcherLog.h" +#include "CreatePatch/FExportPatchSettings.h" + +// engine header +#include "Misc/FileHelper.h" +#include "CoreMinimal.h" +#include "ETargetPlatform.h" +#include "UObject/ObjectMacros.h" +#include "UObject/Object.h" +#include "Engine/EngineTypes.h" +#include "Kismet/KismetStringLibrary.h" +#include "Serialization/JsonSerializer.h" +#include "Serialization/JsonWriter.h" + +#include "FGameFeaturePackagerSettings.generated.h" + +/** Singleton wrapper to allow for using the setting structure in SSettingsView */ +USTRUCT(BlueprintType) +struct HOTPATCHEREDITOR_API FGameFeaturePackagerSettings:public FHotPatcherSettingBase +{ + GENERATED_USTRUCT_BODY() +public: + FGameFeaturePackagerSettings() + { + SerializeAssetRegistryOptions.bSerializeAssetRegistry = true; + NonContentDirs.AddUnique(TEXT("Config")); + } + virtual ~FGameFeaturePackagerSettings(){}; + + FORCEINLINE static FGameFeaturePackagerSettings* Get() + { + static FGameFeaturePackagerSettings StaticIns; + + return &StaticIns; + } + + UPROPERTY(EditAnywhere) + FString FeatureName; + + UPROPERTY(EditAnywhere, BlueprintReadWrite) + bool bAutoLoadFeaturePlugin = true; + // Config/ Script/ etc. + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TArray NonContentDirs; + /* + * Cook Asset in current patch + * shader code gets saved inline inside material assets + * bShareMaterialShaderCode as false + */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Base") + bool bCookPatchAssets = true; + + // UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Base", meta=(EditCondition = "bCookPatchAssets")) + FCookShaderOptions CookShaderOptions; + // UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Base", meta=(EditCondition = "bCookPatchAssets")) + FAssetRegistryOptions SerializeAssetRegistryOptions; + + // support UE4.26 later + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Base") + FIoStoreSettings IoStoreSettings; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base") + FPakEncryptSettings EncryptSettings; + + UPROPERTY(EditAnywhere, Category="Base") + TArray TargetPlatforms; +}; + diff --git a/HotPatcher/Source/HotPatcherEditor/Public/GameFeature/GameFeatureProxy.h b/HotPatcher/Source/HotPatcherEditor/Public/GameFeature/GameFeatureProxy.h new file mode 100644 index 00000000..f042ffd3 --- /dev/null +++ b/HotPatcher/Source/HotPatcherEditor/Public/GameFeature/GameFeatureProxy.h @@ -0,0 +1,21 @@ +#pragma once +#include "ThreadUtils/FThreadUtils.hpp" +#include "FGameFeaturePackagerSettings.h" +// engine header +#include "Templates/SharedPointer.h" +#include "CreatePatch/HotPatcherProxyBase.h" +#include "GameFeatureProxy.generated.h" + + +UCLASS() +class HOTPATCHEREDITOR_API UGameFeatureProxy:public UHotPatcherProxyBase +{ + GENERATED_BODY() +public: + virtual bool DoExport() override; + virtual FGameFeaturePackagerSettings* GetSettingObject()override{ return (FGameFeaturePackagerSettings*)Setting; } + +private: + TSharedPtr PatchSettings; + TSharedPtr ThreadWorker; +}; diff --git a/HotPatcher/Source/HotPatcherRuntime/HotPatcherRuntime.Build.cs b/HotPatcher/Source/HotPatcherRuntime/HotPatcherRuntime.Build.cs index ecc17aa8..06d74e74 100644 --- a/HotPatcher/Source/HotPatcherRuntime/HotPatcherRuntime.Build.cs +++ b/HotPatcher/Source/HotPatcherRuntime/HotPatcherRuntime.Build.cs @@ -76,6 +76,7 @@ public HotPatcherRuntime(ReadOnlyTargetRules Target) : base(Target) PrivateDependencyModuleNames.Add("ShaderCore"); } bLegacyPublicIncludePaths = false; + OptimizeCode = CodeOptimization.InShippingBuildsOnly; } } diff --git a/HotPatcher/Source/HotPatcherRuntime/Private/FlibPakHelper.cpp b/HotPatcher/Source/HotPatcherRuntime/Private/FlibPakHelper.cpp index 29aebc9e..7d55b0ba 100644 --- a/HotPatcher/Source/HotPatcherRuntime/Private/FlibPakHelper.cpp +++ b/HotPatcher/Source/HotPatcherRuntime/Private/FlibPakHelper.cpp @@ -19,8 +19,11 @@ #include "IPlatformFilePak.h" #include "ShaderPipelineCache.h" #include "RHI.h" +#include "AssetRegistryState.h" #include "Misc/Base64.h" #include "Misc/CoreDelegates.h" +#include "Serialization/LargeMemoryReader.h" +#include "ShaderCodeLibrary.h" void UFlibPakHelper::ExecMountPak(FString InPakPath, int32 InPakOrder, FString InMountPoint) { @@ -399,23 +402,93 @@ int32 UFlibPakHelper::GetPakOrderByPakPath(const FString& PakFile) return PakOrder; } -bool UFlibPakHelper::LoadAssetRegistry(const FString& InAssetRegistryBin) +void UFlibPakHelper::ReloadShaderbytecode() { - FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")); - IAssetRegistry& AssetRegistry = AssetRegistryModule.Get(); - bool bSuccess = false; + FShaderCodeLibrary::OpenLibrary("Global", FPaths::ProjectContentDir()); + FShaderCodeLibrary::OpenLibrary(FApp::GetProjectName(), FPaths::ProjectContentDir()); +} + + +bool UFlibPakHelper::LoadShaderbytecode(const FString& LibraryName, const FString& LibraryDir) +{ + bool result = true; + FString FinalLibraryDir = LibraryDir; +#if PLATFORM_IOS + FinalLibraryDir = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*LibraryDir);; +#endif +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 23 + result = FShaderCodeLibrary::OpenLibrary(LibraryName, LibraryDir); +#else + FShaderCodeLibrary::OpenLibrary(LibraryName, LibraryDir); +#endif + UE_LOG(LogHotPatcher,Log,TEXT("Load Shader bytecode %s,Dir: %s, status: %s"),*LibraryName,*FinalLibraryDir,result?TEXT("True"):TEXT("False")); + return result; +} + +void UFlibPakHelper::CloseShaderbytecode(const FString& LibraryName) +{ + FShaderCodeLibrary::CloseLibrary(LibraryName); +} + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 26 +bool UFlibPakHelper::LoadAssetRegistryToState(const TCHAR* Path,FAssetRegistryState& Out) +{ + check(Path); + + TUniquePtr FileReader(IFileManager::Get().CreateFileReader(Path)); + if (FileReader) + { + // It's faster to load the whole file into memory on a Gen5 console + TArray64 Data; + Data.SetNumUninitialized(FileReader->TotalSize()); + FileReader->Serialize(Data.GetData(), Data.Num()); + check(!FileReader->IsError()); + + FLargeMemoryReader MemoryReader(Data.GetData(), Data.Num()); + return Out.Load(MemoryReader, FAssetRegistryLoadOptions{}); + } + + return false; +} +#else +bool UFlibPakHelper::LoadAssetRegistryToState(const TCHAR* Path, FAssetRegistryState& Out) +{ + bool bStatus = false; + FString AssetRegistryPath = Path; FArrayReader SerializedAssetData; - FString AssetRegistryBinPath = InAssetRegistryBin; - UE_LOG(LogHotPatcher,Log,TEXT("Load AssetRegistry %s"),*AssetRegistryBinPath); - if (IFileManager::Get().FileExists(*AssetRegistryBinPath) && FFileHelper::LoadFileToArray(SerializedAssetData, *AssetRegistryBinPath)) + // FString AssetRegistryBinPath = InAssetRegistryBin; + // UE_LOG(LogHotPatcher,Log,TEXT("Load AssetRegistry %s"),*AssetRegistryBinPath); + if (IFileManager::Get().FileExists(*AssetRegistryPath) && FFileHelper::LoadFileToArray(SerializedAssetData, *AssetRegistryPath)) + { + FAssetRegistryState State; + FAssetRegistrySerializationOptions SerializationOptions; + SerializationOptions.bSerializeAssetRegistry = true; + bStatus = State.Serialize(SerializedAssetData, SerializationOptions); + } + return bStatus; +} +#endif + +bool UFlibPakHelper::LoadAssetRegistry(const FString& LibraryName, const FString& LibraryDir) +{ + bool bStatus = false; + FString AssetRegistryPath = FPaths::Combine(LibraryDir,FString::Printf(TEXT("%s.bin"),*LibraryName)); + UE_LOG(LogHotPatcher,Log,TEXT("Load Asset Registry %s"),*AssetRegistryPath); + if(FPaths::FileExists(AssetRegistryPath)) { - SerializedAssetData.Seek(0); - AssetRegistry.Serialize(SerializedAssetData); - bSuccess = true; + FAssetRegistryState State; + if(LoadAssetRegistryToState(*AssetRegistryPath,State)) + { + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")); + AssetRegistryModule.Get().AppendState(State); + bStatus = true; + } } - return bSuccess; + return bStatus; } + + bool UFlibPakHelper::OpenPSO(const FString& Name) { return FShaderPipelineCache::OpenPipelineFileCache(Name,GMaxRHIShaderPlatform); diff --git a/HotPatcher/Source/HotPatcherRuntime/Private/FlibPatchParserHelper.cpp b/HotPatcher/Source/HotPatcherRuntime/Private/FlibPatchParserHelper.cpp index 4d6df555..9bbbb7e2 100644 --- a/HotPatcher/Source/HotPatcherRuntime/Private/FlibPatchParserHelper.cpp +++ b/HotPatcher/Source/HotPatcherRuntime/Private/FlibPatchParserHelper.cpp @@ -19,8 +19,10 @@ #include "HAL/FileManager.h" #include "Engine/EngineTypes.h" #include "JsonObjectConverter.h" +#include "AssetRegistryState.h" #include "Misc/Paths.h" #include "Kismet/KismetStringLibrary.h" +#include "Serialization/LargeMemoryReader.h" TArray UFlibPatchParserHelper::GetAvailableMaps(FString GameName, bool IncludeEngineMaps, bool IncludePluginMaps, bool Sorted) { @@ -1596,31 +1598,6 @@ FString UFlibPatchParserHelper::MountPathToRelativePath(const FString& InMountPa return Path/filename; } - -#include "ShaderCodeLibrary.h" - -void UFlibPatchParserHelper::ReloadShaderbytecode() -{ - FShaderCodeLibrary::OpenLibrary("Global", FPaths::ProjectContentDir()); - FShaderCodeLibrary::OpenLibrary(FApp::GetProjectName(), FPaths::ProjectContentDir()); -} - -bool UFlibPatchParserHelper::LoadShaderbytecode(const FString& LibraryName, const FString& LibraryDir) -{ - bool result = true; - FString FinalLibraryDir = LibraryDir; -#if PLATFORM_IOS - FinalLibraryDir = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*LibraryDir);; -#endif -#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 23 - result = FShaderCodeLibrary::OpenLibrary(LibraryName, LibraryDir); -#else - FShaderCodeLibrary::OpenLibrary(LibraryName, LibraryDir); -#endif - UE_LOG(LogHotPatcher,Log,TEXT("Load Shader bytecode %s,Dir: %s, status: %s"),*LibraryName,*FinalLibraryDir,result?TEXT("True"):TEXT("False")); - return result; -} - FString UFlibPatchParserHelper::SerializeAssetsDependencyAsJsonString( const TArray& InAssetsDependency) { @@ -1746,10 +1723,10 @@ TMap UFlibPatchParserHelper::GetReplacePathMarkMap() return MarkMap; } -FString UFlibPatchParserHelper::ReplaceMarkPath(const FString& Src) +FString UFlibPatchParserHelper::ReplaceMark(const FString& Src) { TMap MarkMap = UFlibPatchParserHelper::GetReplacePathMarkMap(); - auto ReplaceProjectDir = [&MarkMap](const FString& OriginDir)->FString + auto ReplaceStringMark = [&MarkMap](const FString& OriginDir)->FString { TArray MarkKeys; MarkMap.GetKeys(MarkKeys); @@ -1765,14 +1742,17 @@ FString UFlibPatchParserHelper::ReplaceMarkPath(const FString& Src) break; } } - - FPaths::MakeStandardFilename(result); - result = FPaths::ConvertRelativePathToFull(result); return result; }; - return ReplaceProjectDir(Src); + return ReplaceStringMark(Src); +} +FString UFlibPatchParserHelper::ReplaceMarkPath(const FString& Src) +{ + FString result = UFlibPatchParserHelper::ReplaceMark(Src); + FPaths::MakeStandardFilename(result); + result = FPaths::ConvertRelativePathToFull(result); + return result; } - void UFlibPatchParserHelper::ReplacePatherSettingProjectDir(TArray& PlatformAssets) { @@ -1941,3 +1921,84 @@ FString UFlibPatchParserHelper::UAssetMountPathToPackagePath(const FString& InAs return LongPackagePath; } +bool UFlibPatchParserHelper::GetPluginPakPathByName(const FString& PluginName,FString& uPluginAbsPath,FString& uPluginMountPath) +{ + bool bStatus = false; + TSharedPtr FoundPlugin = IPluginManager::Get().FindPlugin(PluginName); + FString uPluginFileAbsPath; + FString uPluginFileMountPath; + if(FoundPlugin.IsValid()) + { + uPluginFileAbsPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(FoundPlugin->GetBaseDir(),FString::Printf(TEXT("%s.uplugin"),*FoundPlugin->GetName()))); + FPaths::NormalizeFilename(uPluginFileAbsPath); + + uPluginFileMountPath = uPluginFileAbsPath; + + if(FPaths::FileExists(uPluginFileAbsPath)) + { + FString EnginePluginPath = FPaths::ConvertRelativePathToFull(FPaths::EnginePluginsDir()); + FString ProjectPluginPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectPluginsDir()); + if(uPluginFileMountPath.StartsWith(EnginePluginPath)) + { + uPluginFileMountPath.RemoveFromStart(EnginePluginPath); + uPluginFileMountPath = FString::Printf(TEXT("../../../Engine/Plugins/%s"),*uPluginFileMountPath); + } + if(uPluginFileMountPath.StartsWith(ProjectPluginPath)) + { + uPluginFileMountPath.RemoveFromStart(ProjectPluginPath); + uPluginFileMountPath = FString::Printf(TEXT("../../../%s/Plugins/%s"),FApp::GetProjectName(),*uPluginFileMountPath); + } + uPluginAbsPath = uPluginFileAbsPath; + uPluginMountPath = uPluginFileMountPath; + bStatus = true; + } + } + return bStatus; +} + +FString UFlibPatchParserHelper::GetPluginMountPoint(const FString& PluginName) +{ + FString uPluginAbsPath; + FString uPluginMountPath; + if(UFlibPatchParserHelper::GetPluginPakPathByName(PluginName,uPluginAbsPath,uPluginMountPath)) + { + uPluginMountPath.RemoveFromEnd(FString::Printf(TEXT("/%s.uplugin"),*PluginName)); + } + return uPluginMountPath; +} + +FString UFlibPatchParserHelper::ParserMountPointRegular(const FString& Src) +{ + FString result; + if(Src.MatchesWildcard(FString::Printf(TEXT("*%s*"),AS_PROJECTDIR_MARK))) + { + result = Src.Replace(AS_PROJECTDIR_MARK,*FString::Printf(TEXT("../../../%s"),FApp::GetProjectName())); + } + if(Src.MatchesWildcard(FString::Printf(TEXT("*%s*"),AS_PLUGINDIR_MARK))) + { + int32 index = Src.Find(AS_PLUGINDIR_MARK); + index += strlen(TCHAR_TO_ANSI(AS_PLUGINDIR_MARK)); + int32 BeginIndex = index + 1; + int32 EndIndex; + Src.FindLastChar(']',EndIndex); + FString PluginName = UKismetStringLibrary::GetSubstring(Src,BeginIndex,EndIndex-BeginIndex); + result = Src.Replace(AS_PLUGINDIR_MARK,TEXT("")); + result = result.Replace(*FString::Printf(TEXT("[%s]"),*PluginName),*UFlibPatchParserHelper::GetPluginMountPoint(PluginName)); + } + return result; +} + +void UFlibPatchParserHelper::ReloadShaderbytecode() +{ + UFlibPakHelper::ReloadShaderbytecode(); +} + +bool UFlibPatchParserHelper::LoadShaderbytecode(const FString& LibraryName, const FString& LibraryDir) +{ + return UFlibPakHelper::LoadShaderbytecode(LibraryName,LibraryDir); +} + +void UFlibPatchParserHelper::CloseShaderbytecode(const FString& LibraryName) +{ + UFlibPakHelper::CloseShaderbytecode(LibraryName); +} diff --git a/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/FExportPatchSettings.h b/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/FExportPatchSettings.h index 839271ba..e3ef42ae 100644 --- a/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/FExportPatchSettings.h +++ b/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/FExportPatchSettings.h @@ -36,25 +36,26 @@ #include "Serialization/JsonSerializer.h" #include "FExportPatchSettings.generated.h" +struct FEncryptSetting +{ + // -encryptindex + bool bEncryptIndex = false; + bool bEncryptAllAssetFiles = false; + bool bEncryptUAssetFiles = false; + bool bEncryptIniFiles = false; + // sign pak + bool bSign = false; +}; USTRUCT(BlueprintType) struct HOTPATCHERRUNTIME_API FPakEncryptSettings { GENERATED_BODY() - // -encrypt - UPROPERTY(EditAnywhere) - bool bEncryptAllAssetFiles = false; - // -encryptindex - UPROPERTY(EditAnywhere) - bool bEncryptIndex = false; // Use DefaultCrypto.ini - UPROPERTY(EditAnywhere) + UPROPERTY(EditAnywhere,BlueprintReadWrite) bool bUseDefaultCryptoIni = false; - // sign pak - UPROPERTY(EditAnywhere,meta=(EditCondition="bUseDefaultCryptoIni")) - bool bSign = false; // crypto.json (option) - UPROPERTY(EditAnywhere,meta=(EditCondition="!bUseDefaultCryptoIni")) + UPROPERTY(EditAnywhere,BlueprintReadWrite,meta=(EditCondition="!bUseDefaultCryptoIni")) FFilePath CryptoKeys; }; @@ -66,14 +67,20 @@ enum class EShaderLibNameRule : uint8 CUSTOM }; + +#define AS_PROJECTDIR_MARK TEXT("[PROJECTDIR]") +#define AS_PLUGINDIR_MARK TEXT("[PLUGINDIR]") + USTRUCT(BlueprintType) struct FCookShaderOptions { GENERATED_BODY() FCookShaderOptions() { - ShderLibMountPoint = FString::Printf(TEXT("../../../%s/ShaderLibs"),FApp::GetProjectName()); + ShderLibMountPointRegular = FString::Printf(TEXT("%s/ShaderLibs"),AS_PROJECTDIR_MARK); } + FString GetShaderLibMountPointRegular()const { return ShderLibMountPointRegular; } + UPROPERTY(EditAnywhere, BlueprintReadWrite) bool bSharedShaderLibrary = false; UPROPERTY(EditAnywhere, BlueprintReadWrite) @@ -86,7 +93,7 @@ struct FCookShaderOptions UPROPERTY(EditAnywhere, BlueprintReadWrite,meta=(EditCondition="ShaderNameRule==EShaderLibNameRule::CUSTOM")) FString CustomShaderName; UPROPERTY(EditAnywhere, BlueprintReadWrite) - FString ShderLibMountPoint; + FString ShderLibMountPointRegular; }; UENUM(BlueprintType) @@ -96,25 +103,27 @@ enum class EAssetRegistryRule : uint8 PER_CHUNK }; + USTRUCT(BlueprintType) -struct FAssetRegistryOptions +struct HOTPATCHERRUNTIME_API FAssetRegistryOptions { GENERATED_BODY() FAssetRegistryOptions() { - AssetRegistryMountPoint = FString::Printf(TEXT("../../../%s/AssetRegistry"),FApp::GetProjectName()); + AssetRegistryMountPointRegular = FString::Printf(TEXT("%s/AssetRegistry"),AS_PROJECTDIR_MARK); AssetRegistryNameRegular = FString::Printf(TEXT("[CHUNK_NAME]_AssetRegistry.bin")); } FString GetAssetRegistryNameRegular(const FString& ChunkName)const { return AssetRegistryNameRegular.Replace(TEXT("[CHUNK_NAME]"),*ChunkName); } - + FString GetAssetRegistryMountPointRegular()const { return AssetRegistryMountPointRegular; } + UPROPERTY(EditAnywhere, BlueprintReadWrite) bool bSerializeAssetRegistry = false; UPROPERTY(EditAnywhere, BlueprintReadWrite) - FString AssetRegistryMountPoint; + FString AssetRegistryMountPointRegular; UPROPERTY(EditAnywhere, BlueprintReadWrite) EAssetRegistryRule AssetRegistryRule = EAssetRegistryRule::PATCH; UPROPERTY(EditAnywhere, BlueprintReadWrite) @@ -225,6 +234,7 @@ struct HOTPATCHERRUNTIME_API FExportPatchSettings:public FHotPatcherSettingBase FORCEINLINE bool IsStorageNewRelease()const{return bStorageNewRelease;} FORCEINLINE bool IsStoragePakFileInfo()const{return bStoragePakFileInfo;} + FORCEINLINE bool IsBackupMetadata()const {return bBackupMetadata;} FORCEINLINE FPakEncryptSettings GetEncryptSettings()const{ return EncryptSettings; } FORCEINLINE bool IsBinariesPatch()const{ return bBinariesPatch; } @@ -340,9 +350,7 @@ struct HOTPATCHERRUNTIME_API FExportPatchSettings:public FHotPatcherSettingBase UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pak Options") FPakEncryptSettings EncryptSettings; - // // crypto.json - // UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pak Options") - // FFilePath CryptoKeys; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pak Options") TArray ReplacePakListTexts; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pak Options") @@ -366,7 +374,8 @@ struct HOTPATCHERRUNTIME_API FExportPatchSettings:public FHotPatcherSettingBase bool bStorageDiffAnalysisResults = true; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SaveTo") bool bStorageAssetDependencies = false; - + UPROPERTY(EditAnywhere,BlueprintReadWrite, Category = "SaveTo") + bool bBackupMetadata = false; // UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Advanced") bool bEnableMultiThread = false; diff --git a/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/FExportReleaseSettings.h b/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/FExportReleaseSettings.h index 8031e77c..deb93917 100644 --- a/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/FExportReleaseSettings.h +++ b/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/FExportReleaseSettings.h @@ -79,6 +79,7 @@ struct HOTPATCHERRUNTIME_API FExportReleaseSettings:public FHotPatcherSettingBas FORCEINLINE bool IsSaveAssetRelatedInfo()const { return bStorageAssetDependencies; } FORCEINLINE bool IsIncludeHasRefAssetsOnly()const { return bIncludeHasRefAssetsOnly; } FORCEINLINE bool IsAnalysisFilterDependencies()const { return bAnalysisFilterDependencies; } + FORCEINLINE bool IsBackupMetadata()const {return bBackupMetadata;} FORCEINLINE TArray GetAssetRegistryDependencyTypes()const { return AssetRegistryDependencyTypes; } FORCEINLINE TArray GetSpecifyAssets()const { return IncludeSpecifyAssets; } FORCEINLINE bool AddSpecifyAsset(FPatcherSpecifyAsset const& InAsset){ return IncludeSpecifyAssets.AddUnique(InAsset) != INDEX_NONE; } @@ -124,9 +125,11 @@ struct HOTPATCHERRUNTIME_API FExportReleaseSettings:public FHotPatcherSettingBas TArray AddExternDirectoryToPak; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ExternFiles") TArray AddExternAssetsToPlatform; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SaveTo") bool bStorageAssetDependencies = false; - + UPROPERTY(EditAnywhere,BlueprintReadWrite, Category = "SaveTo") + bool bBackupMetadata = false; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "SaveTo",meta=(EditCondition="bBackupMetadata")) TArray BackupMetadataPlatforms; }; \ No newline at end of file diff --git a/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/HotPatcherSettingBase.h b/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/HotPatcherSettingBase.h index 8049f292..c770439f 100644 --- a/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/HotPatcherSettingBase.h +++ b/HotPatcher/Source/HotPatcherRuntime/Public/CreatePatch/HotPatcherSettingBase.h @@ -28,7 +28,6 @@ struct HOTPATCHERRUNTIME_API FHotPatcherSettingBase virtual FString GetSaveAbsPath()const; FORCEINLINE virtual bool IsStandaloneMode()const {return bStandaloneMode;} - FORCEINLINE virtual bool IsBackupMetadata()const {return bBackupMetadata;} FORCEINLINE virtual bool IsSaveConfig()const {return bStorageConfig;} FORCEINLINE virtual TArray GetAdditionalCommandletArgs()const{return AdditionalCommandletArgs;} FORCEINLINE virtual FString GetCombinedAdditionalCommandletArgs()const @@ -45,8 +44,6 @@ struct HOTPATCHERRUNTIME_API FHotPatcherSettingBase public: // backup current project Cooked/PLATFORM/PROJECTNAME/Metadata directory UPROPERTY(EditAnywhere, Category = "SaveTo") - bool bBackupMetadata = false; - UPROPERTY(EditAnywhere, Category = "SaveTo") bool bStorageConfig = true; UPROPERTY(EditAnywhere, Category = "SaveTo") FDirectoryPath SavePath; diff --git a/HotPatcher/Source/HotPatcherRuntime/Public/FlibPakHelper.h b/HotPatcher/Source/HotPatcherRuntime/Public/FlibPakHelper.h index 85cfadde..28f10a4e 100644 --- a/HotPatcher/Source/HotPatcherRuntime/Public/FlibPakHelper.h +++ b/HotPatcher/Source/HotPatcherRuntime/Public/FlibPakHelper.h @@ -10,6 +10,7 @@ #include "Templates/SharedPointer.h" #include "Dom/JsonObject.h" #include "IPlatformFilePak.h" +#include "AssetRegistryState.h" #include "FlibPakHelper.generated.h" #if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >=26 @@ -70,8 +71,6 @@ class HOTPATCHERRUNTIME_API UFlibPakHelper : public UBlueprintFunctionLibrary UFUNCTION(BlueprintCallable) static int32 GetPakOrderByPakPath(const FString& PakFile); - UFUNCTION(BlueprintCallable) - static bool LoadAssetRegistry(const FString& InAssetRegistryBin); // Default Load FApp::GetProjectName() on Enging launching UFUNCTION(BlueprintCallable) @@ -85,4 +84,19 @@ class HOTPATCHERRUNTIME_API UFlibPakHelper : public UBlueprintFunctionLibrary #else static TSharedPtr GetPakFileIns(const FString& InPak, const FString& AESKey); #endif + +public: + + // reload Global&Project shaderbytecode + UFUNCTION(BlueprintCallable) + static void ReloadShaderbytecode(); + UFUNCTION(BlueprintCallable,Exec) + static bool LoadShaderbytecode(const FString& LibraryName, const FString& LibraryDir); + UFUNCTION(BlueprintCallable,Exec) + static void CloseShaderbytecode(const FString& LibraryName); + + static bool LoadAssetRegistryToState(const TCHAR* Path,FAssetRegistryState& Out); + UFUNCTION(BlueprintCallable,Exec) + static bool LoadAssetRegistry(const FString& LibraryName, const FString& LibraryDir); + }; diff --git a/HotPatcher/Source/HotPatcherRuntime/Public/FlibPatchParserHelper.h b/HotPatcher/Source/HotPatcherRuntime/Public/FlibPatchParserHelper.h index e649edf3..57110be6 100644 --- a/HotPatcher/Source/HotPatcherRuntime/Public/FlibPatchParserHelper.h +++ b/HotPatcher/Source/HotPatcherRuntime/Public/FlibPatchParserHelper.h @@ -28,6 +28,7 @@ #include "JsonObjectConverter.h" #include "Misc/CommandLine.h" #include "FPlatformExternAssets.h" +#include "AssetRegistryState.h" #include "Containers/UnrealString.h" #include "Templates/SharedPointer.h" #include "Kismet/BlueprintFunctionLibrary.h" @@ -296,12 +297,6 @@ class HOTPATCHERRUNTIME_API UFlibPatchParserHelper : public UBlueprintFunctionLi #endif static FString MountPathToRelativePath(const FString& InMountPath); - // reload Global&Project shaderbytecode - UFUNCTION(BlueprintCallable) - static void ReloadShaderbytecode(); - UFUNCTION(BlueprintCallable,Exec) - static bool LoadShaderbytecode(const FString& LibraryName, const FString& LibraryDir); - static FString SerializeAssetsDependencyAsJsonString(const TArray& InAssetsDependency); static bool SerializePlatformPakInfoToString(const TMap>& InPakFilesMap, FString& OutString); static bool SerializePlatformPakInfoToJsonObject(const TMap>& InPakFilesMap, TSharedPtr& OutJsonObject); @@ -436,6 +431,7 @@ class HOTPATCHERRUNTIME_API UFlibPatchParserHelper : public UBlueprintFunctionLi ); static TMap GetReplacePathMarkMap(); + static FString ReplaceMark(const FString& Src); static FString ReplaceMarkPath(const FString& Src); // [PORJECTDIR] to real path static void ReplacePatherSettingProjectDir(TArray& PlatformAssets); @@ -451,5 +447,19 @@ class HOTPATCHERRUNTIME_API UFlibPatchParserHelper : public UBlueprintFunctionLi static bool MatchStrInArray(const FString& InStr,const TArray& InArray); static FString LoadAESKeyStringFromCryptoFile(const FString& InCryptoJson); static FAES::FAESKey LoadAESKeyFromCryptoFile(const FString& InCryptoJson); +public: + static bool GetPluginPakPathByName(const FString& PluginName,FString& uPluginAbsPath,FString& uPluginMountPath); + // ../../../Example/Plugin/XXXX/ + static FString GetPluginMountPoint(const FString& PluginName); + // [PRIJECTDIR]/AssetRegistry to ../../../Example/AssetRegistry + static FString ParserMountPointRegular(const FString& Src); + +public: + UFUNCTION(BlueprintCallable) + static void ReloadShaderbytecode(); + UFUNCTION(BlueprintCallable,Exec) + static bool LoadShaderbytecode(const FString& LibraryName, const FString& LibraryDir); + UFUNCTION(BlueprintCallable,Exec) + static void CloseShaderbytecode(const FString& LibraryName); };