コード例 #1
0
ファイル: init.cpp プロジェクト: kerbys/warzone2100
/*!
 * \brief Rebuilds the PHYSFS searchPath with mode specific subdirs
 *
 * Priority:
 * maps > mods > base > base.wz
 */
bool rebuildSearchPath( searchPathMode mode, bool force )
{
	static searchPathMode current_mode = mod_clean;
	static std::string current_current_map;
	wzSearchPath * curSearchPath = searchPathRegistry;
	char tmpstr[PATH_MAX] = "\0";

	if (mode != current_mode || (current_map != NULL? current_map : "") != current_current_map || force ||
	    (use_override_mods && strcmp(override_mod_list, getModList())))
	{
		if (mode != mod_clean)
		{
			rebuildSearchPath( mod_clean, false );
		}

		current_mode = mode;
		current_current_map = current_map != NULL? current_map : "";

		// Start at the lowest priority
		while( curSearchPath->lowerPriority )
			curSearchPath = curSearchPath->lowerPriority;

		switch ( mode )
		{
			case mod_clean:
				debug(LOG_WZ, "Cleaning up");
				clearLoadedMods();

				while( curSearchPath )
				{
#ifdef DEBUG
					debug(LOG_WZ, "Removing [%s] from search path", curSearchPath->path);
#endif // DEBUG
					// Remove maps and mods
					removeSubdirs( curSearchPath->path, "maps", NULL );
					removeSubdirs( curSearchPath->path, "mods/music", NULL );
					removeSubdirs( curSearchPath->path, "mods/global", NULL );
					removeSubdirs( curSearchPath->path, "mods/campaign", NULL );
					removeSubdirs( curSearchPath->path, "mods/multiplay", NULL );
					removeSubdirs( curSearchPath->path, "mods/autoload", NULL );

					// Remove multiplay patches
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "mp");
					PHYSFS_removeFromSearchPath( tmpstr );
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "mp.wz");
					PHYSFS_removeFromSearchPath( tmpstr );

					// Remove plain dir
					PHYSFS_removeFromSearchPath( curSearchPath->path );

					// Remove base files
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "base");
					PHYSFS_removeFromSearchPath( tmpstr );
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "base.wz");
					PHYSFS_removeFromSearchPath( tmpstr );

					// remove video search path as well
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "sequences.wz");
					PHYSFS_removeFromSearchPath( tmpstr );
					curSearchPath = curSearchPath->higherPriority;
				}
				break;
			case mod_campaign:
				debug(LOG_WZ, "*** Switching to campaign mods ***");
				clearLoadedMods();

				while (curSearchPath)
				{
					// make sure videos override included files
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "sequences.wz");
					PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND);
					curSearchPath = curSearchPath->higherPriority;
				}
				curSearchPath = searchPathRegistry;
				while (curSearchPath->lowerPriority)
					curSearchPath = curSearchPath->lowerPriority;
				while( curSearchPath )
				{
#ifdef DEBUG
					debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path);
#endif // DEBUG
					// Add global and campaign mods
					PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND );

					addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false );
					addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
					addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
					addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true );
					addSubdirs( curSearchPath->path, "mods/campaign", PHYSFS_APPEND, use_override_mods?override_mods:campaign_mods, true );
					if (!PHYSFS_removeFromSearchPath( curSearchPath->path ))
					{
						debug(LOG_WZ, "* Failed to remove path %s again", curSearchPath->path);
					}

					// Add plain dir
					PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND );

					// Add base files
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "base");
					PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND );
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "base.wz");
					PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND );

					curSearchPath = curSearchPath->higherPriority;
				}
				break;
			case mod_multiplay:
				debug(LOG_WZ, "*** Switching to multiplay mods ***");
				clearLoadedMods();

				while (curSearchPath)
				{
					// make sure videos override included files
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "sequences.wz");
					PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND);
					curSearchPath = curSearchPath->higherPriority;
				}
				// Add the selected map first, for mapmod support
				if (current_map != NULL)
				{
					std::string realPathAndDir = std::string(PHYSFS_getRealDir(current_map)) + current_map;
					PHYSFS_addToSearchPath(realPathAndDir.c_str(), PHYSFS_APPEND);
				}
				curSearchPath = searchPathRegistry;
				while (curSearchPath->lowerPriority)
					curSearchPath = curSearchPath->lowerPriority;
				while( curSearchPath )
				{
#ifdef DEBUG
					debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path);
