What I want to do is to procedural generate a list of maps available in my game menu.
I found some code in GameMapsSettingsCustomization.h:
const FString MapFileWildCard = FString::Printf(TEXT("*%s"), *FPackageName::GetMapPackageExtension());
//TArray<FString> MapNames;
IFileManager::Get().FindFilesRecursive(MapNames, *FPaths::GameContentDir(), *MapFileWildCard, true, false);
MapNames.Sort(](const FString& A, const FString& B) { return FPaths::GetBaseFilename(A) < FPaths::GetBaseFilename(B); });
for (int i = 0; i < MapNames.Num(); ++i)
{
UE_LOG(LogClass, Log, TEXT("GameContentDir map: %s"), *MapNames*);
}
But stepping through FindFilesRecursive I find it is using the windows file system to look for files, so this isn’t going to look inside pak files for files?
I made a custom pak file that has a umap in it, and it is not showing up in FindFilesRecursive, I can see my Pak file is mounted at load time.
Is there something similar to FindFilesRecursive that searches Pak files?
And does a UPackage represent a file that is inside a Pak file? From my searching through the code this appears to be the case but I’m not sure.
I ended with something like this, this piece of code had to load list of maps that are in the specified pak, but then I realized that I didn’t get “friendly/localized” map name with this solution:) And I wrote another solution with simple pak/mod/plugin descriptor.
Of course it need some code hacking at the engine side. This:
TArray<FPakPlatformFile::FPakListEntry> MountedPaks; can't be declared outside engine dll, because it isn't exported from it.
FPakPlatformFile* PakPlatformFile = new FPakPlatformFile();
PakPlatformFile->Initialize(&InnerPlatformFile, TEXT(""));
PakPlatformFile->Mount(*PakToLoad, 0, *(ModDir /*+ TEXT("/") + ModPakFileName*/));
TArray<FPakPlatformFile::FPakListEntry> MountedPaks;
PakPlatformFile->GetMountedPaks(MountedPaks);
//ignore first pak, because it is default game pak and we don't need iterate over it
for (int32 i = 1; i < MountedPaks.Num();i++)
{
const FPakPlatformFile::FPakListEntry& mountedPak = MountedPaks*;
const TMap<FString, FPakDirectory>& pakDirectoryMap = mountedPak.PakFile->GetIndex();
for (TMap<FString, FPakDirectory>::TConstIterator It(pakDirectoryMap); It; ++It)
{
FString Key = It.Key();
const FPakDirectory& Val = It.Value();
for (FPakDirectory::TConstIterator It2(Val); It2; ++It2)
{
FString Key2 = It2.Key();
FPakEntry* pakEntry = It2.Value();
if (Key2.Contains(TEXT(".umap")))
{
//this is where you will get map name of course if your map have *.umap extension:)
Key2 = Key2;
}
}
}
}