diff --git a/QBeat/actions.cpp b/QBeat/actions.cpp index 286b469..69d34dc 100644 --- a/QBeat/actions.cpp +++ b/QBeat/actions.cpp @@ -286,7 +286,11 @@ bool Actions::validateMod(Mod mod, bool includeDependencies ) } for( auto& fileToHash : download.mFileHashes ) { - QFile tempFile(Settings::instance.bsInstall() + "/" + fileToHash.first ); + + QString path = fileToHash.first; + Util::fixPath(path); + + QFile tempFile(Settings::instance.bsInstall() + "/" + path ); tempFile.open(QFile::OpenModeFlag::ReadOnly); if( !tempFile.isOpen() ) { qOut << "ERROR: Failed to open file for mod verification: " + tempFile.fileName() << "\n"; diff --git a/QBeat/util.cpp b/QBeat/util.cpp index 60d6638..36a144b 100644 --- a/QBeat/util.cpp +++ b/QBeat/util.cpp @@ -7,6 +7,22 @@ #include "minizip/unzip.h" +QString Util::mBSPathsToFix[] = { + "Beat Saber_Data", + "DLC", + "MonoBleedingEdge", + "Plugins", + "UserData", + "IPA", + "Libs", + "CustomAvatars", + "CustomSabers", + "CustomNotes", + "CustomCampaigns", + "CustomPlatforms", + "Playlists", +}; + bool Util::extractArchive( QString archivePath, QString destDirectory ) { auto zFile = unzOpen(archivePath.toUtf8()); @@ -48,6 +64,14 @@ bool Util::extractArchive( QString archivePath, QString destDirectory ) QString fileNameStr( fileName ); if( fileNameStr.size() == 0 ) continue; + // Ensure paths such as 'plugins' and corrected to 'Plugins' + // Otherwise mods won't be loaded if the path in the zip + // has one letter the wrong case -_- + // + // Alternative would be to fix the mod loading runtime, simpler + // to just handle it here + fixPath( fileNameStr ); + if( fileNameStr[fileNameLen-1] == '/' ) { // Directory @@ -64,6 +88,7 @@ bool Util::extractArchive( QString archivePath, QString destDirectory ) } auto outFileName = destDirectory + "/" + fileNameStr; + QFileInfo outFileInfo(outFileName); outFileInfo.absoluteDir().mkpath("."); if( !outFileInfo.isDir() ) { @@ -113,4 +138,16 @@ bool Util::extractArchive( QString archivePath, QString destDirectory ) return true; } - +void Util::fixPath( QString& path ) +{ + for( auto& correctPath : mBSPathsToFix ) { + if( path.size() < correctPath.size() ) continue; + QString firstBit = path; + firstBit.chop(path.size() - correctPath.size()); + + if( firstBit.compare( correctPath, Qt::CaseSensitivity::CaseInsensitive ) == 0 ) { + path.remove(0, correctPath.size()); + path.prepend(correctPath); + } + } +} diff --git a/QBeat/util.h b/QBeat/util.h index aa89f48..8318153 100644 --- a/QBeat/util.h +++ b/QBeat/util.h @@ -6,7 +6,26 @@ class Util { public: + /// Extract a zip archive to the specified directory static bool extractArchive( QString archivePath, QString destDirectory ); + + /** + * Fixup a path such as plugins -> Plugins + * Should be called on all file paths to correct issues in the mod manifest/archive contents + */ + static void fixPath( QString& path ); +private: + + /** + * A list of paths known to be wrong in some mod archives + * + * Not a problem on Windows as the filesystem is case insensitive + * but on anything else we end up with files in the wrong folders + * + * Paths will be checked against these and updated to the correct case + * if needed + */ + static QString mBSPathsToFix[]; }; #endif