RealtimeStyleTransferRuntime/Source/LyraGame/Hotfix/LyraHotfixManager.cpp

232 lines
6.6 KiB
C++
Raw Permalink Normal View History

2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "LyraHotfixManager.h"
#include "Misc/AES.h"
#include "Misc/Base64.h"
#include "Misc/CoreDelegates.h"
#include "UObject/UObjectIterator.h"
#include "Engine/NetDriver.h"
#include "Engine/GameEngine.h"
#include "Misc/FileHelper.h"
#include "Misc/CString.h"
#include "DeviceProfiles/DeviceProfileManager.h"
#include "DeviceProfiles/DeviceProfile.h"
#include "Settings/LyraSettingsLocal.h"
#include "TimerManager.h"
#include "HAL/MemoryMisc.h"
int32 ULyraHotfixManager::GameHotfixCounter = 0;
ULyraHotfixManager::ULyraHotfixManager()
{
#if !UE_BUILD_SHIPPING
OnScreenMessageHandle = FCoreDelegates::OnGetOnScreenMessages.AddUObject(this, &ULyraHotfixManager::GetOnScreenMessages);
#endif // !UE_BUILD_SHIPPING
HotfixCompleteDelegateHandle = AddOnHotfixCompleteDelegate_Handle(FOnHotfixCompleteDelegate::CreateUObject(this, &ThisClass::OnHotfixCompleted));
}
void ULyraHotfixManager::Init()
{
Super::Init();
}
void ULyraHotfixManager::OnHotfixCompleted(EHotfixResult HotfixResult)
{
// Reload DDoS detection config for all live Net Drivers (mirrors RepGraph code)
for (TObjectIterator<UNetDriver> It; It; ++It)
{
if (It->IsServer())
{
UE_LOG(LogHotfixManager, Log, TEXT("Reloading DDoS detection settings for NetDriver: %s"), *It->GetName());
It->DDoS.InitConfig();
}
}
if (bHasPendingDeviceProfileHotfix)
{
UE_LOG(LogHotfixManager, Log, TEXT("Re-applying Hotfixed DeviceProfile"));
bHasPendingDeviceProfileHotfix = false;
UDeviceProfileManager::Get().ReapplyDeviceProfile();
ULyraSettingsLocal* GameSettings = ULyraSettingsLocal::Get();
GameSettings->OnHotfixDeviceProfileApplied();
}
#if ENABLE_SHARED_MEMORY_TRACKER
FSharedMemoryTracker::PrintMemoryDiff(TEXT("Hotfix Complete"));
#endif
}
ULyraHotfixManager::~ULyraHotfixManager()
{
ClearOnHotfixCompleteDelegate_Handle(HotfixCompleteDelegateHandle);
#if !UE_BUILD_SHIPPING
FCoreDelegates::OnGetOnScreenMessages.Remove(OnScreenMessageHandle);
#endif // !UE_BUILD_SHIPPING
}
bool ULyraHotfixManager::WantsHotfixProcessing(const FCloudFileHeader& FileHeader)
{
bool bWantsProcessing = Super::WantsHotfixProcessing(FileHeader);
if (!bWantsProcessing)
{
FString SupportedFiles[] = {
TEXT("AssetMigrations.ini")
};
for (FString SupportedFile : SupportedFiles)
{
#if !UE_BUILD_SHIPPING
if (!DebugPrefix.IsEmpty())
{
SupportedFile = DebugPrefix + SupportedFile;
}
#endif
if (SupportedFile == FileHeader.FileName)
{
bWantsProcessing = true;
break;
}
}
}
return bWantsProcessing;
}
bool ULyraHotfixManager::HotfixIniFile(const FString& FileName, const FString& IniData)
{
if (!bHasPendingDeviceProfileHotfix && FileName.EndsWith(TEXT("DEVICEPROFILES.INI"), ESearchCase::IgnoreCase))
{
FConfigFile DeviceProfileHotfixConfig;
DeviceProfileHotfixConfig.CombineFromBuffer(IniData);
TSet<FString> Keys;
for (const auto& DPSection : DeviceProfileHotfixConfig)
{
FString DeviceProfileName, DeviceProfileClass;
if (DPSection.Key.Split(TEXT(" "), &DeviceProfileName, &DeviceProfileClass) && DeviceProfileClass == *UDeviceProfile::StaticClass()->GetName())
{
Keys.Add(DeviceProfileName);
}
}
// Check if any of the hotfixed device profiles are referenced by the currently active profile(s):
bHasPendingDeviceProfileHotfix = UDeviceProfileManager::Get().DoActiveProfilesReference(Keys);
UE_LOG(LogHotfixManager, Log, TEXT("Active device profile was referenced by hotfix = %d"), (uint32)bHasPendingDeviceProfileHotfix);
}
return Super::HotfixIniFile(FileName, IniData);
}
bool ULyraHotfixManager::ApplyHotfixProcessing(const FCloudFileHeader& FileHeader)
{
// This allows json files to be downloaded automatically
const FString Extension = FPaths::GetExtension(FileHeader.FileName);
if (Extension == TEXT("json"))
{
return true;
}
const bool bResult = Super::ApplyHotfixProcessing(FileHeader);
if (bResult && FileHeader.FileName.EndsWith(TEXT("GAME.INI"), ESearchCase::IgnoreCase))
{
GameHotfixCounter++;
if (bHasPendingGameHotfix)
{
bHasPendingGameHotfix = false;
OnPendingGameHotfixChanged.Broadcast(bHasPendingGameHotfix);
}
}
return bResult;
}
bool ULyraHotfixManager::ShouldWarnAboutMissingWhenPatchingFromIni(const FString& AssetPath) const
{
return AssetPath.StartsWith(TEXT("/Engine/")) || AssetPath.StartsWith(TEXT("/Game/"));
}
void ULyraHotfixManager::PatchAssetsFromIniFiles()
{
#if ENABLE_SHARED_MEMORY_TRACKER
FSharedMemoryTracker::PrintMemoryDiff(TEXT("Start - PatchAssetsFromIniFiles"));
#endif
Super::PatchAssetsFromIniFiles();
#if ENABLE_SHARED_MEMORY_TRACKER
FSharedMemoryTracker::PrintMemoryDiff(TEXT("End - PatchAssetsFromIniFiles"));
#endif
}
void ULyraHotfixManager::OnHotfixAvailablityCheck(const TArray<FCloudFileHeader>& PendingChangedFiles, const TArray<FCloudFileHeader>& PendingRemoveFiles)
{
bool bNewPendingGameHotfix = false;
for (int32 Idx = 0; Idx < PendingChangedFiles.Num(); Idx++)
{
if (PendingChangedFiles[Idx].FileName.EndsWith(TEXT("GAME.INI"), ESearchCase::IgnoreCase))
{
bNewPendingGameHotfix = true;
break;
}
}
if (bNewPendingGameHotfix && !bHasPendingGameHotfix)
{
bHasPendingGameHotfix = true;
OnPendingGameHotfixChanged.Broadcast(bHasPendingGameHotfix);
}
}
bool ULyraHotfixManager::PreProcessDownloadedFileData(TArray<uint8>& FileData) const
{
// No need to preprocess if there is no data
if (FileData.Num() == 0)
{
return true;
}
//TODO Any Preprocessing?
return true;
}
#if !UE_BUILD_SHIPPING
void ULyraHotfixManager::GetOnScreenMessages(TMultiMap<FCoreDelegates::EOnScreenMessageSeverity, FText>& OutMessages)
{
// TODO Any messages/errors.
}
#endif // !UE_BUILD_SHIPPING
void ULyraHotfixManager::RequestPatchAssetsFromIniFiles()
{
if (!RequestPatchAssetsHandle.IsValid())
{
RequestPatchAssetsHandle = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateWeakLambda(this, [this](float DeltaTime) {
RequestPatchAssetsHandle.Reset();
UE_LOG(LogHotfixManager, Display, TEXT("Hotfix manager re-calling PatchAssetsFromIniFiles due to new plugins"));
PatchAssetsFromIniFiles();
return false;
}));
}
}
void ULyraHotfixManager::StartHotfixProcess()
{
if (GIsEditor)
{
UE_LOG(LogHotfixManager, Display, TEXT("Hotfixing skipped in development mode."));
TriggerHotfixComplete(EHotfixResult::SuccessNoChange);
return;
}
#if ENABLE_SHARED_MEMORY_TRACKER
FSharedMemoryTracker::PrintMemoryDiff(TEXT("StartHotfixProcess"));
#endif
Super::StartHotfixProcess();
}