#endif // DEBUG
					// Add global and multiplay mods
					PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND );
					addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false );
					addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
					addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true );
					addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true );
					addSubdirs( curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, use_override_mods?override_mods:multiplay_mods, true );
					PHYSFS_removeFromSearchPath( curSearchPath->path );

					// Add multiplay patches
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "mp");
					PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND );
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "mp.wz");
					PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND );

					// Add plain dir
					PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND );

					// Add base files
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "base");
					PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND );
					sstrcpy(tmpstr, curSearchPath->path);
					sstrcat(tmpstr, "base.wz");
					PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND );

					curSearchPath = curSearchPath->higherPriority;
				}
				break;
			default:
				debug(LOG_ERROR, "Can't switch to unknown mods %i", mode);
				return false;
		}
		if (use_override_mods && mode != mod_clean)
		{
			if (strcmp(getModList(),override_mod_list))
			{
				debug(LOG_POPUP, _("The required mod could not be loaded: %s\n\nWarzone will try to load the game without it."), override_mod_list);
			}
			clearOverrideMods();
			current_mode = mod_override;
		}

		// User's home dir must be first so we allways see what we write
		PHYSFS_removeFromSearchPath(PHYSFS_getWriteDir());
		PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), PHYSFS_PREPEND );

#ifdef DEBUG
		printSearchPath();
#endif // DEBUG
	}
	else if (use_override_mods)
	{
		// override mods are already the same as current mods, so no need to do anything
		clearOverrideMods();
	}
	return true;
}
コード例 #2
0
ファイル: main.cpp プロジェクト: GhostKing/warzone2100
/*!
 * \brief Adds default data dirs
 *
 * Priority:
 * Lower loads first. Current:
 * -datadir > User's home dir > source tree data > AutoPackage > BaseDir > DEFAULT_DATADIR
 *
 * Only -datadir and home dir are allways examined. Others only if data still not found.
 *
 * We need ParseCommandLine, before we can add any mods...
 *
 * \sa rebuildSearchPath
 */
