Skip to content

Instantly share code, notes, and snippets.

@schellingb
Created March 26, 2024 03:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save schellingb/c2739dea95f9bea2510c480259998242 to your computer and use it in GitHub Desktop.
Save schellingb/c2739dea95f9bea2510c480259998242 to your computer and use it in GitHub Desktop.
Load GameUserSettings.ini from a UE4 build of a game in a UE5 build of a game
#if PLATFORM_WINDOWS && !WITH_EDITOR && UE_BUILD_SHIPPING
static struct FUE4GameUserSettingsLoader
{
FUE4GameUserSettingsLoader()
{
// This static constructor is called early enough that we can bind these required delegates before engine startup
FCoreDelegates::TSCountPreLoadConfigFileRespondersDelegate().AddStatic(CountPreLoadConfigFileRespondersDelegate);
FCoreDelegates::TSPreLoadConfigFileDelegate().AddStatic(PreLoadConfigFileDelegate);
FCoreDelegates::TSPreSaveConfigFileDelegate().AddStatic(PreSaveConfigFileDelegate);
}
static bool Checked, UpgradeActive;
static FString UE5Path, UE4Path;
static void CountPreLoadConfigFileRespondersDelegate(const TCHAR* inipath, int32& responderCount)
{
if (!FCStringWide::Stristr(inipath, TEXT("GameUserSettings"))) return;
const TCHAR* pWindows = FCString::Strrstr(inipath, TEXT("Windows"));
if (!pWindows) return; // wrong path
if (pWindows != inipath && pWindows[-1] != '/' && pWindows[-1] != '\\') return; // no slash before
if (pWindows[7] != '/' && pWindows[7] != '\\') return; // no slash after
if (!Checked)
{
(UE4Path = UE5Path = inipath).InsertAt((int32)(pWindows - inipath) + 7, TEXT("NoEditor")); // Change UE5's /Windows/ to UE4's /WindowsNoEditor/
UpgradeActive = IFileManager::Get().FileExists(*UE4Path);
Checked = true;
}
if (UpgradeActive) responderCount++;
}
static void PreLoadConfigFileDelegate(const TCHAR* inipath, FString& contents)
{
if (!UpgradeActive || UE5Path != inipath) return;
FFileHelper::LoadFileToString(contents, *UE4Path);
}
static void PreSaveConfigFileDelegate(const TCHAR* inipath, const FString& contents, int32& savedCount)
{
if (!UpgradeActive || UE5Path != inipath) return;
FFileHelper::SaveStringToFile(contents, *UE4Path, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM);
savedCount++;
}
} GDSIniUpgrader;
bool FUE4GameUserSettingsLoader::Checked, FUE4GameUserSettingsLoader::UpgradeActive;
FString FUE4GameUserSettingsLoader::UE5Path, FUE4GameUserSettingsLoader::UE4Path;
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment