/*! * \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; }
/*! * \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; }