static void scanDataDirs( void )
{
	char tmpstr[PATH_MAX], prefix[PATH_MAX];
	char* separator;

#if defined(WZ_OS_MAC)
	// version-independent location for video files
	registerSearchPath("/Library/Application Support/Warzone 2100/", 1);
#endif

	// Find out which PREFIX we are in...
	sstrcpy(prefix, PHYSFS_getBaseDir());

	separator = strrchr(prefix, *PHYSFS_getDirSeparator());
	if (separator)
	{
		*separator = '\0'; // Trim ending '/', which getBaseDir always provides

		separator = strrchr(prefix, *PHYSFS_getDirSeparator());
		if (separator)
		{
			*separator = '\0'; // Skip the last dir from base dir
		}
	}

	// Commandline supplied datadir
	if( strlen( datadir ) != 0 )
		registerSearchPath( datadir, 1 );

	// User's home dir
	registerSearchPath( PHYSFS_getWriteDir(), 2 );
	rebuildSearchPath( mod_multiplay, true );

	if( !PHYSFS_exists("gamedesc.lev") )
	{
		// Data in source tree
		sstrcpy(tmpstr, prefix);
		sstrcat(tmpstr, "/data/");
		registerSearchPath( tmpstr, 3 );
		rebuildSearchPath( mod_multiplay, true );

		if( !PHYSFS_exists("gamedesc.lev") )
		{
			// Relocation for AutoPackage
			sstrcpy(tmpstr, prefix);
			sstrcat(tmpstr, "/share/warzone2100/");
			registerSearchPath( tmpstr, 4 );
			rebuildSearchPath( mod_multiplay, true );

			if( !PHYSFS_exists("gamedesc.lev") )
			{
				// Program dir
				registerSearchPath( PHYSFS_getBaseDir(), 5 );
				rebuildSearchPath( mod_multiplay, true );

				if( !PHYSFS_exists("gamedesc.lev") )
				{
					// Guessed fallback default datadir on Unix
					registerSearchPath( WZ_DATADIR, 6 );
					rebuildSearchPath( mod_multiplay, true );
				}
			}
		}
	}

#ifdef WZ_OS_MAC
	if( !PHYSFS_exists("gamedesc.lev") ) {
		CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
		char resourcePath[PATH_MAX];
		if( CFURLGetFileSystemRepresentation( resourceURL, true,
							(UInt8 *) resourcePath,
							PATH_MAX) ) {
			chdir( resourcePath );
			registerSearchPath( "data", 7 );
			rebuildSearchPath( mod_multiplay, true );
		} else {
			debug( LOG_ERROR, "Could not change to resources directory." );
		}

		if( resourceURL != NULL ) {
			CFRelease( resourceURL );
		}
	}
#endif

	/** Debugging and sanity checks **/

	printSearchPath();

	if( PHYSFS_exists("gamedesc.lev") )
	{
		debug( LOG_WZ, "gamedesc.lev found at %s", PHYSFS_getRealDir( "gamedesc.lev" ) );
	}
	else
	{
		debug( LOG_FATAL, "Could not find game data. Aborting." );
		exit(1);
	}
}
コード例 #3
0
ファイル: init.cpp プロジェクト: perim/warzone2100
static MapFileList listMapFiles()
{
	MapFileList ret, filtered, oldSearchPath;

	char **subdirlist = PHYSFS_enumerateFiles("maps");

	for (char **i = subdirlist; *i != nullptr; ++i)
	{
		std::string wzfile = *i;
		if (*i[0] == '.' || wzfile.substr(wzfile.find_last_of('.') + 1) != "wz")
		{
			continue;
		}

		std::string realFileName = std::string("maps/") + *i;
		ret.push_back(realFileName);
	}
	PHYSFS_freeList(subdirlist);
	// save our current search path(s)
	debug(LOG_WZ, "Map search paths:");
	char **searchPath = PHYSFS_getSearchPath();
	for (char **i = searchPath; *i != nullptr; i++)
	{
		debug(LOG_WZ, "    [%s]", *i);
		oldSearchPath.push_back(*i);
		WZ_PHYSFS_unmount(*i);
	}
	PHYSFS_freeList(searchPath);

	for (const auto &realFileName : ret)
	{
		std::string realFilePathAndName = PHYSFS_getWriteDir() + realFileName;
		if (PHYSFS_mount(realFilePathAndName.c_str(), NULL, PHYSFS_APPEND))
		{
			int unsafe = 0;
			char **filelist = PHYSFS_enumerateFiles("multiplay/maps");

			for (char **file = filelist; *file != nullptr; ++file)
			{
				std::string isDir = std::string("multiplay/maps/") + *file;
				if (WZ_PHYSFS_isDirectory(isDir.c_str()))
				{
					continue;
				}
				std::string checkfile = *file;
				debug(LOG_WZ, "checking ... %s", *file);
				if (checkfile.substr(checkfile.find_last_of('.') + 1) == "gam")
				{
					if (unsafe++ > 1)
					{
						debug(LOG_ERROR, "Map packs are not supported! %s NOT added.", realFilePathAndName.c_str());
						break;
					}
				}
			}
			PHYSFS_freeList(filelist);
			if (unsafe < 2)
			{
				filtered.push_back(realFileName);
			}
			WZ_PHYSFS_unmount(realFilePathAndName.c_str());
		}
		else
		{
			debug(LOG_POPUP, "Could not mount %s, because: %s.\nPlease delete or move the file specified.", realFilePathAndName.c_str(), WZ_PHYSFS_getLastError());
		}
	}

	// restore our search path(s) again
	for (const auto &restorePaths : oldSearchPath)
	{
		PHYSFS_mount(restorePaths.c_str(), NULL, PHYSFS_APPEND);
	}
	debug(LOG_WZ, "Search paths restored");
	printSearchPath();

	return filtered;
}
コード例 #4
0
ファイル: init.cpp プロジェクト: tyagiakhilesh/warzone2100
static MapFileList listMapFiles()
{
	MapFileList ret, filtered, oldSearchPath;

	char **subdirlist = PHYSFS_enumerateFiles("maps");

	for (char **i = subdirlist; *i != NULL; ++i)
	{
		std::string wzfile = *i;
		if (*i[0] == '.' || wzfile.substr(wzfile.find_last_of(".")+1) != "wz")
		{
			continue;
		}

		std::string realFileName = std::string("maps/") + *i;
		ret.push_back(realFileName);
	}
	PHYSFS_freeList(subdirlist);
	// save our current search path(s)
	debug(LOG_WZ, "Map search paths:");
	char **searchPath = PHYSFS_getSearchPath();
	for (char **i = searchPath; *i != NULL; i++)
	{
		debug(LOG_WZ, "    [%s]", *i);
		oldSearchPath.push_back(*i);
		PHYSFS_removeFromSearchPath(*i);
	}
	PHYSFS_freeList(searchPath);

	for (MapFileList::iterator realFileName = ret.begin(); realFileName != ret.end(); ++realFileName)
	{
		std::string realFilePathAndName = PHYSFS_getWriteDir() + *realFileName;
		PHYSFS_addToSearchPath(realFilePathAndName.c_str(), PHYSFS_APPEND);
		int unsafe = 0;
		char **filelist = PHYSFS_enumerateFiles("multiplay/maps");

		for (char **file = filelist; *file != NULL; ++file)
		{
			std::string isDir = std::string("multiplay/maps/") + *file;
			if (PHYSFS_isDirectory(isDir.c_str()))
				continue;
			std::string checkfile = *file;
			debug(LOG_WZ,"checking ... %s", *file);
			if (checkfile.substr(checkfile.find_last_of(".")+ 1) == "gam")
			{
				if (unsafe++ > 1)
				{
					debug(LOG_ERROR, "Map packs are not supported! %s NOT added.", realFilePathAndName.c_str());
					break;
				}
			}
		}
		PHYSFS_freeList(filelist);
		if (unsafe < 2)
		{
			filtered.push_back(realFileName->c_str());
		}
		PHYSFS_removeFromSearchPath(realFilePathAndName.c_str());
	}

	// restore our search path(s) again
	for (MapFileList::iterator restorePaths = oldSearchPath.begin(); restorePaths != oldSearchPath.end(); ++restorePaths)
	{
		PHYSFS_addToSearchPath(restorePaths->c_str(), PHYSFS_APPEND);
	}
	debug(LOG_WZ, "Search paths restored");
	printSearchPath();

	return filtered;
}
コード例 #5
0
ファイル: init.cpp プロジェクト: perim/warzone2100
/*!
 * \brief Rebuilds the PHYSFS searchPath with mode specific subdirs
 *
 * Priority:
 * maps > mods > base > base.wz
 */
