/** * Converts a path pointing into the installed directory (C:\Program Files\MyGame\ExampleGame\Config\ExampleEngine.ini) * to a path that a least-privileged user can write to (C:\<UserDir>\MyGame\ExampleGame\Config\ExampleEngine.ini) * * @param AbsolutePath Source path to convert * * @return Path to the user directory */ FString FFileManagerWindows::ConvertAbsolutePathToUserPath(const TCHAR* AbsolutePath) { // if the user directory has been setup, use it if (WindowsUserDir.Len() > 0) { const UBOOL bUseUnpublished = GIsEditor || (appStristr(appCmdLine(), TEXT("Editor")) != NULL) || (appStristr(appCmdLine(), TEXT("CookPackages")) != NULL) || (appStristr(appCmdLine(), TEXT("UseUnpublished")) != NULL); const TCHAR* ReplaceBit; const TCHAR* UnpublishedPath; const TCHAR* PublishedPath; // @todo ship: Use GSys->Paths or something for the replacement, instead of hardcoded Content FString UserContentPath(AbsolutePath); for (INT Path = 0; Path < 2; Path++) { if (Path == 0) { ReplaceBit = TEXT("\\CookedPC\\"); UnpublishedPath = TEXT("\\Unpublished\\CookedPC\\"); PublishedPath = TEXT("\\Published\\CookedPC\\"); } else { ReplaceBit = TEXT("\\Content\\"); UnpublishedPath = TEXT("\\Unpublished\\Content\\"); PublishedPath = TEXT("\\Published\\Content\\"); } // make sure we aren't using one of the special paths if (UserContentPath.InStr(UnpublishedPath, FALSE, TRUE) == INDEX_NONE && UserContentPath.InStr(PublishedPath, FALSE, TRUE) == INDEX_NONE) { UserContentPath = UserContentPath.Replace(ReplaceBit, bUseUnpublished ? UnpublishedPath : PublishedPath); } } // replace C:\Program Files\MyGame\Binaries with C:\<UserDir>\Binaries return UserContentPath.Replace(*WindowsRootDir, *WindowsUserDir, TRUE); } else { // in the non-installed (dev) case, just return the original path in all cases return AbsolutePath; } }
void appSetRootDirectory2(const char *filename) { char buf[MAX_PACKAGE_PATH], buf2[MAX_PACKAGE_PATH]; appStrncpyz(buf, filename, ARRAY_COUNT(buf)); char *s; // replace slashes for (s = buf; *s; s++) if (*s == '\\') *s = '/'; // cut filename s = strrchr(buf, '/'); *s = 0; // make a copy for fallback strcpy(buf2, buf); FString root; int detected = 0; // weigth; 0 = not detected root = buf; // analyze path const char *pCooked = NULL; for (int i = 0; i < 8; i++) { // find deepest directory name s = strrchr(buf, '/'); if (!s) break; *s++ = 0; bool found = false; if (i == 0) { for (int j = 0; j < ARRAY_COUNT(KnownDirs2); j++) if (!stricmp(KnownDirs2[j], s)) { found = true; break; } } if (found) { if (detected < 1) { detected = 1; root = buf; } } pCooked = appStristr(s, "Cooked"); if (pCooked || appStristr(s, "Content")) { s[-1] = '/'; // put it back if (detected < 2) { detected = 2; root = buf; break; } } } appPrintf("Detected game root %s%s", *root, (detected == false) ? " (no recurse)" : ""); // detect platform if (GForcePlatform == PLATFORM_UNKNOWN && pCooked) { pCooked += 6; // skip "Cooked" string if (!strnicmp(pCooked, "PS3", 3)) GForcePlatform = PLATFORM_PS3; else if (!strnicmp(pCooked, "Xenon", 5)) GForcePlatform = PLATFORM_XBOX360; else if (!strnicmp(pCooked, "IPhone", 6)) GForcePlatform = PLATFORM_IOS; if (GForcePlatform != PLATFORM_UNKNOWN) { static const char *PlatformNames[] = { "", "PC", "XBox360", "PS3", "iPhone", "Android", }; staticAssert(ARRAY_COUNT(PlatformNames) == PLATFORM_COUNT, Verify_PlatformNames); appPrintf("; platform %s", PlatformNames[GForcePlatform]); } } // scan root directory appPrintf("\n"); appSetRootDirectory(*root, detected); }
static bool RegisterGameFile(const char *FullName, FVirtualFileSystem* parentVfs = NULL) { guard(RegisterGameFile); // printf("..file %s\n", FullName); if (!parentVfs) // no nested VFSs { const char* ext = strrchr(FullName, '.'); if (ext) { guard(MountVFS); ext++; FVirtualFileSystem* vfs = NULL; FArchive* reader = NULL; #if SUPPORT_ANDROID if (!stricmp(ext, "obb")) { GForcePlatform = PLATFORM_ANDROID; reader = new FFileReader(FullName); if (!reader) return true; reader->Game = GAME_UE3; vfs = new FObbVFS(FullName); } #endif // SUPPORT_ANDROID #if UNREAL4 if (!stricmp(ext, "pak")) { reader = new FFileReader(FullName); if (!reader) return true; reader->Game = GAME_UE4_BASE; vfs = new FPakVFS(FullName); //!! detect game by file name } #endif // UNREAL4 //!! process other VFS types here if (vfs) { assert(reader); // read VF directory if (!vfs->AttachReader(reader)) { // something goes wrong delete vfs; delete reader; return true; } // add game files int NumVFSFiles = vfs->NumFiles(); for (int i = 0; i < NumVFSFiles; i++) { if (!RegisterGameFile(vfs->FileName(i), vfs)) return false; } return true; } unguard; } } bool IsPackage = false; if (FindExtension(FullName, ARRAY_ARG(PackageExtensions))) { IsPackage = true; } else { #if HAS_SUPORT_FILES if (!FindExtension(FullName, ARRAY_ARG(KnownExtensions))) #endif { // ignore any unknown files inside VFS if (parentVfs) return true; // ignore unknown files inside "cooked" or "content" directories if (appStristr(FullName, "cooked") || appStristr(FullName, "content")) return true; // perhaps this file was exported by our tool - skip it if (FindExtension(FullName, ARRAY_ARG(SkipExtensions))) return true; // unknown file type if (++GNumForeignFiles >= MAX_FOREIGN_FILES) appError("Too many unknown files - bad root directory (%s)?", RootDirectory); return true; } } // create entry CGameFileInfo *info = new CGameFileInfo; GameFiles.Add(info); info->IsPackage = IsPackage; info->FileSystem = parentVfs; if (IsPackage) GNumPackageFiles++; if (!parentVfs) { // regular file FILE* f = fopen(FullName, "rb"); if (f) { fseek(f, 0, SEEK_END); info->SizeInKb = (ftell(f) + 512) / 1024; fclose(f); } else { info->SizeInKb = 0; } // cut RootDirectory from filename const char *s = FullName + strlen(RootDirectory) + 1; assert(s[-1] == '/'); info->RelativeName = appStrdupPool(s); } else { // file in virtual file system info->SizeInKb = parentVfs->GetFileSize(FullName); info->RelativeName = appStrdupPool(FullName); } // find filename const char* s = strrchr(info->RelativeName, '/'); if (s) s++; else s = info->RelativeName; info->ShortFilename = s; // find extension s = strrchr(info->ShortFilename, '.'); if (s) s++; info->Extension = s; #if UNREAL3 if (info->IsPackage && (strnicmp(info->ShortFilename, "startup", 7) == 0)) { // Register a startup package // possible name variants: // - startup // - startup_int // - startup_* int startupWeight = 0; if (info->ShortFilename[7] == '.') startupWeight = 30; // "startup.upk" else if (strnicmp(info->ShortFilename+7, "_int.", 5) == 0) startupWeight = 20; // "startup_int.upk" else if (strnicmp(info->ShortFilename+7, "_loc_int.", 9) == 0) startupWeight = 20; // "startup_int.upk" else if (info->ShortFilename[7] == '_') startupWeight = 1; // non-int locale, lower priority - use if when other is not detected if (startupWeight > GStartupPackageInfoWeight) { GStartupPackageInfoWeight = startupWeight; GStartupPackageInfo = info; } } #endif // UNREAL3 // insert CGameFileInfo into hash table int hash = GetHashForFileName(info->ShortFilename, true); info->HashNext = GGameFileHash[hash]; GGameFileHash[hash] = info; #if DEBUG_HASH printf("--> add(%s) pkg=%d hash=%X\n", info->ShortFilename, info->IsPackage, hash); #endif return true; unguardf("%s", FullName); }