/**
 * 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;
	}
}
예제 #2
0
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);
}
예제 #3
0
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);
}