bool rebuildSearchPath(searchPathMode mode, bool force, const char *current_map)
{
	static searchPathMode current_mode = mod_clean;
	static std::string current_current_map;
	wzSearchPath *curSearchPath = searchPathRegistry;
	char tmpstr[PATH_MAX] = "\0";

	if (mode != current_mode || (current_map != nullptr ? current_map : "") != current_current_map || force ||
	    (use_override_mods && override_mod_list != getModList()))
	{
		if (mode != mod_clean)
		{
			rebuildSearchPath(mod_clean, false);
		}

		current_mode = mode;
		current_current_map = current_map != nullptr ? current_map : "";

		// Start at the lowest priority
		while (curSearchPath->lowerPriority)
		{
			curSearchPath = curSearchPath->lowerPriority;
		}

		switch (mode)
		{
		case mod_clean:
			debug(LOG_WZ, "Cleaning up");
			clearLoadedMods();

			while (curSearchPath)
			{
#ifdef DEBUG
				debug(LOG_WZ, "Removing [%s] from search path", curSearchPath->path);
#endif // DEBUG
				// Remove maps and mods
				removeSubdirs(curSearchPath->path, "maps");
				removeSubdirs(curSearchPath->path, "mods/music");
				removeSubdirs(curSearchPath->path, "mods/global");
				removeSubdirs(curSearchPath->path, "mods");
				removeSubdirs(curSearchPath->path, "mods/autoload");
				removeSubdirs(curSearchPath->path, "mods/campaign");
				removeSubdirs(curSearchPath->path, "mods/multiplay");
				removeSubdirs(curSearchPath->path, "mods/downloads");

				// Remove multiplay patches
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "mp");
				WZ_PHYSFS_unmount(tmpstr);
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "mp.wz");
				WZ_PHYSFS_unmount(tmpstr);

				// Remove plain dir
				WZ_PHYSFS_unmount(curSearchPath->path);

				// Remove base files
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "base");
				WZ_PHYSFS_unmount(tmpstr);
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "base.wz");
				WZ_PHYSFS_unmount(tmpstr);

				// remove video search path as well
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "sequences.wz");
				WZ_PHYSFS_unmount(tmpstr);
				curSearchPath = curSearchPath->higherPriority;
			}
			break;
		case mod_campaign:
			debug(LOG_WZ, "*** Switching to campaign mods ***");
			clearLoadedMods();

			while (curSearchPath)
			{
				// make sure videos override included files
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "sequences.wz");
				PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND);
				curSearchPath = curSearchPath->higherPriority;
			}
			curSearchPath = searchPathRegistry;
			while (curSearchPath->lowerPriority)
			{
				curSearchPath = curSearchPath->lowerPriority;
			}
			while (curSearchPath)
			{
#ifdef DEBUG
				debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path);
#endif // DEBUG
				// Add global and campaign mods
				PHYSFS_mount(curSearchPath->path, NULL, PHYSFS_APPEND);

				addSubdirs(curSearchPath->path, "mods/music", PHYSFS_APPEND, nullptr, false);
				addSubdirs(curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods ? &override_mods : &global_mods, true);
				addSubdirs(curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods ? &override_mods : &global_mods, true);
				addSubdirs(curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods ? &override_mods : nullptr, true);
				addSubdirs(curSearchPath->path, "mods/campaign", PHYSFS_APPEND, use_override_mods ? &override_mods : &campaign_mods, true);
				if (!WZ_PHYSFS_unmount(curSearchPath->path))
				{
					debug(LOG_WZ, "* Failed to remove path %s again", curSearchPath->path);
				}

				// Add plain dir
				PHYSFS_mount(curSearchPath->path, NULL, PHYSFS_APPEND);

				// Add base files
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "base");
				PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND);
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "base.wz");
				PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND);

				curSearchPath = curSearchPath->higherPriority;
			}
			break;
		case mod_multiplay:
			debug(LOG_WZ, "*** Switching to multiplay mods ***");
			clearLoadedMods();

			while (curSearchPath)
			{
				// make sure videos override included files
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "sequences.wz");
				PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND);
				curSearchPath = curSearchPath->higherPriority;
			}
			// Add the selected map first, for mapmod support
			if (current_map != nullptr)
			{
				WzString realPathAndDir = WzString::fromUtf8(PHYSFS_getRealDir(current_map)) + current_map;
				realPathAndDir.replace("/", PHYSFS_getDirSeparator()); // Windows fix
				PHYSFS_mount(realPathAndDir.toUtf8().c_str(), NULL, PHYSFS_APPEND);
			}
			curSearchPath = searchPathRegistry;
			while (curSearchPath->lowerPriority)
			{
				curSearchPath = curSearchPath->lowerPriority;
			}
			while (curSearchPath)
			{
#ifdef DEBUG
				debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path);
#endif // DEBUG
				// Add global and multiplay mods
				PHYSFS_mount(curSearchPath->path, NULL, PHYSFS_APPEND);
				addSubdirs(curSearchPath->path, "mods/music", PHYSFS_APPEND, nullptr, false);
				if (NetPlay.isHost || !NetPlay.bComms)
				{
					addSubdirs(curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods ? &override_mods : &global_mods, true);
					addSubdirs(curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods ? &override_mods : &global_mods, true);
					addSubdirs(curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods ? &override_mods : nullptr, true);
					addSubdirs(curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, use_override_mods ? &override_mods : &multiplay_mods, true);
				}
				else
				{
					std::vector<std::string> hashList;
					for (Sha256 &hash : game.modHashes)
					{
						hashList = {hash.toString()};
						addSubdirs(curSearchPath->path, "mods/downloads", PHYSFS_APPEND, &hashList, true);
					}
				}
				WZ_PHYSFS_unmount(curSearchPath->path);

				// Add multiplay patches
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "mp");
				PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND);
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "mp.wz");
				PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND);

				// Add plain dir
				PHYSFS_mount(curSearchPath->path, NULL, PHYSFS_APPEND);

				// Add base files
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "base");
				PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND);
				sstrcpy(tmpstr, curSearchPath->path);
				sstrcat(tmpstr, "base.wz");
				PHYSFS_mount(tmpstr, NULL, PHYSFS_APPEND);

				curSearchPath = curSearchPath->higherPriority;
			}
			break;
		default:
			debug(LOG_ERROR, "Can't switch to unknown mods %i", mode);
			return false;
		}
		if (use_override_mods && mode != mod_clean)
		{
			if (getModList() != override_mod_list)
			{
				debug(LOG_POPUP, _("The required mod could not be loaded: %s\n\nWarzone will try to load the game without it."), override_mod_list.c_str());
			}
			clearOverrideMods();
			current_mode = mod_override;
		}

		// User's home dir must be first so we always see what we write
		WZ_PHYSFS_unmount(PHYSFS_getWriteDir());
		PHYSFS_mount(PHYSFS_getWriteDir(), NULL, PHYSFS_PREPEND);

#ifdef DEBUG
		printSearchPath();
#endif // DEBUG
	}
	else if (use_override_mods)
	{
		// override mods are already the same as current mods, so no need to do anything
		clearOverrideMods();
	}
	return true;
}